@flowengage/react-chatbot 8.0.94 → 8.0.103
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.
|
@@ -18,7 +18,7 @@ var v = Object.defineProperty, y = Object.getOwnPropertyDescriptor, b = Object.g
|
|
|
18
18
|
}, T = (e) => x.call(e, "module.exports") ? e["module.exports"] : w(v({}, "__esModule", { value: !0 }), e), E = (e) => {
|
|
19
19
|
if (!e || typeof e != "object") throw Error("FlowEngage config is required");
|
|
20
20
|
if (!e.siteId || typeof e.siteId != "string") throw Error("[FlowEngage] config.siteId is required. Pass it as <FlowEngageProvider siteId=\"your-site-id\" /> or config={{ siteId: 'your-site-id' }}.");
|
|
21
|
-
let t = (e.apiBaseUrl || "
|
|
21
|
+
let t = (e.apiBaseUrl || "http://localhost:5008").replace(/\/+$/, "");
|
|
22
22
|
return {
|
|
23
23
|
siteId: e.siteId.trim(),
|
|
24
24
|
apiBaseUrl: t
|
|
@@ -307,18 +307,52 @@ var v = Object.defineProperty, y = Object.getOwnPropertyDescriptor, b = Object.g
|
|
|
307
307
|
})
|
|
308
308
|
});
|
|
309
309
|
},
|
|
310
|
-
async sendAiMessage(
|
|
311
|
-
|
|
310
|
+
async sendAiMessage(i, o, s = "en", c = "", l = null, u = {}, d = null) {
|
|
311
|
+
let f = {
|
|
312
|
+
session_id: i,
|
|
313
|
+
user_query: o,
|
|
314
|
+
lang: s,
|
|
315
|
+
category: c,
|
|
316
|
+
...u || {},
|
|
317
|
+
...l || {}
|
|
318
|
+
};
|
|
319
|
+
if (typeof d != "function") return a("/api/ai/chat", {
|
|
312
320
|
method: "POST",
|
|
321
|
+
body: JSON.stringify(f)
|
|
322
|
+
});
|
|
323
|
+
let p = await z(`${e}/api/ai/chat`, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: {
|
|
326
|
+
"Content-Type": "application/json",
|
|
327
|
+
"x-user-id": t,
|
|
328
|
+
...n ? { "x-site-id": n } : {},
|
|
329
|
+
...r ? { "x-visitor-id": r } : {}
|
|
330
|
+
},
|
|
313
331
|
body: JSON.stringify({
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
lang: n,
|
|
317
|
-
category: r,
|
|
318
|
-
...o || {},
|
|
319
|
-
...i || {}
|
|
332
|
+
...f,
|
|
333
|
+
stream: !0
|
|
320
334
|
})
|
|
321
335
|
});
|
|
336
|
+
if (!(p.headers.get("content-type") || "").includes("text/event-stream")) return R(p);
|
|
337
|
+
let m = p.body.getReader(), h = new TextDecoder(), g = "", _ = null, v = (e) => {
|
|
338
|
+
let t = e.split("\n").find((e) => e.startsWith("data: "));
|
|
339
|
+
if (t) try {
|
|
340
|
+
let e = JSON.parse(t.slice(6));
|
|
341
|
+
e.type === "delta" && e.text ? d(e.text) : e.type === "done" && (_ = e.payload);
|
|
342
|
+
} catch {}
|
|
343
|
+
};
|
|
344
|
+
for (;;) {
|
|
345
|
+
let { done: e, value: t } = await m.read();
|
|
346
|
+
if (e) break;
|
|
347
|
+
g += h.decode(t, { stream: !0 });
|
|
348
|
+
let n;
|
|
349
|
+
for (; (n = g.indexOf("\n\n")) !== -1;) v(g.slice(0, n)), g = g.slice(n + 2);
|
|
350
|
+
}
|
|
351
|
+
if (!_) {
|
|
352
|
+
let e = /* @__PURE__ */ Error("The response stream ended unexpectedly — please try again.");
|
|
353
|
+
throw e.status = 0, e;
|
|
354
|
+
}
|
|
355
|
+
return _;
|
|
322
356
|
},
|
|
323
357
|
async uploadChatFile(e) {
|
|
324
358
|
let t = new FormData();
|
|
@@ -3973,7 +4007,23 @@ function pi({ siteId: e, config: t, children: n, language: r = "en" }) {
|
|
|
3973
4007
|
}
|
|
3974
4008
|
Ce(!0);
|
|
3975
4009
|
try {
|
|
3976
|
-
let o = await Lr(), s = Fr(), l =
|
|
4010
|
+
let o = await Lr(), s = Fr(), l = `stream-preview-${Date.now().toString(36)}`, u = (e) => {
|
|
4011
|
+
F(!1), S((t) => {
|
|
4012
|
+
let n = t.findIndex((e) => e.id === l);
|
|
4013
|
+
if (n === -1) return [...t, {
|
|
4014
|
+
id: l,
|
|
4015
|
+
sender: "bot",
|
|
4016
|
+
message: e,
|
|
4017
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4018
|
+
isStreaming: !0
|
|
4019
|
+
}];
|
|
4020
|
+
let r = [...t];
|
|
4021
|
+
return r[n] = {
|
|
4022
|
+
...r[n],
|
|
4023
|
+
message: r[n].message + e
|
|
4024
|
+
}, r;
|
|
4025
|
+
});
|
|
4026
|
+
}, d = await U.current.sendAiMessage(y, e, r, t, {
|
|
3977
4027
|
...n || {},
|
|
3978
4028
|
...ge ? { email: ge } : {}
|
|
3979
4029
|
}, {
|
|
@@ -3984,17 +4034,17 @@ function pi({ siteId: e, config: t, children: n, language: r = "en" }) {
|
|
|
3984
4034
|
currentPageContent: Ut() || void 0,
|
|
3985
4035
|
...o ? { shopifyCart: o } : {},
|
|
3986
4036
|
...s ? { shopifyCustomerId: s } : {}
|
|
3987
|
-
}
|
|
4037
|
+
}, u), f = d.chat_history || [];
|
|
3988
4038
|
if (console.log("[FWH Nav Debug] API response fields:", {
|
|
3989
|
-
has_navigate: !!
|
|
3990
|
-
navigate:
|
|
3991
|
-
has_pending_navigate: !!
|
|
3992
|
-
pending_navigate:
|
|
3993
|
-
last_bot_msg: [...
|
|
3994
|
-
}),
|
|
4039
|
+
has_navigate: !!d.navigate,
|
|
4040
|
+
navigate: d.navigate,
|
|
4041
|
+
has_pending_navigate: !!d.pending_navigate,
|
|
4042
|
+
pending_navigate: d.pending_navigate,
|
|
4043
|
+
last_bot_msg: [...f].reverse().find((e) => e.sender === "bot")?.message?.substring(0, 80)
|
|
4044
|
+
}), d.pending_navigate?.url) {
|
|
3995
4045
|
let e = {
|
|
3996
|
-
url:
|
|
3997
|
-
section:
|
|
4046
|
+
url: d.pending_navigate.url,
|
|
4047
|
+
section: d.pending_navigate.section || null
|
|
3998
4048
|
};
|
|
3999
4049
|
c.test(a) ? (console.log("[FWH Nav] Auto-navigating (intent detected) →", e.url), it(e.url, { voiceActive: yt.current }).then(({ navigated: t, reason: n }) => {
|
|
4000
4050
|
if (!t) {
|
|
@@ -4007,9 +4057,9 @@ function pi({ siteId: e, config: t, children: n, language: r = "en" }) {
|
|
|
4007
4057
|
}, 300);
|
|
4008
4058
|
})) : (nt.current = e, console.log("[FWH Nav] Stored pending nav →", nt.current));
|
|
4009
4059
|
}
|
|
4010
|
-
if (
|
|
4060
|
+
if (d.navigate?.url) if (G.current) G.current = !1;
|
|
4011
4061
|
else {
|
|
4012
|
-
let { url: e, section: t } =
|
|
4062
|
+
let { url: e, section: t } = d.navigate;
|
|
4013
4063
|
it(e, { voiceActive: yt.current }).then(({ navigated: e, reason: n }) => {
|
|
4014
4064
|
if (!e) {
|
|
4015
4065
|
n === "not-found" ? C() : n === "already-on-page" && T();
|
|
@@ -4021,14 +4071,14 @@ function pi({ siteId: e, config: t, children: n, language: r = "en" }) {
|
|
|
4021
4071
|
}, 300);
|
|
4022
4072
|
});
|
|
4023
4073
|
}
|
|
4024
|
-
else if (
|
|
4025
|
-
let e =
|
|
4074
|
+
else if (d.highlight?.section) {
|
|
4075
|
+
let e = d.highlight.section;
|
|
4026
4076
|
setTimeout(() => {
|
|
4027
4077
|
let t = cr(null, e);
|
|
4028
4078
|
t && lr(t);
|
|
4029
4079
|
}, 150);
|
|
4030
4080
|
} else {
|
|
4031
|
-
let e = [...
|
|
4081
|
+
let e = [...f].reverse().find((e) => e.sender === "bot" || e.sender === "assistant");
|
|
4032
4082
|
if (e?.message) {
|
|
4033
4083
|
let t = ci(e.message);
|
|
4034
4084
|
t && pr(t.url, {
|
|
@@ -4052,9 +4102,9 @@ function pi({ siteId: e, config: t, children: n, language: r = "en" }) {
|
|
|
4052
4102
|
});
|
|
4053
4103
|
}
|
|
4054
4104
|
}
|
|
4055
|
-
S(si(
|
|
4105
|
+
S(si(f)), Array.isArray(d.cart_actions) && d.cart_actions.length && w(d.cart_actions), M(!!d.is_human_handled), A(d.is_human_handled ? "agent" : "ai"), F(!1), Ce(!1), await U.current.updateChatStatus(y, "messageSent");
|
|
4056
4106
|
} catch (e) {
|
|
4057
|
-
S((e) => e.filter((e) => e.id !== u)), F(!1), Ce(!1), e.status === 429 ? (Te(!0), De(e.message), window.setTimeout(() => {
|
|
4107
|
+
S((e) => e.filter((e) => e.id !== u && !e.isStreaming)), F(!1), Ce(!1), e.status === 429 ? (Te(!0), De(e.message), window.setTimeout(() => {
|
|
4058
4108
|
Te(!1), De("");
|
|
4059
4109
|
}, ee)) : h(e);
|
|
4060
4110
|
}
|
|
@@ -9330,20 +9380,15 @@ async function vh(e) {
|
|
|
9330
9380
|
mode: "thinking",
|
|
9331
9381
|
tentative: !0
|
|
9332
9382
|
}))), (le.isPlaying() || re) && !M) {
|
|
9333
|
-
if (r < ie)
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9383
|
+
if (r < ie) j = 0;
|
|
9384
|
+
else if (++j >= ae) {
|
|
9385
|
+
M = !0, j = 0;
|
|
9386
|
+
let e = le.playedMs();
|
|
9387
|
+
le.stop(), ne = !1, re = !1, N && !oe && (clearTimeout(N), N = null), se = !1, C.send(JSON.stringify({
|
|
9388
|
+
type: "VisitorInterrupted",
|
|
9389
|
+
played_ms: Math.round(e)
|
|
9390
|
+
})), console.debug("[FlowEngage] barge-in — visitor spoke over the agent");
|
|
9340
9391
|
}
|
|
9341
|
-
M = !0, j = 0;
|
|
9342
|
-
let e = le.playedMs();
|
|
9343
|
-
le.stop(), ne = !1, re = !1, N && !oe && (clearTimeout(N), N = null), se = !1, C.send(JSON.stringify({
|
|
9344
|
-
type: "VisitorInterrupted",
|
|
9345
|
-
played_ms: Math.round(e)
|
|
9346
|
-
})), console.debug("[FlowEngage] barge-in — visitor spoke over the agent");
|
|
9347
9392
|
}
|
|
9348
9393
|
C.send(uh(t).buffer);
|
|
9349
9394
|
}, ue.connect(de), de.connect(_.destination);
|
|
@@ -12427,7 +12472,8 @@ function n_(e) {
|
|
|
12427
12472
|
}
|
|
12428
12473
|
if (typeof window < "u") try {
|
|
12429
12474
|
let e = new URL(a, window.location.href);
|
|
12430
|
-
if (e.origin !== window.location.origin
|
|
12475
|
+
if (e.hostname === window.location.hostname && e.origin !== window.location.origin) a = e.pathname + e.search + e.hash, $("fwh-navigate-mvp · cross-protocol same-host URL normalized →", a);
|
|
12476
|
+
else if (e.origin !== window.location.origin && /^https?:$/i.test(e.protocol)) {
|
|
12431
12477
|
let t = e.hostname;
|
|
12432
12478
|
return $("fwh-navigate-mvp ✖ external URL blocked:", e.href), `EXTERNAL_LINK_BLOCKED: The URL "${a}" points to an external site (${t}) that opens in a new tab. I cannot open new tabs or navigate to external sites. Tell the visitor exactly this: "That link opens an external app — I'm not able to open it for you, but you can click the link directly in the navigation header."`;
|
|
12433
12479
|
}
|
|
@@ -12476,7 +12522,14 @@ function n_(e) {
|
|
|
12476
12522
|
let e = new URL(a, window.location.href).pathname.split("/").filter(Boolean).pop() || "";
|
|
12477
12523
|
n = e ? e.replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()) : "Home";
|
|
12478
12524
|
} catch {}
|
|
12479
|
-
t && typeof window < "u" && je(t, window.location.href, e, n), gr(e)
|
|
12525
|
+
t && typeof window < "u" && je(t, window.location.href, e, n), gr(e);
|
|
12526
|
+
try {
|
|
12527
|
+
window.__fe_agent_nav = {
|
|
12528
|
+
path: new URL(e, window.location.href).pathname,
|
|
12529
|
+
ts: Date.now()
|
|
12530
|
+
};
|
|
12531
|
+
} catch {}
|
|
12532
|
+
$("fwh-navigate-mvp → real navigation", a);
|
|
12480
12533
|
let i = typeof window < "u" && !window.Shopify && !!qn();
|
|
12481
12534
|
if (typeof window < "u" && window.__fe_triggerVoiceNavHooks && window.__fe_triggerVoiceNavHooks(), i && Rn(12e3), wr(a, { voiceActive: !0 }).catch(() => {}), i) try {
|
|
12482
12535
|
let e = new URL(a, window.location.origin).pathname, t = window.location.pathname, n = Date.now() + 2e3;
|
|
@@ -12514,12 +12567,7 @@ function n_(e) {
|
|
|
12514
12567
|
let g = typeof window < "u" ? window.location.href : i, _ = (h.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()) || "Home", v = zg(h, e), y = !zg(h, t), b = v || y;
|
|
12515
12568
|
return $("fwh-navigate-mvp settled:", h, "target:", e, "match:", b), b ? (_r(), `OK_NAVIGATE_SPA. Visitor is now on: ${g} (page: "${_}") | Section headings: ${u}.${f} ${d}${p} Now confirm the arrival in ONE short sentence phrased for what the visitor actually asked for — mention the page by name and what it lets them do (e.g. for a contact request: "I've taken you to the Contact Us page — filling in this form sends your query straight to our team."). Do NOT use a fixed template. Then, in the same breath, offer either a specific section or a full overview. Then STOP — wait for their reply.`) : (_r(), `NAVIGATION_DID_NOT_HAPPEN. The visitor is STILL on ${g} (page: "${_}") — the navigation did not go through. Do NOT say "I have navigated you". Do NOT claim success. Tell the visitor EXACTLY: "Sorry, I couldn't open that page just now. Would you like me to try again, or is there something else I can help with?" Then STOP and wait for their reply.`);
|
|
12516
12569
|
} catch {}
|
|
12517
|
-
|
|
12518
|
-
try {
|
|
12519
|
-
let e = new URL(a, window.location.href).pathname.split("/").filter(Boolean).pop() || "";
|
|
12520
|
-
o = e ? e.replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()) : "Home";
|
|
12521
|
-
} catch {}
|
|
12522
|
-
return `OK_NAVIGATE_RELOADING. Navigating to the page now; the voice session will resume automatically on the new page. When the session resumes, say 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 the visitor's reply.`;
|
|
12570
|
+
return "OK_NAVIGATE_RELOADING. The page is reloading now and this session is ending. Say NOTHING further — do not confirm the navigation, do not describe the page. The arrival greeting is spoken automatically on the new page; you resume from the visitor's next reply.";
|
|
12523
12571
|
} catch (e) {
|
|
12524
12572
|
let t = `Navigation error: ${e?.message || String(e)}`;
|
|
12525
12573
|
return $("fwh-navigate-mvp ✖", t), xg("Navigation failed", {
|
|
@@ -13302,7 +13350,15 @@ function g_({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
13302
13350
|
ge.current += 1;
|
|
13303
13351
|
let t = ge.current, n = e[t];
|
|
13304
13352
|
if (!n) {
|
|
13305
|
-
he(!1), e.length
|
|
13353
|
+
if (he(!1), e.length) P.current?.sendUserMessage?.("That was the last section. Say so in one short sentence and ask if they want to explore any section further.");
|
|
13354
|
+
else if (t === 0) {
|
|
13355
|
+
let e = "";
|
|
13356
|
+
try {
|
|
13357
|
+
let t = await _e.current?.["fwh-read-content-mvp"]?.({});
|
|
13358
|
+
typeof t == "string" && t && !/^Could not/i.test(t) && (e = t.slice(0, 2800));
|
|
13359
|
+
} catch {}
|
|
13360
|
+
P.current?.sendUserMessage?.(e ? `Give the visitor a complete spoken overview of this page in 4-6 sentences, based ONLY on this page content:\n"""${e}"""\nThen ask which part they'd like to hear more about. Do not call any tool.` : "Give the visitor a complete spoken overview of this page in 4-6 sentences based on what you know about it, then ask which part they'd like to hear more about. Do not call any tool.", { suppressQuestion: !0 });
|
|
13361
|
+
}
|
|
13306
13362
|
return;
|
|
13307
13363
|
}
|
|
13308
13364
|
try {
|
|
@@ -13310,7 +13366,14 @@ function g_({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
13310
13366
|
} catch (e) {
|
|
13311
13367
|
console.warn("[FlowEngage] walkthrough highlight failed:", e?.message || e);
|
|
13312
13368
|
}
|
|
13313
|
-
console.debug(`[FlowEngage] walkthrough step ${t + 1}/${e.length}: ${n}`)
|
|
13369
|
+
console.debug(`[FlowEngage] walkthrough step ${t + 1}/${e.length}: ${n}`);
|
|
13370
|
+
let r = "";
|
|
13371
|
+
try {
|
|
13372
|
+
let e = await _e.current?.["fwh-read-content-mvp"]?.({ section_text: n });
|
|
13373
|
+
typeof e == "string" && e && !/^Could not/i.test(e) && (r = e.slice(0, 2500));
|
|
13374
|
+
} catch {}
|
|
13375
|
+
let i = r ? `Here is this section's full content — describe it from THIS text only, and do not call any tool:\n"""${r}"""\n` : "read the section's content silently first (fwh-read-content-mvp) if you don't already have it. ";
|
|
13376
|
+
P.current?.sendUserMessage?.(`Describe the section titled "${n}" in 3-4 sentences, starting with ${t === 0 ? "Starting with" : "Next —"} ${n}. Describe ONLY this section. If this section contains named sub-items (steps, checklist entries, cards, plans, FAQs, team members), name EVERY one of them in order with a short phrase each — never skip or collapse them into a summary; ` + i + "This section is ON THE PAGE THE VISITOR IS ALREADY ON — do NOT call fwh-navigate-mvp, do not go to a product/detail page, and do not offer to, even if this section's name also matches a page name. Do not mention any other section, do not ask whether to continue, then stop.", { suppressQuestion: !0 });
|
|
13314
13377
|
};
|
|
13315
13378
|
let ge = p(0), P = p(null), _e = p(null), ve = p(""), ye = p(async () => {}), be = p(!1), F = p(!1), xe = p(!1), L = p(!1), Te = p("minimized"), Ee = p(null), De = p(null), Oe = p(null), Ae = p(0), je = p(!1), R = p("idle"), z = p(null), Ne = p(!1), Pe = p(null), Fe = o((e = "minimized") => {
|
|
13316
13379
|
console.warn("[FlowEngage:VoiceDebug] 🛑 requestSessionShutdown called", {
|
|
@@ -13538,8 +13601,9 @@ function g_({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
13538
13601
|
},
|
|
13539
13602
|
onMessage: (t) => {
|
|
13540
13603
|
if (e || ce.current && t.role !== "user" && !/email/i.test(String(t.message || ""))) return;
|
|
13541
|
-
|
|
13542
|
-
|
|
13604
|
+
let n = t.role === "user" && /^(Describe the section titled "|\[SYSTEM:|Give the visitor a complete spoken overview|That was the last section)/.test(String(t.message || "").trim()), r = /\b(?:this|that|the)\s+(?:case\s*stud(?:y|ies)|product|article|blog|post|item|service)\b/i.test(String(t.message || ""));
|
|
13605
|
+
if (!n && !r && t.role === "user" && V.test(String(t.message || ""))) typeof window < "u" && (window.__fe_user_nav_during_speech = null), he(!0), de.current = !1, le.current = 0, ge.current = -1, pe.current = i_(), setTimeout(() => me.current?.(), 400), console.log(`[FlowEngage] walkthrough armed — ${pe.current.length} sections on this page`);
|
|
13606
|
+
else if (!n && t.role === "user" && ue.current) {
|
|
13543
13607
|
let e = String(t.message || "").trim();
|
|
13544
13608
|
Le.test(e) ? de.current && (de.current = !1, console.debug("[FlowEngage] walkthrough resumed by visitor"), setTimeout(() => me.current?.(), 300)) : (de.current = !0, console.debug("[FlowEngage] walkthrough paused — visitor interjected"));
|
|
13545
13609
|
}
|
|
@@ -13547,22 +13611,22 @@ function g_({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
13547
13611
|
let e = pe.current.length;
|
|
13548
13612
|
!e || ge.current >= e - 1 ? he(!1) : console.debug(`[FlowEngage] agent claimed completion at step ${ge.current + 1}/${e} — ignoring, tour continues`);
|
|
13549
13613
|
}
|
|
13550
|
-
let
|
|
13551
|
-
if (
|
|
13552
|
-
if (
|
|
13553
|
-
sender:
|
|
13554
|
-
message:
|
|
13614
|
+
let a = t.role === "user" ? "user" : "bot", o = t.message || t.text || t.content || "";
|
|
13615
|
+
if (o) {
|
|
13616
|
+
if (a === "user" && (ve.current = o, typeof window < "u" && (window.__fe_user_nav_during_speech = null), Ne.current = !0, z.current &&= (clearTimeout(z.current), null), R.current !== "speaking" && (E("thinking"), R.current = "thinking"), Oe && !ye && !ie.current && !fe.current && (ye = !0, se.current = o, ce.current = !0, P.current?.injectAgentSpeech?.("Before I answer that, could you please enter your email in the text box below?", "interrupt"), P.current?.setMicMuted?.(!0), ae.current || (ae.current = !0, oe.current = 0, te(!0), Re()))), l.current = [...l.current, {
|
|
13617
|
+
sender: a,
|
|
13618
|
+
message: o,
|
|
13555
13619
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13556
13620
|
debug: t.debug
|
|
13557
13621
|
}], i) try {
|
|
13558
13622
|
let e = gg(l.current);
|
|
13559
13623
|
e && I(i, e);
|
|
13560
13624
|
} catch {}
|
|
13561
|
-
if (f_(
|
|
13625
|
+
if (f_(a, o)) {
|
|
13562
13626
|
je.current = !0;
|
|
13563
13627
|
return;
|
|
13564
13628
|
}
|
|
13565
|
-
if (F.current &&
|
|
13629
|
+
if (F.current && a === "bot" && /are you still there|still there\??|hello\?|anyone there|checking in|you there|are you available|is anyone|did you step away/i.test(o)) if (Ae.current += 1, Ae.current === 2) try {
|
|
13566
13630
|
P.current?.sendContextualUpdate?.("IMPORTANT: The visitor is muted and has not responded to your last 2 checks. Make exactly ONE more check. If there is still no response, say: 'I feel like you are not active, so I'm ending this session. You can connect with me anytime.' then immediately call the fwh-end-session-mvp tool to end the voice session. Do NOT ask again after that.");
|
|
13567
13631
|
} catch {}
|
|
13568
13632
|
else Ae.current >= 5 && Fe("minimized");
|
|
@@ -13634,37 +13698,36 @@ function g_({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
13634
13698
|
t = i;
|
|
13635
13699
|
return;
|
|
13636
13700
|
}
|
|
13637
|
-
if (k && r(i) === r(k)) {
|
|
13638
|
-
t = i;
|
|
13639
|
-
return;
|
|
13640
|
-
}
|
|
13641
13701
|
if (Date.now() - n < 8e3) {
|
|
13642
13702
|
t = i;
|
|
13643
13703
|
return;
|
|
13644
13704
|
}
|
|
13645
|
-
|
|
13646
|
-
t = i;
|
|
13647
|
-
return;
|
|
13648
|
-
}
|
|
13649
|
-
let a = t;
|
|
13705
|
+
let a = typeof window < "u" && window.__fe_agent_nav || null, o = k && r(i) === r(k) || zn() || a && Date.now() - a.ts < 15e3 && r(a.path) === r(i), s = t;
|
|
13650
13706
|
t = i;
|
|
13651
|
-
let
|
|
13707
|
+
let c = window.location.href, l = typeof document < "u" ? document.title : "", u = typeof document < "u" ? Array.from(document.querySelectorAll("h1, h2, h3, h4")).filter((e) => !e.closest("#flowengage-root, .flowengage-shell")).map((e) => ({
|
|
13652
13708
|
tag: e.tagName,
|
|
13653
13709
|
text: e.textContent.trim()
|
|
13654
13710
|
})).filter((e) => e.text.length > 0 && e.text.length < 200).slice(0, 20) : [];
|
|
13655
13711
|
try {
|
|
13656
13712
|
On();
|
|
13657
13713
|
} catch {}
|
|
13658
|
-
let
|
|
13714
|
+
let d = (e) => (e.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()) || "Home", f = d(s), p = d(i);
|
|
13715
|
+
if (o) {
|
|
13716
|
+
typeof window < "u" && (window.__fe_agent_nav = null), console.log(`[FlowEngage] agent-driven navigation settled: "${s}" → "${i}"`);
|
|
13717
|
+
try {
|
|
13718
|
+
P.current?.sendUserMessage?.(`[SYSTEM: YOU just navigated the visitor to the "${p}" page (${c}) at their request — this was YOUR action, not theirs. Page title: "${l}". Sections: ${JSON.stringify(u)}. Say: "Here we are on the ${p} page." Then introduce this page in 2-3 sentences, and finish by asking: "Would you like me to walk you through it section by section?" NEVER say "I see you've navigated" — the visitor did not navigate, you did. Do NOT call fwh-navigate-mvp again. Wait for their answer before describing sections.]`, { suppressQuestion: !0 });
|
|
13719
|
+
} catch {}
|
|
13720
|
+
return;
|
|
13721
|
+
}
|
|
13659
13722
|
typeof window < "u" && (window.__fe_user_nav_during_speech = {
|
|
13660
|
-
fromPath:
|
|
13723
|
+
fromPath: s,
|
|
13661
13724
|
toPath: i,
|
|
13662
|
-
fromPageName:
|
|
13663
|
-
toPageName:
|
|
13725
|
+
fromPageName: f,
|
|
13726
|
+
toPageName: p,
|
|
13664
13727
|
ts: Date.now()
|
|
13665
|
-
}), console.log(`[FlowEngage] visitor navigation detected: "${
|
|
13728
|
+
}), console.log(`[FlowEngage] visitor navigation detected: "${s}" → "${i}" (agent target: ${k || "none"})`);
|
|
13666
13729
|
try {
|
|
13667
|
-
P.current?.sendUserMessage?.(`[SYSTEM: I navigated away mid-walkthrough — I am now on the "${
|
|
13730
|
+
P.current?.sendUserMessage?.(`[SYSTEM: I navigated away mid-walkthrough — I am now on the "${p}" page (${c}). Page title: "${l}". Sections: ${JSON.stringify(u)}. STOP everything. Do NOT describe the new page. Say EXACTLY: "I see you've navigated to the ${p} page — would you like me to continue what I was explaining, or shall I walk you through this page?" Then wait for my answer. IF I say continue/yes/carry on: resume speaking verbally from where you left off — do NOT call fwh-navigate-mvp, do NOT call fwh-highlight-mvp, the visitor will navigate themselves if needed. IF I want to hear about this page: call fwh-highlight-mvp for sections of "${p}" only.]`);
|
|
13668
13731
|
} catch {}
|
|
13669
13732
|
};
|
|
13670
13733
|
c = window.history.pushState.bind(window.history), window.history.pushState = (...e) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowengage/react-chatbot",
|
|
3
|
-
"version": "8.0.
|
|
4
|
-
"description": "Embeddable AI chat widget for React
|
|
3
|
+
"version": "8.0.103",
|
|
4
|
+
"description": "Embeddable AI chat widget for React — powered by FlowEngage. Drop it in with a single siteId.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
7
7
|
"customer-support",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"scripts": {
|
|
32
32
|
"dev": "vite",
|
|
33
33
|
"build": "vite build",
|
|
34
|
-
"build:embed": "vite build --config vite.embed.config.js &&
|
|
34
|
+
"build:embed": "vite build --config vite.embed.config.js && node -e \"require('fs').copyFileSync('dist/flowengage-embed.js', 'dist/flowengage-embed-' + process.env.npm_package_version + '.js')\"",
|
|
35
35
|
"build:all": "npm run build && npm run build:embed",
|
|
36
36
|
"prepublishOnly": "npm run build:all",
|
|
37
37
|
"lint": "eslint .",
|