@elevenlabs/react-native 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types.d.ts CHANGED
@@ -11,15 +11,6 @@ export type ConversationStatus = "disconnected" | "connecting" | "connected";
11
11
  * Language support
12
12
  */
13
13
  export type Language = "en" | "ja" | "zh" | "de" | "hi" | "fr" | "ko" | "pt" | "pt-br" | "it" | "es" | "id" | "nl" | "tr" | "pl" | "sv" | "bg" | "ro" | "ar" | "cs" | "el" | "fi" | "ms" | "da" | "ta" | "uk" | "ru" | "hu" | "hr" | "sk" | "no" | "vi";
14
- /**
15
- * Client tool call event structure
16
- */
17
- export type ClientToolCallEvent = {
18
- tool_name: string;
19
- tool_call_id: string;
20
- parameters: unknown;
21
- expects_response: boolean;
22
- };
23
14
  /**
24
15
  * Client tools configuration
25
16
  */
@@ -45,7 +36,7 @@ export type Callbacks = {
45
36
  onDisconnect?: (details: string) => void;
46
37
  onError?: (message: string, context?: Record<string, unknown>) => void;
47
38
  onMessage?: (props: {
48
- message: string;
39
+ message: ConversationEvent;
49
40
  source: Role;
50
41
  }) => void;
51
42
  onModeChange?: (prop: {
@@ -86,6 +77,102 @@ export type ConversationConfig = {
86
77
  dynamicVariables?: Record<string, string | number | boolean>;
87
78
  userId?: string;
88
79
  };
80
+ export type UserTranscriptionEvent = {
81
+ type: "user_transcript";
82
+ user_transcription_event: {
83
+ user_transcript: string;
84
+ };
85
+ };
86
+ export type AgentResponseEvent = {
87
+ type: "agent_response";
88
+ agent_response_event: {
89
+ agent_response: string;
90
+ };
91
+ };
92
+ export type AgentResponseCorrectionEvent = {
93
+ type: "agent_response_correction";
94
+ agent_response_correction_event: {
95
+ original_agent_response: string;
96
+ corrected_agent_response: string;
97
+ };
98
+ };
99
+ export type AgentAudioEvent = {
100
+ type: "audio";
101
+ audio_event: {
102
+ audio_base_64: string;
103
+ event_id: number;
104
+ };
105
+ };
106
+ export type InterruptionEvent = {
107
+ type: "interruption";
108
+ interruption_event: {
109
+ event_id: number;
110
+ };
111
+ };
112
+ export type InternalTentativeAgentResponseEvent = {
113
+ type: "internal_tentative_agent_response";
114
+ tentative_agent_response_internal_event: {
115
+ tentative_agent_response: string;
116
+ };
117
+ };
118
+ export type ConfigEvent = {
119
+ type: "conversation_initiation_metadata";
120
+ conversation_initiation_metadata_event: {
121
+ conversation_id: string;
122
+ agent_output_audio_format: string;
123
+ user_input_audio_format?: string;
124
+ };
125
+ };
126
+ export type PingEvent = {
127
+ type: "ping";
128
+ ping_event: {
129
+ event_id: number;
130
+ ping_ms?: number;
131
+ };
132
+ };
133
+ export type ClientToolCallEvent = {
134
+ type: "client_tool_call";
135
+ client_tool_call: {
136
+ tool_name: string;
137
+ tool_call_id: string;
138
+ parameters: any;
139
+ expects_response: boolean;
140
+ };
141
+ };
142
+ export type PongEvent = {
143
+ type: "pong";
144
+ event_id: number;
145
+ };
146
+ export type UserAudioEvent = {
147
+ user_audio_chunk: string;
148
+ };
149
+ export type UserFeedbackEvent = {
150
+ type: "feedback";
151
+ score: "like" | "dislike";
152
+ event_id: number;
153
+ };
154
+ export type ClientToolResultEvent = {
155
+ type: "client_tool_result";
156
+ tool_call_id: string;
157
+ result: any;
158
+ is_error: boolean;
159
+ };
160
+ export type ContextualUpdateEvent = {
161
+ type: "contextual_update";
162
+ text: string;
163
+ };
164
+ export type UserMessageEvent = {
165
+ type: "user_message";
166
+ text: string;
167
+ };
168
+ export type UserActivityEvent = {
169
+ type: "user_activity";
170
+ };
171
+ export type MCPToolApprovalResultEvent = {
172
+ type: "mcp_tool_approval_result";
173
+ tool_call_id: string;
174
+ is_approved: boolean;
175
+ };
89
176
  export type InitiationClientDataEvent = {
90
177
  type: "conversation_initiation_client_data";
91
178
  conversation_config_override?: {
@@ -111,3 +198,4 @@ export type InitiationClientDataEvent = {
111
198
  dynamic_variables?: Record<string, string | number | boolean>;
112
199
  user_id?: string;
113
200
  };
201
+ export type ConversationEvent = UserTranscriptionEvent | AgentResponseEvent | AgentResponseCorrectionEvent | AgentAudioEvent | InterruptionEvent | InternalTentativeAgentResponseEvent | ConfigEvent | PingEvent | ClientToolCallEvent;
@@ -1,2 +1,2 @@
1
- export declare const extractRoomIdFromToken: (token: string) => string;
1
+ export declare const extractConversationIdFromToken: (token: string) => string;
2
2
  export declare const getConversationToken: (agentId: string, tokenFetchUrl?: string) => Promise<string>;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const PACKAGE_VERSION = "0.1.2";
1
+ export declare const PACKAGE_VERSION = "0.2.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevenlabs/react-native",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "ElevenLabs React Native SDK for Conversational AI",
5
5
  "main": "./dist/lib.js",
6
6
  "module": "./dist/lib.module.js",
@@ -16,7 +16,7 @@ interface ConversationOptions extends Callbacks, Partial<ClientToolsConfig> {
16
16
  tokenFetchUrl?: string;
17
17
  }
18
18
 
19
- interface Conversation {
19
+ export interface Conversation {
20
20
  startSession: (config: ConversationConfig) => Promise<void>;
21
21
  endSession: () => Promise<void>;
22
22
  status: ConversationStatus;
@@ -24,6 +24,7 @@ interface Conversation {
24
24
  // TODO: Implement setVolume when LiveKit React Native supports it
25
25
  // setVolume: (volume: number) => void;
26
26
  canSendFeedback: boolean;
27
+ getId: () => string;
27
28
  sendFeedback: (like: boolean) => void;
28
29
  sendContextualUpdate: (text: string) => void;
29
30
  sendUserMessage: (text: string) => void;
@@ -87,7 +88,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
87
88
  const [status, setStatus] = useState<ConversationStatus>('disconnected');
88
89
  const [serverUrl, setServerUrl] = useState(DEFAULT_SERVER_URL);
89
90
  const [tokenFetchUrl, setTokenFetchUrl] = useState<string | undefined>(undefined);
90
- const [roomId, setRoomId] = useState<string>('');
91
+ const [conversationId, setConversationId] = useState<string>('');
91
92
  const [isSpeaking, setIsSpeaking] = useState(false);
92
93
  const [canSendFeedback, setCanSendFeedback] = useState(false);
93
94
 
@@ -119,7 +120,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
119
120
  overrides,
120
121
  customLlmExtraBody,
121
122
  dynamicVariables,
122
- } = useConversationSession(callbacksRef, setStatus, setConnect, setToken, setRoomId, tokenFetchUrl);
123
+ } = useConversationSession(callbacksRef, setStatus, setConnect, setToken, setConversationId, tokenFetchUrl);
123
124
 
124
125
  const {
125
126
  roomConnected,
@@ -128,7 +129,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
128
129
  handleConnected,
129
130
  handleDisconnected,
130
131
  handleError,
131
- } = useLiveKitRoom(callbacksRef, setStatus, roomId);
132
+ } = useLiveKitRoom(callbacksRef, setStatus, conversationId);
132
133
 
133
134
  // Enhanced connection handler to initialize feedback state
134
135
  const handleConnectedWithFeedback = React.useCallback(() => {
@@ -184,6 +185,8 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
184
185
  console.warn('setVolume is not yet implemented in React Native SDK');
185
186
  }, []);
186
187
 
188
+ const getId = () => conversationId;
189
+
187
190
  // Update current event ID for feedback tracking
188
191
  const updateCurrentEventId = React.useCallback((eventId: number) => {
189
192
  currentEventIdRef.current = eventId;
@@ -211,6 +214,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
211
214
  isSpeaking,
212
215
  // setVolume,
213
216
  canSendFeedback,
217
+ getId,
214
218
  sendFeedback,
215
219
  sendContextualUpdate: (text: string) => {
216
220
  sendMessage({
@@ -1,7 +1,7 @@
1
1
  import { useEffect } from 'react';
2
2
  import { useLocalParticipant, useDataChannel } from '@livekit/react-native';
3
3
  import type { LocalParticipant } from 'livekit-client';
4
- import type { Callbacks, ClientToolsConfig, ClientToolCallEvent } from '../types';
4
+ import type { Callbacks, ClientToolsConfig, ClientToolCallEvent, ConversationEvent } from '../types';
5
5
  import React from 'react';
6
6
 
7
7
  interface MessageHandlerProps {
@@ -13,6 +13,10 @@ interface MessageHandlerProps {
13
13
  updateCurrentEventId?: (eventId: number) => void;
14
14
  }
15
15
 
16
+ export function isValidEvent(event: any): event is ConversationEvent {
17
+ return !!event.type;
18
+ }
19
+
16
20
  export const MessageHandler = ({
17
21
  onReady,
18
22
  isConnected,
@@ -36,13 +40,13 @@ export const MessageHandler = ({
36
40
  if (
37
41
  Object.prototype.hasOwnProperty.call(
38
42
  clientTools,
39
- clientToolCall.tool_name
43
+ clientToolCall.client_tool_call.tool_name
40
44
  )
41
45
  ) {
42
46
  try {
43
47
  const result =
44
- (await clientTools[clientToolCall.tool_name](
45
- clientToolCall.parameters
48
+ (await clientTools[clientToolCall.client_tool_call.tool_name](
49
+ clientToolCall.client_tool_call.parameters
46
50
  )) ?? "Client tool execution successful."; // default client-tool call response
47
51
 
48
52
  // The API expects result to be a string, so we need to convert it if it's not already a string
@@ -51,18 +55,18 @@ export const MessageHandler = ({
51
55
 
52
56
  sendMessage({
53
57
  type: "client_tool_result",
54
- tool_call_id: clientToolCall.tool_call_id,
58
+ tool_call_id: clientToolCall.client_tool_call.tool_call_id,
55
59
  result: formattedResult,
56
60
  is_error: false,
57
61
  });
58
62
  } catch (e) {
59
63
  const errorMessage = `Client tool execution failed with following error: ${(e as Error)?.message}`;
60
64
  callbacks.onError?.(errorMessage, {
61
- clientToolName: clientToolCall.tool_name,
65
+ clientToolName: clientToolCall.client_tool_call.tool_name,
62
66
  });
63
67
  sendMessage({
64
68
  type: "client_tool_result",
65
- tool_call_id: clientToolCall.tool_call_id,
69
+ tool_call_id: clientToolCall.client_tool_call.tool_call_id,
66
70
  result: `Client tool execution failed: ${(e as Error)?.message}`,
67
71
  is_error: true,
68
72
  });
@@ -73,13 +77,13 @@ export const MessageHandler = ({
73
77
  return;
74
78
  }
75
79
 
76
- const errorMessage = `Client tool with name ${clientToolCall.tool_name} is not defined on client`;
80
+ const errorMessage = `Client tool with name ${clientToolCall.client_tool_call.tool_name} is not defined on client`;
77
81
  callbacks.onError?.(errorMessage, {
78
- clientToolName: clientToolCall.tool_name,
82
+ clientToolName: clientToolCall.client_tool_call.tool_name,
79
83
  });
80
84
  sendMessage({
81
85
  type: "client_tool_result",
82
- tool_call_id: clientToolCall.tool_call_id,
86
+ tool_call_id: clientToolCall.client_tool_call.tool_call_id,
83
87
  result: errorMessage,
84
88
  is_error: true,
85
89
  });
@@ -90,6 +94,14 @@ export const MessageHandler = ({
90
94
  const decoder = new TextDecoder();
91
95
  const message = JSON.parse(decoder.decode(msg.payload));
92
96
 
97
+ if (!isValidEvent(message)) {
98
+ callbacks.onDebug?.({
99
+ type: "invalid_event",
100
+ message,
101
+ });
102
+ return;
103
+ }
104
+
93
105
  callbacks.onMessage?.({
94
106
  message,
95
107
  source: msg.from?.isAgent ? 'ai' : 'user',
@@ -115,7 +127,7 @@ export const MessageHandler = ({
115
127
  });
116
128
  break;
117
129
  case "client_tool_call":
118
- handleClientToolCall(message.client_tool_call);
130
+ handleClientToolCall(message);
119
131
  break;
120
132
  default:
121
133
  callbacks.onDebug?.(message);
@@ -6,7 +6,7 @@ import type {
6
6
  } from "../types";
7
7
  import {
8
8
  getConversationToken,
9
- extractRoomIdFromToken,
9
+ extractConversationIdFromToken,
10
10
  } from "../utils/tokenUtils";
11
11
 
12
12
  export const useConversationSession = (
@@ -14,7 +14,7 @@ export const useConversationSession = (
14
14
  setStatus: (status: ConversationStatus) => void,
15
15
  setConnect: (connect: boolean) => void,
16
16
  setToken: (token: string) => void,
17
- setRoomId: (roomId: string) => void,
17
+ setConversationId: (conversationId: string) => void,
18
18
  tokenFetchUrl?: string
19
19
  ) => {
20
20
  const [overrides, setOverrides] = useState<ConversationConfig["overrides"]>(
@@ -55,9 +55,9 @@ export const useConversationSession = (
55
55
  throw new Error("Either conversationToken or agentId is required");
56
56
  }
57
57
 
58
- // Extract room ID from token
59
- const extractedRoomId = extractRoomIdFromToken(conversationToken);
60
- setRoomId(extractedRoomId);
58
+ const extractedConversationId =
59
+ extractConversationIdFromToken(conversationToken);
60
+ setConversationId(extractedConversationId);
61
61
 
62
62
  setToken(conversationToken);
63
63
  setConnect(true);
@@ -68,7 +68,14 @@ export const useConversationSession = (
68
68
  throw error;
69
69
  }
70
70
  },
71
- [callbacksRef, setStatus, setConnect, setToken, setRoomId, tokenFetchUrl]
71
+ [
72
+ callbacksRef,
73
+ setStatus,
74
+ setConnect,
75
+ setToken,
76
+ setConversationId,
77
+ tokenFetchUrl,
78
+ ]
72
79
  );
73
80
 
74
81
  const endSession = useCallback(async () => {
@@ -6,7 +6,7 @@ import type { ConversationStatus, Callbacks } from "../types";
6
6
  export const useLiveKitRoom = (
7
7
  callbacksRef: { current: Callbacks },
8
8
  setStatus: (status: ConversationStatus) => void,
9
- roomId: string
9
+ conversationId: string
10
10
  ) => {
11
11
  const [roomConnected, setRoomConnected] = useState(false);
12
12
  const [localParticipant, setLocalParticipant] =
@@ -33,8 +33,8 @@ export const useLiveKitRoom = (
33
33
  const handleConnected = useCallback(() => {
34
34
  setRoomConnected(true);
35
35
  setStatus("connected");
36
- callbacksRef.current.onConnect?.({ conversationId: roomId });
37
- }, [roomId, callbacksRef, setStatus]);
36
+ callbacksRef.current.onConnect?.({ conversationId });
37
+ }, [conversationId, callbacksRef, setStatus]);
38
38
 
39
39
  const handleDisconnected = useCallback(() => {
40
40
  setRoomConnected(false);
package/src/index.ts CHANGED
@@ -1,4 +1,8 @@
1
- export { ElevenLabsProvider, useConversation } from "./ElevenLabsProvider";
1
+ export {
2
+ ElevenLabsProvider,
3
+ useConversation,
4
+ type Conversation,
5
+ } from "./ElevenLabsProvider";
2
6
 
3
7
  export type {
4
8
  ConversationStatus,
@@ -7,4 +11,5 @@ export type {
7
11
  Callbacks,
8
12
  ConversationOptions,
9
13
  ConversationConfig,
14
+ ConversationEvent,
10
15
  } from "./types";
package/src/types.ts CHANGED
@@ -47,16 +47,6 @@ export type Language =
47
47
  | "no"
48
48
  | "vi";
49
49
 
50
- /**
51
- * Client tool call event structure
52
- */
53
- export type ClientToolCallEvent = {
54
- tool_name: string;
55
- tool_call_id: string;
56
- parameters: unknown;
57
- expects_response: boolean;
58
- };
59
-
60
50
  /**
61
51
  * Client tools configuration
62
52
  */
@@ -92,7 +82,7 @@ export type Callbacks = {
92
82
  onDebug?: (props: unknown) => void;
93
83
  onDisconnect?: (details: string) => void;
94
84
  onError?: (message: string, context?: Record<string, unknown>) => void;
95
- onMessage?: (props: { message: string; source: Role }) => void;
85
+ onMessage?: (props: { message: ConversationEvent; source: Role }) => void;
96
86
  onModeChange?: (prop: { mode: Mode }) => void;
97
87
  onStatusChange?: (prop: { status: ConversationStatus }) => void;
98
88
  onCanSendFeedbackChange?: (prop: { canSendFeedback: boolean }) => void;
@@ -127,6 +117,114 @@ export type ConversationConfig = {
127
117
  userId?: string;
128
118
  };
129
119
 
120
+ export type UserTranscriptionEvent = {
121
+ type: "user_transcript";
122
+ user_transcription_event: { user_transcript: string };
123
+ };
124
+
125
+ export type AgentResponseEvent = {
126
+ type: "agent_response";
127
+ agent_response_event: { agent_response: string };
128
+ };
129
+
130
+ export type AgentResponseCorrectionEvent = {
131
+ type: "agent_response_correction";
132
+ agent_response_correction_event: {
133
+ original_agent_response: string;
134
+ corrected_agent_response: string;
135
+ };
136
+ };
137
+ export type AgentAudioEvent = {
138
+ type: "audio";
139
+ audio_event: {
140
+ audio_base_64: string;
141
+ event_id: number;
142
+ };
143
+ };
144
+
145
+ export type InterruptionEvent = {
146
+ type: "interruption";
147
+ interruption_event: {
148
+ event_id: number;
149
+ };
150
+ };
151
+
152
+ export type InternalTentativeAgentResponseEvent = {
153
+ type: "internal_tentative_agent_response";
154
+ tentative_agent_response_internal_event: {
155
+ tentative_agent_response: string;
156
+ };
157
+ };
158
+
159
+ export type ConfigEvent = {
160
+ type: "conversation_initiation_metadata";
161
+ conversation_initiation_metadata_event: {
162
+ conversation_id: string;
163
+ agent_output_audio_format: string;
164
+ user_input_audio_format?: string;
165
+ };
166
+ };
167
+
168
+ export type PingEvent = {
169
+ type: "ping";
170
+ ping_event: {
171
+ event_id: number;
172
+ ping_ms?: number;
173
+ };
174
+ };
175
+
176
+ export type ClientToolCallEvent = {
177
+ type: "client_tool_call";
178
+ client_tool_call: {
179
+ tool_name: string;
180
+ tool_call_id: string;
181
+ parameters: any;
182
+ expects_response: boolean;
183
+ };
184
+ };
185
+
186
+ export type PongEvent = {
187
+ type: "pong";
188
+ event_id: number;
189
+ };
190
+
191
+ export type UserAudioEvent = {
192
+ user_audio_chunk: string;
193
+ };
194
+
195
+ export type UserFeedbackEvent = {
196
+ type: "feedback";
197
+ score: "like" | "dislike";
198
+ event_id: number;
199
+ };
200
+
201
+ export type ClientToolResultEvent = {
202
+ type: "client_tool_result";
203
+ tool_call_id: string;
204
+ result: any;
205
+ is_error: boolean;
206
+ };
207
+
208
+ export type ContextualUpdateEvent = {
209
+ type: "contextual_update";
210
+ text: string;
211
+ };
212
+
213
+ export type UserMessageEvent = {
214
+ type: "user_message";
215
+ text: string;
216
+ };
217
+
218
+ export type UserActivityEvent = {
219
+ type: "user_activity";
220
+ };
221
+
222
+ export type MCPToolApprovalResultEvent = {
223
+ type: "mcp_tool_approval_result";
224
+ tool_call_id: string;
225
+ is_approved: boolean;
226
+ };
227
+
130
228
  export type InitiationClientDataEvent = {
131
229
  type: "conversation_initiation_client_data";
132
230
  conversation_config_override?: {
@@ -152,3 +250,14 @@ export type InitiationClientDataEvent = {
152
250
  dynamic_variables?: Record<string, string | number | boolean>;
153
251
  user_id?: string;
154
252
  };
253
+
254
+ export type ConversationEvent =
255
+ | UserTranscriptionEvent
256
+ | AgentResponseEvent
257
+ | AgentResponseCorrectionEvent
258
+ | AgentAudioEvent
259
+ | InterruptionEvent
260
+ | InternalTentativeAgentResponseEvent
261
+ | ConfigEvent
262
+ | PingEvent
263
+ | ClientToolCallEvent;
@@ -1,11 +1,13 @@
1
1
  import { PACKAGE_VERSION } from "../version";
2
2
 
3
- export const extractRoomIdFromToken = (token: string): string => {
3
+ export const extractConversationIdFromToken = (token: string): string => {
4
4
  try {
5
5
  const tokenPayload = JSON.parse(atob(token.split(".")[1]));
6
- return tokenPayload.video?.room || "";
6
+ const roomId = tokenPayload.video?.room || "";
7
+
8
+ return roomId.match(/(conv_[a-zA-Z0-9]+)/)?.[0] || "";
7
9
  } catch (error) {
8
- console.warn("Could not extract room ID from token");
10
+ console.warn("Could not extract conversation ID from token");
9
11
  return "";
10
12
  }
11
13
  };
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated during build
2
- export const PACKAGE_VERSION = "0.1.2";
2
+ export const PACKAGE_VERSION = "0.2.1";