@flowengage/react-chatbot 8.0.17 → 8.0.18

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.
@@ -28894,14 +28894,28 @@ function HO(e) {
28894
28894
  function $(...e) {
28895
28895
  Ln() && console.log("[FlowEngage:voice-tools]", ...e);
28896
28896
  }
28897
- function UO(e) {
28897
+ function UO() {
28898
+ if (typeof document > "u") return !1;
28899
+ let e = /(^|\W)(404|page not found|not found|page (?:doesn'?t|does not) exist|no longer exists|couldn'?t find (?:this|that|the) page|error 404|oops[!,. ].*(?:not found|doesn'?t exist))(\W|$)/i, t = (document.title || "").trim();
28900
+ if (t && e.test(t)) return !0;
28901
+ let n = document.querySelector("main, [role=\"main\"], #content, .content") || document.body;
28902
+ if (n) {
28903
+ let t = n.querySelectorAll("h1, h2");
28904
+ for (let n of t) {
28905
+ let t = (n.textContent || "").replace(/\s+/g, " ").trim();
28906
+ if (t && t.length < 80 && e.test(t)) return !0;
28907
+ }
28908
+ }
28909
+ return !1;
28910
+ }
28911
+ function WO(e) {
28898
28912
  try {
28899
28913
  let t = e.ownerDocument?.defaultView;
28900
28914
  if (t) return t.getComputedStyle(e);
28901
28915
  } catch {}
28902
28916
  return window.getComputedStyle(e);
28903
28917
  }
28904
- function WO(e) {
28918
+ function GO(e) {
28905
28919
  let t = /* @__PURE__ */ new Set();
28906
28920
  function n(r) {
28907
28921
  if (!r || t.has(r)) return;
@@ -28914,10 +28928,10 @@ function WO(e) {
28914
28928
  }
28915
28929
  typeof document < "u" && n(document);
28916
28930
  }
28917
- function GO(e) {
28931
+ function KO(e) {
28918
28932
  return e == null ? null : String(e).replace(/\u00a0/g, " ").replace(/\s*\*+\s*$/u, "").replace(/\s+/g, " ").trim();
28919
28933
  }
28920
- function KO(e) {
28934
+ function qO(e) {
28921
28935
  let t = e.ownerDocument || document, n = e.getAttribute("aria-labelledby");
28922
28936
  if (n) {
28923
28937
  let e = n.trim().split(/\s+/).filter(Boolean), r = [];
@@ -28925,40 +28939,40 @@ function KO(e) {
28925
28939
  let e = t.getElementById(n);
28926
28940
  e?.textContent && r.push(e.textContent.trim());
28927
28941
  } catch {}
28928
- if (r.length) return GO(r.join(" "));
28942
+ if (r.length) return KO(r.join(" "));
28929
28943
  }
28930
- if (e.labels && e.labels.length) return GO(e.labels[0].textContent);
28944
+ if (e.labels && e.labels.length) return KO(e.labels[0].textContent);
28931
28945
  let r = e.id;
28932
28946
  if (r) try {
28933
28947
  let e = t.querySelector(`label[for="${CSS.escape(r)}"]`);
28934
- if (e) return GO(e.textContent);
28948
+ if (e) return KO(e.textContent);
28935
28949
  } catch {
28936
28950
  let e = t.querySelector(`label[for="${r.replace(/"/g, "\\\"")}"]`);
28937
- if (e) return GO(e.textContent);
28951
+ if (e) return KO(e.textContent);
28938
28952
  }
28939
28953
  let i = e.previousElementSibling;
28940
28954
  for (let e = 0; e < 6 && i; e += 1) {
28941
- if (i.tagName === "LABEL") return GO(i.textContent);
28955
+ if (i.tagName === "LABEL") return KO(i.textContent);
28942
28956
  let e = (i.className || "").toString().toLowerCase();
28943
28957
  if (/chakra-form__label|formlabel|field-label|form-label|mui-form-label/.test(e)) {
28944
- let e = GO(i.textContent);
28958
+ let e = KO(i.textContent);
28945
28959
  if (e) return e;
28946
28960
  }
28947
28961
  i = i.previousElementSibling;
28948
28962
  }
28949
28963
  let a = e.parentElement;
28950
28964
  for (let e = 0; e < 5 && a; e += 1) {
28951
- if (a.tagName === "LABEL") return GO(a.textContent);
28965
+ if (a.tagName === "LABEL") return KO(a.textContent);
28952
28966
  let e = a.querySelector?.(":scope > label, :scope > [class*='FormLabel'], :scope > [class*='form__label']");
28953
- if (e?.textContent) return GO(e.textContent);
28967
+ if (e?.textContent) return KO(e.textContent);
28954
28968
  a = a.parentElement;
28955
28969
  }
28956
28970
  let o = e.getAttribute("aria-label");
28957
- return o ? GO(o) : null;
28971
+ return o ? KO(o) : null;
28958
28972
  }
28959
- function qO() {
28973
+ function JO() {
28960
28974
  let e = [];
28961
- return WO((t) => {
28975
+ return GO((t) => {
28962
28976
  e.push(...Array.from(t.querySelectorAll("input, select, textarea")).filter((e) => {
28963
28977
  if (Un(e)) return !1;
28964
28978
  let t = (e.type || "").toLowerCase();
@@ -28969,15 +28983,15 @@ function qO() {
28969
28983
  "image"
28970
28984
  ].includes(t) || e.disabled || e.readOnly) return !1;
28971
28985
  try {
28972
- let t = UO(e);
28986
+ let t = WO(e);
28973
28987
  if (t.display === "none" || t.visibility === "hidden") return !1;
28974
28988
  } catch {}
28975
28989
  return !0;
28976
28990
  }));
28977
28991
  }), e;
28978
28992
  }
28979
- function JO() {
28980
- return qO().map((e, t) => {
28993
+ function YO() {
28994
+ return JO().map((e, t) => {
28981
28995
  let n = {
28982
28996
  formIndex: 0,
28983
28997
  fieldIndex: t,
@@ -28985,7 +28999,7 @@ function JO() {
28985
28999
  type: e.type || "text",
28986
29000
  name: e.name || null,
28987
29001
  id: e.id || null,
28988
- label: KO(e),
29002
+ label: qO(e),
28989
29003
  placeholder: e.placeholder || null
28990
29004
  };
28991
29005
  return e.tagName === "SELECT" && (n.options = Array.from(e.options).filter((e) => e.value !== "" && !e.disabled).map((e) => ({
@@ -28994,13 +29008,13 @@ function JO() {
28994
29008
  })), n.currentValue = e.value || null), n;
28995
29009
  });
28996
29010
  }
28997
- function YO() {
29011
+ function XO() {
28998
29012
  let e = [];
28999
- return WO((t) => {
29013
+ return GO((t) => {
29000
29014
  e.push(...Array.from(t.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"]")).filter((e) => {
29001
29015
  if (Un(e) || e.disabled) return !1;
29002
29016
  try {
29003
- let t = UO(e);
29017
+ let t = WO(e);
29004
29018
  if (t.display === "none" || t.visibility === "hidden") return !1;
29005
29019
  } catch {}
29006
29020
  return !0;
@@ -29012,7 +29026,7 @@ function YO() {
29012
29026
  type: e.type || e.tagName
29013
29027
  }));
29014
29028
  }
29015
- function XO(e, t) {
29029
+ function ZO(e, t) {
29016
29030
  try {
29017
29031
  if (!e?.getBoundingClientRect || !t?.getBoundingClientRect) return Infinity;
29018
29032
  let n = e.getBoundingClientRect(), r = t.getBoundingClientRect(), i = {
@@ -29027,7 +29041,7 @@ function XO(e, t) {
29027
29041
  return Infinity;
29028
29042
  }
29029
29043
  }
29030
- function ZO(e, t) {
29044
+ function QO(e, t) {
29031
29045
  let n = String(t || "").toLowerCase().trim();
29032
29046
  if (!n) return 0;
29033
29047
  let r = (e.innerText || e.textContent || "").replace(/\s+/g, " ").trim(), i = [
@@ -29045,14 +29059,14 @@ function ZO(e, t) {
29045
29059
  for (let e of a) i.includes(e) && (o += 1);
29046
29060
  return o / a.length * 92;
29047
29061
  }
29048
- function QO(e, t) {
29062
+ function $O(e, t) {
29049
29063
  let n = [];
29050
- WO((e) => {
29064
+ GO((e) => {
29051
29065
  let t = Array.from(e.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"], a[href]"));
29052
29066
  n.push(...t.filter((e) => {
29053
29067
  if (Un(e) || e.disabled) return !1;
29054
29068
  try {
29055
- let t = UO(e);
29069
+ let t = WO(e);
29056
29070
  if (t.display === "none" || t.visibility === "hidden" || t.opacity === "0") return !1;
29057
29071
  } catch {}
29058
29072
  return !0;
@@ -29060,7 +29074,7 @@ function QO(e, t) {
29060
29074
  });
29061
29075
  let r = 0, i = n.map((t) => ({
29062
29076
  el: t,
29063
- s: ZO(t, e)
29077
+ s: QO(t, e)
29064
29078
  }));
29065
29079
  for (let { s: e } of i) e > r && (r = e);
29066
29080
  if (r < 28) return null;
@@ -29070,14 +29084,14 @@ function QO(e, t) {
29070
29084
  if (o.length) {
29071
29085
  let e = a[0], t = Infinity;
29072
29086
  for (let n of a) for (let r of o) {
29073
- let i = XO(n, r);
29087
+ let i = ZO(n, r);
29074
29088
  i < t && (t = i, e = n);
29075
29089
  }
29076
29090
  return e;
29077
29091
  }
29078
29092
  return a[0];
29079
29093
  }
29080
- function $O(e) {
29094
+ function ek(e) {
29081
29095
  if (e == null) return {};
29082
29096
  if (typeof e == "string") {
29083
29097
  let t = e.trim();
@@ -29090,12 +29104,12 @@ function $O(e) {
29090
29104
  }
29091
29105
  return e;
29092
29106
  }
29093
- function ek(e) {
29107
+ function tk(e) {
29094
29108
  if (!e || typeof e != "object") return null;
29095
29109
  let t = e.url ?? e.target_url ?? e.page_url ?? e.pageUrl ?? e.link ?? e.href ?? e.path;
29096
29110
  return t == null ? null : String(t).trim() || null;
29097
29111
  }
29098
- function tk() {
29112
+ function nk() {
29099
29113
  let e = {};
29100
29114
  document.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach((t) => {
29101
29115
  if (t.id) return;
@@ -29110,7 +29124,7 @@ function tk() {
29110
29124
  e[r] = !0, t.id = r;
29111
29125
  });
29112
29126
  }
29113
- function nk() {
29127
+ function rk() {
29114
29128
  let e = (e) => {
29115
29129
  let t = Array.from(e).filter((e) => !e.closest("#flowengage-root, .flowengage-shell, .flowengage-widget-root") && !e.closest("nav, footer, header, aside, .nav, .footer, .header, .sidebar")), n = [], r = 0;
29116
29130
  for (; r < t.length;) {
@@ -29132,7 +29146,7 @@ function nk() {
29132
29146
  let n = [...new Set(t)], r = ((typeof document < "u" ? document.title : "") || "").replace(/\s*[-–—|·]\s*.+$/, "").trim().toLowerCase();
29133
29147
  return (r ? n.filter((e) => e.toLowerCase().trim() !== r) : n).slice(0, 15);
29134
29148
  }
29135
- function rk(e) {
29149
+ function ik(e) {
29136
29150
  if (!e || typeof document > "u") return "";
29137
29151
  let t = new Set([
29138
29152
  "script",
@@ -29203,11 +29217,11 @@ function rk(e) {
29203
29217
  return d.has(t) ? !1 : (d.add(t), !0);
29204
29218
  }).join("\n").replace(/\n{3,}/g, "\n\n").trim();
29205
29219
  }
29206
- function ik(e) {
29220
+ function ak(e) {
29207
29221
  let t = e.siteId || null, n = (e.apiBaseUrl || "").replace(/\/$/, ""), r = typeof e.getLastUserVoiceText == "function" ? e.getLastUserVoiceText : null, i = [], a = {
29208
29222
  "fwh-navigate-mvp": async (n) => {
29209
29223
  $("fwh-navigate-mvp ▶ raw parameters:", n);
29210
- let i = $O(n), a = ek(i);
29224
+ let i = ek(n), a = tk(i);
29211
29225
  if ($("fwh-navigate-mvp · coerced:", {
29212
29226
  url: a,
29213
29227
  sectionText: i.section_text ?? i.sectionText ?? i.section,
@@ -29273,8 +29287,8 @@ function ik(e) {
29273
29287
  typeof window < "u" && window.scrollTo(0, 0);
29274
29288
  } catch {}
29275
29289
  let s = [], c = Date.now() + 12e3;
29276
- for (; Date.now() < c && (await new Promise((e) => setTimeout(e, 300)), s = nk(), !(s.length >= 1)););
29277
- tk(), $("fwh-navigate-mvp → page headings collected:", s);
29290
+ for (; Date.now() < c && (await new Promise((e) => setTimeout(e, 300)), s = rk(), !(s.length >= 1)););
29291
+ nk(), $("fwh-navigate-mvp → page headings collected:", s);
29278
29292
  let l = s.length ? s.join(" | ") : "none", u = s.length ? "Use ONLY these exact heading strings for fwh-highlight-mvp — never invent or abbreviate." : "No headings collected yet — call fwh-get-current-page-mvp immediately (no speech) to get the live headings before speaking or highlighting.", d = "";
29279
29293
  try {
29280
29294
  if (s.length > 0) {
@@ -29282,14 +29296,14 @@ function ik(e) {
29282
29296
  for (let n of e) {
29283
29297
  let e = Sr(null, n);
29284
29298
  if (e) {
29285
- let r = rk(e).substring(0, 800);
29299
+ let r = ik(e).substring(0, 800);
29286
29300
  r && t.push(`[Section: ${n}] ${r}`);
29287
29301
  }
29288
29302
  }
29289
29303
  t.length > 0 && (d = ` CONTENT FOR FIRST FEW SECTIONS: ${t.join(" | ")}. Use this content to answer immediately if the visitor asks about one of these sections.`);
29290
29304
  }
29291
29305
  } catch {}
29292
- return i ? (jr(), `OK_NAVIGATE_SPA. Visitor is now on: ${r} (page: "${o}") | Section headings: ${l}. ${u}${d} Speak EXACTLY: "I have navigated you on ${o} page. Do you want to know about any specific section or want a complete overview?" Then STOP — wait for their reply.`) : (jr(), `OK_NAVIGATE_SPA. CURRENT PAGE IS: ${r} (page: "${o}") | Section headings: ${l}. ${u}${d} Speak EXACTLY: "I have navigated you on ${o} page. Do you want to know about any specific section or want a complete overview?" Then STOP — wait for their reply.`);
29306
+ return UO() ? (jr(), $("fwh-navigate-mvp ✖ landed on a not-found/404 page:", r), `NAVIGATION_PAGE_NOT_FOUND. The page at ${r} does not exist — it shows a "not found"/404 error, not real content. Do NOT offer a page overview, do NOT describe or highlight any sections, do NOT claim the navigation succeeded. Tell the visitor EXACTLY: "It looks like that page doesn't exist — I couldn't find it. Would you like me to take you somewhere else?" Then STOP and wait for their reply.`) : i ? (jr(), `OK_NAVIGATE_SPA. Visitor is now on: ${r} (page: "${o}") | Section headings: ${l}. ${u}${d} Speak EXACTLY: "I have navigated you on ${o} page. Do you want to know about any specific section or want a complete overview?" Then STOP — wait for their reply.`) : (jr(), `OK_NAVIGATE_SPA. CURRENT PAGE IS: ${r} (page: "${o}") | Section headings: ${l}. ${u}${d} Speak EXACTLY: "I have navigated you on ${o} page. Do you want to know about any specific section or want a complete overview?" Then STOP — wait for their reply.`);
29293
29307
  } catch {}
29294
29308
  let o = "this";
29295
29309
  try {
@@ -29310,34 +29324,34 @@ function ik(e) {
29310
29324
  },
29311
29325
  "fwh-highlight-mvp": async (e) => {
29312
29326
  $("fwh-highlight-mvp ▶", e);
29313
- let t = $O(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText;
29327
+ let t = ek(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText;
29314
29328
  if (typeof window < "u" && window.__fe_user_nav_during_speech) {
29315
29329
  let e = window.__fe_user_nav_during_speech, t = window.location.pathname;
29316
29330
  if (Date.now() - e.ts >= 3e4) window.__fe_user_nav_during_speech = null;
29317
29331
  else return $("flowengage_highlight ✖ blocked — user navigated during speech", e), `NAV_CHANGED: The visitor navigated from "${e.fromPageName}" to "${e.toPageName}" (current path: ${t}) while you were speaking. STOP the current walkthrough immediately. DO NOT call flowengage_highlight again. Say out loud: "I see you've navigated to the ${e.toPageName} page — do you want me to continue what I was explaining, or shall I guide you through this page?" Wait for the visitor's answer before doing anything else.`;
29318
29332
  }
29319
- tk();
29333
+ nk();
29320
29334
  let i = ((e) => e && e.replace(/^\d+\.\s*/, "").replace(/^["']|["']$/g, "").trim())(r), a = Sr(n || null, i || null);
29321
29335
  if (!a && i) {
29322
29336
  let e = Date.now() + 600;
29323
- for (; !a && Date.now() < e;) await new Promise((e) => setTimeout(e, 50)), tk(), a = Sr(null, i);
29337
+ for (; !a && Date.now() < e;) await new Promise((e) => setTimeout(e, 50)), nk(), a = Sr(null, i);
29324
29338
  }
29325
29339
  if (!a) {
29326
29340
  $("fwh-highlight-mvp ✖ no element for:", i || n);
29327
- let e = nk(), t = e.length ? `Page headings: ${e.map((e) => `"${e}"`).join(" | ")}. Use one of these EXACT strings for section_text — no numbers, no quotes around them.` : "No headings found — skip highlight and continue speaking.";
29341
+ let e = rk(), t = e.length ? `Page headings: ${e.map((e) => `"${e}"`).join(" | ")}. Use one of these EXACT strings for section_text — no numbers, no quotes around them.` : "No headings found — skip highlight and continue speaking.";
29328
29342
  return `HIGHLIGHT_NOT_FOUND: "${i || n}" on the current page. ${t}`;
29329
29343
  }
29330
29344
  return Bn(a), $("fwh-highlight-mvp ✓", i || n), `OK_HIGHLIGHT: "${i || n}". WALKTHROUGH: continue immediately to the next section — do NOT pause between sections.`;
29331
29345
  },
29332
29346
  "fwh-read-content-mvp": async (e) => {
29333
29347
  $("fwh-read-content-mvp ▶", e);
29334
- let t = $O(e), n = t?.section_text || t?.sectionText || "";
29348
+ let t = ek(e), n = t?.section_text || t?.sectionText || "";
29335
29349
  try {
29336
29350
  let e = "";
29337
29351
  if (n) {
29338
29352
  let t = Sr(null, n);
29339
29353
  if (!t) return `Could not find section "${n}" on the page.`;
29340
- e = rk(t);
29354
+ e = ik(t);
29341
29355
  } else {
29342
29356
  let t = (document.querySelector("main") || document.querySelector("article") || document.querySelector("[role=\"main\"]") || document.querySelector("#content") || document.querySelector(".content") || document.body).cloneNode(!0);
29343
29357
  t.querySelectorAll("nav, footer, header, aside, script, style, noscript, .nav, .footer, .header, .sidebar, #flowengage-root, .flowengage-shell, .flowengage-widget-root").forEach((e) => e.remove()), e = t.textContent.replace(/\s+/g, " ").trim();
@@ -29349,7 +29363,7 @@ function ik(e) {
29349
29363
  },
29350
29364
  "fwh-page-content-mvp": async (e) => {
29351
29365
  $("fwh-page-content-mvp ▶", e);
29352
- let r = $O(e), i = r?.url || r?.page_url || "";
29366
+ let r = ek(e), i = r?.url || r?.page_url || "";
29353
29367
  if ($("fwh-page-content-mvp · url:", i, "siteId:", t, "apiBase:", n || "(empty)"), !i) return $("fwh-page-content-mvp ✖ missing url"), "Missing url parameter.";
29354
29368
  if (!t) return $("fwh-page-content-mvp ✖ no siteId"), "Site is not configured.";
29355
29369
  if (!n) return $("fwh-page-content-mvp ✖ no api base"), "API base URL is missing; cannot fetch page content.";
@@ -29381,7 +29395,7 @@ function ik(e) {
29381
29395
  },
29382
29396
  "fwh-search-mvp": async (e) => {
29383
29397
  $("fwh-search-mvp ▶", e);
29384
- let r = $O(e).query;
29398
+ let r = ek(e).query;
29385
29399
  if (!r) return $("fwh-search-mvp ✖ missing query"), "Missing query parameter.";
29386
29400
  if (!t) return $("fwh-search-mvp ✖ no siteId"), "Search unavailable (no siteId configured).";
29387
29401
  if (!n) return $("fwh-search-mvp ✖ no api base"), "Search unavailable (no API base URL).";
@@ -29419,7 +29433,7 @@ function ik(e) {
29419
29433
  "[class*='menu'] a",
29420
29434
  "[class*='header'] a"
29421
29435
  ];
29422
- if (WO((t) => {
29436
+ if (GO((t) => {
29423
29437
  for (let r of n) try {
29424
29438
  t.querySelectorAll(r).forEach((t) => {
29425
29439
  if (Un(t)) return;
@@ -29427,7 +29441,7 @@ function ik(e) {
29427
29441
  if (!r || !n || n === "#" || n.startsWith("javascript:")) return;
29428
29442
  try {
29429
29443
  let e = t.parentElement;
29430
- if (e && UO(e).display === "none" && !e.closest("nav, [role='navigation'], header, [class*='nav'], [class*='menu']")) return;
29444
+ if (e && WO(e).display === "none" && !e.closest("nav, [role='navigation'], header, [class*='nav'], [class*='menu']")) return;
29431
29445
  } catch {}
29432
29446
  let i = r.toLowerCase() + "|" + n;
29433
29447
  e.has(i) || e.set(i, {
@@ -29438,7 +29452,7 @@ function ik(e) {
29438
29452
  } catch {}
29439
29453
  t.querySelectorAll("select").forEach((t) => {
29440
29454
  if (Un(t)) return;
29441
- let n = KO(t);
29455
+ let n = qO(t);
29442
29456
  /nav|menu|page|section|go to/i.test(n || t.name || t.id || "") && Array.from(t.options).forEach((r) => {
29443
29457
  if (!r.value || r.disabled) return;
29444
29458
  let i = r.text.trim();
@@ -29460,7 +29474,7 @@ function ik(e) {
29460
29474
  "fwh-request-email-mvp": async () => ($("fwh-request-email-mvp ▶"), typeof e.requestEmailCollection == "function" && e.requestEmailCollection(), "EMAIL_BOX_SHOWN. An email input text box is now visible to the visitor. Say EXACTLY: \"Please enter your email in the text box to continue.\" Then stop and wait silently — do NOT ask them to say it aloud, do NOT repeat, and do NOT answer any other question until you receive the EMAIL_SAVED message."),
29461
29475
  "fwh-get-current-page-mvp": async () => {
29462
29476
  if ($("fwh-get-current-page-mvp ▶"), typeof window > "u") return "Cannot determine current page (no browser context).";
29463
- let e = window.location.href, t = window.location.pathname, n = document.title || "", r = nk();
29477
+ let e = window.location.href, t = window.location.pathname, n = document.title || "", r = rk();
29464
29478
  if ($("fwh-get-current-page-mvp ✓", {
29465
29479
  url: e,
29466
29480
  path: t,
@@ -29470,7 +29484,7 @@ function ik(e) {
29470
29484
  return `CURRENT_PAGE. URL: ${e} | Title: ${n} | Page sections (${r.length} total): ${i}. *** WALKTHROUGH RULES: (1) For fwh-highlight-mvp, pass the heading text EXACTLY as shown — no numbers, no extra punctuation, no paraphrasing. (2) TIMING IS CRITICAL: the tool fires AFTER the speech that comes before it. This means: put the SHORT TRANSITION (1-5 words) BEFORE the tool call, put the FULL DESCRIPTION AFTER the tool call. Pattern: "Transition phrase." + fwh-highlight-mvp("Heading") + "Full description (3-4 sentences)". NEVER describe a section before calling its highlight tool. (3) DO NOT call this tool again. If the visitor requested a walkthrough: START IT NOW — "Let me walk you through this." + fwh-highlight-mvp("${r[0] || "first heading"}") + "Description..." etc. Cover ALL ${r.length} sections without pausing. ***`;
29471
29485
  },
29472
29486
  "fwh-list-forms-mvp": async () => {
29473
- let e = JO(), t = YO();
29487
+ let e = YO(), t = XO();
29474
29488
  $("fwh-list-forms-mvp ✓", `${e.length} field(s)`, `${t.length} button(s)`);
29475
29489
  let n = e.map((e) => ({
29476
29490
  ...e,
@@ -29484,9 +29498,9 @@ function ik(e) {
29484
29498
  },
29485
29499
  "fwh-fill-form-mvp": async () => "FORM_FILLING_DISABLED: Form filling is not available at this time. Tell the visitor what fields are present (use fwh-list-forms-mvp) and ask them to fill the form themselves.",
29486
29500
  "fwh-click-button-mvp": async (e) => {
29487
- let t = $O(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
29501
+ let t = ek(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
29488
29502
  if ($("fwh-click-button-mvp ▶", n), !n) return "Missing button_text: pass the visible label, e.g. Conduct Audit.";
29489
- let r = QO(n, i);
29503
+ let r = $O(n, i);
29490
29504
  if (!r) return $("fwh-click-button-mvp ✖ no match"), `Could not find a button matching "${n}". Call fwh-list-forms-mvp to see button texts.`;
29491
29505
  try {
29492
29506
  DO(`Clicking ${n}...`, { spinner: !0 });
@@ -29529,7 +29543,7 @@ function ik(e) {
29529
29543
  }
29530
29544
  //#endregion
29531
29545
  //#region src/utils/wrapVoiceToolsForLogging.js
29532
- function ak(e) {
29546
+ function ok(e) {
29533
29547
  return !e || typeof e != "object" ? e : Object.fromEntries(Object.entries(e).map(([e, t]) => [e, async (n) => {
29534
29548
  let r = Ln();
29535
29549
  r ? console.log("[FlowEngage:voice-tool] ▶", e, n) : console.info(`[FlowEngage] voice tool » ${e}`);
@@ -29546,7 +29560,7 @@ function ak(e) {
29546
29560
  }
29547
29561
  //#endregion
29548
29562
  //#region src/components/FlowEngageWidget.jsx
29549
- var ok = {
29563
+ var sk = {
29550
29564
  blue: "#135bd8",
29551
29565
  red: "#ef334b",
29552
29566
  yellow: "#ffbd2e",
@@ -29554,7 +29568,7 @@ var ok = {
29554
29568
  highlight: "rgba(255,255,255,0.9)",
29555
29569
  green: "#10b981"
29556
29570
  };
29557
- function sk(e) {
29571
+ function ck(e) {
29558
29572
  if (!Array.isArray(e) || e.length < 2) return "linear-gradient(145deg, #dce8f022 0%, #e8dff522 45%, #f5e0e022 100%), #f7f8fa";
29559
29573
  let [t, n, r] = e;
29560
29574
  return e.length >= 3 && r ? [
@@ -29568,12 +29582,12 @@ function sk(e) {
29568
29582
  "#f7f8fa"
29569
29583
  ].join(", ");
29570
29584
  }
29571
- function ck(e) {
29585
+ function lk(e) {
29572
29586
  if (!e || typeof e != "string") return "#1a1a1a";
29573
29587
  let t = e.replace("#", ""), n = t.length === 3 ? t.split("").map((e) => e + e).join("") : t, r = parseInt(n.slice(0, 2), 16) / 255, i = parseInt(n.slice(2, 4), 16) / 255, a = parseInt(n.slice(4, 6), 16) / 255, o = (e) => e <= .04045 ? e / 12.92 : ((e + .055) / 1.055) ** 2.4;
29574
29588
  return .2126 * o(r) + .7152 * o(i) + .0722 * o(a) > .179 ? "#1a1a1a" : "#ffffff";
29575
29589
  }
29576
- function lk(t) {
29590
+ function uk(t) {
29577
29591
  let [n, r] = e.useState(null), i = typeof t == "string" ? t.trim() : "";
29578
29592
  return e.useEffect(() => {
29579
29593
  if (!i) {
@@ -29591,8 +29605,8 @@ function lk(t) {
29591
29605
  };
29592
29606
  }, [i]), n;
29593
29607
  }
29594
- function uk({ logo: t, style: n }) {
29595
- let r = lk(typeof t == "string" ? t : null);
29608
+ function dk({ logo: t, style: n }) {
29609
+ let r = uk(typeof t == "string" ? t : null);
29596
29610
  if (!t) return null;
29597
29611
  if (typeof t == "string") return r ? /* @__PURE__ */ g("img", {
29598
29612
  src: r,
@@ -29617,7 +29631,7 @@ function uk({ logo: t, style: n }) {
29617
29631
  children: i
29618
29632
  }) : null;
29619
29633
  }
29620
- function dk({ title: e }) {
29634
+ function fk({ title: e }) {
29621
29635
  return /* @__PURE__ */ g("div", {
29622
29636
  style: {
29623
29637
  width: "100%",
@@ -29635,18 +29649,18 @@ function dk({ title: e }) {
29635
29649
  children: String(e || "FE").split(/\s+/).filter(Boolean).slice(0, 2).map((e) => e[0]?.toUpperCase() || "").join("") || "FE"
29636
29650
  });
29637
29651
  }
29638
- function fk(e, t) {
29652
+ function pk(e, t) {
29639
29653
  let n = (t || "").trim();
29640
29654
  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) || e === "bot" && (/\b(that'?s all|we'?re done)\b/i.test(n) || /\b(goodbye|bye)\b/i.test(n) || /\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))) : !1;
29641
29655
  }
29642
- function pk({ orbColors: e, ...t }) {
29656
+ function mk({ orbColors: e, ...t }) {
29643
29657
  return /* @__PURE__ */ g(pO, {
29644
29658
  colors: e,
29645
29659
  ...t
29646
29660
  });
29647
29661
  }
29648
- function mk({ copy: e, orbColors: t, primaryColor: n, onYes: r, onLater: i, isMobile: a, isClosing: o }) {
29649
- let s = n || ok.green, c = ck(s), l = a ? 72 : 94, u = /* @__PURE__ */ _("div", {
29662
+ function hk({ copy: e, orbColors: t, primaryColor: n, onYes: r, onLater: i, isMobile: a, isClosing: o }) {
29663
+ let s = n || sk.green, c = lk(s), l = a ? 72 : 94, u = /* @__PURE__ */ _("div", {
29650
29664
  style: {
29651
29665
  display: "flex",
29652
29666
  alignItems: a ? "flex-end" : "center",
@@ -29772,7 +29786,7 @@ function mk({ copy: e, orbColors: t, primaryColor: n, onYes: r, onLater: i, isMo
29772
29786
  delay: 0
29773
29787
  },
29774
29788
  style: { flexShrink: 0 },
29775
- children: /* @__PURE__ */ g(pk, {
29789
+ children: /* @__PURE__ */ g(mk, {
29776
29790
  size: l,
29777
29791
  orbColors: t
29778
29792
  })
@@ -29804,8 +29818,8 @@ function mk({ copy: e, orbColors: t, primaryColor: n, onYes: r, onLater: i, isMo
29804
29818
  children: u
29805
29819
  })] });
29806
29820
  }
29807
- function hk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onClose: a, isMobile: o, isClosing: s }) {
29808
- let c = n || ok.green, l = ck(c);
29821
+ function gk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onClose: a, isMobile: o, isClosing: s }) {
29822
+ let c = n || sk.green, l = lk(c);
29809
29823
  return /* @__PURE__ */ _(Fm.div, {
29810
29824
  initial: {
29811
29825
  scale: 50 / 350,
@@ -29876,7 +29890,7 @@ function hk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onC
29876
29890
  children: /* @__PURE__ */ g("polyline", { points: "6 9 12 15 18 9" })
29877
29891
  })
29878
29892
  }),
29879
- /* @__PURE__ */ g(pk, {
29893
+ /* @__PURE__ */ g(mk, {
29880
29894
  size: 72,
29881
29895
  orbColors: t
29882
29896
  }),
@@ -29945,7 +29959,7 @@ function hk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onC
29945
29959
  ]
29946
29960
  });
29947
29961
  }
29948
- function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i, apiBaseUrl: a, chatId: s, historyRef: l, onMessageSync: u, voiceEndCounter: d, websiteName: f, voiceFirstMessage: h, captureVisitorEmail: v, emailRequired: y }) {
29962
+ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i, apiBaseUrl: a, chatId: s, historyRef: l, onMessageSync: u, voiceEndCounter: d, websiteName: f, voiceFirstMessage: h, captureVisitorEmail: v, emailRequired: y }) {
29949
29963
  c(() => (console.log("[FlowEngage:VoiceDebug] 🔵 VoiceMode MOUNTED"), () => console.log("[FlowEngage:VoiceDebug] 🔴 VoiceMode UNMOUNTED")), []);
29950
29964
  let [b, x] = m("idle"), [S, C] = m(!1), [w, T] = m(!1), [ee, te] = m(!1), [ne, re] = m(""), [E, ie] = m(""), ae = p(!1), oe = p(!1), D = p(null), se = p(0), ce = p(""), le = p(null), ue = p(""), de = p(async () => {}), fe = p(!1), pe = p(!1), me = p(!1), he = p(!1), ge = p("minimized"), _e = p(null), ve = p(null), ye = p(null), be = p(0), xe = p(!1), Se = p("idle"), Ce = p(!1), we = p(!1), Te = p(null), Ee = p(null), De = p(!1), Oe = o((e = "minimized") => {
29951
29965
  console.warn("[FlowEngage:VoiceDebug] 🛑 requestSessionShutdown called", {
@@ -30044,7 +30058,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30044
30058
  }
30045
30059
  Ne();
30046
30060
  } });
30047
- let t = ak(ik({
30061
+ let t = ok(ak({
30048
30062
  siteId: i || null,
30049
30063
  apiBaseUrl: a || null,
30050
30064
  chatId: s || null,
@@ -30149,7 +30163,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30149
30163
  let e = SO(l.current);
30150
30164
  e && O(i, e);
30151
30165
  } catch {}
30152
- if (fk(n, r)) {
30166
+ if (pk(n, r)) {
30153
30167
  xe.current = !0;
30154
30168
  return;
30155
30169
  }
@@ -30446,7 +30460,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30446
30460
  },
30447
30461
  children: "Muted"
30448
30462
  }),
30449
- /* @__PURE__ */ g(pk, {
30463
+ /* @__PURE__ */ g(mk, {
30450
30464
  size: 72,
30451
30465
  voiceState: b,
30452
30466
  isMuted: S,
@@ -30670,7 +30684,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30670
30684
  ]
30671
30685
  });
30672
30686
  }
30673
- function _k({ orbColors: e }) {
30687
+ function vk({ orbColors: e }) {
30674
30688
  let t = Array.isArray(e) && e.length > 0 ? e : [
30675
30689
  "#135bd8",
30676
30690
  "#ef334b",
@@ -30689,7 +30703,7 @@ function _k({ orbColors: e }) {
30689
30703
  `.replace(/\s+/g, " ").trim()
30690
30704
  } });
30691
30705
  }
30692
- var vk = () => /* @__PURE__ */ g("div", {
30706
+ var yk = () => /* @__PURE__ */ g("div", {
30693
30707
  style: {
30694
30708
  display: "flex",
30695
30709
  marginBottom: "12px",
@@ -30719,7 +30733,7 @@ var vk = () => /* @__PURE__ */ g("div", {
30719
30733
  } }, e))
30720
30734
  })
30721
30735
  });
30722
- function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i, quickChatOptions: a, onQuickChatSelect: o, isMobile: s, chatHistory: l, isAiTyping: u, isAgentTyping: d, activeScreen: f, agentName: v, agentHeadshot: y, fallbackAgentName: b, input: x, setInput: S, onSubmit: C, isConversationEnded: w, isLoading: T, isRateLimited: ee, rateLimitMessage: te, selectedFile: ne, onFileSelect: re, onRemoveSelectedFile: E, attachmentError: ie, isUploadingAttachment: ae, requiresEmail: oe, emailInput: D, setEmailInput: se, emailError: ce, emailCaptureSuccess: le, replyContext: ue, setReplyContext: de, webRTCError: fe, micError: pe, setMicError: me, dismissCallError: he, activeCallId: ge, isCallMuted: _e, toggleCallMute: ve, endWebRTCCall: ye, formatCallDuration: be, callDurationSeconds: xe, isCallMinimized: Se, onExpand: Ce, onCollapse: we, onStartVoice: Te, voiceEnabled: Ee, headerBgColor: De, onNewChat: Oe, showPoweredBy: ke, privacyPolicyUrl: O, getVisitorChatHistory: Ae, resumeChat: je, isSessionRestoring: Me, isClosing: Ne }) {
30736
+ function bk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i, quickChatOptions: a, onQuickChatSelect: o, isMobile: s, chatHistory: l, isAiTyping: u, isAgentTyping: d, activeScreen: f, agentName: v, agentHeadshot: y, fallbackAgentName: b, input: x, setInput: S, onSubmit: C, isConversationEnded: w, isLoading: T, isRateLimited: ee, rateLimitMessage: te, selectedFile: ne, onFileSelect: re, onRemoveSelectedFile: E, attachmentError: ie, isUploadingAttachment: ae, requiresEmail: oe, emailInput: D, setEmailInput: se, emailError: ce, emailCaptureSuccess: le, replyContext: ue, setReplyContext: de, webRTCError: fe, micError: pe, setMicError: me, dismissCallError: he, activeCallId: ge, isCallMuted: _e, toggleCallMute: ve, endWebRTCCall: ye, formatCallDuration: be, callDurationSeconds: xe, isCallMinimized: Se, onExpand: Ce, onCollapse: we, onStartVoice: Te, voiceEnabled: Ee, headerBgColor: De, onNewChat: Oe, showPoweredBy: ke, privacyPolicyUrl: O, getVisitorChatHistory: Ae, resumeChat: je, isSessionRestoring: Me, isClosing: Ne }) {
30723
30737
  let Pe = l.length > 0, Fe = T || ee || w, Ie = !!ge, [Le, Re] = m(!1), [ze, Be] = m(!1), [Ve, k] = m([]), [He, Ue] = m(!1), We = p(null), [Ge, Ke] = m(() => typeof window < "u" ? window.visualViewport?.height ?? window.innerHeight : 600), [qe, Je] = m(0);
30724
30738
  c(() => {
30725
30739
  if (!s) return;
@@ -30859,7 +30873,7 @@ function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
30859
30873
  justifyContent: "center",
30860
30874
  height: "40px"
30861
30875
  },
30862
- children: i ? /* @__PURE__ */ g(uk, {
30876
+ children: i ? /* @__PURE__ */ g(dk, {
30863
30877
  logo: i,
30864
30878
  style: {
30865
30879
  height: "34px",
@@ -30872,7 +30886,7 @@ function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
30872
30886
  height: "40px",
30873
30887
  flexShrink: 0
30874
30888
  },
30875
- children: /* @__PURE__ */ g(dk, { title: e.chatTitle })
30889
+ children: /* @__PURE__ */ g(fk, { title: e.chatTitle })
30876
30890
  })
30877
30891
  }), o && /* @__PURE__ */ g("div", {
30878
30892
  style: {
@@ -31303,11 +31317,11 @@ function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
31303
31317
  isLoading: T,
31304
31318
  isAgentTyping: d,
31305
31319
  setReplyContext: de,
31306
- TypingDots: vk,
31320
+ TypingDots: yk,
31307
31321
  primaryColor: n,
31308
31322
  agentHeadshot: y,
31309
31323
  agentDisplayName: v || b,
31310
- botAvatarNode: /* @__PURE__ */ g(_k, { orbColors: t })
31324
+ botAvatarNode: /* @__PURE__ */ g(vk, { orbColors: t })
31311
31325
  }) : Me ? /* @__PURE__ */ _("div", {
31312
31326
  style: {
31313
31327
  flex: 1,
@@ -31348,7 +31362,7 @@ function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
31348
31362
  padding: "28px 24px"
31349
31363
  },
31350
31364
  children: [
31351
- /* @__PURE__ */ g(pk, {
31365
+ /* @__PURE__ */ g(mk, {
31352
31366
  size: 94,
31353
31367
  orbColors: t
31354
31368
  }),
@@ -31513,7 +31527,7 @@ function yk({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
31513
31527
  ]
31514
31528
  });
31515
31529
  }
31516
- function bk() {
31530
+ function xk() {
31517
31531
  let { status: e, runtimeConfig: t, resolvedConfig: n, chatHistory: r, isOpen: i, activeScreen: a, isHumanHandled: s, agentName: l, agentHeadshot: u, visitorEmail: h, isAgentTyping: v, isAiTyping: y, isLoading: b, isRateLimited: x, rateLimitMessage: S, isConversationEnded: C, incomingCall: w, activeCallId: T, callConnectionState: ee, callConnectedAt: te, isCallMuted: ne, webRTCError: re, language: E, chatId: ie, historyRef: ae, onMessageSync: oe, sendMessage: D, uploadChatFile: se, openWidget: ce, captureVisitorEmail: le, setVoiceMode: ue, endConversation: de, startNewChat: me, acceptCall: he, rejectCall: ge, endWebRTCCall: _e, toggleCallMute: ve, dismissCallError: ye, startTyping: be, stopTyping: xe, updateTypingDraft: Se, getVisitorChatHistory: Ce, resumeChat: we, isSessionRestoring: Te, openToChatCounter: Ee, voiceEndCounter: De } = In();
31518
31532
  c(() => {
31519
31533
  try {
@@ -31535,7 +31549,7 @@ function bk() {
31535
31549
  small: 50,
31536
31550
  medium: 64,
31537
31551
  large: 80
31538
- }, Be = ze[Me.orbSize] || ze.small, Ve = Me.position || "bottom-right", k = O.fallbackAgentName || "Agent", He = sk(Ie ?? Me.chatBgColors), Ue = O.logo || O.logoUrl || null, We = E || "en", Ge = Oe.recommendations?.[We] || [], Ke = (ke.recommendations?.[We] ?? Ge).filter((e) => String(e?.label ?? "").trim()).map((e, t) => ({
31552
+ }, Be = ze[Me.orbSize] || ze.small, Ve = Me.position || "bottom-right", k = O.fallbackAgentName || "Agent", He = ck(Ie ?? Me.chatBgColors), Ue = O.logo || O.logoUrl || null, We = E || "en", Ge = Oe.recommendations?.[We] || [], Ke = (ke.recommendations?.[We] ?? Ge).filter((e) => String(e?.label ?? "").trim()).map((e, t) => ({
31539
31553
  id: e.key || `qr-${t}`,
31540
31554
  label: e.label,
31541
31555
  message: e.label,
@@ -31824,7 +31838,7 @@ function bk() {
31824
31838
  onWheel: (e) => e.stopPropagation(),
31825
31839
  onTouchMove: (e) => e.stopPropagation(),
31826
31840
  children: [
31827
- j === "entry_prompt" && /* @__PURE__ */ g(mk, {
31841
+ j === "entry_prompt" && /* @__PURE__ */ g(hk, {
31828
31842
  copy: it,
31829
31843
  orbColors: Ie,
31830
31844
  primaryColor: Re,
@@ -31907,13 +31921,13 @@ function bk() {
31907
31921
  children: ee === "connected" ? `${Jt(St)} with ${st}` : `Tap to return to ${st}`
31908
31922
  })]
31909
31923
  })]
31910
- }), /* @__PURE__ */ g(pk, {
31924
+ }), /* @__PURE__ */ g(mk, {
31911
31925
  size: Be,
31912
31926
  orbColors: Ie,
31913
31927
  onClick: T ? Ut : Fe ? Qt : en
31914
31928
  })]
31915
31929
  }),
31916
- j === "connection_modal" && /* @__PURE__ */ g(hk, {
31930
+ j === "connection_modal" && /* @__PURE__ */ g(gk, {
31917
31931
  copy: it,
31918
31932
  orbColors: Ie,
31919
31933
  primaryColor: Re,
@@ -31923,7 +31937,7 @@ function bk() {
31923
31937
  isMobile: zt,
31924
31938
  isClosing: Pt
31925
31939
  }),
31926
- j === "voice_mode" && /* @__PURE__ */ g(gk, {
31940
+ j === "voice_mode" && /* @__PURE__ */ g(_k, {
31927
31941
  orbColors: Ie,
31928
31942
  onEnterChat: en,
31929
31943
  onEndChat: tn,
@@ -31958,7 +31972,7 @@ function bk() {
31958
31972
  orbColors: Ie,
31959
31973
  chatHistory: r
31960
31974
  }),
31961
- j === "text_chat" && /* @__PURE__ */ g(yk, {
31975
+ j === "text_chat" && /* @__PURE__ */ g(bk, {
31962
31976
  isClosing: Pt,
31963
31977
  copy: it,
31964
31978
  orbColors: Ie,
@@ -32024,7 +32038,7 @@ function bk() {
32024
32038
  }
32025
32039
  //#endregion
32026
32040
  //#region src/components/ErrorBoundary.jsx
32027
- var xk = class extends e.Component {
32041
+ var Sk = class extends e.Component {
32028
32042
  constructor(e) {
32029
32043
  super(e), this.state = { hasError: !1 };
32030
32044
  }
@@ -32039,4 +32053,4 @@ var xk = class extends e.Component {
32039
32053
  }
32040
32054
  };
32041
32055
  //#endregion
32042
- export { pO as AnimatedOrb, xk as ErrorBoundary, Gr as FlowEngageProvider, bk as FlowEngageWidget, In as useFlowEngage };
32056
+ export { pO as AnimatedOrb, Sk as ErrorBoundary, Gr as FlowEngageProvider, xk as FlowEngageWidget, In as useFlowEngage };