@facepe/widget-mobile-app 1.4.0 → 1.5.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
@@ -246,7 +246,8 @@ const styles = StyleSheet.create({
246
246
 
247
247
  | Prop | Type | Default | Description |
248
248
  | :--- | :--- | :--- | :--- |
249
- | `avatarKey` | `string` | *(optional)* | Specific avatar key or ID assigned to your company. |
249
+ | `agentId` | `string` | first agent assigned to the user | The agent to talk to — its id from the FacePe dashboard (SDK page) or `GET /agents`. |
250
+ | `avatarKey` | `string` | *(deprecated)* | The same as `agentId`, for apps written before agents. |
250
251
  | `language` | `string` | `'en'` | Spoken language code (`'en'`, `'hi'`, `'es'`, `'ta'`, `'te'`, etc.). |
251
252
  | `style` | `ViewStyle` | `undefined` | Style applied to avatar container. |
252
253
  | `videoStyle` | `ViewStyle` | `undefined` | Style applied to native video view. |
@@ -312,7 +313,7 @@ when the component unmounts.
312
313
  ```json
313
314
  {
314
315
  "conversationId": "cm_usage_123",
315
- "avatar": { "id": "cm_avatar_456", "name": "Dharun" },
316
+ "agent": { "id": "cm_agent_456", "name": "Front Desk" },
316
317
  "language": "en",
317
318
  "platform": "android",
318
319
  "sdkVersion": "1.3.0",
@@ -330,7 +331,7 @@ when the component unmounts.
330
331
  | Field | Meaning |
331
332
  |---|---|
332
333
  | `conversationId` | The conversation's FacePe id (its usage record) |
333
- | `avatar` | `{ id, name }` of the avatar |
334
+ | `agent` | `{ id, name }` of the agent that held the conversation (`avatar` is the same, kept for older apps) |
334
335
  | `language` | The language requested for the conversation |
335
336
  | `platform` | `web`, `android` or `ios` |
336
337
  | `sdkVersion` | The SDK version that recorded it |
@@ -338,7 +339,7 @@ when the component unmounts.
338
339
  | `durationSec` | Length in seconds |
339
340
  | `endReason` | `ended` (the user or your code ended it), `disconnected` (the stream dropped), `unmounted` (the component went away) |
340
341
  | `transcript` | Every line in order: `{ role: "user" \| "assistant", text, at }` |
341
- | `form` | For a form avatar: `{ title, complete, fields: [{ label, question, required, value }] }`; `null` otherwise |
342
+ | `form` | For a form avatar: `{ title, complete, fields: [{ label, question, required, value }], documents, uploadWhere }` — `documents` are what the avatar asked the customer to upload at the end; `null` for other avatars |
342
343
 
343
344
  For an avatar that **fills a form**, the record also carries the form as the
344
345
  conversation filled it: each question with the customer's answer (`value` is
@@ -354,7 +355,9 @@ For other avatars `form` is `null`.
354
355
  { "label": "Name", "question": "Could you please tell me your full name?", "required": true, "value": "Tony" },
355
356
  { "label": "Phone", "question": "What is the best phone number to reach you?", "required": true, "value": "9659390715" },
356
357
  { "label": "Email", "question": "May I have your email address?", "required": false, "value": "tony@gmail.com" }
357
- ]
358
+ ],
359
+ "documents": ["ID proof (Aadhaar / PAN)", "Address proof"],
360
+ "uploadWhere": "on our website"
358
361
  }
359
362
  ```
360
363
 
@@ -66,8 +66,18 @@ const joinNumberParts = (text) => text.replace(/\d+(?:[ \t]*[-\u2010\u2011\u2013
66
66
  const digits = m.replace(/\D/g, '');
67
67
  return digits.length >= 7 ? digits : m;
68
68
  });
69
- export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', style, videoStyle, objectFit = 'cover', mirror = false, autoStart = true, enableMic = true, onTranscript, onSpeakStart, onSpeakEnd, onUserSpeakStart, onUserSpeakEnd, onOrderUpdate, onCheckout, onStatusChange, onError, onConversationEnd, posterUrl, }, ref) => {
69
+ /**
70
+ * Calls the gateway's agent route; a FacePe server from before agents has
71
+ * only the avatar route (404), so that one is tried next.
72
+ */
73
+ async function gatewayFetch(base, agentPath, avatarPath, init) {
74
+ const res = await fetch(`${base}${agentPath}`, init);
75
+ return res.status === 404 ? fetch(`${base}${avatarPath}`, init) : res;
76
+ }
77
+ export const FacePeMobileAvatar = forwardRef(({ agentId, avatarKey, language = 'en', style, videoStyle, objectFit = 'cover', mirror = false, autoStart = true, enableMic = true, onTranscript, onSpeakStart, onSpeakEnd, onUserSpeakStart, onUserSpeakEnd, onOrderUpdate, onCheckout, onStatusChange, onError, onConversationEnd, posterUrl, }, ref) => {
70
78
  const { token, loading: tokenLoading, error: tokenError, apiBaseUrl, refreshToken } = useFacePeMobileContext();
79
+ // The agent to talk to (`avatarKey` is its name from before agents).
80
+ const chosenAgent = agentId ?? avatarKey;
71
81
  // The avatar's portrait, shown until its video arrives. Looked up from the
72
82
  // avatars this token may use, unless the app gave one (or null for none).
73
83
  const [autoPoster, setAutoPoster] = useState(null);
@@ -77,13 +87,14 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
77
87
  let cancelled = false;
78
88
  void (async () => {
79
89
  try {
80
- const res = await fetch(`${apiBaseUrl.replace(/\/+$/, '')}/avatars`, {
90
+ const res = await gatewayFetch(apiBaseUrl.replace(/\/+$/, ''), '/agents', '/avatars', {
81
91
  headers: { Authorization: `Bearer ${token}` },
82
92
  });
83
93
  if (!res.ok)
84
94
  return;
85
- const avatars = (await res.json())?.data?.avatars ?? [];
86
- const avatar = avatarKey ? avatars.find((a) => a.id === avatarKey) : avatars[0];
95
+ const data = (await res.json())?.data;
96
+ const agents = data?.agents ?? data?.avatars ?? [];
97
+ const avatar = chosenAgent ? agents.find((a) => a.id === chosenAgent) : agents[0];
87
98
  if (!cancelled)
88
99
  setAutoPoster(avatar?.previewUrl ?? null);
89
100
  }
@@ -94,7 +105,7 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
94
105
  return () => {
95
106
  cancelled = true;
96
107
  };
97
- }, [token, apiBaseUrl, avatarKey, posterUrl]);
108
+ }, [token, apiBaseUrl, chosenAgent, posterUrl]);
98
109
  const poster = posterUrl !== undefined ? posterUrl : autoPoster;
99
110
  const [status, setStatus] = useState('idle');
100
111
  const [videoTrack, setVideoTrack] = useState(null);
@@ -143,7 +154,8 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
143
154
  const token = tokenRef.current;
144
155
  if (conv.conversationId && transcript.length > 0 && token) {
145
156
  try {
146
- const res = await fetch(`${apiBaseUrl.replace(/\/+$/, '')}/avatar-sessions/${encodeURIComponent(conv.conversationId)}/form`, {
157
+ const id = encodeURIComponent(conv.conversationId);
158
+ const res = await gatewayFetch(apiBaseUrl.replace(/\/+$/, ''), `/agent-sessions/${id}/form`, `/avatar-sessions/${id}/form`, {
147
159
  method: 'POST',
148
160
  headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
149
161
  body: JSON.stringify({ transcript: transcript.map(({ role, text }) => ({ role, text })) }),
@@ -158,7 +170,8 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
158
170
  try {
159
171
  onConversationEndRef.current?.({
160
172
  conversationId: conv.conversationId,
161
- avatar: conv.avatar,
173
+ agent: conv.agent,
174
+ avatar: conv.agent,
162
175
  language: conv.language,
163
176
  platform: Platform.OS === 'ios' ? 'ios' : Platform.OS === 'android' ? 'android' : 'web',
164
177
  sdkVersion: SDK_VERSION,
@@ -219,7 +232,7 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
219
232
  return;
220
233
  try {
221
234
  const cleanBase = apiBaseUrl.replace(/\/+$/, '');
222
- await fetch(`${cleanBase}/avatar-sessions/${uId}/end`, {
235
+ await gatewayFetch(cleanBase, `/agent-sessions/${uId}/end`, `/avatar-sessions/${uId}/end`, {
223
236
  method: 'POST',
224
237
  headers: {
225
238
  'Content-Type': 'application/json',
@@ -256,29 +269,30 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
256
269
  throw new Error('Authentication token not available. Please verify your token provider.');
257
270
  }
258
271
  const cleanBase = apiBaseUrl.replace(/\/+$/, '');
259
- // Resolve target avatar ID
260
- let targetAvatarId = avatarKey;
261
- if (!targetAvatarId) {
262
- // No avatar given: use the first one assigned to this token's user.
263
- const listRes = await fetch(`${cleanBase}/avatars`, {
272
+ // The agent to talk to
273
+ let targetAgentId = chosenAgent;
274
+ if (!targetAgentId) {
275
+ // No agent given: use the first one assigned to this token's user.
276
+ const listRes = await gatewayFetch(cleanBase, '/agents', '/avatars', {
264
277
  method: 'GET',
265
278
  headers: {
266
279
  Authorization: `Bearer ${currentToken}`,
267
280
  },
268
281
  });
269
282
  if (listRes.ok) {
270
- const listData = await listRes.json();
271
- const avatars = listData?.data?.avatars || [];
272
- if (avatars.length > 0) {
273
- targetAvatarId = avatars[0].id;
283
+ const listData = (await listRes.json())?.data;
284
+ const agents = listData?.agents || listData?.avatars || [];
285
+ if (agents.length > 0) {
286
+ targetAgentId = agents[0].id;
274
287
  }
275
288
  }
276
289
  }
277
- if (!targetAvatarId) {
278
- throw new Error('No Avatar configured or assigned to this token.');
290
+ if (!targetAgentId) {
291
+ throw new Error('No agent is assigned to these keys. Create one on the FacePe dashboard (Agents).');
279
292
  }
280
293
  // Request live streaming session from FacePe SDK backend
281
- const sessionResp = await fetch(`${cleanBase}/avatars/${targetAvatarId}/sessions`, {
294
+ const agentPath = encodeURIComponent(targetAgentId);
295
+ const sessionResp = await gatewayFetch(cleanBase, `/agents/${agentPath}/sessions`, `/avatars/${agentPath}/sessions`, {
282
296
  method: 'POST',
283
297
  headers: {
284
298
  'Content-Type': 'application/json',
@@ -288,7 +302,7 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
288
302
  });
289
303
  if (!sessionResp.ok) {
290
304
  const errBody = await sessionResp.json().catch(() => ({}));
291
- const errMsg = errBody?.error?.message || errBody?.message || 'Failed to initialize avatar session';
305
+ const errMsg = errBody?.error?.message || errBody?.message || 'Failed to start the conversation';
292
306
  throw new Error(errMsg);
293
307
  }
294
308
  const sessionPayload = await sessionResp.json();
@@ -296,7 +310,10 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
296
310
  usageIdRef.current = sessionInfo?.usageId || null;
297
311
  conversationRef.current = {
298
312
  conversationId: usageIdRef.current,
299
- avatar: { id: String(sessionInfo?.avatar?.id ?? targetAvatarId), name: String(sessionInfo?.avatar?.name ?? '') },
313
+ agent: (() => {
314
+ const who = sessionInfo?.agent ?? sessionInfo?.avatar;
315
+ return { id: String(who?.id ?? targetAgentId), name: String(who?.name ?? '') };
316
+ })(),
300
317
  language: language ?? null,
301
318
  startedAt: new Date(),
302
319
  lines: [],
@@ -554,7 +571,7 @@ export const FacePeMobileAvatar = forwardRef(({ avatarKey, language = 'en', styl
554
571
  }
555
572
  }, [
556
573
  hasLiveKit,
557
- avatarKey,
574
+ chosenAgent,
558
575
  language,
559
576
  enableMic,
560
577
  apiBaseUrl,
package/dist/types.d.ts CHANGED
@@ -35,10 +35,20 @@ export interface FacePeFilledForm {
35
35
  /** Every required question has an answer. */
36
36
  complete: boolean;
37
37
  fields: FacePeFormAnswer[];
38
+ /** Documents the customer was asked to upload once the form was done (may be empty). */
39
+ documents: string[];
40
+ /** Where to upload them, as the company wrote it (empty when not set). */
41
+ uploadWhere: string;
38
42
  }
39
43
  export interface FacePeConversation {
40
44
  /** The conversation's id (its FacePe usage record), or null if none was opened. */
41
45
  conversationId: string | null;
46
+ /** The agent that held the conversation. */
47
+ agent: {
48
+ id: string;
49
+ name: string;
50
+ };
51
+ /** @deprecated The same as `agent` (kept for apps from before agents). */
42
52
  avatar: {
43
53
  id: string;
44
54
  name: string;
@@ -84,7 +94,12 @@ export interface TokenProviderParams {
84
94
  }
85
95
  export type TokenProvider = (params: TokenProviderParams) => Promise<string>;
86
96
  export interface FacePeMobileAvatarProps {
87
- /** Specific avatar identifier or key override */
97
+ /**
98
+ * The agent to talk to (its id, from the FacePe dashboard's SDK page or
99
+ * GET /agents). Without one, the first agent assigned to the keys' user.
100
+ */
101
+ agentId?: string;
102
+ /** @deprecated Use `agentId` (the same id; kept for apps from before agents). */
88
103
  avatarKey?: string;
89
104
  /** Language to converse in ('en', 'es', 'hi', etc.) */
90
105
  language?: string;
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** This package's version, reported in conversation records. Keep in step with package.json. */
2
- export declare const SDK_VERSION = "1.4.0";
2
+ export declare const SDK_VERSION = "1.5.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** This package's version, reported in conversation records. Keep in step with package.json. */
2
- export const SDK_VERSION = '1.4.0';
2
+ export const SDK_VERSION = '1.5.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@facepe/widget-mobile-app",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "FacePe AI 3D Video Avatar Native Live Streaming SDK for React Native (iOS & Android)",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",