@oshara/voice-sdk 0.1.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.
Files changed (61) hide show
  1. package/README.md +198 -0
  2. package/dist/appearance-CNWT8x1G.cjs +2 -0
  3. package/dist/appearance-CNWT8x1G.cjs.map +1 -0
  4. package/dist/appearance-i6QBkpCk.js +650 -0
  5. package/dist/appearance-i6QBkpCk.js.map +1 -0
  6. package/dist/consent-CK9VXNPa.js +54 -0
  7. package/dist/consent-CK9VXNPa.js.map +1 -0
  8. package/dist/consent-D7QNSkQD.cjs +2 -0
  9. package/dist/consent-D7QNSkQD.cjs.map +1 -0
  10. package/dist/core/analytics.d.ts +30 -0
  11. package/dist/core/appearance.d.ts +113 -0
  12. package/dist/core/audioSettings.d.ts +69 -0
  13. package/dist/core/consent.d.ts +17 -0
  14. package/dist/core/createVoiceAgent.d.ts +79 -0
  15. package/dist/core/events.d.ts +103 -0
  16. package/dist/core/formController.d.ts +28 -0
  17. package/dist/core/forms.d.ts +235 -0
  18. package/dist/core/index.d.ts +29 -0
  19. package/dist/core/prevContext.d.ts +26 -0
  20. package/dist/core/transport.d.ts +30 -0
  21. package/dist/core/types.d.ts +49 -0
  22. package/dist/core/voice.d.ts +79 -0
  23. package/dist/createVoiceAgent-BM3HODS6.js +1058 -0
  24. package/dist/createVoiceAgent-BM3HODS6.js.map +1 -0
  25. package/dist/createVoiceAgent-CJWxWzz6.cjs +4 -0
  26. package/dist/createVoiceAgent-CJWxWzz6.cjs.map +1 -0
  27. package/dist/index.cjs +2 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.js +44 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/react/index.d.ts +60 -0
  32. package/dist/react.cjs +2 -0
  33. package/dist/react.cjs.map +1 -0
  34. package/dist/react.js +115 -0
  35. package/dist/react.js.map +1 -0
  36. package/dist/styles.css +1838 -0
  37. package/dist/ui/index.d.ts +21 -0
  38. package/dist/ui/ui.d.ts +165 -0
  39. package/dist/ui.cjs +284 -0
  40. package/dist/ui.cjs.map +1 -0
  41. package/dist/ui.js +1153 -0
  42. package/dist/ui.js.map +1 -0
  43. package/package.json +67 -0
  44. package/src/core/analytics.ts +111 -0
  45. package/src/core/appearance.ts +464 -0
  46. package/src/core/audioSettings.ts +180 -0
  47. package/src/core/consent.ts +78 -0
  48. package/src/core/createVoiceAgent.ts +280 -0
  49. package/src/core/events.ts +120 -0
  50. package/src/core/formController.ts +317 -0
  51. package/src/core/forms.ts +861 -0
  52. package/src/core/index.ts +121 -0
  53. package/src/core/prevContext.ts +153 -0
  54. package/src/core/transport.ts +118 -0
  55. package/src/core/types.ts +66 -0
  56. package/src/core/voice.ts +1179 -0
  57. package/src/react/index.ts +238 -0
  58. package/src/ui/index.ts +507 -0
  59. package/src/ui/styles.css +1838 -0
  60. package/src/ui/ui.ts +1672 -0
  61. package/src/vite-env.d.ts +10 -0
