@flowengage/react-chatbot 8.0.13 → 8.0.15
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.
|
@@ -29482,32 +29482,6 @@ function ik(e) {
|
|
|
29482
29482
|
});
|
|
29483
29483
|
},
|
|
29484
29484
|
"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.",
|
|
29485
|
-
"fwh-save-email-mvp": async (r) => {
|
|
29486
|
-
$("fwh-save-email-mvp ▶", r);
|
|
29487
|
-
let i = ($O(r)?.email || "").trim();
|
|
29488
|
-
if (!i || !i.includes("@")) return "INVALID_EMAIL: The email address is not valid. Ask the visitor to repeat it clearly, or tell them to type it in the field below.";
|
|
29489
|
-
if (!n) return "Cannot save email: API base URL not configured.";
|
|
29490
|
-
let a = e.chatId || null;
|
|
29491
|
-
if (!a) return "Cannot save email: no active chat session.";
|
|
29492
|
-
try {
|
|
29493
|
-
let e = await (await fetch(`${n}/api/voice/save-visitor-email`, {
|
|
29494
|
-
method: "POST",
|
|
29495
|
-
headers: { "Content-Type": "application/json" },
|
|
29496
|
-
body: JSON.stringify({
|
|
29497
|
-
chatId: a,
|
|
29498
|
-
email: i,
|
|
29499
|
-
siteId: t
|
|
29500
|
-
})
|
|
29501
|
-
})).json();
|
|
29502
|
-
if (!e.success) return `Failed to save email: ${e.error || "unknown error"}`;
|
|
29503
|
-
try {
|
|
29504
|
-
typeof window < "u" && window.dispatchEvent(new CustomEvent("fe:voice-email-saved", { detail: { email: i } }));
|
|
29505
|
-
} catch {}
|
|
29506
|
-
return $("fwh-save-email-mvp ✓", i), `EMAIL_SAVED: ${i}. Now answer the visitor's original question.`;
|
|
29507
|
-
} catch (e) {
|
|
29508
|
-
return $("fwh-save-email-mvp ✖", e.message), `Failed to save email: ${e.message}`;
|
|
29509
|
-
}
|
|
29510
|
-
},
|
|
29511
29485
|
"fwh-click-button-mvp": async (e) => {
|
|
29512
29486
|
let t = $O(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
|
|
29513
29487
|
if ($("fwh-click-button-mvp ▶", n), !n) return "Missing button_text: pass the visible label, e.g. Conduct Audit.";
|
|
@@ -29970,21 +29944,17 @@ function hk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onC
|
|
|
29970
29944
|
]
|
|
29971
29945
|
});
|
|
29972
29946
|
}
|
|
29973
|
-
function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i, apiBaseUrl: a, chatId: s, historyRef: l, onMessageSync: u, voiceEndCounter: d, websiteName: f,
|
|
29947
|
+
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 }) {
|
|
29974
29948
|
c(() => (console.log("[FlowEngage:VoiceDebug] 🔵 VoiceMode MOUNTED"), () => console.log("[FlowEngage:VoiceDebug] 🔴 VoiceMode UNMOUNTED")), []);
|
|
29975
|
-
let [v, y] = m("idle"), [b, x] = m(!1), [S, C] = m(!1),
|
|
29976
|
-
c(() => {
|
|
29977
|
-
ge.current = h;
|
|
29978
|
-
}, [h]);
|
|
29979
|
-
let _e = p(!1), ve = p(null), ye = p(!1), be = p(!1), xe = p(null), Se = p(null), Ce = p(!1), we = o((e = "minimized") => {
|
|
29949
|
+
let [v, y] = m("idle"), [b, x] = m(!1), [S, C] = m(!1), w = p(null), T = p(""), ee = p(async () => {}), te = p(!1), ne = p(!1), re = p(!1), E = p(!1), ie = p("minimized"), ae = p(null), oe = p(null), D = p(null), se = p(0), ce = p(!1), le = p("idle"), ue = p(!1), de = p(!1), fe = p(null), pe = p(null), me = p(!1), he = o((e = "minimized") => {
|
|
29980
29950
|
console.warn("[FlowEngage:VoiceDebug] 🛑 requestSessionShutdown called", {
|
|
29981
29951
|
destination: e,
|
|
29982
29952
|
stack: (/* @__PURE__ */ Error()).stack?.split("\n").slice(1, 4).join(" | ")
|
|
29983
|
-
}),
|
|
29984
|
-
|
|
29953
|
+
}), ie.current = e, E.current = !0, queueMicrotask(() => {
|
|
29954
|
+
te.current || (te.current = !0, ee.current?.());
|
|
29985
29955
|
});
|
|
29986
|
-
}, [l]),
|
|
29987
|
-
|
|
29956
|
+
}, [l]), ge = o(async (e) => {
|
|
29957
|
+
E.current = !0;
|
|
29988
29958
|
try {
|
|
29989
29959
|
Bn();
|
|
29990
29960
|
} catch {}
|
|
@@ -29992,9 +29962,9 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
29992
29962
|
Ve(i);
|
|
29993
29963
|
} catch {}
|
|
29994
29964
|
try {
|
|
29995
|
-
await
|
|
29965
|
+
await w.current?.endSession?.();
|
|
29996
29966
|
} catch {}
|
|
29997
|
-
let t =
|
|
29967
|
+
let t = ae.current, n = oe.current;
|
|
29998
29968
|
if (t && s && a) {
|
|
29999
29969
|
let e = n ? Math.round((Date.now() - n) / 1e3) : 0;
|
|
30000
29970
|
fetch(`${a}/api/voice/save-chat-recording`, {
|
|
@@ -30008,7 +29978,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30008
29978
|
})
|
|
30009
29979
|
}).catch((e) => console.warn("[FlowEngage] save-chat-recording failed:", e.message));
|
|
30010
29980
|
}
|
|
30011
|
-
if (
|
|
29981
|
+
if (ae.current = null, oe.current = null, w.current = null, y("idle"), x(!1), te.current = !1, Ir(), i) try {
|
|
30012
29982
|
je(i);
|
|
30013
29983
|
} catch {}
|
|
30014
29984
|
typeof u == "function" && await u(l.current), e?.();
|
|
@@ -30019,10 +29989,10 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30019
29989
|
s,
|
|
30020
29990
|
a
|
|
30021
29991
|
]);
|
|
30022
|
-
|
|
30023
|
-
|
|
29992
|
+
return ee.current = () => ge(ie.current === "chat" ? t : n), c(() => {
|
|
29993
|
+
ne.current = b;
|
|
30024
29994
|
}, [b]), c(() => {
|
|
30025
|
-
d &&
|
|
29995
|
+
d && he("chat");
|
|
30026
29996
|
}, [d]), c(() => {
|
|
30027
29997
|
let e = !1, o = null, c = null, d = null;
|
|
30028
29998
|
return (async () => {
|
|
@@ -30032,13 +30002,13 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30032
30002
|
}
|
|
30033
30003
|
try {
|
|
30034
30004
|
if ((await navigator.mediaDevices.getUserMedia({ audio: !0 })).getTracks().forEach((e) => e.stop()), e) return;
|
|
30035
|
-
l.current = [],
|
|
30005
|
+
l.current = [], T.current = "", te.current = !1, re.current = !1, E.current = !1, ie.current = "minimized", Fr({ onBeforeNavigate: () => {
|
|
30036
30006
|
if (i && l.current.length > 0) try {
|
|
30037
30007
|
let e = SO(l.current);
|
|
30038
30008
|
e && O(i, e);
|
|
30039
30009
|
} catch {}
|
|
30040
30010
|
if (!or()) {
|
|
30041
|
-
let e =
|
|
30011
|
+
let e = ae.current, t = oe.current;
|
|
30042
30012
|
if (e && s && a) try {
|
|
30043
30013
|
let n = t ? Math.round((Date.now() - t) / 1e3) : 0, r = JSON.stringify({
|
|
30044
30014
|
chatId: s,
|
|
@@ -30051,7 +30021,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30051
30021
|
headers: { "Content-Type": "application/json" },
|
|
30052
30022
|
body: r,
|
|
30053
30023
|
keepalive: !0
|
|
30054
|
-
}).catch(() => {}),
|
|
30024
|
+
}).catch(() => {}), ae.current = null, oe.current = null;
|
|
30055
30025
|
} catch {}
|
|
30056
30026
|
}
|
|
30057
30027
|
Ne();
|
|
@@ -30060,17 +30030,17 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30060
30030
|
siteId: i || null,
|
|
30061
30031
|
apiBaseUrl: a || null,
|
|
30062
30032
|
chatId: s || null,
|
|
30063
|
-
getLastUserVoiceText: () =>
|
|
30033
|
+
getLastUserVoiceText: () => T.current,
|
|
30064
30034
|
requestEndSession: () => {
|
|
30065
|
-
|
|
30035
|
+
ce.current = !0;
|
|
30066
30036
|
}
|
|
30067
|
-
})), n = i ? Ae(i) : null, u = !!n?.transcript, p = i ? Ve(i) : null, m = !!p,
|
|
30037
|
+
})), n = i ? Ae(i) : null, u = !!n?.transcript, p = i ? Ve(i) : null, m = !!p, g = typeof window < "u" ? window.location.pathname : "/", _ = typeof document < "u" ? document.title : "", v = g.replace(/^\/[a-z]{2}(?:-[a-z]{2})?(?=\/|$)/i, "") || "/", b = v === "/" || v === "", S = null;
|
|
30068
30038
|
try {
|
|
30069
30039
|
let e = await fetch(`${a}/api/voice/signed-url?siteId=${encodeURIComponent(i || "")}`, {
|
|
30070
30040
|
method: "GET",
|
|
30071
30041
|
headers: { "Content-Type": "application/json" }
|
|
30072
30042
|
});
|
|
30073
|
-
if (e.ok)
|
|
30043
|
+
if (e.ok) S = (await e.json()).signedUrl || null, S && console.log("[FlowEngage] ✅ Using signed ElevenLabs URL");
|
|
30074
30044
|
else if (e.status === 429) {
|
|
30075
30045
|
let t = await e.json().catch(() => ({}));
|
|
30076
30046
|
throw Error(t.message || "Too many voice sessions started. Please wait a minute before trying again.");
|
|
@@ -30079,55 +30049,55 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30079
30049
|
if (e.message && e.message.includes("Too many voice sessions")) throw e;
|
|
30080
30050
|
console.warn("[FlowEngage] ⚠️ Signed URL fetch error:", e.message);
|
|
30081
30051
|
}
|
|
30082
|
-
let
|
|
30052
|
+
let C = {
|
|
30083
30053
|
clientTools: t,
|
|
30084
30054
|
connectionType: "websocket",
|
|
30085
30055
|
minSpeechDurationMs: 50,
|
|
30086
|
-
...
|
|
30087
|
-
},
|
|
30088
|
-
|
|
30089
|
-
let
|
|
30090
|
-
if (
|
|
30091
|
-
let e = p?.pageName ||
|
|
30092
|
-
|
|
30093
|
-
} else if (u)
|
|
30056
|
+
...S ? { signedUrl: S } : { agentId: r }
|
|
30057
|
+
}, ee = (g.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()), D = "";
|
|
30058
|
+
_ && _.includes("|") && (D = _.split("|").map((e) => e.trim()).filter(Boolean).reduce((e, t) => e.length <= t.length ? e : t));
|
|
30059
|
+
let ge = D || ee || "this page";
|
|
30060
|
+
if (S) if (m) {
|
|
30061
|
+
let e = p?.pageName || ge;
|
|
30062
|
+
C.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})`);
|
|
30063
|
+
} else if (u) C.overrides = { agent: { firstMessage: "I'm still here. Go ahead!" } };
|
|
30094
30064
|
else {
|
|
30095
30065
|
let e = f || "";
|
|
30096
|
-
|
|
30066
|
+
C.overrides = { agent: { firstMessage: h || (b ? e ? `Hi, welcome to ${e}!` : "Hi, welcome!" : `Welcome to the ${ge} page!`) } }, b || console.log(`[FlowEngage] 🏠 Page-context override: "${ge}" for ${g}`);
|
|
30097
30067
|
}
|
|
30098
|
-
else u && (
|
|
30099
|
-
let
|
|
30100
|
-
...
|
|
30068
|
+
else u && (C.overrides = { agent: { firstMessage: "" } });
|
|
30069
|
+
let _e = !1, ve = 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, ye = !1, be = !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, xe = await ED.startSession({
|
|
30070
|
+
...C,
|
|
30101
30071
|
onConnect: ({ conversationId: e }) => {
|
|
30102
|
-
|
|
30072
|
+
ae.current = e, oe.current = Date.now(), console.log("[FlowEngage] 🎙️ AI chat session connected:", e);
|
|
30103
30073
|
},
|
|
30104
30074
|
onUnhandledClientToolCall: (e) => console.error("[FlowEngage] Unhandled tool:", e?.tool_name),
|
|
30105
30075
|
onModeChange: ({ mode: t }) => {
|
|
30106
30076
|
if (!e) {
|
|
30107
30077
|
if (t === "speaking") {
|
|
30108
|
-
|
|
30078
|
+
pe.current &&= (clearTimeout(pe.current), null), y("speaking"), le.current = "speaking", ue.current = !0, me.current = !1, fe.current &&= (clearTimeout(fe.current), null);
|
|
30109
30079
|
return;
|
|
30110
30080
|
}
|
|
30111
|
-
if (
|
|
30112
|
-
|
|
30081
|
+
if (le.current = "listening", ce.current) {
|
|
30082
|
+
ce.current = !1, he();
|
|
30113
30083
|
return;
|
|
30114
30084
|
}
|
|
30115
|
-
if (
|
|
30116
|
-
|
|
30085
|
+
if (ve && !_e) {
|
|
30086
|
+
_e = !0;
|
|
30117
30087
|
try {
|
|
30118
|
-
|
|
30088
|
+
w.current?.sendContextualUpdate?.(ve);
|
|
30119
30089
|
} catch {}
|
|
30120
30090
|
}
|
|
30121
|
-
if (
|
|
30122
|
-
|
|
30091
|
+
if (be && !ye) {
|
|
30092
|
+
ye = !0;
|
|
30123
30093
|
try {
|
|
30124
|
-
|
|
30094
|
+
w.current?.sendContextualUpdate?.(be);
|
|
30125
30095
|
} catch {}
|
|
30126
30096
|
}
|
|
30127
|
-
|
|
30128
|
-
e ||
|
|
30129
|
-
if (!e &&
|
|
30130
|
-
|
|
30097
|
+
pe.current && clearTimeout(pe.current), pe.current = setTimeout(() => {
|
|
30098
|
+
e || le.current !== "speaking" && (me.current || (pe.current = null, le.current = "listening", y("listening"), ue.current && de.current && !ne.current && (fe.current && clearTimeout(fe.current), fe.current = setTimeout(() => {
|
|
30099
|
+
if (!e && le.current === "listening" && !ne.current) try {
|
|
30100
|
+
w.current?.sendContextualUpdate?.("The visitor has been silent for a while. Ask one short, natural question to re-engage — for example: 'Is there anything specific you'd like to know more about?' or 'What else can I help you with today?' Keep it to one sentence.");
|
|
30131
30101
|
} catch {}
|
|
30132
30102
|
}, 15e3))));
|
|
30133
30103
|
}, 1200);
|
|
@@ -30138,22 +30108,10 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30138
30108
|
let n = t.role === "user" ? "user" : "bot", r = t.message || t.text || t.content || "";
|
|
30139
30109
|
if (r) {
|
|
30140
30110
|
if (n === "user") {
|
|
30141
|
-
|
|
30111
|
+
T.current = r, me.current = !0, de.current = !0, pe.current &&= (clearTimeout(pe.current), null), fe.current &&= (clearTimeout(fe.current), null);
|
|
30142
30112
|
try {
|
|
30143
30113
|
Bn();
|
|
30144
30114
|
} catch {}
|
|
30145
|
-
if (!ge.current && !_e.current) {
|
|
30146
|
-
_e.current = !0;
|
|
30147
|
-
try {
|
|
30148
|
-
E.current?.sendContextualUpdate?.("COLLECT_EMAIL: Before answering the visitor's question, you MUST first ask for their email address. Say: 'Before I answer, could I get your email address? You can also type it in the field below.' Do NOT answer their question yet — wait for the email first.");
|
|
30149
|
-
} catch {}
|
|
30150
|
-
T(!0), ve.current && clearTimeout(ve.current), ve.current = setTimeout(() => {
|
|
30151
|
-
ve.current = null;
|
|
30152
|
-
try {
|
|
30153
|
-
E.current?.sendContextualUpdate?.("The visitor has not provided their email for 1 minute and appears to have left. Say exactly: '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.");
|
|
30154
|
-
} catch {}
|
|
30155
|
-
}, 6e4);
|
|
30156
|
-
}
|
|
30157
30115
|
}
|
|
30158
30116
|
if (l.current = [...l.current, {
|
|
30159
30117
|
sender: n,
|
|
@@ -30164,50 +30122,50 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30164
30122
|
e && O(i, e);
|
|
30165
30123
|
} catch {}
|
|
30166
30124
|
if (fk(n, r)) {
|
|
30167
|
-
|
|
30125
|
+
ce.current = !0;
|
|
30168
30126
|
return;
|
|
30169
30127
|
}
|
|
30170
|
-
if (
|
|
30171
|
-
|
|
30128
|
+
if (ne.current && n === "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(r)) if (se.current += 1, se.current === 2) try {
|
|
30129
|
+
w.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.");
|
|
30172
30130
|
} catch {}
|
|
30173
|
-
else
|
|
30131
|
+
else se.current >= 5 && he("minimized");
|
|
30174
30132
|
}
|
|
30175
30133
|
},
|
|
30176
30134
|
onError: (t) => {
|
|
30177
|
-
if (!e && !
|
|
30178
|
-
|
|
30135
|
+
if (!e && !E.current && !re.current && !Re()) {
|
|
30136
|
+
re.current = !0, console.error("[FlowEngageVoiceCall] session:error", {
|
|
30179
30137
|
message: t?.message,
|
|
30180
30138
|
name: t?.name,
|
|
30181
30139
|
raw: t
|
|
30182
30140
|
});
|
|
30183
30141
|
try {
|
|
30184
|
-
|
|
30142
|
+
w.current?.setMicMuted?.(!0);
|
|
30185
30143
|
} catch {}
|
|
30186
|
-
x(!0), y("error"),
|
|
30144
|
+
x(!0), y("error"), he("chat");
|
|
30187
30145
|
}
|
|
30188
30146
|
},
|
|
30189
30147
|
onDisconnect: (t) => {
|
|
30190
|
-
if (e ||
|
|
30148
|
+
if (e || E.current || re.current || Re()) return;
|
|
30191
30149
|
let n = l.current?.length || 0;
|
|
30192
30150
|
console.warn("[FlowEngageVoiceCall] session:disconnected", {
|
|
30193
30151
|
historyCount: n,
|
|
30194
30152
|
reason: t?.reason,
|
|
30195
30153
|
closeCode: t?.context?.code,
|
|
30196
30154
|
closeReason: t?.context?.reason || t?.message,
|
|
30197
|
-
lastUserText:
|
|
30198
|
-
wasMuted:
|
|
30199
|
-
}),
|
|
30155
|
+
lastUserText: T.current || "",
|
|
30156
|
+
wasMuted: ne.current
|
|
30157
|
+
}), re.current = !0;
|
|
30200
30158
|
try {
|
|
30201
|
-
|
|
30159
|
+
w.current?.setMicMuted?.(!0);
|
|
30202
30160
|
} catch {}
|
|
30203
|
-
x(!0),
|
|
30161
|
+
x(!0), he("chat");
|
|
30204
30162
|
}
|
|
30205
30163
|
});
|
|
30206
30164
|
if (e) {
|
|
30207
|
-
console.warn("[FlowEngage:VoiceDebug] ❌ cancelled=true after startSession resolved — killing session immediately"),
|
|
30165
|
+
console.warn("[FlowEngage:VoiceDebug] ❌ cancelled=true after startSession resolved — killing session immediately"), xe.endSession().catch(() => {});
|
|
30208
30166
|
return;
|
|
30209
30167
|
}
|
|
30210
|
-
o =
|
|
30168
|
+
o = xe, w.current = xe, y("listening");
|
|
30211
30169
|
try {
|
|
30212
30170
|
let e = typeof window < "u" ? window.location.href : "", r = "[]";
|
|
30213
30171
|
try {
|
|
@@ -30219,7 +30177,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30219
30177
|
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(" | "));
|
|
30220
30178
|
} catch {}
|
|
30221
30179
|
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` : "";
|
|
30222
|
-
|
|
30180
|
+
xe.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.`);
|
|
30223
30181
|
} catch {}
|
|
30224
30182
|
if (typeof window < "u") {
|
|
30225
30183
|
let t = window.location.pathname, n = () => {
|
|
@@ -30248,7 +30206,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30248
30206
|
ts: Date.now()
|
|
30249
30207
|
});
|
|
30250
30208
|
try {
|
|
30251
|
-
|
|
30209
|
+
w.current?.sendUserMessage?.(`[SYSTEM: I navigated away mid-walkthrough — I am now on the "${l}" page (${i}). Page title: "${a}". Sections: ${JSON.stringify(o)}. STOP everything. Do NOT describe the new page. Say EXACTLY: "I see you've navigated to the ${l} 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 flowengage_navigate, do NOT call flowengage_highlight, the visitor will navigate themselves if needed. IF I want to hear about this page: call flowengage_highlight for sections of "${l}" only.]`);
|
|
30252
30210
|
} catch {}
|
|
30253
30211
|
};
|
|
30254
30212
|
c = window.history.pushState.bind(window.history), window.history.pushState = (...e) => {
|
|
@@ -30256,7 +30214,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30256
30214
|
}, d = () => setTimeout(n, 50), window.addEventListener("popstate", d);
|
|
30257
30215
|
}
|
|
30258
30216
|
} catch (r) {
|
|
30259
|
-
e || (console.error("[FlowEngage] startSession failed", r), r.message && r.message.includes("Too many voice sessions") ? (alert(r.message), n && n("minimized")) : (y("error"),
|
|
30217
|
+
e || (console.error("[FlowEngage] startSession failed", r), r.message && r.message.includes("Too many voice sessions") ? (alert(r.message), n && n("minimized")) : (y("error"), ie.current = "chat", window.setTimeout(() => {
|
|
30260
30218
|
e || t?.();
|
|
30261
30219
|
}, 0)));
|
|
30262
30220
|
}
|
|
@@ -30265,15 +30223,15 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30265
30223
|
agentId: r,
|
|
30266
30224
|
siteId: i,
|
|
30267
30225
|
apiBaseUrl: a
|
|
30268
|
-
}), e = !0,
|
|
30226
|
+
}), e = !0, E.current = !0;
|
|
30269
30227
|
try {
|
|
30270
30228
|
Bn();
|
|
30271
30229
|
} catch {}
|
|
30272
30230
|
if (i) try {
|
|
30273
30231
|
Ve(i);
|
|
30274
30232
|
} catch {}
|
|
30275
|
-
typeof window < "u" && (window.__fe_user_nav_during_speech = null), Ir(),
|
|
30276
|
-
let t = o ||
|
|
30233
|
+
typeof window < "u" && (window.__fe_user_nav_during_speech = null), Ir(), fe.current &&= (clearTimeout(fe.current), null), pe.current &&= (clearTimeout(pe.current), null), ue.current = !1, me.current = !1, le.current = "idle", c && typeof window < "u" && (window.history.pushState = c), d && typeof window < "u" && window.removeEventListener("popstate", d);
|
|
30234
|
+
let t = o || w.current, n = ae.current, f = oe.current;
|
|
30277
30235
|
if (t?.endSession?.().catch(() => {}), n && s && a) {
|
|
30278
30236
|
let e = f ? Math.round((Date.now() - f) / 1e3) : 0, t = JSON.stringify({
|
|
30279
30237
|
chatId: s,
|
|
@@ -30286,7 +30244,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30286
30244
|
headers: { "Content-Type": "application/json" },
|
|
30287
30245
|
body: t,
|
|
30288
30246
|
keepalive: !0
|
|
30289
|
-
}).catch(() => {}),
|
|
30247
|
+
}).catch(() => {}), ae.current = null, oe.current = null;
|
|
30290
30248
|
}
|
|
30291
30249
|
typeof u == "function" && l.current.length > 0 && u(l.current).catch?.(() => {});
|
|
30292
30250
|
};
|
|
@@ -30294,50 +30252,16 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30294
30252
|
r,
|
|
30295
30253
|
i,
|
|
30296
30254
|
a,
|
|
30297
|
-
|
|
30255
|
+
he
|
|
30298
30256
|
]), c(() => {
|
|
30299
30257
|
if (!S) return;
|
|
30300
30258
|
let e = (e) => {
|
|
30301
30259
|
let t = e.composedPath?.()?.[0] || e.target;
|
|
30302
|
-
|
|
30260
|
+
D.current && !D.current.contains(t) && C(!1);
|
|
30303
30261
|
};
|
|
30304
30262
|
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
30305
|
-
}, [S]),
|
|
30306
|
-
|
|
30307
|
-
ve.current &&= (clearTimeout(ve.current), null), e?.detail?.email && (ge.current = e.detail.email), T(!1), te(""), re("");
|
|
30308
|
-
};
|
|
30309
|
-
return window.addEventListener("fe:voice-email-saved", e), () => window.removeEventListener("fe:voice-email-saved", e);
|
|
30310
|
-
}, []);
|
|
30311
|
-
let Ee = async () => {
|
|
30312
|
-
let e = ee.trim();
|
|
30313
|
-
if (!e || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)) {
|
|
30314
|
-
re("Please enter a valid email address.");
|
|
30315
|
-
return;
|
|
30316
|
-
}
|
|
30317
|
-
re("");
|
|
30318
|
-
try {
|
|
30319
|
-
if (!(await (await fetch(`${a}/api/voice/save-visitor-email`, {
|
|
30320
|
-
method: "POST",
|
|
30321
|
-
headers: { "Content-Type": "application/json" },
|
|
30322
|
-
body: JSON.stringify({
|
|
30323
|
-
chatId: s,
|
|
30324
|
-
email: e,
|
|
30325
|
-
siteId: i
|
|
30326
|
-
})
|
|
30327
|
-
})).json()).success) {
|
|
30328
|
-
re("Could not save email. Please try again.");
|
|
30329
|
-
return;
|
|
30330
|
-
}
|
|
30331
|
-
window.dispatchEvent(new CustomEvent("fe:voice-email-saved", { detail: { email: e } }));
|
|
30332
|
-
try {
|
|
30333
|
-
E.current?.sendContextualUpdate?.(`EMAIL_SAVED: ${e}. The visitor has typed their email in the widget. Now answer their original question.`);
|
|
30334
|
-
} catch {}
|
|
30335
|
-
} catch {
|
|
30336
|
-
re("Could not save email. Please try again.");
|
|
30337
|
-
}
|
|
30338
|
-
};
|
|
30339
|
-
return /* @__PURE__ */ _("div", {
|
|
30340
|
-
ref: fe,
|
|
30263
|
+
}, [S]), /* @__PURE__ */ _("div", {
|
|
30264
|
+
ref: D,
|
|
30341
30265
|
style: {
|
|
30342
30266
|
position: "relative",
|
|
30343
30267
|
display: "flex",
|
|
@@ -30398,82 +30322,6 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30398
30322
|
},
|
|
30399
30323
|
children: "Could not start voice session."
|
|
30400
30324
|
}),
|
|
30401
|
-
w && /* @__PURE__ */ _("div", {
|
|
30402
|
-
style: {
|
|
30403
|
-
background: "rgba(15,22,36,0.92)",
|
|
30404
|
-
backdropFilter: "blur(12px)",
|
|
30405
|
-
WebkitBackdropFilter: "blur(12px)",
|
|
30406
|
-
border: "1px solid rgba(255,255,255,0.15)",
|
|
30407
|
-
borderRadius: "12px",
|
|
30408
|
-
padding: "10px 12px",
|
|
30409
|
-
display: "flex",
|
|
30410
|
-
flexDirection: "column",
|
|
30411
|
-
gap: "6px",
|
|
30412
|
-
width: "240px"
|
|
30413
|
-
},
|
|
30414
|
-
children: [
|
|
30415
|
-
/* @__PURE__ */ g("span", {
|
|
30416
|
-
style: {
|
|
30417
|
-
color: "rgba(255,255,255,0.7)",
|
|
30418
|
-
fontSize: "11px",
|
|
30419
|
-
fontWeight: 500
|
|
30420
|
-
},
|
|
30421
|
-
children: "Type your email to continue"
|
|
30422
|
-
}),
|
|
30423
|
-
/* @__PURE__ */ _("div", {
|
|
30424
|
-
style: {
|
|
30425
|
-
display: "flex",
|
|
30426
|
-
gap: "6px",
|
|
30427
|
-
alignItems: "center"
|
|
30428
|
-
},
|
|
30429
|
-
children: [/* @__PURE__ */ g("input", {
|
|
30430
|
-
type: "email",
|
|
30431
|
-
value: ee,
|
|
30432
|
-
onChange: (e) => {
|
|
30433
|
-
te(e.target.value), re("");
|
|
30434
|
-
},
|
|
30435
|
-
onKeyDown: (e) => {
|
|
30436
|
-
e.key === "Enter" && Ee();
|
|
30437
|
-
},
|
|
30438
|
-
placeholder: "you@example.com",
|
|
30439
|
-
style: {
|
|
30440
|
-
flex: 1,
|
|
30441
|
-
background: "rgba(255,255,255,0.08)",
|
|
30442
|
-
border: "1px solid rgba(255,255,255,0.2)",
|
|
30443
|
-
borderRadius: "8px",
|
|
30444
|
-
color: "white",
|
|
30445
|
-
fontSize: "13px",
|
|
30446
|
-
padding: "6px 10px",
|
|
30447
|
-
outline: "none"
|
|
30448
|
-
}
|
|
30449
|
-
}), /* @__PURE__ */ g("button", {
|
|
30450
|
-
onClick: Ee,
|
|
30451
|
-
style: {
|
|
30452
|
-
width: "30px",
|
|
30453
|
-
height: "30px",
|
|
30454
|
-
borderRadius: "8px",
|
|
30455
|
-
background: "#2563eb",
|
|
30456
|
-
border: "none",
|
|
30457
|
-
color: "white",
|
|
30458
|
-
fontSize: "16px",
|
|
30459
|
-
cursor: "pointer",
|
|
30460
|
-
display: "flex",
|
|
30461
|
-
alignItems: "center",
|
|
30462
|
-
justifyContent: "center",
|
|
30463
|
-
flexShrink: 0
|
|
30464
|
-
},
|
|
30465
|
-
children: "→"
|
|
30466
|
-
})]
|
|
30467
|
-
}),
|
|
30468
|
-
ne && /* @__PURE__ */ g("span", {
|
|
30469
|
-
style: {
|
|
30470
|
-
color: "#f87171",
|
|
30471
|
-
fontSize: "11px"
|
|
30472
|
-
},
|
|
30473
|
-
children: ne
|
|
30474
|
-
})
|
|
30475
|
-
]
|
|
30476
|
-
}),
|
|
30477
30325
|
/* @__PURE__ */ _("div", {
|
|
30478
30326
|
style: {
|
|
30479
30327
|
display: "flex",
|
|
@@ -30482,16 +30330,16 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30482
30330
|
},
|
|
30483
30331
|
children: [/* @__PURE__ */ g("button", {
|
|
30484
30332
|
onClick: async () => {
|
|
30485
|
-
if (
|
|
30333
|
+
if (w.current) try {
|
|
30486
30334
|
if (b) {
|
|
30487
|
-
|
|
30335
|
+
se.current = 0, await w.current.setMicMuted?.(!1), x(!1);
|
|
30488
30336
|
try {
|
|
30489
|
-
|
|
30337
|
+
w.current.sendContextualUpdate?.("The visitor has unmuted. Resume normal interaction and wait for them to speak.");
|
|
30490
30338
|
} catch {}
|
|
30491
30339
|
} else {
|
|
30492
|
-
|
|
30340
|
+
se.current = 0, await w.current.setMicMuted?.(!0), x(!0);
|
|
30493
30341
|
try {
|
|
30494
|
-
|
|
30342
|
+
w.current.sendContextualUpdate?.("The visitor has muted their microphone. Do NOT speak, ask if they are there, or prompt them in any way. Stay completely silent until they unmute.");
|
|
30495
30343
|
} catch {}
|
|
30496
30344
|
}
|
|
30497
30345
|
} catch {}
|
|
@@ -30590,7 +30438,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30590
30438
|
children: [
|
|
30591
30439
|
/* @__PURE__ */ _("button", {
|
|
30592
30440
|
onClick: () => {
|
|
30593
|
-
C(!1),
|
|
30441
|
+
C(!1), ie.current = "chat", ge(t);
|
|
30594
30442
|
},
|
|
30595
30443
|
style: {
|
|
30596
30444
|
display: "flex",
|
|
@@ -30619,7 +30467,7 @@ function gk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
|
|
|
30619
30467
|
}),
|
|
30620
30468
|
/* @__PURE__ */ _("button", {
|
|
30621
30469
|
onClick: () => {
|
|
30622
|
-
C(!1),
|
|
30470
|
+
C(!1), ie.current = "minimized", ge(n);
|
|
30623
30471
|
},
|
|
30624
30472
|
style: {
|
|
30625
30473
|
display: "flex",
|
|
@@ -31547,13 +31395,7 @@ function bk() {
|
|
|
31547
31395
|
} catch {}
|
|
31548
31396
|
}, []), c(() => {
|
|
31549
31397
|
Ee && M !== "voice_mode" && M !== "text_chat" && M !== "call_screen" && (ue?.(!1), dt("text_chat"));
|
|
31550
|
-
}, [Ee])
|
|
31551
|
-
let e = (e) => {
|
|
31552
|
-
let t = e?.detail?.email;
|
|
31553
|
-
t && typeof le == "function" && le(t);
|
|
31554
|
-
};
|
|
31555
|
-
return window.addEventListener("fe:voice-email-saved", e), () => window.removeEventListener("fe:voice-email-saved", e);
|
|
31556
|
-
}, [le]);
|
|
31398
|
+
}, [Ee]);
|
|
31557
31399
|
let Oe = t?.widgetSettings || {}, ke = n?.widgetSettings || {}, O = {
|
|
31558
31400
|
...Oe.branding || {},
|
|
31559
31401
|
...ke.branding || {}
|
|
@@ -31967,7 +31809,7 @@ function bk() {
|
|
|
31967
31809
|
onMessageSync: oe,
|
|
31968
31810
|
voiceEndCounter: De,
|
|
31969
31811
|
websiteName: t?.websiteName,
|
|
31970
|
-
|
|
31812
|
+
voiceFirstMessage: Oe.voiceFirstMessage || null
|
|
31971
31813
|
}, "voice"),
|
|
31972
31814
|
M === "call_screen" && /* @__PURE__ */ g(bO, {
|
|
31973
31815
|
incomingCall: w,
|