@flowengage/react-chatbot 1.0.7 → 1.0.9

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.
@@ -2715,44 +2715,21 @@ function vn({ siteId: e, config: t, children: n, language: r = "en" }) {
2715
2715
  Fe(e), e && (ct.current = !1);
2716
2716
  }
2717
2717
  }, At = async (e) => {
2718
- if (console.log("[FlowEngage:voice-sync] onMessageSync called", {
2719
- hasSynced: ct.current,
2720
- messageCount: e?.length ?? 0,
2721
- hasChatId: !!v,
2722
- hasApi: !!w.current
2723
- }), ct.current) {
2724
- console.warn("[FlowEngage:voice-sync] SKIPPED — hasSyncedRef is already true (duplicate call)");
2725
- return;
2726
- }
2727
- if (ct.current = !0, !w.current || !v || !e?.length) {
2728
- console.warn("[FlowEngage:voice-sync] SKIPPED — missing data:", {
2729
- api: !!w.current,
2730
- chatId: v || "(empty)",
2731
- messages: e?.length ?? 0
2732
- }), Fe(!1);
2733
- return;
2734
- }
2735
- console.log("[FlowEngage:voice-sync] Syncing", e.length, "messages for chatId:", v);
2736
- try {
2737
- let t = await w.current.syncVoice(v, e);
2738
- if (console.log("[FlowEngage:voice-sync] syncVoice response:", {
2739
- success: t?.success,
2740
- count: t?.count,
2741
- chatHistoryLength: t?.chat_history?.length ?? 0
2742
- }), t?.chat_history?.length) b(pn(t.chat_history)), console.log("[FlowEngage:voice-sync] ✓ setChatHistory with", t.chat_history.length, "messages");
2743
- else if (t?.success) {
2744
- console.log("[FlowEngage:voice-sync] No chat_history in response, falling back to loadHistory");
2745
- try {
2718
+ if (!ct.current) {
2719
+ if (ct.current = !0, !w.current || !v || !e?.length) {
2720
+ Fe(!1);
2721
+ return;
2722
+ }
2723
+ try {
2724
+ let t = await w.current.syncVoice(v, e);
2725
+ if (t?.chat_history?.length) b(pn(t.chat_history));
2726
+ else if (t?.success) try {
2746
2727
  let e = await w.current.loadHistory(v, r);
2747
- console.log("[FlowEngage:voice-sync] loadHistory response:", { chatHistoryLength: e?.chat_history?.length ?? 0 }), e?.chat_history?.length && (b(pn(e.chat_history)), console.log("[FlowEngage:voice-sync] ✓ setChatHistory via loadHistory fallback"));
2748
- } catch (e) {
2749
- console.error("[FlowEngage:voice-sync] loadHistory fallback failed:", e);
2750
- }
2751
- } else console.warn("[FlowEngage:voice-sync] syncVoice returned no success and no chat_history:", t);
2752
- } catch (e) {
2753
- console.error("[FlowEngage:voice-sync] ✖ syncVoice API failed:", e);
2754
- } finally {
2755
- console.log("[FlowEngage:voice-sync] Setting isVoiceMode → false"), Fe(!1);
2728
+ e?.chat_history?.length && b(pn(e.chat_history));
2729
+ } catch {}
2730
+ } catch {} finally {
2731
+ Fe(!1);
2732
+ }
2756
2733
  }
2757
2734
  }, E = async () => {
2758
2735
  if (!(!w.current || !v)) {
@@ -22169,13 +22146,41 @@ function rg(e) {
22169
22146
  }
22170
22147
  }
22171
22148
  function ig(e) {
22149
+ if (!e) return null;
22150
+ try {
22151
+ return e.closest("form");
22152
+ } catch {
22153
+ let t = e.parentElement;
22154
+ for (; t;) {
22155
+ if (t.tagName === "FORM") return t;
22156
+ t = t.parentElement;
22157
+ }
22158
+ return null;
22159
+ }
22160
+ }
22161
+ function ag(e) {
22162
+ if (!e) return null;
22163
+ let t = e.querySelector("h1, h2, h3, h4, h5, legend");
22164
+ if (t) return t.textContent.replace(/\s+/g, " ").trim().slice(0, 60);
22165
+ let n = e.getAttribute("aria-label");
22166
+ if (n) return n.trim().slice(0, 60);
22167
+ let r = e.getAttribute("title");
22168
+ if (r) return r.trim().slice(0, 60);
22169
+ let i = e.previousElementSibling;
22170
+ for (let e = 0; e < 3 && i; e++) {
22171
+ if (/^H[1-5]$/.test(i.tagName)) return i.textContent.replace(/\s+/g, " ").trim().slice(0, 60);
22172
+ i = i.previousElementSibling;
22173
+ }
22174
+ return null;
22175
+ }
22176
+ function og(e) {
22172
22177
  try {
22173
22178
  let t = e.ownerDocument?.defaultView;
22174
22179
  if (t) return t.getComputedStyle(e);
22175
22180
  } catch {}
22176
22181
  return window.getComputedStyle(e);
22177
22182
  }
22178
- function ag(e) {
22183
+ function sg(e) {
22179
22184
  let t = /* @__PURE__ */ new Set();
22180
22185
  function n(r) {
22181
22186
  if (!r || t.has(r)) return;
@@ -22188,10 +22193,10 @@ function ag(e) {
22188
22193
  }
22189
22194
  typeof document < "u" && n(document);
22190
22195
  }
22191
- function og(e) {
22196
+ function cg(e) {
22192
22197
  return e == null ? null : String(e).replace(/\u00a0/g, " ").replace(/\s*\*+\s*$/u, "").replace(/\s+/g, " ").trim();
22193
22198
  }
22194
- function sg(e) {
22199
+ function lg(e) {
22195
22200
  let t = e.ownerDocument || document, n = e.getAttribute("aria-labelledby");
22196
22201
  if (n) {
22197
22202
  let e = n.trim().split(/\s+/).filter(Boolean), r = [];
@@ -22199,40 +22204,40 @@ function sg(e) {
22199
22204
  let e = t.getElementById(n);
22200
22205
  e?.textContent && r.push(e.textContent.trim());
22201
22206
  } catch {}
22202
- if (r.length) return og(r.join(" "));
22207
+ if (r.length) return cg(r.join(" "));
22203
22208
  }
22204
- if (e.labels && e.labels.length) return og(e.labels[0].textContent);
22209
+ if (e.labels && e.labels.length) return cg(e.labels[0].textContent);
22205
22210
  let r = e.id;
22206
22211
  if (r) try {
22207
22212
  let e = t.querySelector(`label[for="${CSS.escape(r)}"]`);
22208
- if (e) return og(e.textContent);
22213
+ if (e) return cg(e.textContent);
22209
22214
  } catch {
22210
22215
  let e = t.querySelector(`label[for="${r.replace(/"/g, "\\\"")}"]`);
22211
- if (e) return og(e.textContent);
22216
+ if (e) return cg(e.textContent);
22212
22217
  }
22213
22218
  let i = e.previousElementSibling;
22214
22219
  for (let e = 0; e < 6 && i; e += 1) {
22215
- if (i.tagName === "LABEL") return og(i.textContent);
22220
+ if (i.tagName === "LABEL") return cg(i.textContent);
22216
22221
  let e = (i.className || "").toString().toLowerCase();
22217
22222
  if (/chakra-form__label|formlabel|field-label|form-label|mui-form-label/.test(e)) {
22218
- let e = og(i.textContent);
22223
+ let e = cg(i.textContent);
22219
22224
  if (e) return e;
22220
22225
  }
22221
22226
  i = i.previousElementSibling;
22222
22227
  }
22223
22228
  let a = e.parentElement;
22224
22229
  for (let e = 0; e < 5 && a; e += 1) {
22225
- if (a.tagName === "LABEL") return og(a.textContent);
22230
+ if (a.tagName === "LABEL") return cg(a.textContent);
22226
22231
  let e = a.querySelector?.(":scope > label, :scope > [class*='FormLabel'], :scope > [class*='form__label']");
22227
- if (e?.textContent) return og(e.textContent);
22232
+ if (e?.textContent) return cg(e.textContent);
22228
22233
  a = a.parentElement;
22229
22234
  }
22230
22235
  let o = e.getAttribute("aria-label");
22231
- return o ? og(o) : null;
22236
+ return o ? cg(o) : null;
22232
22237
  }
22233
- function cg() {
22238
+ function ug() {
22234
22239
  let e = [];
22235
- return ag((t) => {
22240
+ return sg((t) => {
22236
22241
  e.push(...Array.from(t.querySelectorAll("input, select, textarea")).filter((e) => {
22237
22242
  if (rg(e)) return !1;
22238
22243
  let t = (e.type || "").toLowerCase();
@@ -22243,7 +22248,7 @@ function cg() {
22243
22248
  "image"
22244
22249
  ].includes(t) || e.disabled || e.readOnly) return !1;
22245
22250
  try {
22246
- let t = ig(e);
22251
+ let t = og(e);
22247
22252
  if (t.display === "none" || t.visibility === "hidden" || parseFloat(t.opacity) === 0) return !1;
22248
22253
  } catch {}
22249
22254
  try {
@@ -22253,25 +22258,32 @@ function cg() {
22253
22258
  }));
22254
22259
  }), e;
22255
22260
  }
22256
- function lg() {
22257
- return cg().map((e, t) => ({
22258
- formIndex: 0,
22259
- fieldIndex: t,
22260
- tag: e.tagName,
22261
- type: e.type || "text",
22262
- name: e.name || null,
22263
- id: e.id || null,
22264
- label: sg(e),
22265
- placeholder: e.placeholder || null
22266
- }));
22261
+ function dg() {
22262
+ let e = ug(), t = /* @__PURE__ */ new Map(), n = 0;
22263
+ return e.map((e, r) => {
22264
+ let i = ig(e), a = i || "__orphan__";
22265
+ t.has(a) || t.set(a, n++);
22266
+ let o = t.get(a);
22267
+ return {
22268
+ formIndex: o,
22269
+ formName: (i ? ag(i) : null) || `Form ${o}`,
22270
+ fieldIndex: r,
22271
+ tag: e.tagName,
22272
+ type: e.type || "text",
22273
+ name: e.name || null,
22274
+ id: e.id || null,
22275
+ label: lg(e),
22276
+ placeholder: e.placeholder || null
22277
+ };
22278
+ });
22267
22279
  }
22268
- function ug() {
22280
+ function fg() {
22269
22281
  let e = [];
22270
- return ag((t) => {
22282
+ return sg((t) => {
22271
22283
  e.push(...Array.from(t.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"]")).filter((e) => {
22272
22284
  if (rg(e) || e.disabled) return !1;
22273
22285
  try {
22274
- let t = ig(e);
22286
+ let t = og(e);
22275
22287
  if (t.display === "none" || t.visibility === "hidden" || parseFloat(t.opacity) === 0) return !1;
22276
22288
  } catch {}
22277
22289
  return !0;
@@ -22283,15 +22295,15 @@ function ug() {
22283
22295
  type: e.type || e.tagName
22284
22296
  }));
22285
22297
  }
22286
- function dg(e) {
22298
+ function pg(e) {
22287
22299
  return String(e || "").toLowerCase().replace(/\u00a0/g, " ").replace(/\*/g, "").replace(/\s+/g, " ").trim();
22288
22300
  }
22289
- function fg(e) {
22290
- let t = dg(e);
22301
+ function mg(e) {
22302
+ let t = pg(e);
22291
22303
  return t = t.replace(/\s+field\s*$/i, "").trim(), t;
22292
22304
  }
22293
- function pg(e, t) {
22294
- let n = fg(t);
22305
+ function hg(e, t) {
22306
+ let n = mg(t);
22295
22307
  if (!n) return 0;
22296
22308
  let r = (e.name || "").toLowerCase(), i = (e.id || "").toLowerCase();
22297
22309
  if (r === "url" && /url|website|domain|site|audit/.test(n) || (i === "url-input" || i.endsWith("-url-input")) && /url|website|domain|site|audit/.test(n)) return 100;
@@ -22303,12 +22315,12 @@ function pg(e, t) {
22303
22315
  e.name,
22304
22316
  e.id,
22305
22317
  e.placeholder,
22306
- sg(e),
22318
+ lg(e),
22307
22319
  e.getAttribute("aria-label"),
22308
22320
  e.getAttribute("title"),
22309
22321
  e.getAttribute("data-testid"),
22310
22322
  e.getAttribute("autocomplete")
22311
- ].filter(Boolean).map((e) => dg(e)), s = 0;
22323
+ ].filter(Boolean).map((e) => pg(e)), s = 0;
22312
22324
  for (let e of o) {
22313
22325
  if (!e) continue;
22314
22326
  if (e === n) {
@@ -22328,16 +22340,16 @@ function pg(e, t) {
22328
22340
  }
22329
22341
  return s;
22330
22342
  }
22331
- var mg = 22;
22332
- function hg(e, t) {
22343
+ var gg = 22;
22344
+ function _g(e, t) {
22333
22345
  let n = null, r = 0;
22334
22346
  for (let i of e) {
22335
- let e = pg(i, t);
22347
+ let e = hg(i, t);
22336
22348
  e > r && (r = e, n = i);
22337
22349
  }
22338
- return !n || r < mg ? null : n;
22350
+ return !n || r < gg ? null : n;
22339
22351
  }
22340
- function gg(e, t, n) {
22352
+ function vg(e, t, n) {
22341
22353
  let r = String(t || "").toLowerCase().trim(), i = String(n || "").trim();
22342
22354
  if (!(/^https?:\/\//i.test(i) || /\.\w{2,}(\/|\s|$)/.test(i) || r.includes("url") || r.includes("website") || r.includes("domain") || r.includes("site"))) return null;
22343
22355
  let a = null, o = 0;
@@ -22357,7 +22369,7 @@ function gg(e, t, n) {
22357
22369
  t.name,
22358
22370
  t.id,
22359
22371
  t.placeholder,
22360
- sg(t),
22372
+ lg(t),
22361
22373
  t.getAttribute("aria-label"),
22362
22374
  t.getAttribute("autocomplete")
22363
22375
  ].filter(Boolean).join(" ").toLowerCase();
@@ -22365,15 +22377,15 @@ function gg(e, t, n) {
22365
22377
  }
22366
22378
  return !a || o < 42 ? null : a;
22367
22379
  }
22368
- function _g(e) {
22380
+ function yg(e) {
22369
22381
  let t = String(e ?? "").trim();
22370
22382
  return t ? /^https?:\/\//i.test(t) ? !0 : /\.\w{2,}(\/|\s|$)/.test(t) : !1;
22371
22383
  }
22372
- function vg(e) {
22384
+ function bg(e) {
22373
22385
  let t = String(e ?? "").toLowerCase().trim();
22374
22386
  return t ? !!(t === "url" || t === "website" || t === "website url" || t === "website_url" || t === "enter website url" || t.includes("website") || t.includes("domain") || /(enter\s+website|site\s*url|page\s*url)/.test(t)) : !1;
22375
22387
  }
22376
- function yg(e) {
22388
+ function xg(e) {
22377
22389
  if (!e || e.tagName !== "INPUT" && e.tagName !== "TEXTAREA") return !1;
22378
22390
  let t = (e.type || "").toLowerCase();
22379
22391
  return ![
@@ -22385,22 +22397,22 @@ function yg(e) {
22385
22397
  "file"
22386
22398
  ].includes(t);
22387
22399
  }
22388
- function bg(e) {
22389
- if (!yg(e)) return !1;
22400
+ function Sg(e) {
22401
+ if (!xg(e)) return !1;
22390
22402
  let t = (e.name || "").toLowerCase(), n = (e.id || "").toLowerCase(), r = [
22391
22403
  e.name,
22392
22404
  e.id,
22393
22405
  e.placeholder,
22394
- sg(e),
22406
+ lg(e),
22395
22407
  e.getAttribute("aria-label")
22396
22408
  ].filter(Boolean).join(" ").toLowerCase();
22397
22409
  return t === "url" || n === "url-input" || n.endsWith("-url-input") || /(website\s*url|enter\s+website|site\s*url)/.test(r) || /(website|domain)/.test(r) && /(url|site)/.test(r);
22398
22410
  }
22399
- function xg(e, t, n) {
22400
- let r = String(t ?? ""), i = String(n ?? ""), a = wg(e, r) || hg(e, r) || gg(e, r, i);
22411
+ function Cg(e, t, n) {
22412
+ let r = String(t ?? ""), i = String(n ?? ""), a = Eg(e, r) || _g(e, r) || vg(e, r, i);
22401
22413
  if (!a) return [];
22402
22414
  let o = new Set([a]);
22403
- if (_g(i) && vg(r)) for (let t of e) t !== a && bg(t) && o.add(t);
22415
+ if (yg(i) && bg(r)) for (let t of e) t !== a && Sg(t) && o.add(t);
22404
22416
  let s = Array.from(o);
22405
22417
  return s.sort((e, t) => {
22406
22418
  if (e === t) return 0;
@@ -22408,7 +22420,7 @@ function xg(e, t, n) {
22408
22420
  return n & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : n & Node.DOCUMENT_POSITION_PRECEDING ? 1 : 0;
22409
22421
  }), s;
22410
22422
  }
22411
- function Sg(e, t) {
22423
+ function wg(e, t) {
22412
22424
  try {
22413
22425
  if (!e?.getBoundingClientRect || !t?.getBoundingClientRect) return Infinity;
22414
22426
  let n = e.getBoundingClientRect(), r = t.getBoundingClientRect(), i = {
@@ -22423,17 +22435,17 @@ function Sg(e, t) {
22423
22435
  return Infinity;
22424
22436
  }
22425
22437
  }
22426
- function Cg(e) {
22438
+ function Tg(e) {
22427
22439
  if (!e || typeof e != "string") return null;
22428
22440
  let t = null;
22429
- return ag((n) => {
22441
+ return sg((n) => {
22430
22442
  try {
22431
22443
  let r = n.getElementById(e);
22432
22444
  r && !rg(r) && r.matches?.("input, select, textarea") && (t = r);
22433
22445
  } catch {}
22434
22446
  }), t;
22435
22447
  }
22436
- function wg(e, t) {
22448
+ function Eg(e, t) {
22437
22449
  let n = String(t ?? "").trim();
22438
22450
  if (!n) return null;
22439
22451
  let r = n.match(/^name:\s*([\w.-]+)$/i);
@@ -22443,12 +22455,12 @@ function wg(e, t) {
22443
22455
  }
22444
22456
  let i = n.match(/^id:\s*([\w.-]+)$/i);
22445
22457
  if (i) {
22446
- let e = Cg(i[1]);
22458
+ let e = Tg(i[1]);
22447
22459
  if (e) return e;
22448
22460
  }
22449
22461
  let a = n.startsWith("#") ? n.slice(1) : n;
22450
22462
  if (/^[\w-]+$/.test(a)) {
22451
- let e = Cg(a);
22463
+ let e = Tg(a);
22452
22464
  if (e) return e;
22453
22465
  }
22454
22466
  let o = n.toLowerCase().replace(/\s+/g, " ");
@@ -22458,7 +22470,7 @@ function wg(e, t) {
22458
22470
  }
22459
22471
  return null;
22460
22472
  }
22461
- function Tg(e, t) {
22473
+ function Dg(e, t) {
22462
22474
  let n = String(t || "").toLowerCase().trim();
22463
22475
  if (!n) return 0;
22464
22476
  let r = [
@@ -22475,13 +22487,13 @@ function Tg(e, t) {
22475
22487
  for (let e of i) r.includes(e) && (a += 1);
22476
22488
  return a / i.length * 92;
22477
22489
  }
22478
- function Eg(e, t) {
22490
+ function Og(e, t) {
22479
22491
  let n = [];
22480
- ag((e) => {
22492
+ sg((e) => {
22481
22493
  n.push(...Array.from(e.querySelectorAll("button, [role=\"button\"], input[type=\"submit\"], input[type=\"button\"]")).filter((e) => {
22482
22494
  if (rg(e) || e.disabled) return !1;
22483
22495
  try {
22484
- let t = ig(e);
22496
+ let t = og(e);
22485
22497
  if (t.display === "none" || t.visibility === "hidden" || parseFloat(t.opacity) === 0) return !1;
22486
22498
  } catch {}
22487
22499
  return !0;
@@ -22489,7 +22501,7 @@ function Eg(e, t) {
22489
22501
  });
22490
22502
  let r = 0, i = n.map((t) => ({
22491
22503
  el: t,
22492
- s: Tg(t, e)
22504
+ s: Dg(t, e)
22493
22505
  }));
22494
22506
  for (let { s: e } of i) e > r && (r = e);
22495
22507
  if (r < 36) return null;
@@ -22499,14 +22511,14 @@ function Eg(e, t) {
22499
22511
  if (o.length) {
22500
22512
  let e = a[0], t = Infinity;
22501
22513
  for (let n of a) for (let r of o) {
22502
- let i = Sg(n, r);
22514
+ let i = wg(n, r);
22503
22515
  i < t && (t = i, e = n);
22504
22516
  }
22505
22517
  return e;
22506
22518
  }
22507
22519
  return a[0];
22508
22520
  }
22509
- function Dg(e) {
22521
+ function kg(e) {
22510
22522
  if (e == null) return {};
22511
22523
  if (typeof e == "string") {
22512
22524
  let t = e.trim();
@@ -22519,8 +22531,8 @@ function Dg(e) {
22519
22531
  }
22520
22532
  return e;
22521
22533
  }
22522
- function Og(e) {
22523
- let t = Dg(e);
22534
+ function Ag(e) {
22535
+ let t = kg(e);
22524
22536
  if (Array.isArray(t) && t.length > 0) {
22525
22537
  let e = t[0];
22526
22538
  if (e?.field_key != null || e?.fieldKey != null) return t.map((e) => ({
@@ -22548,7 +22560,31 @@ function Og(e) {
22548
22560
  value: e?.value ?? e?.Value
22549
22561
  })) : [];
22550
22562
  }
22551
- function kg(e) {
22563
+ function jg(e) {
22564
+ if (!e || typeof e != "string") return e;
22565
+ let t = e.trim();
22566
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t) ? t : (t = t.replace(/\s+at\s+the\s+rate\s*(of)?\s+/gi, "@"), t = t.replace(/\s+at\s+/gi, "@"), t = t.replace(/\s+dot\s+/gi, "."), t = t.replace(/\s+/g, ""), t = t.replace(/\.{2,}/g, ".").replace(/\.$/, ""), t);
22567
+ }
22568
+ function Mg(e) {
22569
+ if (!e || typeof e != "string") return e;
22570
+ let t = {
22571
+ zero: "0",
22572
+ one: "1",
22573
+ two: "2",
22574
+ three: "3",
22575
+ four: "4",
22576
+ five: "5",
22577
+ six: "6",
22578
+ seven: "7",
22579
+ eight: "8",
22580
+ nine: "9",
22581
+ oh: "0",
22582
+ o: "0"
22583
+ }, n = e.toLowerCase().trim();
22584
+ for (let [e, r] of Object.entries(t)) n = n.replace(RegExp(`\\b${e}\\b`, "g"), r);
22585
+ return n = n.replace(/[^\d+]/g, ""), n;
22586
+ }
22587
+ function Ng(e) {
22552
22588
  if (!e || typeof e != "string") return [];
22553
22589
  let t = e.trim();
22554
22590
  if (!t || /\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\b/i.test(t)) return [];
@@ -22567,7 +22603,7 @@ function kg(e) {
22567
22603
  }
22568
22604
  return [];
22569
22605
  }
22570
- function Ag(e) {
22606
+ function Pg(e) {
22571
22607
  if (!e || typeof e != "string") return [];
22572
22608
  let t = e.trim();
22573
22609
  if (!t) return [];
@@ -22579,15 +22615,19 @@ function Ag(e) {
22579
22615
  field_key: e,
22580
22616
  value: i
22581
22617
  }));
22582
- }, o = t.match(/^\s*([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})\s*$/i);
22583
- if (o) return a("Email Address", o[1]), n;
22584
- let s = t.match(/\b(?:please\s+)?(?:enter|type|put)\s+(.+?)\s+in(?:to)?\s+(?:the\s+)?(?:full\s*name|full\s*name\s*field|name\s*field)\b/i);
22585
- if (s && a("Full Name", s[1]), s = t.match(/\bfull\s*name,?\s*(?:please\s+)?(?:enter|type|put)\s+(.+?)(?:\.|$|!|\?)/i), s && a("Full Name", s[1]), s = t.match(/\bfull\s*name\s*(?:is|:|please\s+enter|-)\s*(.+?)(?:\.|$|(?=\s+(?:and|my\s+email|email|message))\b)/i), s && a("Full Name", s[1]), s = t.match(/\b(.+?)\s+for\s+(?:the\s+)?full\s*name\b/i), s) {
22586
- let e = s[1].trim();
22618
+ }, o = jg(t), s = i.test(o), c = o.match(/^\s*([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})\s*$/i);
22619
+ if (c) return a("Email Address", c[1]), n;
22620
+ if (!i.test(t) && s) {
22621
+ let e = o.match(i);
22622
+ if (e) return a("Email Address", e[1]), n;
22623
+ }
22624
+ let l = t.match(/\b(?:please\s+)?(?:enter|type|put)\s+(.+?)\s+in(?:to)?\s+(?:the\s+)?(?:full\s*name|full\s*name\s*field|name\s*field)\b/i);
22625
+ if (l && a("Full Name", l[1]), l = t.match(/\bfull\s*name,?\s*(?:please\s+)?(?:enter|type|put)\s+(.+?)(?:\.|$|!|\?)/i), l && a("Full Name", l[1]), l = t.match(/\bfull\s*name\s*(?:is|:|please\s+enter|-)\s*(.+?)(?:\.|$|(?=\s+(?:and|my\s+email|email|message))\b)/i), l && a("Full Name", l[1]), l = t.match(/\b(.+?)\s+for\s+(?:the\s+)?full\s*name\b/i), l) {
22626
+ let e = l[1].trim();
22587
22627
  e.length > 1 && e.length < 120 && !/@/.test(e) && a("Full Name", e);
22588
22628
  }
22589
- if (s = t.match(/\b(?:email|e-mail)(?:\s*address)?\s*(?:is|:|please\s+use|enter|-)\s*([^\s@]+@[^\s@]+\.[^\s,]+)/i), s && a("Email Address", s[1]), s = t.match(/\b(?:enter|type|put)\s+([^\s@]+@[^\s@]+\.[^\s,]+)\s+in(?:to)?\s+(?:the\s+)?(?:email|e-mail)/i), s && a("Email Address", s[1]), s = t.match(/\b(?:message|comment)\s*(?:is|:|please\s+enter|-)\s*(.+)$/is), s) {
22590
- let e = s[1].trim();
22629
+ if (l = t.match(/\b(?:email|e-mail)(?:\s*address)?\s*(?:is|:|please\s+use|enter|-)\s*([^\s@]+@[^\s@]+\.[^\s,]+)/i), l && a("Email Address", l[1]), l = t.match(/\b(?:enter|type|put)\s+([^\s@]+@[^\s@]+\.[^\s,]+)\s+in(?:to)?\s+(?:the\s+)?(?:email|e-mail)/i), l && a("Email Address", l[1]), l = t.match(/\b(?:message|comment)\s*(?:is|:|please\s+enter|-)\s*(.+)$/is), l) {
22630
+ let e = l[1].trim();
22591
22631
  e.length > 0 && a("Message", e);
22592
22632
  }
22593
22633
  if (!n.some((e) => /email/i.test(String(e.field_key)))) {
@@ -22603,17 +22643,17 @@ function Ag(e) {
22603
22643
  }
22604
22644
  return n;
22605
22645
  }
22606
- function jg(e) {
22646
+ function Fg(e) {
22607
22647
  if (!e || typeof e != "object") return null;
22608
22648
  let t = e.url ?? e.target_url ?? e.page_url ?? e.pageUrl ?? e.link ?? e.href ?? e.path;
22609
22649
  return t == null ? null : String(t).trim() || null;
22610
22650
  }
22611
- function Mg(e) {
22651
+ function Ig(e) {
22612
22652
  if (!e || typeof e != "object") return null;
22613
22653
  let t = e.query ?? e.q ?? e.search ?? e.text ?? e.keywords;
22614
22654
  return t == null ? null : String(t).trim() || null;
22615
22655
  }
22616
- function Ng(e) {
22656
+ function Lg(e) {
22617
22657
  let t = e.ownerDocument?.defaultView || window, n = e.tagName === "TEXTAREA" ? t.HTMLTextAreaElement.prototype : t.HTMLInputElement.prototype, r = Object.getOwnPropertyDescriptor(n, "value");
22618
22658
  return (e, t) => {
22619
22659
  try {
@@ -22622,7 +22662,7 @@ function Ng(e) {
22622
22662
  r?.set ? r.set.call(e, t) : e.value = t;
22623
22663
  };
22624
22664
  }
22625
- async function Pg(e, t, n) {
22665
+ async function Rg(e, t, n) {
22626
22666
  if (!n?.skipScroll) try {
22627
22667
  e.scrollIntoView({
22628
22668
  behavior: "smooth",
@@ -22661,7 +22701,7 @@ async function Pg(e, t, n) {
22661
22701
  "on"
22662
22702
  ].includes(String(t).toLowerCase().trim()), e.dispatchEvent(new Event("input", a)), e.dispatchEvent(new Event("change", a)), Gh(e), !0;
22663
22703
  let o = String(t);
22664
- r === "INPUT" || r === "TEXTAREA" ? await eg(e, o, Ng(e)) : (e.value = o, e.dispatchEvent(new Event("input", a)), e.dispatchEvent(new Event("change", a))), e.dispatchEvent(new Event("change", a)), e.dispatchEvent(new Event("blur", a));
22704
+ r === "INPUT" || r === "TEXTAREA" ? await eg(e, o, Lg(e)) : (e.value = o, e.dispatchEvent(new Event("input", a)), e.dispatchEvent(new Event("change", a))), e.dispatchEvent(new Event("change", a)), e.dispatchEvent(new Event("blur", a));
22665
22705
  try {
22666
22706
  e.focus({ preventScroll: !0 });
22667
22707
  } catch {}
@@ -22677,11 +22717,11 @@ async function Pg(e, t, n) {
22677
22717
  } catch {}
22678
22718
  return !0;
22679
22719
  }
22680
- function Fg(e) {
22681
- let t = e.siteId || null, n = (e.apiBaseUrl || "").replace(/\/$/, ""), r = typeof e.getLastUserVoiceText == "function" ? e.getLastUserVoiceText : null, i = [], a = {
22720
+ function zg(e) {
22721
+ let t = e.siteId || null, n = (e.apiBaseUrl || "").replace(/\/$/, ""), r = typeof e.getLastUserVoiceText == "function" ? e.getLastUserVoiceText : null, i = [], a = null, o = {
22682
22722
  navigate_to_page: async (n) => {
22683
22723
  $("navigate_to_page ▶ raw parameters:", n);
22684
- let r = Dg(n), i = jg(r), a = r.section_text ?? r.sectionText ?? r.section;
22724
+ let r = kg(n), i = Fg(r), a = r.section_text ?? r.sectionText ?? r.section;
22685
22725
  if ($("navigate_to_page · coerced:", {
22686
22726
  url: i,
22687
22727
  sectionText: a
@@ -22705,8 +22745,16 @@ function Fg(e) {
22705
22745
  found: !!e
22706
22746
  });
22707
22747
  }
22708
- let e = `OK_NAVIGATION ${i}`;
22709
- return $("navigate_to_page ✓", e), e;
22748
+ let e = "";
22749
+ try {
22750
+ let t = dg(), n = fg();
22751
+ if (t.length > 0) {
22752
+ let r = t.map((e) => e.label || e.placeholder || e.name || e.id).filter(Boolean).join(", "), i = n.map((e) => e.text).filter(Boolean).join(", ");
22753
+ e = ` This page has a form with fields: [${r}]` + (i ? ` and buttons: [${i}].` : ".") + " Call list_page_forms then start filling.";
22754
+ }
22755
+ } catch {}
22756
+ let t = `OK_NAVIGATION ${i}${e}`;
22757
+ return $("navigate_to_page ✓", t), t;
22710
22758
  } catch (e) {
22711
22759
  Hh(), Lh(200);
22712
22760
  let t = `Navigation error: ${e?.message || String(e)}`;
@@ -22715,12 +22763,12 @@ function Fg(e) {
22715
22763
  },
22716
22764
  highlight_on_page: async (e) => {
22717
22765
  $("highlight_on_page ▶", e);
22718
- let t = Dg(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText, i = rn(n || null, r || null);
22766
+ let t = kg(e), n = t?.section_id || t?.sectionId, r = t?.section_text || t?.sectionText, i = rn(n || null, r || null);
22719
22767
  return i ? (an(i), $("highlight_on_page ✓"), "Highlighted the section.") : ($("highlight_on_page ✖ no element"), "Could not find that section on the page.");
22720
22768
  },
22721
22769
  search_site_content: async (e) => {
22722
22770
  $("search_site_content ▶", e);
22723
- let r = Mg(Dg(e));
22771
+ let r = Ig(kg(e));
22724
22772
  if ($("search_site_content · query:", r, "siteId:", t, "apiBase:", n || "(empty)"), Ih("Searching site content…", { spinner: !0 }), !r) return Lh(), $("search_site_content ✖ missing query"), "Missing query parameter.";
22725
22773
  if (!t) return Lh(), $("search_site_content ✖ no siteId"), "Site is not configured for search.";
22726
22774
  if (!n) return Lh(), $("search_site_content ✖ no api base"), "API base URL is missing; cannot search.";
@@ -22754,20 +22802,20 @@ function Fg(e) {
22754
22802
  duration: 2e3
22755
22803
  }), Zh(!0), Uh(), typeof e.requestEndSession == "function" && e.requestEndSession(), "Voice session is ending."),
22756
22804
  list_page_forms: async () => {
22757
- let e = lg(), t = ug();
22758
- return $("list_page_forms ✓", `${e.length} field(s)`, `${t.length} button(s)`), JSON.stringify({
22805
+ let e = dg(), t = fg();
22806
+ return $("list_page_forms ✓", `${e.length} field(s)`, `${t.length} button(s)`), a = null, JSON.stringify({
22759
22807
  fields: e,
22760
22808
  buttons: t,
22761
- hint: "field_key: placeholder/label, name (e.g. url), id (e.g. url-input). If the page has two URL boxes, fill_form_fields sets all matching URL inputs. click_page_button picks the Conduct Audit nearest the filled field when labels duplicate."
22809
+ hint: "Fields are grouped by formIndex/formName. Work with ONE form at a time — only fill fields from the same formIndex. Do not jump to fields in a different form. field_key: use placeholder, label, name, or id from this list. click_page_button picks the button nearest the filled fields."
22762
22810
  });
22763
22811
  },
22764
22812
  fill_form_fields: async (e) => {
22765
22813
  try {
22766
22814
  $("fill_form_fields ▶ raw:", e);
22767
- let t = Og(e);
22815
+ let t = Ag(e);
22768
22816
  if (!t.length && r) {
22769
- let e = r(), n = kg(e);
22770
- n.length ? $("fill_form_fields · inferred URL from last user utterance (model omitted usable fields):", n) : (n = Ag(e), n.length && $("fill_form_fields · inferred contact fields from last user utterance (empty tool params):", n)), n.length && (t = n);
22817
+ let e = r(), n = Ng(e);
22818
+ n.length ? $("fill_form_fields · inferred URL from last user utterance (model omitted usable fields):", n) : (n = Pg(e), n.length && $("fill_form_fields · inferred contact fields from last user utterance (empty tool params):", n)), n.length && (t = n);
22771
22819
  }
22772
22820
  if ($("fill_form_fields · normalized fields:", t), !t.length) return "No fields provided. Call list_page_forms for field_key strings, then fill_form_fields with { \"fields\": [ { \"field_key\": \"<label or placeholder from list>\", \"value\": \"<user value>\" } ] }. Never use empty {}. Pass the value the user just said (email, message, name, URL) in fields.";
22773
22821
  t.length > 1 && Ih(`Filling ${t.length} fields…`);
@@ -22775,25 +22823,37 @@ function Fg(e) {
22775
22823
  for (let e of t) {
22776
22824
  let t = e?.field_key ?? e?.fieldKey, r = e?.value;
22777
22825
  if (t == null || r == null) continue;
22778
- Ih(`Filling ${t}…`), $("fill_form_fields · processing field:", t, "=", r);
22779
- let a = cg();
22780
- $("fill_form_fields · visible inputs count:", a.length);
22781
- let o = xg(a, String(t), r);
22782
- if (o.length) {
22783
- for (let e = 0; e < o.length; e++) await Pg(o[e], r, { skipScroll: e > 0 }), await new Promise((e) => setTimeout(e, 80));
22784
- i = o, n.push(String(t));
22785
- continue;
22826
+ let o = String(t).toLowerCase();
22827
+ /email|e-mail|mail/.test(o) ? r = jg(r) : /phone|mobile|tel|cell/.test(o) && (r = Mg(r)), Ih(`Filling ${t}…`), $("fill_form_fields · processing field:", t, "=", r);
22828
+ let s = ug(), c = s;
22829
+ if (a) {
22830
+ let e = s.filter((e) => ig(e) === a);
22831
+ e.length > 0 && (c = e, $("fill_form_fields · scoped to active form, inputs:", e.length));
22832
+ }
22833
+ $("fill_form_fields · visible inputs count:", s.length, "scoped:", c.length);
22834
+ let l = !1;
22835
+ for (let e of [c, ...c === s ? [] : [s]]) {
22836
+ let o = Cg(e, String(t), r);
22837
+ if (o.length) {
22838
+ for (let e = 0; e < o.length; e++) await Rg(o[e], r, { skipScroll: e > 0 }), await new Promise((e) => setTimeout(e, 80));
22839
+ i = o, a = ig(o[0]) || a, n.push(String(t)), l = !0;
22840
+ break;
22841
+ }
22842
+ let s = Eg(e, String(t));
22843
+ if (s ||= _g(e, String(t)), s ||= vg(e, String(t), r), s) {
22844
+ await Rg(s, r), i = [s], a = ig(s) || a, n.push(String(t)), l = !0;
22845
+ break;
22846
+ }
22786
22847
  }
22787
- let s = wg(a, String(t));
22788
- s ||= hg(a, String(t)), s ||= gg(a, String(t), r), s ? (await Pg(s, r), i = [s], n.push(String(t))) : $("fill_form_fields · no match for field:", t);
22848
+ l || $("fill_form_fields · no match for field:", t);
22789
22849
  }
22790
22850
  Lh(400);
22791
22851
  try {
22792
22852
  Zh();
22793
22853
  } catch {}
22794
22854
  if (!n.length) return $("fill_form_fields ✖ no matches"), "Could not match any fields. Call list_page_forms and use field_key values that match placeholder, label, name, or id (e.g. Enter Website URL). Ensure the form is on the page, not the chat panel.";
22795
- let a = `OK_FILLED: ${n.join(", ")}`;
22796
- return $("fill_form_fields ✓", a), a;
22855
+ let o = `OK_FILLED: ${n.join(", ")}`;
22856
+ return $("fill_form_fields ✓", o), o;
22797
22857
  } catch (e) {
22798
22858
  Lh(), Uh(), Zh(!0);
22799
22859
  let t = `fill_form_fields error: ${e?.message || String(e)}`;
@@ -22801,10 +22861,10 @@ function Fg(e) {
22801
22861
  }
22802
22862
  },
22803
22863
  click_page_button: async (e) => {
22804
- let t = Dg(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
22864
+ let t = kg(e), n = (t.button_text ?? t.buttonText ?? t.text ?? "").trim();
22805
22865
  if ($("click_page_button ▶", n), !n) return "Missing button_text: pass the visible label, e.g. Conduct Audit.";
22806
22866
  Ih(`Clicking "${n}"…`);
22807
- let r = Eg(n, i);
22867
+ let r = Og(n, i);
22808
22868
  if (!r) return Lh(200), $("click_page_button ✖ no match"), `Could not find a button matching "${n}". Call list_page_forms to see button texts.`;
22809
22869
  try {
22810
22870
  try {
@@ -22825,15 +22885,31 @@ function Fg(e) {
22825
22885
  try {
22826
22886
  await Qh(r);
22827
22887
  } catch {}
22888
+ let e = ig(r) || a, t = [];
22889
+ if (e) {
22890
+ let n = Array.from(e.querySelectorAll("input[required], textarea[required], select[required]")).filter((e) => !rg(e));
22891
+ for (let e of n) if (!(e.value || "").trim()) {
22892
+ let n = lg(e) || e.placeholder || e.name || e.type;
22893
+ t.push(n);
22894
+ }
22895
+ }
22896
+ if (t.length > 0) {
22897
+ Lh(200);
22898
+ try {
22899
+ Zh();
22900
+ } catch {}
22901
+ let e = `Cannot submit — these required fields are still empty: ${t.join(", ")}. Fill them first with fill_form_fields, then click again.`;
22902
+ return $("click_page_button ✖ empty required fields:", t), e;
22903
+ }
22828
22904
  r.focus?.(), r.click();
22829
- let e = (r.textContent || r.value || r.getAttribute("aria-label") || "").trim().slice(0, 80) || "button";
22905
+ let n = (r.textContent || r.value || r.getAttribute("aria-label") || "").trim().slice(0, 80) || "button";
22830
22906
  Lh(600);
22831
22907
  try {
22832
22908
  Zh();
22833
22909
  } catch {}
22834
- Uh();
22835
- let t = `OK_CLICK ${e}`;
22836
- return $("click_page_button ✓", t), t;
22910
+ Uh(), a = null, i = [];
22911
+ let o = `OK_CLICK ${n}`;
22912
+ return $("click_page_button ✓", o), o;
22837
22913
  } catch (e) {
22838
22914
  Lh(200), Zh(!0);
22839
22915
  let t = `Click failed: ${e?.message || String(e)}`;
@@ -22842,19 +22918,19 @@ function Fg(e) {
22842
22918
  }
22843
22919
  };
22844
22920
  return {
22845
- ...a,
22846
- navigateToPage: a.navigate_to_page,
22847
- highlightOnPage: a.highlight_on_page,
22848
- searchSiteContent: a.search_site_content,
22849
- endVoiceSession: a.end_voice_session,
22850
- listPageForms: a.list_page_forms,
22851
- fillFormFields: a.fill_form_fields,
22852
- clickPageButton: a.click_page_button
22921
+ ...o,
22922
+ navigateToPage: o.navigate_to_page,
22923
+ highlightOnPage: o.highlight_on_page,
22924
+ searchSiteContent: o.search_site_content,
22925
+ endVoiceSession: o.end_voice_session,
22926
+ listPageForms: o.list_page_forms,
22927
+ fillFormFields: o.fill_form_fields,
22928
+ clickPageButton: o.click_page_button
22853
22929
  };
22854
22930
  }
22855
22931
  //#endregion
22856
22932
  //#region src/utils/wrapVoiceToolsForLogging.js
22857
- function Ig(e) {
22933
+ function Bg(e) {
22858
22934
  return !e || typeof e != "object" ? e : Object.fromEntries(Object.entries(e).map(([e, t]) => [e, async (n) => {
22859
22935
  let r = Zt();
22860
22936
  r ? console.log("[FlowEngage:voice-tool] ▶", e, n) : console.info(`[FlowEngage] voice tool » ${e}`);
@@ -22864,28 +22940,27 @@ function Ig(e) {
22864
22940
  }
22865
22941
  //#endregion
22866
22942
  //#region src/components/VoiceInterface.jsx
22867
- var Lg = {
22943
+ var Vg = {
22868
22944
  idle: "rgba(99,102,241,0.18)",
22869
22945
  listening: "rgba(16,185,129,0.25)",
22870
22946
  speaking: "rgba(245,158,11,0.25)",
22871
22947
  error: "rgba(239,68,68,0.2)"
22872
- }, Rg = {
22948
+ }, Hg = {
22873
22949
  idle: "#6366f1",
22874
22950
  listening: "#10b981",
22875
22951
  speaking: "#f59e0b",
22876
22952
  error: "#ef4444"
22877
22953
  };
22878
- function zg(e, t) {
22954
+ function Ug(e, t) {
22879
22955
  let n = (t || "").trim();
22880
22956
  return n ? !!(/\b(let'?s|let us)\s+(end|stop|finish|wrap up|close)\s+(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\bend\s+(this\s+)?(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\b(hang\s+up|disconnect)\b/i.test(n) || /\b(that'?s all|we'?re done)\b/i.test(n) || e === "bot" && (/\b(I'?ll|I will|Let me|I can|I'?m going to)\s+(end|close)\s+(the\s+)?(voice\s+)?(session|call)\b/i.test(n) || /\b(ending|closing)\s+(the\s+)?(voice\s+)?session\b|\bvoice\s+session\s+(is\s+)?(now\s+)?(ended|over|closing)\b/i.test(n) || /\b(session|call)\s+(is\s+)?(now\s+)?(ended|over)\b/i.test(n) || /\bwe\s+can\s+end\s+(the\s+)?(session|call)?\s*(here|now)\b/i.test(n) || /\b(wrapping\s+up|signing\s+off)\b/i.test(n)) || /^(goodbye|bye|that'?s all|we'?re done|hang up|disconnect)\b/i.test(n)) : !1;
22881
22957
  }
22882
- function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
22958
+ function Wg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
22883
22959
  let [h, g] = s("idle"), [ee, te] = s(null), [_, ne] = s(!1), re = o(null), ie = o(null), ae = o(""), oe = o(async () => {}), se = o(!1), v = n(async () => {
22884
- console.log("[FlowEngage:voice-sync] handleEnd called — historyRef has", d.current?.length ?? 0, "messages");
22885
22960
  try {
22886
22961
  await re.current?.endSession?.();
22887
22962
  } catch {}
22888
- re.current = null, ne(!1), g("idle"), se.current = !1, typeof p == "function" ? (console.log("[FlowEngage:voice-sync] Calling onMessageSync with", d.current?.length ?? 0, "messages:", d.current), await p(d.current), console.log("[FlowEngage:voice-sync] onMessageSync completed")) : console.warn("[FlowEngage:voice-sync] onMessageSync is NOT a function — transcript will be lost!"), typeof c == "function" && c();
22963
+ re.current = null, ne(!1), g("idle"), se.current = !1, typeof p == "function" && await p(d.current), typeof c == "function" && c();
22889
22964
  }, [
22890
22965
  d,
22891
22966
  p,
@@ -22897,7 +22972,7 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22897
22972
  try {
22898
22973
  if (await navigator.mediaDevices.getUserMedia({ audio: !0 }), t) return;
22899
22974
  d.current = [], ae.current = "", se.current = !1;
22900
- let i = Ig(Fg({
22975
+ let i = Bg(zg({
22901
22976
  siteId: r || null,
22902
22977
  apiBaseUrl: a || null,
22903
22978
  getLastUserVoiceText: () => ae.current,
@@ -22924,7 +22999,7 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22924
22999
  message: r,
22925
23000
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
22926
23001
  };
22927
- n === "user" && (ae.current = r), d.current = [...d.current, i], console.log(`[FlowEngage:voice-sync] onMessage [${n}]: "${r.slice(0, 80)}" — historyRef now has ${d.current.length} entries`), zg(n, r) && queueMicrotask(() => {
23002
+ n === "user" && (ae.current = r), d.current = [...d.current, i], Ug(n, r) && queueMicrotask(() => {
22928
23003
  se.current || (se.current = !0, oe.current?.());
22929
23004
  });
22930
23005
  },
@@ -22932,7 +23007,7 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22932
23007
  t || (console.error("[VoiceInterface] ElevenLabs error", e), g("error"), te("Voice session encountered an error."));
22933
23008
  },
22934
23009
  onDisconnect: () => {
22935
- t || (console.warn("[FlowEngage:voice-sync] ⚠ session DISCONNECTED — historyRef has", d.current?.length ?? 0, "messages that may NOT be synced (onDisconnect does not call onMessageSync)"), ne(!1), g("idle"));
23010
+ t || (console.log("[VoiceInterface] session disconnected"), ne(!1), g("idle"));
22936
23011
  }
22937
23012
  });
22938
23013
  if (t) {
@@ -22947,7 +23022,12 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22947
23022
  } catch {
22948
23023
  t = "[]";
22949
23024
  }
22950
- o.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}. Navigation: search_site_content then navigate_to_page with section_text when relevant — no permission ask. Forms: use fill_form_fields then click_page_button (e.g. Conduct Audit) when the user wants to submit. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end; you may also say you are ending the voice session.`);
23025
+ let n = "";
23026
+ try {
23027
+ let e = await i.search_site_content({ query: "pages" }), t = typeof e == "string" ? JSON.parse(e) : e;
23028
+ Array.isArray(t) && t.length && (n = ` Site pages available: ${t.map((e) => `${e.title || ""} (${e.url || ""})`).join(", ")}.`);
23029
+ } catch {}
23030
+ o.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}.${n} Navigation: when the user wants to go to any page (contact, pricing, about, services, etc.), call search_site_content then navigate_to_page immediately — never ask permission. After navigating to a page with a form, call list_page_forms and proactively start helping the user fill it. Forms: use fill_form_fields then click_page_button (e.g. Conduct Audit, Send Message) when the user wants to submit. Fill each field immediately after the user answers — never skip ahead. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end.`);
22951
23031
  } catch {}
22952
23032
  typeof m == "function" && m();
22953
23033
  } catch (e) {
@@ -22963,7 +23043,7 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
22963
23043
  d,
22964
23044
  m
22965
23045
  ]);
22966
- let ce = h === "listening" || h === "speaking", le = Rg[h] || Rg.idle, ue = Lg[h] || Lg.idle;
23046
+ let ce = h === "listening" || h === "speaking", le = Hg[h] || Hg.idle, ue = Vg[h] || Vg.idle;
22967
23047
  return /* @__PURE__ */ u("div", {
22968
23048
  ref: ie,
22969
23049
  style: {
@@ -23069,7 +23149,7 @@ function Bg({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23069
23149
  }
23070
23150
  //#endregion
23071
23151
  //#region src/components/FlowEngageWidget.jsx
23072
- var Vg = [
23152
+ var Gg = [
23073
23153
  {
23074
23154
  key: "become_client",
23075
23155
  label: "Become a Client"
@@ -23090,7 +23170,7 @@ var Vg = [
23090
23170
  key: "looking_for_job",
23091
23171
  label: "Looking for a Job"
23092
23172
  }
23093
- ], Hg = () => /* @__PURE__ */ l("div", {
23173
+ ], Kg = () => /* @__PURE__ */ l("div", {
23094
23174
  style: {
23095
23175
  display: "flex",
23096
23176
  marginBottom: "12px",
@@ -23121,7 +23201,7 @@ var Vg = [
23121
23201
  } }, e)), /* @__PURE__ */ l("style", { children: "\n @keyframes fe-dot-bounce {\n 0%, 80%, 100% { transform: translateY(0); opacity: 0.5; }\n 40% { transform: translateY(-5px); opacity: 1; }\n }\n " })]
23122
23202
  })
23123
23203
  });
23124
- function Ug() {
23204
+ function qg() {
23125
23205
  let { status: e, runtimeConfig: t, resolvedConfig: n, chatId: r, chatHistory: o, isOpen: c, activeScreen: d, isHumanHandled: f, agentName: p, agentHeadshot: m, visitorEmail: h, isAgentTyping: g, isAiTyping: ee, isLoading: te, isVoiceMode: _, isRateLimited: ne, rateLimitMessage: re, isConversationEnded: ie, incomingCall: ae, activeCallId: oe, callConnectionState: se, callConnectedAt: v, isCallMuted: ce, webRTCError: le, language: ue, historyRef: y, onMessageSync: b, endConversation: de, acceptCall: fe, rejectCall: pe, endWebRTCCall: me, toggleCallMute: he, dismissCallError: ge, captureVisitorEmail: _e, openWidget: ve, closeWidget: ye, sendMessage: be, setVoiceMode: xe, startTyping: Se, stopTyping: Ce, updateTypingDraft: we } = Xt(), [Te, Ee] = s(""), [De, Oe] = s(null), [ke, Ae] = s(null), [je, Me] = s(null), [Ne, Pe] = s(0), [x, Fe] = s(h || ""), [Ie, Le] = s("");
23126
23206
  i(() => {
23127
23207
  try {
@@ -23149,7 +23229,7 @@ function Ug() {
23149
23229
  outline: "none",
23150
23230
  fontFamily: "ui-sans-serif, system-ui, sans-serif",
23151
23231
  ...c ? {} : Ue
23152
- }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || Vg, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23232
+ }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || Gg, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23153
23233
  let e = o.findIndex((e) => e.sender === "user");
23154
23234
  return e === -1 ? !1 : o.slice(e + 1).some((e) => e.sender === "bot" || e.sender === "ai" || e.sender === "agent");
23155
23235
  }, [o]), rt = !h && tt && nt;
@@ -23277,7 +23357,7 @@ function Ug() {
23277
23357
  flexDirection: "column"
23278
23358
  },
23279
23359
  className: "fe-screen-fade-in",
23280
- children: /* @__PURE__ */ l(Bg, {
23360
+ children: /* @__PURE__ */ l(Wg, {
23281
23361
  agentId: T,
23282
23362
  chatId: r,
23283
23363
  siteId: Ye,
@@ -23310,7 +23390,7 @@ function Ug() {
23310
23390
  isAiTyping: ee,
23311
23391
  isAgentTyping: g,
23312
23392
  setReplyContext: Me,
23313
- TypingDots: Hg,
23393
+ TypingDots: Kg,
23314
23394
  primaryColor: Ve,
23315
23395
  agentHeadshot: $e,
23316
23396
  agentDisplayName: p || Ze
@@ -23389,4 +23469,4 @@ function Ug() {
23389
23469
  }) : null;
23390
23470
  }
23391
23471
  //#endregion
23392
- export { vn as FlowEngageProvider, Ug as FlowEngageWidget, Xt as useFlowEngage };
23472
+ export { vn as FlowEngageProvider, qg as FlowEngageWidget, Xt as useFlowEngage };