@flowengage/react-chatbot 8.0.19 → 8.0.20

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.
@@ -29148,10 +29148,31 @@ function rk() {
29148
29148
  a.length > 2 && a.length < 200 && n.push(a), r++;
29149
29149
  }
29150
29150
  return n;
29151
- }, t = e((document.querySelector("main, [role='main']") || document.body).querySelectorAll("h1, h2, h3"));
29152
- t.length || (t = e(document.body.querySelectorAll("h1, h2, h3"))), t.length || (t = e(document.body.querySelectorAll("h4, h5")));
29153
- let n = [...new Set(t)], r = ((typeof document < "u" ? document.title : "") || "").replace(/\s*[-–—|·]\s*.+$/, "").trim().toLowerCase();
29154
- return (r ? n.filter((e) => e.toLowerCase().trim() !== r) : n).slice(0, 15);
29151
+ }, t = document.querySelector("main, [role='main']") || document.body, n = e(t.querySelectorAll("h1, h2, h3"));
29152
+ n.length || (n = e(document.body.querySelectorAll("h1, h2, h3"))), n.length || (n = e(document.body.querySelectorAll("h4, h5")));
29153
+ let r = [...new Set(n)].slice(0, 15), i = Array.from(t.querySelectorAll("h1")).filter((e) => !e.closest("#flowengage-root, .flowengage-shell, .flowengage-widget-root") && !e.closest("nav, footer, header, aside, .nav, .footer, .header, .sidebar")), a = null;
29154
+ if (i.length === 1) {
29155
+ let e = Un(i[0]);
29156
+ e && r[0] && r[0].toLowerCase().trim() === e.toLowerCase().trim() && (a = r[0]);
29157
+ }
29158
+ let o = "";
29159
+ try {
29160
+ let e = t.querySelector("h1, h2, h3, h4, h5");
29161
+ if (e) {
29162
+ let n = document.createRange();
29163
+ n.setStart(t, 0), n.setEndBefore(e);
29164
+ let r = n.cloneContents(), i = [];
29165
+ r.querySelectorAll("p, li").forEach((e) => {
29166
+ let t = e.textContent.replace(/\s+/g, " ").trim();
29167
+ t.length > 20 && i.push(t);
29168
+ }), o = i.join(" ").slice(0, 600);
29169
+ }
29170
+ } catch {}
29171
+ return {
29172
+ headings: r,
29173
+ pageTitleHeading: a,
29174
+ introText: o
29175
+ };
29155
29176
  }