@@ -0,0 +1,650 @@
1
+ function H(t) {
2
+ var o;
3
+ const n = (e, i) => {
4
+ var s;
5
+ const r = {
6
+ name: e.name,
7
+ label: e.label,
8
+ type: e.type,
9
+ required: !!e.required,
10
+ step: i
11
+ };
12
+ return (s = e.options) != null && s.length && (r.options = e.options.map(
13
+ (f) => typeof f == "string" ? { value: f, label: f } : { value: f.value, label: f.label ?? f.value }
14
+ )), e.pattern && (r.pattern = e.pattern), e.min !== void 0 && (r.min = e.min), e.max !== void 0 && (r.max = e.max), r;
15
+ };
16
+ if ((o = t.steps) != null && o.length) {
17
+ const e = [];
18
+ return t.steps.forEach((i, r) => {
19
+ for (const s of i.fields)
20
+ s.type !== "display" && s.name && e.push(n(s, r));
21
+ }), e;
22
+ }
23
+ return F(t).map((e) => n(e, 0));
24
+ }
25
+ function V(t, n, o) {
26
+ var _;
27
+ if (!t) return !1;
28
+ const e = t.trim().toLowerCase();
29
+ if (!e.startsWith("form.") || !e.endsWith(".action"))
30
+ return !1;
31
+ const i = e.slice(5, -7);
32
+ if (!i || !n || typeof n != "object") return !1;
33
+ const r = n, s = o.current();
34
+ if (!s || s.trim().toLowerCase() !== i) return !1;
35
+ const f = l(r.form_id);
36
+ if (f && f.trim().toLowerCase() !== i)
37
+ return !1;
38
+ const d = (l(r.type) ?? l(r.event) ?? "").trim().toLowerCase();
39
+ if (d === "form_step") {
40
+ const c = (_ = l(r.direction)) == null ? void 0 : _.trim().toLowerCase();
41
+ if (c === "next" || c === "back")
42
+ return o.step(c), !0;
43
+ const m = r.step_index;
44
+ return typeof m == "number" && Number.isFinite(m) && o.step(m), !0;
45
+ }
46
+ return d === "form_submit" ? (o.submit(), !0) : d === "form_close" ? (o.close(), !0) : !1;
47
+ }
48
+ function F(t) {
49
+ var o;
50
+ return ((o = t.steps) != null && o.length ? t.steps.flatMap((e) => e.fields) : t.fields).filter((e) => e.type !== "display" && !!e.name);
51
+ }
52
+ function G(t, n) {
53
+ var o;
54
+ if ((o = t.steps) != null && o.length) {
55
+ const e = t.steps[Math.max(0, Math.min(n, t.steps.length - 1))];
56
+ return (e == null ? void 0 : e.fields) ?? [];
57
+ }
58
+ return t.fields;
59
+ }
60
+ function J(t) {
61
+ var n;
62
+ return ((n = t.steps) == null ? void 0 : n.length) || 1;
63
+ }
64
+ const j = /^[^\s@]+@[^\s@]+\.[^\s@]+$/, C = /^[+()\-.\s\d]+$/;
65
+ function Q(t, n) {
66
+ const o = [];
67
+ for (const e of t) {
68
+ if (e.type === "display" || !e.name) continue;
69
+ const r = (n[e.name] ?? "").trim();
70
+ if (!r) {
71
+ e.required && o.push({ name: e.name, label: e.label, message: `${e.label} is required.` });
72
+ continue;
73
+ }
74
+ if (e.type === "email" && !j.test(r)) {
75
+ o.push({ name: e.name, label: e.label, message: "Enter a valid email address." });
76
+ continue;
77
+ }
78
+ if (e.type === "tel") {
79
+ const s = r.replace(/\D/g, "");
80
+ if (!C.test(r) || s.length < 7) {
81
+ o.push({ name: e.name, label: e.label, message: "Enter a valid phone number." });
82
+ continue;
83
+ }
84
+ }
85
+ if (e.type === "number") {
86
+ const s = Number(r);
87
+ if (!Number.isFinite(s)) {
88
+ o.push({ name: e.name, label: e.label, message: "Enter a valid number." });
89
+ continue;
90
+ }
91
+ if (e.min !== void 0 && s < e.min) {
92
+ o.push({ name: e.name, label: e.label, message: `Must be at least ${e.min}.` });
93
+ continue;
94
+ }
95
+ if (e.max !== void 0 && s > e.max) {
96
+ o.push({ name: e.name, label: e.label, message: `Must be at most ${e.max}.` });
97
+ continue;
98
+ }
99
+ }
100
+ if (e.pattern)
101
+ try {
102
+ if (!new RegExp(e.pattern).test(r)) {
103
+ o.push({ name: e.name, label: e.label, message: `Please enter a valid ${e.label.toLowerCase()}.` });
104
+ continue;
105
+ }
106
+ } catch {
107
+ }
108
+ }
109
+ return o;
110
+ }
111
+ const T = [
112
+ "Enterprise Voice Platform (OVIP)",
113
+ "Fine-Tuning Automation (OFTA)",
114
+ "Consumer / Kids Products",
115
+ "Investor Relations",
116
+ "Partnership / Integration"
117
+ ], $ = [
118
+ {
119
+ id: "book-demo",
120
+ title: "Book a demo",
121
+ subtitle: "The voice agent filled this from the call. Review and edit before sending.",
122
+ submit_url: "/api/book-demo/",
123
+ submit_label: "Confirm & send",
124
+ success_message: "Thanks! Your demo request has been sent. We'll get back to you soon.",
125
+ topics: ["book-demo.form", "book-demo.review", "form.book-demo"],
126
+ event_types: ["book_demo_form", "book-demo-form"],
127
+ // Match the webapp's help-desk-call echo so the agent sees the same
128
+ // event type from either surface. Default would have been
129
+ // "book-demo_submitted" (hyphen).
130
+ confirmation_type: "book_demo_submitted",
131
+ fields: [
132
+ { name: "name", label: "Full name", type: "text", required: !0, placeholder: "Your full name" },
133
+ { name: "organization", label: "Organization", type: "text", required: !0, placeholder: "Your company or organization" },
134
+ { name: "email", label: "Email", type: "email", required: !0, placeholder: "you@organization.com" },
135
+ {
136
+ name: "interested_in",
137
+ label: "I'm interested in...",
138
+ type: "select",
139
+ required: !0,
140
+ options: T,
141
+ default_value: T[0]
142
+ },
143
+ {
144
+ name: "description",
145
+ label: "Why do you want to book a demo?",
146
+ type: "textarea",
147
+ required: !0,
148
+ rows: 4,
149
+ placeholder: "Describe your use case, goals, or questions..."
150
+ }
151
+ ]
152
+ },
153
+ {
154
+ id: "reservation",
155
+ title: "Make a reservation",
156
+ subtitle: "The voice agent filled this from the call. Review and edit before sending.",
157
+ submit_url: "/api/reservations/",
158
+ submit_label: "Confirm reservation",
159
+ success_message: "Reservation confirmed. We'll send a confirmation email shortly.",
160
+ topics: ["reservation.form", "form.reservation"],
161
+ event_types: ["reservation_form", "reservation-form"],
162
+ fields: [
163
+ { name: "name", label: "Name", type: "text", required: !0, placeholder: "Your name" },
164
+ { name: "email", label: "Email", type: "email", required: !0, placeholder: "you@example.com" },
165
+ { name: "phone", label: "Phone", type: "tel", placeholder: "+977 98XXXXXXXX" },
166
+ { name: "party_size", label: "Party size", type: "text", required: !0, placeholder: "e.g. 4" },
167
+ { name: "date", label: "Date", type: "text", required: !0, placeholder: "YYYY-MM-DD" },
168
+ { name: "time", label: "Time", type: "text", required: !0, placeholder: "HH:MM" },
169
+ { name: "notes", label: "Notes", type: "textarea", rows: 3, placeholder: "Allergies, occasion, seating preference…" }
170
+ ]
171
+ }
172
+ ];
173
+ function Z(t, n, o) {
174
+ var f, d, _;
175
+ if (!n || typeof n != "object") return null;
176
+ const e = (c) => c.trim().toLowerCase();
177
+ if (t) {
178
+ const c = e(t);
179
+ for (const m of o) {
180
+ if ((f = m.topics) != null && f.some((A) => e(A) === c)) return m;
181
+ const b = e(m.id);
182
+ if (c === `${b}.form` || c === `${b}.review` || c === `form.${b}` || c === b)
183
+ return m;
184
+ }
185
+ }
186
+ const i = n, r = l(i.form_id) ?? l(i.formId);
187
+ if (r) {
188
+ const c = e(r), m = o.find((b) => e(b.id) === c);
189
+ if (m) return m;
190
+ }
191
+ const s = (d = [i.type, i.event, i.kind, i.intent].map(l).find((c) => !!c)) == null ? void 0 : d.toLowerCase();
192
+ if (s)
193
+ for (const c of o) {
194
+ if ((_ = c.event_types) != null && _.some((b) => e(b) === s)) return c;
195
+ const m = e(c.id);
196
+ if (s === m || s === `${m}_form` || s === `${m}-form` || s === `${m.replace(/-/g, "_")}_form`)
197
+ return c;
198
+ }
199
+ return null;
200
+ }
201
+ function K(t, n) {
202
+ if (!t || typeof t != "object") return null;
203
+ const o = t, e = ["draft", "form", "payload", "data", "fields", "values"].map((r) => o[r]).find((r) => r && typeof r == "object"), i = {};
204
+ for (const r of F(n)) {
205
+ if (!r.name) continue;
206
+ const s = l(e == null ? void 0 : e[r.name]) ?? l(o[r.name]);
207
+ s && (i[r.name] = s);
208
+ }
209
+ return Object.keys(i).length > 0 ? i : null;
210
+ }
211
+ function ee(t) {
212
+ const n = {};
213
+ for (const o of F(t))
214
+ o.name && (n[o.name] = o.default_value ?? "");
215
+ return n;
216
+ }
217
+ function te(t, n) {
218
+ if (!n) return t;
219
+ const o = { ...t };
220
+ for (const [e, i] of Object.entries(n))
221
+ typeof i == "string" && i.trim() && (o[e] = i.trim());
222
+ return o;
223
+ }
224
+ function ne(t, n) {
225
+ const o = F(t).map((e) => `${e.label.toLowerCase()}: ${(n[e.name] ?? "").trim()}`).filter((e) => !e.endsWith(": "));
226
+ return `I have confirmed and submitted the "${t.title}" form: ${o.join("; ")}.`;
227
+ }
228
+ function P(t) {
229
+ var n;
230
+ return (n = t.steps) != null && n.length ? t.steps.flatMap((o) => o.fields) : t.fields;
231
+ }
232
+ async function oe({
233
+ definition: t,
234
+ values: n,
235
+ apiUrl: o,
236
+ slug: e,
237
+ sessionId: i,
238
+ apiKey: r,
239
+ fetch: s
240
+ }) {
241
+ const f = o.replace(/\/+$/, "");
242
+ let d, _, c, m = !1;
243
+ if (t.submit_url)
244
+ d = /^https?:\/\//i.test(t.submit_url) ? t.submit_url : `${f}/${t.submit_url.replace(/^\/+/, "")}`, c = t.submit_method ?? "POST", _ = n;
245
+ else {
246
+ m = !0, d = `${f}/api/agents/${e}/form-responses/`, c = "POST";
247
+ const I = P(t).filter((h) => h.name && h.type !== "display").map((h) => ({
248
+ name: h.name,
249
+ label: h.label,
250
+ value: n[h.name] ?? ""
251
+ }));
252
+ _ = {
253
+ form_id: t.id,
254
+ form_data: I,
255
+ ...i ? { session_id: i } : {}
256
+ };
257
+ }
258
+ const b = { "Content-Type": "application/json" };
259
+ m && (r != null && r.trim()) && (b["x-api-key"] = r.trim());
260
+ const k = await (s ?? (typeof globalThis.fetch == "function" ? globalThis.fetch.bind(globalThis) : (() => {
261
+ throw new Error("[voice-agent] No fetch available; pass config.fetch.");
262
+ })()))(d, {
263
+ method: c,
264
+ headers: b,
265
+ body: JSON.stringify(_)
266
+ }), g = await k.json().catch(() => null);
267
+ if (!k.ok)
268
+ throw new Error(
269
+ (g == null ? void 0 : g.error) || (g == null ? void 0 : g.detail) || `We couldn't send your request right now (HTTP ${k.status}).`
270
+ );
271
+ return g;
272
+ }
273
+ function S(t) {
274
+ if (!Array.isArray(t)) return [];
275
+ const n = [];
276
+ for (const o of t) {
277
+ if (!o || typeof o != "object") continue;
278
+ const e = o, i = l(e.id);
279
+ if (!i) continue;
280
+ const r = L(e.steps), s = O(e.fields);
281
+ !r.length && !s.length || n.push({
282
+ id: i,
283
+ title: l(e.title) ?? i,
284
+ subtitle: l(e.subtitle),
285
+ fields: s,
286
+ steps: r.length ? r : void 0,
287
+ layout: q(e.layout),
288
+ disabled: e.disabled === !0 ? !0 : void 0,
289
+ submit_url: l(e.submit_url) ?? null,
290
+ submit_method: y(
291
+ ["POST", "PUT", "PATCH"],
292
+ e.submit_method
293
+ ),
294
+ submit_label: l(e.submit_label),
295
+ success_message: l(e.success_message),
296
+ topics: N(e.topics),
297
+ event_types: N(e.event_types),
298
+ confirmation_topic: l(e.confirmation_topic),
299
+ confirmation_type: l(e.confirmation_type)
300
+ });
301
+ }
302
+ return n;
303
+ }
304
+ function O(t) {
305
+ if (!Array.isArray(t)) return [];
306
+ const n = [];
307
+ for (const o of t) {
308
+ if (!o || typeof o != "object") continue;
309
+ const e = o, i = y(
310
+ [
311
+ "text",
312
+ "email",
313
+ "tel",
314
+ "textarea",
315
+ "select",
316
+ "number",
317
+ "date",
318
+ "time",
319
+ "checkbox",
320
+ "radio",
321
+ "display"
322
+ ],
323
+ e.type
324
+ ) ?? "text", r = l(e.name);
325
+ i !== "display" && !r || n.push({
326
+ name: r,
327
+ label: l(e.label) ?? r ?? "",
328
+ type: i,
329
+ placeholder: l(e.placeholder),
330
+ required: e.required === !0,
331
+ options: z(e.options),
332
+ rows: typeof e.rows == "number" && Number.isFinite(e.rows) && e.rows > 0 ? e.rows : void 0,
333
+ default_value: l(e.default_value),
334
+ help_text: l(e.help_text),
335
+ pattern: l(e.pattern),
336
+ min: E(e.min),
337
+ max: E(e.max),
338
+ width: y(["full", "half"], e.width)
339
+ });
340
+ }
341
+ return n;
342
+ }
343
+ function L(t) {
344
+ if (!Array.isArray(t)) return [];
345
+ const n = [];
346
+ for (const [o, e] of t.entries()) {
347
+ if (!e || typeof e != "object") continue;
348
+ const i = e, r = O(i.fields);
349
+ r.length && n.push({
350
+ id: l(i.id) ?? `step-${o + 1}`,
351
+ title: l(i.title),
352
+ subtitle: l(i.subtitle),
353
+ fields: r,
354
+ next_label: l(i.next_label),
355
+ back_label: l(i.back_label)
356
+ });
357
+ }
358
+ return n;
359
+ }
360
+ function q(t) {
361
+ if (!t || typeof t != "object") return;
362
+ const n = t, o = {}, e = y(["stack", "grid"], n.field_layout);
363
+ e && (o.field_layout = e);
364
+ const i = y(["comfortable", "compact"], n.density);
365
+ i && (o.density = i);
366
+ const r = y(["top", "inline"], n.label_position);
367
+ return r && (o.label_position = r), Object.keys(o).length ? o : void 0;
368
+ }
369
+ function z(t) {
370
+ if (!Array.isArray(t)) return;
371
+ const n = [];
372
+ for (const o of t) {
373
+ if (typeof o == "string") {
374
+ const e = o.trim();
375
+ e && n.push(e);
376
+ continue;
377
+ }
378
+ if (o && typeof o == "object") {
379
+ const e = o, i = l(e.value);
380
+ if (!i) continue;
381
+ const r = l(e.label);
382
+ n.push(r ? { value: i, label: r } : { value: i });
383
+ }
384
+ }
385
+ return n.length ? n : void 0;
386
+ }
387
+ function E(t) {
388
+ if (typeof t == "number" && Number.isFinite(t)) return t;
389
+ if (typeof t == "string") {
390
+ const n = Number(t.trim());
391
+ if (Number.isFinite(n)) return n;
392
+ }
393
+ }
394
+ function l(t) {
395
+ if (typeof t != "string") return;
396
+ const n = t.trim();
397
+ return n || void 0;
398
+ }
399
+ function N(t) {
400
+ if (!Array.isArray(t)) return;
401
+ const n = t.map(l).filter((o) => !!o);
402
+ return n.length ? n : void 0;
403
+ }
404
+ function y(t, n) {
405
+ return typeof n == "string" && t.includes(n) ? n : void 0;
406
+ }
407
+ const a = {
408
+ name: "Voice Assistant",
409
+ subtitle: "Tap below to start a voice conversation.",
410
+ logo_url: "",
411
+ // Empty by default — only show FAB text when the backend explicitly
412
+ // configures fab_label/fab_sublabel. Otherwise the FAB is icon-only.
413
+ fab_label: "",
414
+ fab_sublabel: "",
415
+ start_button_text: "Start Call",
416
+ powered_by_text: "Powered by Oshara.ai",
417
+ powered_by_url: "",
418
+ theme: {
419
+ primary_color: "#6366F1",
420
+ accent_color: "#22D3EE",
421
+ background_color: "#FFFFFF",
422
+ text_color: "#0F172A",
423
+ user_bubble_color: "#6366F1",
424
+ user_bubble_text_color: "#FFFFFF",
425
+ agent_bubble_color: "#F1F5F9",
426
+ agent_bubble_text_color: "#0F172A"
427
+ },
428
+ dimensions: {
429
+ fab_size: 64,
430
+ panel_width: 380,
431
+ panel_height: 620,
432
+ border_radius: 24
433
+ },
434
+ layout: {
435
+ position: "bottom-right",
436
+ font_family: "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
437
+ },
438
+ labels: {
439
+ idle: "Idle",
440
+ connecting: "Connecting…",
441
+ listening: "Listening",
442
+ speaking: "Speaking…",
443
+ thinking: "Thinking…",
444
+ muted: "Microphone muted",
445
+ call_ended: "Call ended",
446
+ transcript_placeholder: "Your live transcript will appear here",
447
+ language_label: "Language"
448
+ },
449
+ languages: [
450
+ { code: "en", label: "English", native_label: "English" },
451
+ { code: "ne", label: "Nepali", native_label: "नेपाली" }
452
+ ],
453
+ default_language: "en",
454
+ max_call_seconds: 0,
455
+ terms_url: "",
456
+ terms_label: "Terms & Conditions",
457
+ consent_text: "By starting the call, you agree to our",
458
+ forms: $,
459
+ show_audio_settings: !0
460
+ }, D = [
461
+ "bottom-right",
462
+ "bottom-left",
463
+ "top-right",
464
+ "top-left"
465
+ ];
466
+ function M(t) {
467
+ if (!t || typeof t != "object") return a;
468
+ const n = w(t), o = w(n.theme), e = w(n.dimensions), i = w(n.layout), r = w(n.labels);
469
+ return {
470
+ name: u(n.name) ?? a.name,
471
+ subtitle: p(n.subtitle, a.subtitle),
472
+ logo_url: p(n.logo_url, a.logo_url),
473
+ fab_label: p(n.fab_label, a.fab_label),
474
+ fab_sublabel: p(
475
+ n.fab_sublabel,
476
+ a.fab_sublabel
477
+ ),
478
+ start_button_text: u(n.start_button_text) ?? a.start_button_text,
479
+ powered_by_text: p(
480
+ n.powered_by_text,
481
+ a.powered_by_text
482
+ ),
483
+ powered_by_url: p(
484
+ n.powered_by_url,
485
+ a.powered_by_url
486
+ ),
487
+ theme: {
488
+ primary_color: u(o.primary_color) ?? a.theme.primary_color,
489
+ accent_color: u(o.accent_color) ?? a.theme.accent_color,
490
+ background_color: u(o.background_color) ?? a.theme.background_color,
491
+ text_color: u(o.text_color) ?? a.theme.text_color,
492
+ user_bubble_color: u(o.user_bubble_color) ?? a.theme.user_bubble_color,
493
+ user_bubble_text_color: u(o.user_bubble_text_color) ?? a.theme.user_bubble_text_color,
494
+ agent_bubble_color: u(o.agent_bubble_color) ?? a.theme.agent_bubble_color,
495
+ agent_bubble_text_color: u(o.agent_bubble_text_color) ?? a.theme.agent_bubble_text_color
496
+ },
497
+ dimensions: {
498
+ fab_size: x(e.fab_size) ?? a.dimensions.fab_size,
499
+ panel_width: x(e.panel_width) ?? a.dimensions.panel_width,
500
+ panel_height: x(e.panel_height) ?? a.dimensions.panel_height,
501
+ border_radius: x(e.border_radius) ?? a.dimensions.border_radius
502
+ },
503
+ layout: {
504
+ position: X(D, i.position) ?? a.layout.position,
505
+ font_family: p(
506
+ i.font_family,
507
+ a.layout.font_family
508
+ )
509
+ },
510
+ labels: {
511
+ idle: u(r.idle) ?? a.labels.idle,
512
+ connecting: u(r.connecting) ?? a.labels.connecting,
513
+ listening: u(r.listening) ?? a.labels.listening,
514
+ speaking: u(r.speaking) ?? a.labels.speaking,
515
+ thinking: u(r.thinking) ?? a.labels.thinking,
516
+ muted: u(r.muted) ?? a.labels.muted,
517
+ call_ended: u(r.call_ended) ?? a.labels.call_ended,
518
+ transcript_placeholder: p(
519
+ r.transcript_placeholder,
520
+ a.labels.transcript_placeholder
521
+ ),
522
+ language_label: u(r.language_label) ?? a.labels.language_label
523
+ },
524
+ languages: U(n.languages),
525
+ default_language: u(n.default_language) ?? a.default_language,
526
+ max_call_seconds: W(n.max_call_seconds) ?? a.max_call_seconds,
527
+ terms_url: p(n.terms_url, a.terms_url),
528
+ terms_label: u(n.terms_label) ?? a.terms_label,
529
+ consent_text: p(
530
+ n.consent_text,
531
+ a.consent_text
532
+ ),
533
+ forms: R(n.forms),
534
+ show_audio_settings: typeof n.show_audio_settings == "boolean" ? n.show_audio_settings : a.show_audio_settings
535
+ };
536
+ }
537
+ function R(t) {
538
+ const n = S(t), o = /* @__PURE__ */ new Map();
539
+ for (const e of $) o.set(e.id, e);
540
+ for (const e of n) o.set(e.id, e);
541
+ return Array.from(o.values());
542
+ }
543
+ function U(t) {
544
+ if (!Array.isArray(t)) return a.languages;
545
+ const n = /* @__PURE__ */ new Set(), o = [];
546
+ for (const e of t) {
547
+ if (!v(e)) continue;
548
+ const i = u(e.code);
549
+ if (!i || n.has(i)) continue;
550
+ const r = u(e.label) ?? i.toUpperCase(), s = u(e.native_label) ?? r;
551
+ n.add(i), o.push({ code: i, label: r, native_label: s });
552
+ }
553
+ return o.length ? o : a.languages;
554
+ }
555
+ async function re(t) {
556
+ var i;
557
+ const n = t.appearanceUrl || `${t.apiUrl.replace(/\/$/, "")}/api/agents/${encodeURIComponent(
558
+ t.slug
559
+ )}/appearance/`, o = { Accept: "application/json" };
560
+ (i = t.apiKey) != null && i.trim() && (o["x-api-key"] = t.apiKey.trim());
561
+ const e = t.fetch ?? (typeof globalThis.fetch == "function" ? globalThis.fetch.bind(globalThis) : null);
562
+ if (!e)
563
+ return console.warn("[voice-agent] no fetch available; using default appearance"), a;
564
+ console.info("[voice-agent] fetching appearance from", n);
565
+ try {
566
+ const r = await e(n, { method: "GET", headers: o });
567
+ if (!r.ok)
568
+ return console.warn(
569
+ `[voice-agent] appearance fetch returned ${r.status}; using defaults`
570
+ ), a;
571
+ const s = await r.json();
572
+ console.info("[voice-agent] appearance response", s);
573
+ const f = Y(s), d = M(f);
574
+ return console.info("[voice-agent] applied appearance", d), d;
575
+ } catch (r) {
576
+ return console.warn("[voice-agent] appearance fetch failed; using defaults:", r), a;
577
+ }
578
+ }
579
+ function Y(t) {
580
+ if (!v(t)) return null;
581
+ const n = t, o = [
582
+ n.data,
583
+ n.appearance,
584
+ n.widget_appearance,
585
+ n
586
+ ];
587
+ for (const e of o)
588
+ if (v(e))
589
+ return e;
590
+ return null;
591
+ }
592
+ function v(t) {
593
+ return t !== null && typeof t == "object" && !Array.isArray(t);
594
+ }
595
+ function w(t) {
596
+ return v(t) ? t : {};
597
+ }
598
+ function u(t) {
599
+ if (typeof t != "string") return;
600
+ const n = t.trim();
601
+ return n || void 0;
602
+ }
603
+ function p(t, n) {
604
+ return typeof t == "string" ? t : n;
605
+ }
606
+ function B(t) {
607
+ return typeof t == "number" && Number.isFinite(t) && t > 0 ? t : void 0;
608
+ }
609
+ function W(t) {
610
+ if (typeof t == "number" && Number.isFinite(t) && t >= 0)
611
+ return t;
612
+ if (typeof t == "string") {
613
+ const n = t.trim();
614
+ if (!n) return;
615
+ const o = Number(n);
616
+ if (Number.isFinite(o) && o >= 0) return o;
617
+ }
618
+ }
619
+ function x(t) {
620
+ const n = B(t);
621
+ if (n !== void 0) return n;
622
+ if (typeof t != "string") return;
623
+ const o = t.trim().match(/^(\d+(?:\.\d+)?)px$/i);
624
+ if (!o) return;
625
+ const e = Number(o[1]);
626
+ return Number.isFinite(e) && e > 0 ? e : void 0;
627
+ }
628
+ function X(t, n) {
629
+ return typeof n == "string" && t.includes(n) ? n : void 0;
630
+ }
631
+ export {
632
+ a as D,
633
+ $ as a,
634
+ H as b,
635
+ F as c,
636
+ G as d,
637
+ K as e,
638
+ re as f,
639
+ M as g,
640
+ V as h,
641
+ ee as i,
642
+ te as j,
643
+ ne as k,
644
+ Z as m,
645
+ S as n,
646
+ oe as s,
647
+ J as t,
648
+ Q as v
649
+ };
650
+ //# sourceMappingURL=appearance-i6QBkpCk.js.map