@flowengage/react-chatbot 1.1.0 → 1.1.2

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.
@@ -171,12 +171,14 @@ var d = Object.defineProperty, f = (e, t) => {
171
171
  body: JSON.stringify({ session_id: e })
172
172
  });
173
173
  },
174
- async syncVoice(e, t) {
174
+ async syncVoice(e, r) {
175
175
  return i("/api/ai/voice/sync", {
176
176
  method: "POST",
177
177
  body: JSON.stringify({
178
178
  session_id: e,
179
- messages: t
179
+ messages: r,
180
+ ...t ? { userId: String(t) } : {},
181
+ ...n ? { siteId: String(n) } : {}
180
182
  })
181
183
  });
182
184
  },
@@ -264,13 +266,15 @@ var d = Object.defineProperty, f = (e, t) => {
264
266
  site_id: n
265
267
  });
266
268
  },
267
- beaconSyncVoice(e, t, n, r) {
269
+ beaconSyncVoice(r, i) {
268
270
  if (typeof navigator > "u" || !navigator.sendBeacon) return !1;
269
- let i = new Blob([JSON.stringify({
270
- session_id: n,
271
- messages: r
272
- })], { type: "application/json" });
273
- return navigator.sendBeacon(`${e}/api/ai/voice/sync`, i);
271
+ let a = {
272
+ session_id: r,
273
+ messages: i,
274
+ ...t ? { userId: String(t) } : {},
275
+ ...n ? { siteId: String(n) } : {}
276
+ }, o = new Blob([JSON.stringify(a)], { type: "application/json" });
277
+ return navigator.sendBeacon(`${e}/api/ai/voice/sync`, o);
274
278
  }
275
279
  };
276
280
  }, y = Object.create(null);
@@ -2423,8 +2427,8 @@ function vn({ siteId: e, config: t, children: n, language: r = "en" }) {
2423
2427
  };
2424
2428
  }, [c, r]), i(() => () => {
2425
2429
  if (x && !ct.current && st.current.length > 0) {
2426
- let e = T.current, t = st.current, n = w.current, r = _?.apiBaseUrl || "", i = _?.userId || "";
2427
- n && e && t.length > 0 && (console.log("[FlowEngageProvider] safety-net: syncing voice transcript on unmount"), n.beaconSyncVoice(r, i, e, t) || n.syncVoice(e, t).catch(() => {}), ct.current = !0);
2430
+ let e = T.current, t = st.current, n = w.current;
2431
+ n && e && t.length > 0 && (console.log("[FlowEngageProvider] safety-net: syncing voice transcript on unmount"), n.beaconSyncVoice(e, t) || n.syncVoice(e, t).catch(() => {}), ct.current = !0);
2428
2432
  }
2429
2433
  }, [x, _]), i(() => {
2430
2434
  if (!w.current || !v || d !== "ready" || he) return;
@@ -22269,7 +22273,24 @@ function Sg() {
22269
22273
  }));
22270
22274
  }), e;
22271
22275
  }
