@elevenlabs/react-native 0.1.1 → 0.2.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/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
  */
@@ -31,6 +22,7 @@ export type ClientToolsConfig = {
31
22
  */
32
23
  export type ConversationOptions = {
33
24
  serverUrl?: string;
25
+ tokenFetchUrl?: string;
34
26
  clientTools?: Record<string, (parameters: unknown) => Promise<string | number | undefined> | string | number | undefined>;
35
27
  } & Partial<Callbacks>;
36
28
  /**
@@ -44,7 +36,7 @@ export type Callbacks = {
44
36
  onDisconnect?: (details: string) => void;
45
37
  onError?: (message: string, context?: Record<string, unknown>) => void;
46
38
  onMessage?: (props: {
47
- message: string;
39
+ message: ConversationEvent;
48
40
  source: Role;
49
41
  }) => void;
50
42
  onModeChange?: (prop: {
@@ -61,6 +53,7 @@ export type Callbacks = {
61
53
  export type ConversationConfig = {
62
54
  agentId?: string;
63
55
  conversationToken?: string;
56
+ tokenFetchUrl?: string;
64
57
  overrides?: {
65
58
  agent?: {
66
59
  prompt?: {
@@ -84,6 +77,102 @@ export type ConversationConfig = {
84
77
  dynamicVariables?: Record<string, string | number | boolean>;
85
78
  userId?: string;
86
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
+ };
87
176
  export type InitiationClientDataEvent = {
88
177
  type: "conversation_initiation_client_data";
89
178
  conversation_config_override?: {
@@ -109,3 +198,4 @@ export type InitiationClientDataEvent = {
109
198
  dynamic_variables?: Record<string, string | number | boolean>;
110
199
  user_id?: string;
111
200
  };
201
+ export type ConversationEvent = UserTranscriptionEvent | AgentResponseEvent | AgentResponseCorrectionEvent | AgentAudioEvent | InterruptionEvent | InternalTentativeAgentResponseEvent | ConfigEvent | PingEvent | ClientToolCallEvent;
@@ -1,2 +1,2 @@
1
1
  export declare const extractRoomIdFromToken: (token: string) => string;
2
- export declare const getConversationToken: (agentId: string) => Promise<string>;
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.1";
1
+ export declare const PACKAGE_VERSION = "0.2.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevenlabs/react-native",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "ElevenLabs React Native SDK for Conversational AI",
5
5
  "main": "./dist/lib.js",
6
6
  "module": "./dist/lib.module.js",
@@ -13,9 +13,10 @@ import { LiveKitRoomWrapper } from './components/LiveKitRoomWrapper';
13
13
 
14
14
  interface ConversationOptions extends Callbacks, Partial<ClientToolsConfig> {
15
15
  serverUrl?: string;
16
+ tokenFetchUrl?: string;
16
17
  }
17
18
 
18
- interface Conversation {
19
+ export interface Conversation {
19
20
  startSession: (config: ConversationConfig) => Promise<void>;
20
21
  endSession: () => Promise<void>;
21
22
  status: ConversationStatus;
@@ -33,9 +34,11 @@ interface ElevenLabsContextType {
33
34
  conversation: Conversation;
34
35
  callbacksRef: { current: Callbacks };
35
36
  serverUrl: string;
37
+ tokenFetchUrl?: string;
36
38
  clientTools: ClientToolsConfig['clientTools'];
37
39
  setCallbacks: (callbacks: Callbacks) => void;
38
40
  setServerUrl: (url: string) => void;
41
+ setTokenFetchUrl: (url: string) => void;
39
42
  setClientTools: (tools: ClientToolsConfig['clientTools']) => void;
40
43
  }
41
44
 
@@ -47,7 +50,7 @@ export const useConversation = (options: ConversationOptions = {}): Conversation
47
50
  throw new Error('useConversation must be used within ElevenLabsProvider');
48
51
  }
49
52
 
50
- const { serverUrl, clientTools, ...callbacks } = options;
53
+ const { serverUrl, tokenFetchUrl, clientTools, ...callbacks } = options;
51
54
 
52
55
  React.useEffect(() => {
53
56
  if (serverUrl) {
@@ -55,6 +58,12 @@ export const useConversation = (options: ConversationOptions = {}): Conversation
55
58
  }
56
59
  }, [context, serverUrl]);
57
60
 
61
+ React.useEffect(() => {
62
+ if (tokenFetchUrl) {
63
+ context.setTokenFetchUrl(tokenFetchUrl);
64
+ }
65
+ }, [context, tokenFetchUrl]);
66
+
58
67
  if (clientTools) {
59
68
  context.setClientTools(clientTools);
60
69
  }
@@ -77,6 +86,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
77
86
  const [connect, setConnect] = useState(false);
78
87
  const [status, setStatus] = useState<ConversationStatus>('disconnected');
79
88
  const [serverUrl, setServerUrl] = useState(DEFAULT_SERVER_URL);
89
+ const [tokenFetchUrl, setTokenFetchUrl] = useState<string | undefined>(undefined);
80
90
  const [roomId, setRoomId] = useState<string>('');
81
91
  const [isSpeaking, setIsSpeaking] = useState(false);
82
92
  const [canSendFeedback, setCanSendFeedback] = useState(false);
@@ -109,7 +119,7 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
109
119
  overrides,
110
120
  customLlmExtraBody,
111
121
  dynamicVariables,
112
- } = useConversationSession(callbacksRef, setStatus, setConnect, setToken, setRoomId);
122
+ } = useConversationSession(callbacksRef, setStatus, setConnect, setToken, setRoomId, tokenFetchUrl);
113
123
 
114
124
  const {
115
125
  roomConnected,
@@ -230,9 +240,11 @@ export const ElevenLabsProvider: React.FC<ElevenLabsProviderProps> = ({ children
230
240
  conversation,
231
241
  callbacksRef,
232
242
  serverUrl,
243
+ tokenFetchUrl,
233
244
  clientTools: clientToolsRef.current,
234
245
  setCallbacks,
235
246
  setServerUrl,
247
+ setTokenFetchUrl: setTokenFetchUrl,
236
248
  setClientTools,
237
249
  };
238
250
 
@@ -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);
@@ -14,7 +14,8 @@ 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
+ setRoomId: (roomId: string) => void,
18
+ tokenFetchUrl?: string
18
19
  ) => {
19
20
  const [overrides, setOverrides] = useState<ConversationConfig["overrides"]>(
20
21
  {}
@@ -44,7 +45,12 @@ export const useConversationSession = (
44
45
  "Getting conversation token for agentId:",
45
46
  config.agentId
46
47
  );
47
- conversationToken = await getConversationToken(config.agentId);
48
+ // Use tokenFetchUrl from config first, then from hook parameter, then default
49
+ const urlToUse = config.tokenFetchUrl || tokenFetchUrl;
50
+ conversationToken = await getConversationToken(
51
+ config.agentId,
52
+ urlToUse
53
+ );
48
54
  } else {
49
55
  throw new Error("Either conversationToken or agentId is required");
50
56
  }
@@ -62,7 +68,7 @@ export const useConversationSession = (
62
68
  throw error;
63
69
  }
64
70
  },
65
- [callbacksRef, setStatus, setConnect, setToken, setRoomId]
71
+ [callbacksRef, setStatus, setConnect, setToken, setRoomId, tokenFetchUrl]
66
72
  );
67
73
 
68
74
  const endSession = useCallback(async () => {
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,
@@ -6,4 +10,6 @@ export type {
6
10
  Role,
7
11
  Callbacks,
8
12
  ConversationOptions,
13
+ ConversationConfig,
14
+ ConversationEvent,
9
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
  */
@@ -74,6 +64,7 @@ export type ClientToolsConfig = {
74
64
  */
75
65
  export type ConversationOptions = {
76
66
  serverUrl?: string;
67
+ tokenFetchUrl?: string;
77
68
  clientTools?: Record<
78
69
  string,
79
70
  (
@@ -91,7 +82,7 @@ export type Callbacks = {
91
82
  onDebug?: (props: unknown) => void;
92
83
  onDisconnect?: (details: string) => void;
93
84
  onError?: (message: string, context?: Record<string, unknown>) => void;
94
- onMessage?: (props: { message: string; source: Role }) => void;
85
+ onMessage?: (props: { message: ConversationEvent; source: Role }) => void;
95
86
  onModeChange?: (prop: { mode: Mode }) => void;
96
87
  onStatusChange?: (prop: { status: ConversationStatus }) => void;
97
88
  onCanSendFeedbackChange?: (prop: { canSendFeedback: boolean }) => void;
@@ -101,6 +92,7 @@ export type Callbacks = {
101
92
  export type ConversationConfig = {
102
93
  agentId?: string;
103
94
  conversationToken?: string;
95
+ tokenFetchUrl?: string;
104
96
  overrides?: {
105
97
  agent?: {
106
98
  prompt?: {
@@ -125,6 +117,114 @@ export type ConversationConfig = {
125
117
  userId?: string;
126
118
  };
127
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
+
128
228
  export type InitiationClientDataEvent = {
129
229
  type: "conversation_initiation_client_data";
130
230
  conversation_config_override?: {
@@ -150,3 +250,14 @@ export type InitiationClientDataEvent = {
150
250
  dynamic_variables?: Record<string, string | number | boolean>;
151
251
  user_id?: string;
152
252
  };
253
+
254
+ export type ConversationEvent =
255
+ | UserTranscriptionEvent
256
+ | AgentResponseEvent
257
+ | AgentResponseCorrectionEvent
258
+ | AgentAudioEvent
259
+ | InterruptionEvent
260
+ | InternalTentativeAgentResponseEvent
261
+ | ConfigEvent
262
+ | PingEvent
263
+ | ClientToolCallEvent;
@@ -11,10 +11,13 @@ export const extractRoomIdFromToken = (token: string): string => {
11
11
  };
12
12
 
13
13
  export const getConversationToken = async (
14
- agentId: string
14
+ agentId: string,
15
+ tokenFetchUrl?: string
15
16
  ): Promise<string> => {
17
+ const baseUrl =
18
+ tokenFetchUrl || "https://api.elevenlabs.io/v1/convai/conversation/token";
16
19
  const response = await fetch(
17
- `https://api.elevenlabs.io/v1/convai/conversation/token?agent_id=${agentId}&source=react_native_sdk&version=${PACKAGE_VERSION}`
20
+ `${baseUrl}?agent_id=${agentId}&source=react_native_sdk&version=${PACKAGE_VERSION}`
18
21
  );
19
22
 
20
23
  const data = await response.json();
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.1";
2
+ export const PACKAGE_VERSION = "0.2.0";