29156
29177
  function ik(e) {
29157
29178
  if (!e || typeof document > "u") return "";
@@ -29204,6 +29225,21 @@ function ik(e) {
29204
29225
  t.length && l.push(t.join("\n"));
29205
29226
  return;
29206
29227
  }
29228
+ if (n === "form") {
29229
+ let t = Array.from(e.querySelectorAll("input, textarea, select")).map((e) => {
29230
+ let t = (e.getAttribute("type") || "text").toLowerCase();
29231
+ if ([
29232
+ "hidden",
29233
+ "submit",
29234
+ "button",
29235
+ "reset"
29236
+ ].includes(t)) return null;
29237
+ let n = e.getAttribute("placeholder") || e.getAttribute("aria-label") || e.getAttribute("name") || t;
29238
+ return n ? String(n).trim().slice(0, 40) : null;
29239
+ }).filter(Boolean), n = e.querySelector("button[type=\"submit\"], input[type=\"submit\"]"), r = n ? (n.textContent || n.value || "Submit").trim().slice(0, 40) : "Submit";
29240
+ t.length && l.push(`[FORM PRESENT: ${t.length} field(s) — ${t.join(", ")}. Submit button: "${r}"]`);
29241
+ return;
29242
+ }
29207
29243
  if (n === "p" || n === "blockquote") {
29208
29244
  let t = e.textContent.replace(/\s+/g, " ").trim();
29209
29245
  t.length > 2 && l.push(t);
@@ -29293,10 +29329,10 @@ function ak(e) {
29293
29329
  try {
29294
29330
  typeof window < "u" && window.scrollTo(0, 0);
29295
29331
  } catch {}
29296
- let s = [], c = Date.now() + 12e3;
29297
- for (; Date.now() < c && (await new Promise((e) => setTimeout(e, 300)), s = rk(), !(s.length >= 1)););
29298
- nk(), $("fwh-navigate-mvp → page headings collected:", s);
29299
- 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 = "";
29332
+ let s = [], c = null, l = "", u = Date.now() + 12e3;
29333
+ for (; Date.now() < u && (await new Promise((e) => setTimeout(e, 300)), {headings: s, pageTitleHeading: c, introText: l} = rk(), !(s.length >= 1)););
29334
+ nk(), $("fwh-navigate-mvp → page headings collected:", s, "titleHeading:", c);
29335
+ let d = s.length ? s.join(" | ") : "none", f = 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.", p = c ? ` "${c}" is the PAGE TITLE, not a content section — do not fwh-highlight-mvp it separately; if doing a walkthrough, just fold this intro into your opening line: "${l || "(no intro text found)"}"` : l ? ` No separate page-title heading detected, but this intro text precedes the first section — mention it briefly before covering sections: "${l}"` : "", m = "";
29300
29336
  try {
29301
29337
  if (s.length > 0) {
29302
29338
  let e = s.slice(0, 3), t = [];
@@ -29307,10 +29343,10 @@ function ak(e) {
29307
29343
  r && t.push(`[Section: ${n}] ${r}`);
29308
29344
  }
29309
29345
  }
29310
- 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.`);
29346
+ t.length > 0 && (m = ` CONTENT FOR FIRST FEW SECTIONS: ${t.join(" | ")}. Use this content to answer immediately if the visitor asks about one of these sections.`);
29311
29347
  }
29312
29348
  } catch {}
29313
- return UO() ? (Ar(), $("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 ? (Ar(), `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.`) : (Ar(), `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.`);
29349
+ return UO() ? (Ar(), $("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 ? (Ar(), `OK_NAVIGATE_SPA. Visitor is now on: ${r} (page: "${o}") | Section headings: ${d}.${p} ${f}${m} 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.`) : (Ar(), `OK_NAVIGATE_SPA. CURRENT PAGE IS: ${r} (page: "${o}") | Section headings: ${d}.${p} ${f}${m} 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.`);
29314
29350
  } catch {}
29315
29351
  let o = "this";
29316
29352
  try {
@@ -29345,7 +29381,7 @@ function ak(e) {
29345
29381
  }
29346
29382
  if (!a) {
29347
29383
  $("fwh-highlight-mvp ✖ no element for:", i || n);
29348
- 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.";
29384
+ let { headings: 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.";
29349
29385
  return `HIGHLIGHT_NOT_FOUND: "${i || n}" on the current page. ${t}`;
29350
29386
  }
29351
29387
  return zn(a), $("fwh-highlight-mvp ✓", i || n), `OK_HIGHLIGHT: "${i || n}". WALKTHROUGH: continue immediately to the next section — do NOT pause between sections.`;
@@ -29481,14 +29517,16 @@ function ak(e) {
29481
29517
  "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."),
29482
29518
  "fwh-get-current-page-mvp": async () => {
29483
29519
  if ($("fwh-get-current-page-mvp ▶"), typeof window > "u") return "Cannot determine current page (no browser context).";
29484
- let e = window.location.href, t = window.location.pathname, n = document.title || "", r = rk();
29485
- if ($("fwh-get-current-page-mvp ✓", {
29520
+ let e = window.location.href, t = window.location.pathname, n = document.title || "", { headings: r, pageTitleHeading: i, introText: a } = rk();
29521
+ $("fwh-get-current-page-mvp ✓", {
29486
29522
  url: e,
29487
29523
  path: t,
29488
29524
  title: n
29489
- }), $("fwh-get-current-page-mvp → page headings collected:", r), !r.length) return `CURRENT_PAGE. URL: ${e} | Title: ${n} | No headings found on this page. Describe the page from your knowledge without calling this tool again.`;
29490
- let i = r.map((e) => `"${e}"`).join(" | ");
29491
- 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. ***`;
29525
+ }), $("fwh-get-current-page-mvp → page headings collected:", r, "titleHeading:", i);
29526
+ let o = i ? ` NOTE: "${i}" is the PAGE TITLE, not a content section — do NOT fwh-highlight-mvp it or list it as a separate section in a walkthrough. Instead, open with a brief 1-2 sentence summary of this intro text before covering the real sections: "${a || "(no intro text captured)"}"` : a ? ` NOTE: no separate page-title heading was detected, but this intro text appears before the first section — open your walkthrough with a brief 1-2 sentence summary of it before covering sections: "${a}"` : "";
29527
+ if (!r.length) return `CURRENT_PAGE. URL: ${e} | Title: ${n} |${o} No structured section headings found on this page. If there is intro text above, describe it; otherwise describe the page from your knowledge. Do not call this tool again.`;
29528
+ let s = r.map((e) => `"${e}"`).join(" | ");
29529
+ return `CURRENT_PAGE. URL: ${e} | Title: ${n} | Page sections (${r.length} total): ${s}.${o} *** 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${o ? " (open with the intro note above first)" : ""} — "Let me walk you through this." + fwh-highlight-mvp("${r[0] || "first heading"}") + "Description..." etc. Cover ALL ${r.length} sections without pausing. ***`;
29492
29530
  },
29493
29531
  "fwh-list-forms-mvp": async () => {
29494
29532
  let e = YO(), t = XO();
@@ -30102,13 +30140,13 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30102
30140
  if (S) if (m) {
30103
30141
  let e = p?.pageName || ne;
30104
30142
  w.overrides = { agent: { firstMessage: `I have navigated you on ${e} page. Do you want to know about any specific section or want a complete overview?` } }, console.log(`[FlowEngage] 🔄 Agent-nav resume: firstMessage set for "${e}" (${g})`);
30105
- } else if (u) w.overrides = { agent: { firstMessage: "I'm still here. Go ahead!" } };
30143
+ } else if (u) w.overrides = { agent: { firstMessage: `Welcome back! I see you're now on the ${ne} page. Would you like me to continue what I was explaining before, or would you like to know about this page instead?` } };
30106
30144
  else {
30107
30145
  let e = f || "";
30108
30146
  w.overrides = { agent: { firstMessage: h || (b ? e ? `Hi, welcome to ${e}! How may I help you?` : "Hi, welcome! How may I help you?" : `Welcome to the ${ne} page!`) } }, b || console.log(`[FlowEngage] 🏠 Page-context override: "${ne}" for ${g}`);
30109
30147
  }
30110
30148
  else u && (w.overrides = { agent: { firstMessage: "" } });
30111
- let re = !1, E = m ? `NAVIGATION COMPLETE — The exact phrase "I have navigated you on [page] page. Do you want to know about any specific section or want a complete overview?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until the visitor responds. When they reply: if they name a specific section → call fwh-get-current-page-mvp then answer immediately; if they say "overview" or anything non-specific → call fwh-get-current-page-mvp (zero speech) then do a full highlighted walkthrough.` : null, ie = !1, D = !m && !u ? "Your greeting has been spoken. Wait for the visitor to ask a question or tell you what they need. Do NOT auto-start a walkthrough or highlight any sections — let the visitor lead." : null, de = !1, ye = !1, ke = !!y, je = await ED.startSession({
30149
+ let re = !1, E = m ? `NAVIGATION COMPLETE — The exact phrase "I have navigated you on [page] page. Do you want to know about any specific section or want a complete overview?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until the visitor responds. When they reply: if they name a specific section → call fwh-get-current-page-mvp then answer immediately; if they say "overview" or anything non-specific → call fwh-get-current-page-mvp (zero speech) then do a full highlighted walkthrough.` : null, ie = !1, D = !m && !u ? "Your greeting has been spoken. Wait for the visitor to ask a question or tell you what they need. Do NOT auto-start a walkthrough or highlight any sections — let the visitor lead." : null, de = u && !m, ye = !1, ke = de ? `The question "Would you like me to continue what I was explaining before, or would you like to know about this page instead?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript, or the visitor navigated before saying much)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until they respond. When they reply: if they want you to CONTINUE the previous topic → resume verbally from the prior transcript above, do NOT call fwh-get-current-page-mvp or describe the new page unless they ask. If they want to know about THIS page → call fwh-get-current-page-mvp (zero speech) then proceed as a normal fresh-page walkthrough/description. If their reply is ambiguous, ask them to clarify which they'd prefer rather than guessing.` : null, je = !1, Pe = !1, Fe = !!y, Ie = await ED.startSession({
30112
30150
  ...w,
30113
30151
  onConnect: ({ conversationId: e }) => {
30114
30152
  _e.current = e, ve.current = Date.now(), console.log("[FlowEngage] 🎙️ AI chat session connected:", e);
@@ -30124,8 +30162,8 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30124
30162
  xe.current = !1, Oe();
30125
30163
  return;
30126
30164
  }
30127
- if (ke && !ye) {
30128
- ye = !0, re = !0, ie = !0;
30165
+ if (Fe && !Pe) {
30166
+ Pe = !0, re = !0, ie = !0;
30129
30167
  try {
30130
30168
  le.current?.sendContextualUpdate?.("CRITICAL — EMAIL REQUIRED BEFORE ANYTHING ELSE. The visitor has not provided their email. Do NOT speak right now. Wait silently for the visitor to speak first. The MOMENT the visitor says ANYTHING — a question, a request, or just a greeting — your ENTIRE next response must be EXACTLY this one sentence: \"Before I answer that, could you please enter your email in the text box below?\" Do NOT answer their question. Do NOT say anything about the topic. Do NOT begin an answer and then switch — your first word must be \"Before\". After you say that sentence, stay completely silent until you receive an EMAIL_SAVED message, then thank them briefly and answer their question in full.");
30131
30169
  } catch {}
@@ -30136,6 +30174,12 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30136
30174
  le.current?.sendContextualUpdate?.(E);
30137
30175
  } catch {}
30138
30176
  }
30177
+ if (ke && !ye) {
30178
+ ye = !0;
30179
+ try {
30180
+ le.current?.sendContextualUpdate?.(ke);
30181
+ } catch {}
30182
+ }
30139
30183
  if (D && !ie) {
30140
30184
  ie = !0;
30141
30185
  try {
@@ -30160,7 +30204,7 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30160
30204
  try {
30161
30205
  Bn();
30162
30206
  } catch {}
30163
- ke && !de && !ae.current && (de = !0, ce.current = r, oe.current || (oe.current = !0, se.current = 0, te(!0), Me()));
30207
+ Fe && !je && !ae.current && (je = !0, ce.current = r, oe.current || (oe.current = !0, se.current = 0, te(!0), Me()));
30164
30208
  }
30165
30209
  if (l.current = [...l.current, {
30166
30210
  sender: n,
@@ -30211,10 +30255,10 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30211
30255
  }
30212
30256
  });
30213
30257
  if (e) {
30214
- console.warn("[FlowEngage:VoiceDebug] ❌ cancelled=true after startSession resolved — killing session immediately"), je.endSession().catch(() => {});
30258
+ console.warn("[FlowEngage:VoiceDebug] ❌ cancelled=true after startSession resolved — killing session immediately"), Ie.endSession().catch(() => {});
30215
30259
  return;
30216
30260
  }
30217
- o = je, le.current = je, x("listening");
30261
+ o = Ie, le.current = Ie, x("listening");
30218
30262
  try {
30219
30263
  let e = typeof window < "u" ? window.location.href : "", r = "[]";
30220
30264
  try {
@@ -30226,7 +30270,7 @@ function _k({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
30226
30270
  n.length || (n = Array.from(document.body.querySelectorAll("h1, h2, h3")).filter((t) => !t.closest(e)).map((e) => e.textContent.replace(/\s+/g, " ").trim()).filter((e) => e.length > 2 && e.length < 200)), n.length && (a = [...new Set(n)].slice(0, 15).join(" | "));
30227
30271
  } catch {}
30228
30272
  let o = u && !m ? `RESUMING PRIOR SESSION — DO NOT GREET. The visitor is continuing the same conversation after a page reload. Do not introduce yourself or re-state your capabilities. Wait silently until the visitor speaks; if you must speak first, briefly acknowledge where you left off in one short sentence.\nPrior transcript:\n${n?.transcript || ""}\n\n` : "";
30229
- je.sendContextualUpdate(`${o}SESSION_CONTEXT (NOT a tool result — do NOT treat as CURRENT_PAGE): Visitor is on: ${e} | Approx headings for awareness only: ${a}. SiteId: ${i || "unknown"}. Forms: ${r}. The visitor is ALREADY on this page — do NOT offer to navigate there. WALKTHROUGH RULE: When the visitor asks for a walkthrough or overview of this page, you MUST IMMEDIATELY call fwh-get-current-page-mvp (zero speech — call it silently with NO words before it) to get the exact highlightable headings. The approximate headings above are for routing awareness ONLY — they are NOT precise enough for fwh-highlight-mvp. Do NOT skip fwh-get-current-page-mvp. Voice: call end_voice_session or say you are ending the session to stop.`);
30273
+ Ie.sendContextualUpdate(`${o}SESSION_CONTEXT (NOT a tool result — do NOT treat as CURRENT_PAGE): Visitor is on: ${e} | Approx headings for awareness only: ${a}. SiteId: ${i || "unknown"}. Forms: ${r}. The visitor is ALREADY on this page — do NOT offer to navigate there. WALKTHROUGH RULE: When the visitor asks for a walkthrough or overview of this page, you MUST IMMEDIATELY call fwh-get-current-page-mvp (zero speech — call it silently with NO words before it) to get the exact highlightable headings. The approximate headings above are for routing awareness ONLY — they are NOT precise enough for fwh-highlight-mvp. Do NOT skip fwh-get-current-page-mvp. Voice: call end_voice_session or say you are ending the session to stop.`);
30230
30274
  } catch {}
30231
30275
  if (typeof window < "u") {
30232
30276
  let t = window.location.pathname, n = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "8.0.19",
3
+ "version": "8.0.20",
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",