22272
- function Cg() {
22276
+ function Cg(e) {
22277
+ if (!e || typeof e.closest != "function") return !1;
22278
+ try {
22279
+ return !!e.closest("footer, [role=\"contentinfo\"], #footer, .site-footer, [class*=\"footer\"], [id*=\"footer\"]");
22280
+ } catch {
22281
+ return !1;
22282
+ }
22283
+ }
22284
+ function wg() {
22285
+ let e = Sg();
22286
+ for (let t of e) {
22287
+ if ((t.type || "").toLowerCase() !== "email" || Cg(t)) continue;
22288
+ let e = gg(t);
22289
+ if (e) return e;
22290
+ }
22291
+ return null;
22292
+ }
22293
+ function Tg() {
22273
22294
  let e = Sg(), t = /* @__PURE__ */ new Map(), n = 0;
22274
22295
  return e.map((e, r) => {
22275
22296
  let i = gg(e), a = i || "__orphan__";
@@ -22288,7 +22309,7 @@ function Cg() {
22288
22309
  };
22289
22310
  });
22290
22311
  }
22291
- function wg() {
22312
+ function Eg() {
22292
22313
  let e = [];
22293
22314
  return yg((t) => {
22294
22315
  e.push(...Array.from(t.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"]")).filter((e) => {
@@ -22306,18 +22327,18 @@ function wg() {
22306
22327
  type: e.type || e.tagName
22307
22328
  }));
22308
22329
  }
22309
- function Tg(e) {
22330
+ function Dg(e) {
22310
22331
  return String(e || "").toLowerCase().replace(/\u00a0/g, " ").replace(/\*/g, "").replace(/\s+/g, " ").trim();
22311
22332
  }
22312
- function Eg(e) {
22313
- let t = Tg(e);
22333
+ function Og(e) {
22334
+ let t = Dg(e);
22314
22335
  return t = t.replace(/\s+field\s*$/i, "").trim(), t;
22315
22336
  }
22316
- function Dg(e, t) {
22317
- let n = Eg(t);
22337
+ function kg(e, t) {
22338
+ let n = Og(t);
22318
22339
  if (!n) return 0;
22319
22340
  let r = (e.name || "").toLowerCase(), i = (e.id || "").toLowerCase();
22320
- if (r === "url" && /url|website|domain|site|audit/.test(n) || (i === "url-input" || i.endsWith("-url-input")) && /url|website|domain|site|audit/.test(n)) return 100;
22341
+ if (r === "url" && /url|website|domain|audit|conduct|site(\s|$)|page(\s|$)/.test(n) && !/email|e-mail|mail|name|message|phone/.test(n) || (i === "url-input" || i.endsWith("-url-input")) && /url|website|domain|audit|conduct/.test(n) && !/email|e-mail|mail|name|message|phone/.test(n)) return 100;
22321
22342
  let a = (e.type || "").toLowerCase();
22322
22343
  if (a === "email" && /email|e-mail|mail/.test(n)) return 100;
22323
22344
  if (a === "tel" && /phone|mobile|tel|cell/.test(n)) return 95;
@@ -22331,7 +22352,7 @@ function Dg(e, t) {
22331
22352
  e.getAttribute("title"),
22332
22353
  e.getAttribute("data-testid"),
22333
22354
  e.getAttribute("autocomplete")
22334
- ].filter(Boolean).map((e) => Tg(e)), s = 0;
22355
+ ].filter(Boolean).map((e) => Dg(e)), s = 0;
22335
22356
  for (let e of o) {
22336
22357
  if (!e) continue;
22337
22358
  if (e === n) {
@@ -22351,18 +22372,18 @@ function Dg(e, t) {
22351
22372
  }
22352
22373
  return s;
22353
22374
  }
22354
- var Og = 22;
22355
- function kg(e, t) {
22375
+ var Ag = 22;
22376
+ function jg(e, t) {
22356
22377
  let n = null, r = 0;
22357
22378
  for (let i of e) {
22358
- let e = Dg(i, t);
22379
+ let e = kg(i, t);
22359
22380
  e > r && (r = e, n = i);
22360
22381
  }
22361
- return !n || r < Og ? null : n;
22382
+ return !n || r < Ag ? null : n;
22362
22383
  }
22363
- function Ag(e, t, n) {
22384
+ function Mg(e, t, n) {
22364
22385
  let r = String(t || "").toLowerCase().trim(), i = String(n || "").trim();
22365
- if (!(/^https?:\/\//i.test(i) || /\.\w{2,}(\/|\s|$)/.test(i) || r.includes("url") || r.includes("website") || r.includes("domain") || r.includes("site"))) return null;
22386
+ if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i) || !(/^https?:\/\//i.test(i) || /\.\w{2,}(\/|\s|$)/.test(i) || r.includes("url") || r.includes("website") || r.includes("domain") || r.includes("site"))) return null;
22366
22387
  let a = null, o = 0;
22367
22388
  for (let t of e) {
22368
22389
  if (t.tagName !== "INPUT" && t.tagName !== "TEXTAREA") continue;
@@ -22388,15 +22409,15 @@ function Ag(e, t, n) {
22388
22409
  }
22389
22410
  return !a || o < 42 ? null : a;
22390
22411
  }
22391
- function jg(e) {
22412
+ function Ng(e) {
22392
22413
  let t = String(e ?? "").trim();
22393
- return t ? /^https?:\/\//i.test(t) ? !0 : /\.\w{2,}(\/|\s|$)/.test(t) : !1;
22414
+ return !t || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t) ? !1 : /^https?:\/\//i.test(t) ? !0 : /\.\w{2,}(\/|\s|$)/.test(t);
22394
22415
  }
22395
- function Mg(e) {
22416
+ function Pg(e) {
22396
22417
  let t = String(e ?? "").toLowerCase().trim();
22397
22418
  return t ? !!(t === "url" || t === "website" || t === "website url" || t === "website_url" || t === "enter website url" || t.includes("website") || t.includes("domain") || /(enter\s+website|site\s*url|page\s*url)/.test(t)) : !1;
22398
22419
  }
22399
- function Ng(e) {
22420
+ function Fg(e) {
22400
22421
  if (!e || e.tagName !== "INPUT" && e.tagName !== "TEXTAREA") return !1;
22401
22422
  let t = (e.type || "").toLowerCase();
22402
22423
  return ![
@@ -22408,8 +22429,8 @@ function Ng(e) {
22408
22429
  "file"
22409
22430
  ].includes(t);
22410
22431
  }
22411
- function Pg(e) {
22412
- if (!Ng(e)) return !1;
22432
+ function Ig(e) {
22433
+ if (!Fg(e)) return !1;
22413
22434
  let t = (e.name || "").toLowerCase(), n = (e.id || "").toLowerCase(), r = [
22414
22435
  e.name,
22415
22436
  e.id,
@@ -22419,11 +22440,11 @@ function Pg(e) {
22419
22440
  ].filter(Boolean).join(" ").toLowerCase();
22420
22441
  return t === "url" || n === "url-input" || n.endsWith("-url-input") || /(website\s*url|enter\s+website|site\s*url)/.test(r) || /(website|domain)/.test(r) && /(url|site)/.test(r);
22421
22442
  }
22422
- function Fg(e, t, n) {
22423
- let r = String(t ?? ""), i = String(n ?? ""), a = Rg(e, r) || kg(e, r) || Ag(e, r, i);
22443
+ function Lg(e, t, n) {
22444
+ let r = String(t ?? ""), i = String(n ?? ""), a = Bg(e, r) || jg(e, r) || Mg(e, r, i);
22424
22445
  if (!a) return [];
22425
22446
  let o = new Set([a]);
22426
- if (jg(i) && Mg(r)) for (let t of e) t !== a && Pg(t) && o.add(t);
22447
+ if (Ng(i) && Pg(r)) for (let t of e) t !== a && Ig(t) && o.add(t);
22427
22448
  let s = Array.from(o);
22428
22449
  return s.sort((e, t) => {
22429
22450
  if (e === t) return 0;
@@ -22431,7 +22452,7 @@ function Fg(e, t, n) {
22431
22452
  return n & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : n & Node.DOCUMENT_POSITION_PRECEDING ? 1 : 0;
22432
22453
  }), s;
22433
22454
  }
22434
- function Ig(e, t) {
22455
+ function Rg(e, t) {
22435
22456
  try {
22436
22457
  if (!e?.getBoundingClientRect || !t?.getBoundingClientRect) return Infinity;
22437
22458
  let n = e.getBoundingClientRect(), r = t.getBoundingClientRect(), i = {
@@ -22446,7 +22467,7 @@ function Ig(e, t) {
22446
22467
  return Infinity;
22447
22468
  }
22448
22469
  }
22449
- function Lg(e) {
22470
+ function zg(e) {
22450
22471
  if (!e || typeof e != "string") return null;
22451
22472
  let t = null;
22452
22473
  return yg((n) => {
@@ -22456,7 +22477,7 @@ function Lg(e) {
22456
22477
  } catch {}
22457
22478
  }), t;
22458
22479
  }
22459
- function Rg(e, t) {
22480
+ function Bg(e, t) {
22460
22481
  let n = String(t ?? "").trim();
22461
22482
  if (!n) return null;
22462
22483
  let r = n.match(/^name:\s*([\w.-]+)$/i);
@@ -22466,12 +22487,12 @@ function Rg(e, t) {
22466
22487
  }
22467
22488
  let i = n.match(/^id:\s*([\w.-]+)$/i);
22468
22489
  if (i) {
22469
- let e = Lg(i[1]);
22490
+ let e = zg(i[1]);
22470
22491
  if (e) return e;
22471
22492
  }
22472
22493
  let a = n.startsWith("#") ? n.slice(1) : n;
22473
22494
  if (/^[\w-]+$/.test(a)) {
22474
- let e = Lg(a);
22495
+ let e = zg(a);
22475
22496
  if (e) return e;
22476
22497
  }
22477
22498
  let o = n.toLowerCase().replace(/\s+/g, " ");
@@ -22481,7 +22502,7 @@ function Rg(e, t) {
22481
22502
  }
22482
22503
  return null;
22483
22504
  }
22484
- function zg(e, t) {
22505
+ function Vg(e, t) {
22485
22506
  let n = String(t || "").toLowerCase().trim();
22486
22507
  if (!n) return 0;
22487
22508
  let r = [
@@ -22498,7 +22519,7 @@ function zg(e, t) {
22498
22519
  for (let e of i) r.includes(e) && (a += 1);
22499
22520
  return a / i.length * 92;
22500
22521
  }
22501
- function Bg(e, t) {
22522
+ function Hg(e, t) {
22502
22523
  let n = [];
22503
22524
  yg((e) => {
22504
22525
  n.push(...Array.from(e.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"]")).filter((e) => {
@@ -22512,7 +22533,7 @@ function Bg(e, t) {
22512
22533
  });
22513
22534
  let r = 0, i = n.map((t) => ({
22514
22535
  el: t,
22515
- s: zg(t, e)
22536
+ s: Vg(t, e)
22516
22537
  }));
22517
22538
  for (let { s: e } of i) e > r && (r = e);
22518
22539
  if (r < 36) return null;
@@ -22522,14 +22543,14 @@ function Bg(e, t) {
22522
22543
  if (o.length) {
22523
22544
  let e = a[0], t = Infinity;
22524
22545
  for (let n of a) for (let r of o) {
22525
- let i = Ig(n, r);
22546
+ let i = Rg(n, r);
22526
22547
  i < t && (t = i, e = n);
22527
22548
  }
22528
22549
  return e;
22529
22550
  }
22530
22551
  return a[0];
22531
22552
  }
22532
- function Vg(e) {
22553
+ function Ug(e) {
22533
22554
  if (e == null) return {};
22534
22555
  if (typeof e == "string") {
22535
22556
  let t = e.trim();
@@ -22542,8 +22563,8 @@ function Vg(e) {
22542
22563
  }
22543
22564
  return e;
22544
22565
  }
22545
- function Hg(e) {
22546
- let t = Vg(e);
22566
+ function Wg(e) {
22567
+ let t = Ug(e);
22547
22568
  if (Array.isArray(t) && t.length > 0) {
22548
22569
  let e = t[0];
22549
22570
  if (e?.field_key != null || e?.fieldKey != null) return t.map((e) => ({
@@ -22571,12 +22592,12 @@ function Hg(e) {
22571
22592
  value: e?.value ?? e?.Value
22572
22593
  })) : [];
22573
22594
  }
22574
- function Ug(e) {
22595
+ function Gg(e) {
22575
22596
  if (!e || typeof e != "string") return e;
22576
22597
  let t = e.trim();
22577
22598
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t) ? t : (t = t.replace(/\s+at\s+the\s+rate\s*(of)?\s+/gi, "@"), t = t.replace(/\s+at\s+/gi, "@"), t = t.replace(/\s+dot\s+/gi, "."), t = t.replace(/\s+/g, ""), t = t.replace(/\.{2,}/g, ".").replace(/\.$/, ""), t);
22578
22599
  }
22579
- function Wg(e) {
22600
+ function Kg(e) {
22580
22601
  if (!e || typeof e != "string") return e;
22581
22602
  let t = {
22582
22603
  zero: "0",
@@ -22595,7 +22616,7 @@ function Wg(e) {
22595
22616
  for (let [e, r] of Object.entries(t)) n = n.replace(RegExp(`\\b${e}\\b`, "g"), r);
22596
22617
  return n = n.replace(/[^\d+]/g, ""), n;
22597
22618
  }
22598
- function Gg(e) {
22619
+ function qg(e) {
22599
22620
  if (!e || typeof e != "string") return [];
22600
22621
  let t = e.trim();
22601
22622
  if (!t || /\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\b/i.test(t)) return [];
@@ -22614,7 +22635,7 @@ function Gg(e) {
22614
22635
  }
22615
22636
  return [];
22616
22637
  }
22617
- function Kg(e) {
22638
+ function Jg(e) {
22618
22639
  if (!e || typeof e != "string") return [];
22619
22640
  let t = e.trim();
22620
22641
  if (!t) return [];
@@ -22626,7 +22647,7 @@ function Kg(e) {
22626
22647
  field_key: e,
22627
22648
  value: i
22628
22649
  }));
22629
- }, o = Ug(t), s = i.test(o), c = o.match(/^\s*([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})\s*$/i);
22650
+ }, o = Gg(t), s = i.test(o), c = o.match(/^\s*([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})\s*$/i);
22630
22651
  if (c) return a("Email Address", c[1]), n;
22631
22652
  if (!i.test(t) && s) {
22632
22653
  let e = o.match(i);
@@ -22654,17 +22675,17 @@ function Kg(e) {
22654
22675
  }
22655
22676
  return n;
22656
22677
  }
22657
- function qg(e) {
22678
+ function Yg(e) {
22658
22679
  if (!e || typeof e != "object") return null;
22659
22680
  let t = e.url ?? e.target_url ?? e.page_url ?? e.pageUrl ?? e.link ?? e.href ?? e.path;
22660
22681
  return t == null ? null : String(t).trim() || null;
22661
22682
  }
22662
- function Jg(e) {
22683
+ function Xg(e) {
22663
22684
  if (!e || typeof e != "object") return null;
22664
- let t = e.query ?? e.q ?? e.search ?? e.text ?? e.keywords;
22685
+ let t = e.query ?? e.q ?? e.search ?? e.text ?? e.keywords ?? e.search_query ?? e.searchQuery ?? e.question ?? e.prompt ?? e.topic ?? e.intent;
22665
22686
  return t == null ? null : String(t).trim() || null;
22666
22687
  }
22667
- function Yg(e) {
22688
+ function Zg(e) {
22668
22689
  let t = e.ownerDocument?.defaultView || window, n = e.tagName === "TEXTAREA" ? t.HTMLTextAreaElement.prototype : t.HTMLInputElement.prototype, r = Object.getOwnPropertyDescriptor(n, "value");
22669
22690
  return (e, t) => {
22670
22691
  try {
@@ -22673,7 +22694,7 @@ function Yg(e) {
22673
22694
  r?.set ? r.set.call(e, t) : e.value = t;
22674
22695
  };
22675
22696
  }
22676
- async function Xg(e, t, n) {
22697
+ async function Qg(e, t, n) {
22677
22698
  if (!n?.skipScroll) try {
22678
22699
  e.scrollIntoView({
22679
22700
  behavior: "smooth",
@@ -22713,7 +22734,7 @@ async function Xg(e, t, n) {
22713
22734
  ].includes(String(t).toLowerCase().trim()), e.dispatchEvent(new Event("input", a)), e.dispatchEvent(new Event("change", a)), cg(e), !0;
22714
22735
  let o = String(t);
22715
22736
  if (r === "INPUT" || r === "TEXTAREA") {
22716
- let t = Yg(e);
22737
+ let t = Zg(e);
22717
22738
  try {
22718
22739
  await eg(e, o, t);
22719
22740
  } catch {
@@ -22743,11 +22764,11 @@ async function Xg(e, t, n) {
22743
22764
  } catch {}
22744
22765
  return cg(e), !0;
22745
22766
  }
22746
- function Zg(e) {
22767
+ function $g(e) {
22747
22768
  let t = e.siteId || null, n = (e.apiBaseUrl || "").replace(/\/$/, ""), r = typeof e.getLastUserVoiceText == "function" ? e.getLastUserVoiceText : null, i = [], a = null, o = {
22748
22769
  navigate_to_page: async (n) => {
22749
22770
  $("navigate_to_page ▶ raw parameters:", n);
22750
- let r = Vg(n), i = qg(r), a = r.section_text ?? r.sectionText ?? r.section;
22771
+ let r = Ug(n), i = Yg(r), a = r.section_text ?? r.sectionText ?? r.section;
22751
22772
  if ($("navigate_to_page · coerced:", {
22752
22773
  url: i,
22753
22774
  sectionText: a
@@ -22755,7 +22776,8 @@ function Zg(e) {
22755
22776
  let e = "Missing url: pass a string url, path like /pricing, or JSON with a url field.";
22756
22777
  return $("navigate_to_page ✖", e), e;
22757
22778
  }
22758
- if (rg(`Navigating to ${i.replace(/^https?:\/\/[^/]+/, "") || "/"}…`), ag(), !await ln(i, {
22779
+ let o = typeof window < "u" ? sn(i) : i;
22780
+ if (rg(`Navigating to ${String(o).replace(/^https?:\/\/[^/]+/, "") || "/"}…`), ag(), !await ln(o, {
22759
22781
  siteId: t,
22760
22782
  apiBaseUrl: e.apiBaseUrl
22761
22783
  })) {
@@ -22764,7 +22786,7 @@ function Zg(e) {
22764
22786
  return $("navigate_to_page ✖ blocked", e), e;
22765
22787
  }
22766
22788
  try {
22767
- if ($("navigate_to_page → shadowNavigate", i), await dn(i, { sectionText: a || void 0 }), await new Promise((e) => setTimeout(e, 600)), og(), ig(300), a && typeof a == "string") {
22789
+ if ($("navigate_to_page → shadowNavigate", o), await dn(o, { sectionText: a || void 0 }), await new Promise((e) => setTimeout(e, 600)), og(), ig(300), a && typeof a == "string") {
22768
22790
  let e = rn(null, a);
22769
22791
  e && an(e), $("navigate_to_page · highlight", {
22770
22792
  sectionText: a,
@@ -22773,13 +22795,13 @@ function Zg(e) {
22773
22795
  }
22774
22796
  let e = "";
22775
22797
  try {
22776
- let t = Cg(), n = wg();
22798
+ let t = Tg(), n = Eg();
22777
22799
  if (t.length > 0) {
22778
22800
  let r = t.map((e) => e.label || e.placeholder || e.name || e.id).filter(Boolean).join(", "), i = n.map((e) => e.text).filter(Boolean).join(", ");
22779
22801
  e = ` This page has a form with fields: [${r}]` + (i ? ` and buttons: [${i}].` : ".") + " Call list_page_forms then start filling.";
22780
22802
  }
22781
22803
  } catch {}
22782
- let t = `OK_NAVIGATION ${i}${e}`;
22804
+ let t = `OK_NAVIGATION ${o}${e}`;
22783
22805
  return $("navigate_to_page ✓", t), t;
22784
22806
  } catch (e) {
22785
22807
  og(), ig(200);
@@ -22789,12 +22811,12 @@ function Zg(e) {
22789
22811
  },
22790
22812
  highlight_on_page: async (e) => {
22791
22813
  $("highlight_on_page ▶", e);
22792
- let t = Vg(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText, i = rn(n || null, r || null);
22814
+ let t = Ug(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText, i = rn(n || null, r || null);
22793
22815
  return i ? (an(i), $("highlight_on_page ✓"), "Highlighted the section.") : ($("highlight_on_page ✖ no element"), "Could not find that section on the page.");
22794
22816
  },
22795
22817
  search_site_content: async (e) => {
22796
22818
  $("search_site_content ▶", e);
22797
- let r = Jg(Vg(e));
22819
+ let r = Xg(Ug(e));
22798
22820
  if ($("search_site_content · query:", r, "siteId:", t, "apiBase:", n || "(empty)"), rg("Searching site content…", { spinner: !0 }), !r) return ig(), $("search_site_content ✖ missing query"), "Missing query parameter.";
22799
22821
  if (!t) return ig(), $("search_site_content ✖ no siteId"), "Site is not configured for search.";
22800
22822
  if (!n) return ig(), $("search_site_content ✖ no api base"), "API base URL is missing; cannot search.";
@@ -22828,20 +22850,20 @@ function Zg(e) {
22828
22850
  duration: 2e3
22829
22851
  }), dg(!0), lg(), typeof e.requestEndSession == "function" && e.requestEndSession(), "Voice session is ending."),
22830
22852
  list_page_forms: async () => {
22831
- let e = Cg(), t = wg();
22832
- return $("list_page_forms ✓", `${e.length} field(s)`, `${t.length} button(s)`), a = null, JSON.stringify({
22853
+ let e = Tg(), t = Eg();
22854
+ return $("list_page_forms ✓", `${e.length} field(s)`, `${t.length} button(s)`), a = wg(), $("list_page_forms · activeFormAncestor", a ? "contact-preferring" : "none"), JSON.stringify({
22833
22855
  fields: e,
22834
22856
  buttons: t,
22835
- hint: "Fields are grouped by formIndex/formName. Work with ONE form at a time — only fill fields from the same formIndex. Do not jump to fields in a different form. field_key: use placeholder, label, name, or id from this list. click_page_button picks the button nearest the filled fields."
22857
+ hint: "Fields are grouped by formIndex/formName. Work with ONE form at a time — only fill fields from the same formIndex. Do not jump to fields in a different form. On pages with a contact form AND a footer 'Conduct Audit' / website URL field: only use the contact form unless the visitor explicitly asks to run an audit. Contact forms: fill in order Full Name → Email Address → Message. Message must be a short note the visitor wants to send (one or two sentences), never a recap of the whole chat or assistant replies. field_key: use placeholder, label, name, or id from this list. click_page_button picks the button nearest the filled fields (e.g. Send Message on the same form)."
22836
22858
  });
22837
22859
  },
22838
22860
  fill_form_fields: async (e) => {
22839
22861
  try {
22840
22862
  $("fill_form_fields ▶ raw:", e);
22841
- let t = Hg(e);
22863
+ let t = Wg(e);
22842
22864
  if (!t.length && r) {
22843
- let e = r(), n = Gg(e);
22844
- n.length ? $("fill_form_fields · inferred URL from last user utterance (model omitted usable fields):", n) : (n = Kg(e), n.length && $("fill_form_fields · inferred contact fields from last user utterance (empty tool params):", n)), n.length && (t = n);
22865
+ let e = r(), n = qg(e);
22866
+ n.length ? $("fill_form_fields · inferred URL from last user utterance (model omitted usable fields):", n) : (n = Jg(e), n.length && $("fill_form_fields · inferred contact fields from last user utterance (empty tool params):", n)), n.length && (t = n);
22845
22867
  }
22846
22868
  if ($("fill_form_fields · normalized fields:", t), !t.length) return "No fields provided. Call list_page_forms for field_key strings, then fill_form_fields with { \"fields\": [ { \"field_key\": \"<label or placeholder from list>\", \"value\": \"<user value>\" } ] }. Never use empty {}. Pass the value the user just said (email, message, name, URL) in fields.";
22847
22869
  t.length > 1 && rg(`Filling ${t.length} fields…`);
@@ -22850,7 +22872,16 @@ function Zg(e) {
22850
22872
  let t = e?.field_key ?? e?.fieldKey, r = e?.value;
22851
22873
  if (t == null || r == null) continue;
22852
22874
  let o = String(t).toLowerCase();
22853
- /email|e-mail|mail/.test(o) ? r = Ug(r) : /phone|mobile|tel|cell/.test(o) && (r = Wg(r)), rg(`Filling ${t}…`), $("fill_form_fields · processing field:", t, "=", r);
22875
+ if (/email|e-mail|mail/.test(o)) r = Gg(r);
22876
+ else if (/phone|mobile|tel|cell/.test(o)) r = Kg(r);
22877
+ else if (Pg(t) || o === "url") {
22878
+ let e = String(r ?? "").trim();
22879
+ if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) || /\bat\b/i.test(e) && /\bdot\b/i.test(e)) {
22880
+ let n = Gg(e);
22881
+ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n.trim()) && ($("fill_form_fields · remapping url/website intent to Email Address (value is an email)"), t = "Email Address", o = "email address", r = n.trim());
22882
+ }
22883
+ }
22884
+ rg(`Filling ${t}…`), $("fill_form_fields · processing field:", t, "=", r);
22854
22885
  let s = Sg(), c = s;
22855
22886
  if (a) {
22856
22887
  let e = s.filter((e) => gg(e) === a);
@@ -22859,15 +22890,15 @@ function Zg(e) {
22859
22890
  $("fill_form_fields · visible inputs count:", s.length, "scoped:", c.length);
22860
22891
  let l = !1;
22861
22892
  for (let e of [c, ...c === s ? [] : [s]]) {
22862
- let o = Fg(e, String(t), r);
22893
+ let o = Lg(e, String(t), r);
22863
22894
  if (o.length) {
22864
- for (let e = 0; e < o.length; e++) await Xg(o[e], r, { skipScroll: e > 0 }), await new Promise((e) => setTimeout(e, 80));
22895
+ for (let e = 0; e < o.length; e++) await Qg(o[e], r, { skipScroll: e > 0 }), await new Promise((e) => setTimeout(e, 80));
22865
22896
  i = o, a = gg(o[0]) || a, n.push(String(t)), l = !0;
22866
22897
  break;
22867
22898
  }
22868
- let s = Rg(e, String(t));
22869
- if (s ||= kg(e, String(t)), s ||= Ag(e, String(t), r), s) {
22870
- await Xg(s, r), i = [s], a = gg(s) || a, n.push(String(t)), l = !0;
22899
+ let s = Bg(e, String(t));
22900
+ if (s ||= jg(e, String(t)), s ||= Mg(e, String(t), r), s) {
22901
+ await Qg(s, r), i = [s], a = gg(s) || a, n.push(String(t)), l = !0;
22871
22902
  break;
22872
22903
  }
22873
22904
  }
@@ -22887,10 +22918,10 @@ function Zg(e) {
22887
22918
  }
22888
22919
  },
22889
22920
  click_page_button: async (e) => {
22890
- let t = Vg(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
22921
+ let t = Ug(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
22891
22922
  if ($("click_page_button ▶", n), !n) return "Missing button_text: pass the visible label, e.g. Conduct Audit.";
22892
22923
  rg(`Clicking "${n}"…`);
22893
- let r = Bg(n, i);
22924
+ let r = Hg(n, i);
22894
22925
  if (!r) return ig(200), $("click_page_button ✖ no match"), `Could not find a button matching "${n}". Call list_page_forms to see button texts.`;
22895
22926
  try {
22896
22927
  try {
@@ -22956,32 +22987,39 @@ function Zg(e) {
22956
22987
  }
22957
22988
  //#endregion
22958
22989
  //#region src/utils/wrapVoiceToolsForLogging.js
22959
- function Qg(e) {
22990
+ function e_(e) {
22960
22991
  return !e || typeof e != "object" ? e : Object.fromEntries(Object.entries(e).map(([e, t]) => [e, async (n) => {
22961
22992
  let r = Zt();
22962
22993
  r ? console.log("[FlowEngage:voice-tool] ▶", e, n) : console.info(`[FlowEngage] voice tool » ${e}`);
22963
- let i = await t(n), a = typeof i == "string" ? i.length > 220 ? `${i.slice(0, 220)}…` : i : String(i);
22994
+ let i;
22995
+ try {
22996
+ i = await t(n);
22997
+ } catch (t) {
22998
+ let n = `Tool error: ${t?.message || String(t)}`;
22999
+ return console.error(`[FlowEngage] voice tool ${e} threw:`, t), n;
23000
+ }
23001
+ let a = typeof i == "string" ? i.length > 220 ? `${i.slice(0, 220)}…` : i : String(i);
22964
23002
  return r ? console.log("[FlowEngage:voice-tool] ◀", e, a) : console.info(`[FlowEngage] voice tool « ${e}:`, a), i;
22965
23003
  }]));
22966
23004
  }
22967
23005
  //#endregion
22968
23006
  //#region src/components/VoiceInterface.jsx
22969
- var $g = {
23007
+ var t_ = {
22970
23008
  idle: "rgba(99,102,241,0.18)",
22971
23009
  listening: "rgba(16,185,129,0.25)",
22972
23010
  speaking: "rgba(245,158,11,0.25)",
22973
23011
  error: "rgba(239,68,68,0.2)"
22974
- }, e_ = {
23012
+ }, n_ = {
22975
23013
  idle: "#6366f1",
22976
23014
  listening: "#10b981",
22977
23015
  speaking: "#f59e0b",
22978
23016
  error: "#ef4444"
22979
23017
  };
22980
- function t_(e, t) {
23018
+ function r_(e, t) {
22981
23019
  let n = (t || "").trim();
22982
23020
  return n ? !!(/\b(let'?s|let us)\s+(end|stop|finish|wrap up|close)\s+(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\bend\s+(this\s+)?(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\b(hang\s+up|disconnect)\b/i.test(n) || /\b(that'?s all|we'?re done)\b/i.test(n) || e === "bot" && (/\b(I'?ll|I will|Let me|I can|I'?m going to)\s+(end|close)\s+(the\s+)?(voice\s+)?(session|call)\b/i.test(n) || /\b(ending|closing)\s+(the\s+)?(voice\s+)?session\b|\bvoice\s+session\s+(is\s+)?(now\s+)?(ended|over|closing)\b/i.test(n) || /\b(session|call)\s+(is\s+)?(now\s+)?(ended|over)\b/i.test(n) || /\bwe\s+can\s+end\s+(the\s+)?(session|call)?\s*(here|now)\b/i.test(n) || /\b(wrapping\s+up|signing\s+off)\b/i.test(n)) || /^(goodbye|bye|that'?s all|we'?re done|hang up|disconnect)\b/i.test(n)) : !1;
22983
23021
  }
22984
- function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
23022
+ function i_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
22985
23023
  let [h, g] = s("idle"), [ee, te] = s(null), [_, ne] = s(!1), re = o(null), ie = o(null), ae = o(""), oe = o(async () => {}), se = o(!1), v = n(async () => {
22986
23024
  try {
22987
23025
  await re.current?.endSession?.();
@@ -22998,7 +23036,7 @@ function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22998
23036
  try {
22999
23037
  if (await navigator.mediaDevices.getUserMedia({ audio: !0 }), t) return;
23000
23038
  d.current = [], ae.current = "", se.current = !1;
23001
- let i = Qg(Zg({
23039
+ let i = e_($g({
23002
23040
  siteId: r || null,
23003
23041
  apiBaseUrl: a || null,
23004
23042
  getLastUserVoiceText: () => ae.current,
@@ -23025,7 +23063,7 @@ function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23025
23063
  message: r,
23026
23064
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
23027
23065
  };
23028
- n === "user" && (ae.current = r), d.current = [...d.current, i], t_(n, r) && queueMicrotask(() => {
23066
+ n === "user" && (ae.current = r), d.current = [...d.current, i], r_(n, r) && queueMicrotask(() => {
23029
23067
  se.current || (se.current = !0, oe.current?.());
23030
23068
  });
23031
23069
  },
@@ -23048,7 +23086,7 @@ function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23048
23086
  } catch {
23049
23087
  t = "[]";
23050
23088
  }
23051
- o.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}. Navigation: when the user wants to go to any page (contact, pricing, about, services, etc.), call search_site_content then navigate_to_page immediately — never ask permission. After navigating to a page with a form, call list_page_forms and proactively start helping the user fill it. Forms: use fill_form_fields then click_page_button (e.g. Conduct Audit, Send Message) when the user wants to submit. Fill each field immediately after the user answers — never skip ahead. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end.`);
23089
+ o.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}. Navigation: when the user wants to go to any page (contact, pricing, about, services, etc.), call search_site_content then navigate_to_page immediately — never ask permission. After navigating to a page with a form, call list_page_forms and proactively start helping the user fill it. Contact / lead forms: use only the main contact form (Full Name, Email, Message). Ignore footer “Conduct Audit” or marketing URL fields unless the user explicitly asks to run a website audit. Fill in order: name → email → message. Message must be a short visitor note (what they want from the team), not a transcript of the conversation. Forms: use fill_form_fields then click_page_button (e.g. Send Message) when appropriate. Fill each field right after the user gives that value — do not click submit until required fields are filled. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end.`);
23052
23090
  } catch {}
23053
23091
  typeof m == "function" && m();
23054
23092
  } catch (e) {
@@ -23064,7 +23102,7 @@ function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23064
23102
  d,
23065
23103
  m
23066
23104
  ]);
23067
- let ce = h === "listening" || h === "speaking", le = e_[h] || e_.idle, ue = $g[h] || $g.idle;
23105
+ let ce = h === "listening" || h === "speaking", le = n_[h] || n_.idle, ue = t_[h] || t_.idle;
23068
23106
  return /* @__PURE__ */ u("div", {
23069
23107
  ref: ie,
23070
23108
  style: {
@@ -23170,7 +23208,7 @@ function n_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23170
23208
  }
23171
23209
  //#endregion
23172
23210
  //#region src/components/FlowEngageWidget.jsx
23173
- var r_ = [
23211
+ var a_ = [
23174
23212
  {
23175
23213
  key: "become_client",
23176
23214
  label: "Become a Client"
@@ -23191,7 +23229,7 @@ var r_ = [
23191
23229
  key: "looking_for_job",
23192
23230
  label: "Looking for a Job"
23193
23231
  }
23194
- ], i_ = () => /* @__PURE__ */ l("div", {
23232
+ ], o_ = () => /* @__PURE__ */ l("div", {
23195
23233
  style: {
23196
23234
  display: "flex",
23197
23235
  marginBottom: "12px",
@@ -23222,7 +23260,7 @@ var r_ = [
23222
23260
  } }, e)), /* @__PURE__ */ l("style", { children: "\n @keyframes fe-dot-bounce {\n 0%, 80%, 100% { transform: translateY(0); opacity: 0.5; }\n 40% { transform: translateY(-5px); opacity: 1; }\n }\n " })]
23223
23261
  })
23224
23262
  });
23225
- function a_() {
23263
+ function s_() {
23226
23264
  let { status: e, runtimeConfig: t, resolvedConfig: n, chatId: r, chatHistory: o, isOpen: c, activeScreen: d, isHumanHandled: f, agentName: p, agentHeadshot: m, visitorEmail: h, isAgentTyping: g, isAiTyping: ee, isLoading: te, isVoiceMode: _, isRateLimited: ne, rateLimitMessage: re, isConversationEnded: ie, incomingCall: ae, activeCallId: oe, callConnectionState: se, callConnectedAt: v, isCallMuted: ce, webRTCError: le, language: ue, historyRef: y, onMessageSync: b, endConversation: de, acceptCall: fe, rejectCall: pe, endWebRTCCall: me, toggleCallMute: he, dismissCallError: ge, captureVisitorEmail: _e, openWidget: ve, closeWidget: ye, sendMessage: be, setVoiceMode: xe, startTyping: Se, stopTyping: Ce, updateTypingDraft: we } = Xt(), [Te, Ee] = s(""), [De, Oe] = s(null), [ke, Ae] = s(null), [je, Me] = s(null), [Ne, Pe] = s(0), [x, Fe] = s(h || ""), [Ie, Le] = s("");
23227
23265
  i(() => {
23228
23266
  try {
@@ -23250,7 +23288,7 @@ function a_() {
23250
23288
  outline: "none",
23251
23289
  fontFamily: "ui-sans-serif, system-ui, sans-serif",
23252
23290
  ...c ? {} : Ue
23253
- }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || r_, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23291
+ }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || a_, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23254
23292
  let e = o.findIndex((e) => e.sender === "user");
23255
23293
  return e === -1 ? !1 : o.slice(e + 1).some((e) => e.sender === "bot" || e.sender === "ai" || e.sender === "agent");
23256
23294
  }, [o]), rt = !h && tt && nt;
@@ -23378,7 +23416,7 @@ function a_() {
23378
23416
  flexDirection: "column"
23379
23417
  },
23380
23418
  className: "fe-screen-fade-in",
23381
- children: /* @__PURE__ */ l(n_, {
23419
+ children: /* @__PURE__ */ l(i_, {
23382
23420
  agentId: T,
23383
23421
  chatId: r,
23384
23422
  siteId: Ye,
@@ -23411,7 +23449,7 @@ function a_() {
23411
23449
  isAiTyping: ee,
23412
23450
  isAgentTyping: g,
23413
23451
  setReplyContext: Me,
23414
- TypingDots: i_,
23452
+ TypingDots: o_,
23415
23453
  primaryColor: Ve,
23416
23454
  agentHeadshot: $e,
23417
23455
  agentDisplayName: p || Ze
@@ -23490,4 +23528,4 @@ function a_() {
23490
23528
  }) : null;
23491
23529
  }
23492
23530
  //#endregion
23493
- export { vn as FlowEngageProvider, a_ as FlowEngageWidget, Xt as useFlowEngage };
23531
+ export { vn as FlowEngageProvider, s_ as FlowEngageWidget, Xt as useFlowEngage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Embeddable AI chat widget for React — powered by FlowEngage. Drop it in with a single siteId.",
5
5
  "keywords": [
6
6
  "chatbot",