@modelnex/sdk 0.5.44 → 0.5.45

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.
package/dist/index.mjs CHANGED
@@ -1,25 +1,32 @@
1
1
  import {
2
2
  collectEditableControls,
3
+ emitSdkDebugLog,
4
+ extractInteractiveElements,
3
5
  findEditableControlInShadowRoot,
6
+ generateFingerprint,
4
7
  generateMinifiedAOM,
5
8
  isEditableControlDisabled,
9
+ isSdkDebugEnabled,
6
10
  isValueBearingElement,
7
11
  readEditableControlName,
8
12
  readEditableControlPlaceholder,
9
13
  readEditableControlType,
10
14
  readEditableControlValue,
11
- resolveEditableControlElement
12
- } from "./chunk-H4LUY7LI.mjs";
15
+ resolveEditableControlElement,
16
+ sanitizeAgentDebug,
17
+ sanitizeChatMessages,
18
+ useAutoExtract
19
+ } from "./chunk-SXGINP3O.mjs";
13
20
 
14
21
  // src/index.ts
15
- import React8, { useState as useState15, useCallback as useCallback14, useEffect as useEffect19, useMemo as useMemo5 } from "react";
22
+ import React8, { useState as useState14, useCallback as useCallback13, useEffect as useEffect18, useMemo as useMemo5 } from "react";
16
23
 
17
24
  // src/context.ts
18
25
  import { createContext } from "react";
19
26
  var ModelNexContext = createContext(null);
20
27
 
21
28
  // src/hooks/useModelNexSocket.ts
22
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
29
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
23
30
  import { io } from "socket.io-client";
24
31
 
25
32
  // src/utils/socket-io-transports.ts
@@ -34,390 +41,11 @@ function resolveSocketIoTransports(serverUrl, order) {
34
41
  return ["websocket", "polling"];
35
42
  }
36
43
 
37
- // src/auto-extract.ts
38
- import { useState, useEffect as useEffect2, useRef as useRef2, useCallback as useCallback2 } from "react";
39
-
40
- // src/utils/dev-logging.ts
41
- function isSdkDebugEnabled(devMode) {
42
- if (devMode) return true;
43
- if (typeof window !== "undefined" && Boolean(window.MODELNEX_DEBUG)) {
44
- return true;
45
- }
46
- return process.env.NODE_ENV === "development";
47
- }
48
- function emitSdkDebugLog(message, payload, options) {
49
- if (!isSdkDebugEnabled(options?.devMode)) return;
50
- if (payload && Object.keys(payload).length > 0) {
51
- console.log(message, payload);
52
- } else {
53
- console.log(message);
54
- }
55
- if (options?.dispatchEvent && typeof window !== "undefined") {
56
- window.dispatchEvent(new CustomEvent("modelnex-debug", { detail: { msg: message, data: payload } }));
57
- }
58
- }
59
- function sanitizeActionList(actions) {
60
- if (!Array.isArray(actions) || actions.length === 0) return void 0;
61
- return actions.map(({ actionId }) => ({ actionId }));
62
- }
63
- function sanitizeAgentDebug(debug) {
64
- if (!debug) return void 0;
65
- const actions = sanitizeActionList(debug.actions);
66
- const traces = Array.isArray(debug.traces) && debug.traces.length > 0 ? debug.traces.map((trace) => ({
67
- step: trace.step,
68
- actions: sanitizeActionList(trace.actions) ?? [],
69
- results: Array.isArray(trace.results) && trace.results.length > 0 ? trace.results.map(({ actionId, success }) => ({ actionId, success })) : void 0
70
- })) : void 0;
71
- if ((!actions || actions.length === 0) && (!traces || traces.length === 0)) {
72
- return void 0;
73
- }
74
- return {
75
- ...actions ? { actions } : {},
76
- ...traces ? { traces } : {}
77
- };
78
- }
79
- function sanitizeChatMessages(messages, devMode) {
80
- const includeDebug = isSdkDebugEnabled(devMode);
81
- return messages.map((message) => {
82
- if (message.role !== "assistant") {
83
- return message;
84
- }
85
- return {
86
- ...message,
87
- debug: includeDebug ? sanitizeAgentDebug(message.debug) : void 0
88
- };
89
- });
90
- }
91
-
92
- // src/auto-extract.ts
93
- function simpleHash(str) {
94
- let hash = 0;
95
- for (let i = 0; i < str.length; i++) {
96
- const char = str.charCodeAt(i);
97
- hash = (hash << 5) - hash + char;
98
- hash |= 0;
99
- }
100
- return (hash >>> 0).toString(16).padStart(8, "0");
101
- }
102
- function isStableDomId(id) {
103
- if (!id) return false;
104
- const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
105
- const REACT_USE_ID_RE = /^(?:radix-)?:[rR][^\s]*$/;
106
- if (REACT_USE_ID_RE.test(id)) return false;
107
- if (/^\d+$/.test(id)) return false;
108
- if (UUID_RE.test(id)) return false;
109
- return true;
110
- }
111
- function getNearestHeading(el) {
112
- const shellContainer = el.closest('nav, aside, header, [role="navigation"], [role="complementary"], [role="banner"]');
113
- const boundary = shellContainer || document.body;
114
- let current = el;
115
- while (current && current !== boundary) {
116
- let sibling = current.previousElementSibling;
117
- while (sibling) {
118
- if (/^H[1-6]$/.test(sibling.tagName)) {
119
- return sibling.textContent?.trim().slice(0, 100) || null;
120
- }
121
- const innerHeading = sibling.querySelector("h1, h2, h3, h4, h5, h6");
122
- if (innerHeading) {
123
- return innerHeading.textContent?.trim().slice(0, 100) || null;
124
- }
125
- sibling = sibling.previousElementSibling;
126
- }
127
- const parentHeading = current.parentElement?.querySelector("h1, h2, h3, h4, h5, h6");
128
- if (parentHeading && !current.contains(parentHeading)) {
129
- return parentHeading.textContent?.trim().slice(0, 100) || null;
130
- }
131
- current = current.parentElement;
132
- }
133
- return null;
134
- }
135
- function getParentContainer(el) {
136
- let current = el.parentElement;
137
- while (current && current !== document.body) {
138
- const role = current.getAttribute("role");
139
- const tag = current.tagName.toLowerCase();
140
- const state = current.getAttribute("data-state");
141
- if (role === "dialog" || role === "alertdialog" || tag === "dialog") {
142
- const title = current.querySelector('h2, h3, [class*="title"]');
143
- const titleText = title?.textContent?.trim().slice(0, 60) || "";
144
- return titleText ? `dialog:${titleText}` : "dialog";
145
- }
146
- if (role === "menu" || role === "listbox") {
147
- return role;
148
- }
149
- if (current.hasAttribute("popover") || state === "open" && current.getAttribute("data-radix-popper-content-wrapper") !== null) {
150
- return "popover";
151
- }
152
- if (current.getAttribute("data-radix-menu-content") !== null || role === "menubar") {
153
- return "dropdown-menu";
154
- }
155
- if (role === "tabpanel") {
156
- const label = current.getAttribute("aria-label") || current.getAttribute("aria-labelledby");
157
- return label ? `tabpanel:${label.slice(0, 40)}` : "tabpanel";
158
- }
159
- if (tag === "nav" || role === "navigation") {
160
- const label = current.getAttribute("aria-label");
161
- return label ? `navigation:${label.slice(0, 40)}` : "navigation";
162
- }
163
- if (tag === "aside") {
164
- return "sidebar";
165
- }
166
- if (tag === "header") {
167
- return "header";
168
- }
169
- current = current.parentElement;
170
- }
171
- return null;
172
- }
173
- function getRowContext(el) {
174
- let current = el.parentElement;
175
- while (current && current !== document.body) {
176
- const tag = current.tagName.toLowerCase();
177
- if (tag === "tr" || tag === "li" || current.getAttribute("role") === "row" || current.getAttribute("role") === "listitem") {
178
- const rowText = current.textContent?.trim().replace(/\s+/g, " ").slice(0, 120) || "";
179
- return rowText;
180
- }
181
- current = current.parentElement;
182
- }
183
- return "";
184
- }
185
- function getNearestAncestorId(el) {
186
- let current = el.parentElement;
187
- while (current && current !== document.body) {
188
- const aid = current.id;
189
- if (isStableDomId(aid)) {
190
- return aid;
191
- }
192
- const ancestorTestId = current.getAttribute("data-testid");
193
- if (ancestorTestId) return `[data-testid="${ancestorTestId}"]`;
194
- current = current.parentElement;
195
- }
196
- return null;
197
- }
198
- function generateFingerprint(el) {
199
- const tag = el.tagName.toLowerCase();
200
- const testId = el.getAttribute("data-testid");
201
- const id = el.id;
202
- const name = el.getAttribute("name");
203
- const ariaLabel = el.getAttribute("aria-label");
204
- const type = el.type || "";
205
- const text = el.textContent?.trim().slice(0, 80) || "";
206
- if (testId) return `tid:${testId}`;
207
- if (isStableDomId(id)) return `id:${id}`;
208
- if (name) return `name:${tag}:${name}`;
209
- if (ariaLabel) {
210
- const rowCtx2 = getRowContext(el);
211
- if (rowCtx2) {
212
- return `aria:${simpleHash(ariaLabel + ":" + rowCtx2)}:${ariaLabel.slice(0, 40)}`;
213
- }
214
- return `aria:${simpleHash(ariaLabel)}:${ariaLabel.slice(0, 40)}`;
215
- }
216
- if (tag === "a") {
217
- const href = el.getAttribute("href");
218
- if (href && href !== "#" && !href.startsWith("javascript:")) {
219
- return `href:${simpleHash(href + ":" + text)}:${text.slice(0, 30) || href.slice(0, 30)}`;
220
- }
221
- }
222
- const ancestorId = getNearestAncestorId(el);
223
- if (ancestorId) {
224
- return `anc:${simpleHash(ancestorId + ":" + tag + ":" + text)}:${text.slice(0, 30) || tag}`;
225
- }
226
- const heading = getNearestHeading(el) || "";
227
- const rowCtx = getRowContext(el);
228
- const raw = `${tag}:${type}:${text}:${heading}:${rowCtx}`;
229
- return `hash:${simpleHash(raw)}:${text.slice(0, 30) || tag}`;
230
- }
231
- function classifyRole(el) {
232
- const tag = el.tagName.toLowerCase();
233
- const role = el.getAttribute("role");
234
- if (tag === "button" || role === "button") return "button";
235
- if (tag === "a") return "link";
236
- if (tag === "input") return "input";
237
- if (tag === "textarea") return "textarea";
238
- if (tag === "select") return "select";
239
- if (tag === "form") return "form";
240
- if (tag === "label") return "label";
241
- if (role === "link") return "link";
242
- if (role === "menuitem") return "menuitem";
243
- if (role === "menuitemcheckbox") return "menuitem";
244
- if (role === "menuitemradio") return "menuitem";
245
- if (role === "tab") return "tab";
246
- if (role === "checkbox") return "checkbox";
247
- if (role === "radio") return "radio";
248
- if (role === "switch") return "switch";
249
- if (role === "slider") return "slider";
250
- if (role === "combobox") return "combobox";
251
- if (role === "option") return "option";
252
- if (role === "treeitem") return "treeitem";
253
- if (role === "gridcell") return "gridcell";
254
- if (el.hasAttribute("tabindex") && el.getAttribute("tabindex") !== "-1") return "interactive";
255
- if (el.hasAttribute("cmdk-item")) return "menuitem";
256
- return null;
257
- }
258
- var INTERACTIVE_SELECTOR = [
259
- "button",
260
- "a",
261
- // All anchor tags (SPA links may not have href)
262
- 'input:not([type="hidden"])',
263
- "textarea",
264
- "select",
265
- "label[for]",
266
- '[role="button"]',
267
- '[role="link"]',
268
- '[role="menuitem"]',
269
- '[role="menuitemcheckbox"]',
270
- '[role="menuitemradio"]',
271
- '[role="tab"]',
272
- '[role="checkbox"]',
273
- '[role="radio"]',
274
- '[role="switch"]',
275
- '[role="slider"]',
276
- '[role="combobox"]',
277
- '[role="option"]',
278
- '[role="treeitem"]',
279
- '[role="gridcell"]',
280
- '[tabindex]:not([tabindex="-1"])',
281
- "[data-discover]",
282
- // React Router links
283
- "[cmdk-item]",
284
- // cmdk menu items
285
- "form"
286
- ].join(", ");
287
- function isVisible(el) {
288
- if (el.offsetParent === null) {
289
- const computed = window.getComputedStyle(el);
290
- if (computed.position !== "fixed" && computed.position !== "sticky") {
291
- if (computed.display === "none" || computed.visibility === "hidden") {
292
- return false;
293
- }
294
- const rect2 = el.getBoundingClientRect();
295
- if (rect2.width === 0 && rect2.height === 0) return false;
296
- }
297
- }
298
- const style = window.getComputedStyle(el);
299
- if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
300
- return false;
301
- }
302
- const rect = el.getBoundingClientRect();
303
- return rect.width > 0 && rect.height > 0;
304
- }
305
- function extractInteractiveElements() {
306
- const elements = [];
307
- const seen = /* @__PURE__ */ new Set();
308
- try {
309
- const nodes = document.querySelectorAll(INTERACTIVE_SELECTOR);
310
- nodes.forEach((node) => {
311
- const el = node;
312
- if (!isVisible(el)) return;
313
- if (el.closest(".modelnex-chat-panel, .modelnex-studio-overlay, [data-modelnex-internal]")) return;
314
- const role = classifyRole(el);
315
- if (!role) return;
316
- let fingerprint = generateFingerprint(el);
317
- if (seen.has(fingerprint)) {
318
- let idx = 2;
319
- while (seen.has(`${fingerprint}#${idx}`)) idx++;
320
- fingerprint = `${fingerprint}#${idx}`;
321
- }
322
- seen.add(fingerprint);
323
- const rect = el.getBoundingClientRect();
324
- const text = el.textContent?.trim().slice(0, 200) || "";
325
- elements.push({
326
- fingerprint,
327
- tagName: el.tagName.toLowerCase(),
328
- text,
329
- role,
330
- rect: {
331
- top: rect.top,
332
- left: rect.left,
333
- width: rect.width,
334
- height: rect.height
335
- },
336
- attributes: {
337
- id: el.id || void 0,
338
- name: el.getAttribute("name") || void 0,
339
- type: el.type || void 0,
340
- ariaLabel: el.getAttribute("aria-label") || void 0,
341
- dataTestId: el.getAttribute("data-testid") || void 0,
342
- href: el.href || void 0,
343
- placeholder: el.placeholder || void 0
344
- },
345
- nearestHeading: getNearestHeading(el),
346
- parentContainer: getParentContainer(el),
347
- disabled: el.disabled || el.getAttribute("aria-disabled") === "true",
348
- element: el
349
- });
350
- });
351
- } catch (err) {
352
- console.warn("[ModelNex] Auto-extraction error:", err);
353
- }
354
- return elements;
355
- }
356
- function useAutoExtract(devMode) {
357
- const [elements, setElements] = useState([]);
358
- const timerRef = useRef2(null);
359
- const lastSnapshotRef = useRef2("");
360
- const scan = useCallback2(() => {
361
- if (typeof document === "undefined") return;
362
- const extracted = extractInteractiveElements();
363
- const snapshot = JSON.stringify(extracted.map((e) => ({
364
- fingerprint: e.fingerprint,
365
- role: e.role,
366
- text: e.text,
367
- rect: e.rect,
368
- disabled: e.disabled,
369
- nearestHeading: e.nearestHeading,
370
- parentContainer: e.parentContainer
371
- })));
372
- if (snapshot === lastSnapshotRef.current) return;
373
- lastSnapshotRef.current = snapshot;
374
- emitSdkDebugLog("[ModelNex AutoExtract] Scan complete", {
375
- elementCount: extracted.length
376
- }, { devMode });
377
- setElements(extracted);
378
- }, [devMode]);
379
- useEffect2(() => {
380
- const initialTimer = setTimeout(scan, 300);
381
- const observer = new MutationObserver((mutations) => {
382
- const hasRelevantMutation = mutations.some((mutation) => {
383
- const target = mutation.target;
384
- if (target?.closest?.(".modelnex-chat-panel, .modelnex-studio-overlay, [data-modelnex-internal]")) {
385
- return false;
386
- }
387
- return true;
388
- });
389
- if (!hasRelevantMutation) return;
390
- if (timerRef.current) clearTimeout(timerRef.current);
391
- timerRef.current = setTimeout(scan, 500);
392
- });
393
- observer.observe(document.body, {
394
- childList: true,
395
- subtree: true,
396
- attributes: true,
397
- attributeFilter: ["disabled", "aria-disabled", "hidden", "style", "class"]
398
- });
399
- const handlePositionChange = () => {
400
- if (timerRef.current) clearTimeout(timerRef.current);
401
- timerRef.current = setTimeout(scan, 200);
402
- };
403
- window.addEventListener("scroll", handlePositionChange, { passive: true });
404
- window.addEventListener("resize", handlePositionChange, { passive: true });
405
- return () => {
406
- clearTimeout(initialTimer);
407
- if (timerRef.current) clearTimeout(timerRef.current);
408
- observer.disconnect();
409
- window.removeEventListener("scroll", handlePositionChange);
410
- window.removeEventListener("resize", handlePositionChange);
411
- };
412
- }, [scan]);
413
- return elements;
414
- }
415
-
416
44
  // src/utils/dom-summary.ts
417
45
  function textOf(el) {
418
46
  return el?.textContent?.trim().slice(0, 200) ?? "";
419
47
  }
420
- function isVisible2(el) {
48
+ function isVisible(el) {
421
49
  const htmlEl = el;
422
50
  const style = window.getComputedStyle(htmlEl);
423
51
  if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
@@ -488,7 +116,7 @@ function captureDomSummary(tags) {
488
116
  const alerts = safeQueryAll('[role="alert"], [role="status"]').map(textOf).filter(Boolean);
489
117
  const allButtons = safeQueryAll('button, [role="button"], a[class*="btn"], a[class*="Button"], a');
490
118
  const disabledButtons = allButtons.filter((b) => b.disabled || b.getAttribute("aria-disabled") === "true").map((b) => ({ text: textOf(b), fingerprint: generateFingerprint(b) })).filter((o) => !!o.text);
491
- const enabledButtons = allButtons.filter((b) => !b.disabled && b.getAttribute("aria-disabled") !== "true").filter((b) => isVisible2(b)).map((b) => ({ text: textOf(b), fingerprint: generateFingerprint(b) })).filter((o) => !!o.text).slice(0, 40);
119
+ const enabledButtons = allButtons.filter((b) => !b.disabled && b.getAttribute("aria-disabled") !== "true").filter((b) => isVisible(b)).map((b) => ({ text: textOf(b), fingerprint: generateFingerprint(b) })).filter((o) => !!o.text).slice(0, 40);
492
120
  const visibleDialogs = safeQueryAll('[role="dialog"], [data-state="open"], dialog[open]').map((d) => {
493
121
  const title = d.querySelector('h2, h3, [class*="title"]');
494
122
  return title ? textOf(title) : textOf(d).slice(0, 100);
@@ -692,16 +320,16 @@ function useModelNexSocket({
692
320
  websiteId,
693
321
  devMode
694
322
  }) {
695
- const socketRef = useRef3(null);
696
- const actionsRef = useRef3(actions);
697
- const contextsRef = useRef3(contexts);
698
- const documentationRef = useRef3(documentation);
699
- const tagsRef = useRef3(tags);
323
+ const socketRef = useRef2(null);
324
+ const actionsRef = useRef2(actions);
325
+ const contextsRef = useRef2(contexts);
326
+ const documentationRef = useRef2(documentation);
327
+ const tagsRef = useRef2(tags);
700
328
  actionsRef.current = actions;
701
329
  contextsRef.current = contexts;
702
330
  documentationRef.current = documentation;
703
331
  tagsRef.current = tags;
704
- useEffect3(() => {
332
+ useEffect2(() => {
705
333
  if (disabled) {
706
334
  socketRef.current = null;
707
335
  onSocketId?.(null);
@@ -834,7 +462,7 @@ function useModelNexSocket({
834
462
  socket.disconnect();
835
463
  };
836
464
  }, [disabled, onSocketId, serverUrl]);
837
- useEffect3(() => {
465
+ useEffect2(() => {
838
466
  if (disabled) {
839
467
  return;
840
468
  }
@@ -852,10 +480,10 @@ function useModelNexSocket({
852
480
  }
853
481
 
854
482
  // src/hooks/useFieldHighlight.ts
855
- import { useEffect as useEffect4, useRef as useRef4 } from "react";
483
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
856
484
  function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
857
- const highlightedRef = useRef4(/* @__PURE__ */ new Map());
858
- useEffect4(() => {
485
+ const highlightedRef = useRef3(/* @__PURE__ */ new Map());
486
+ useEffect3(() => {
859
487
  const prev = highlightedRef.current;
860
488
  prev.forEach((_, fieldId) => {
861
489
  if (!stagingFields.has(fieldId)) {
@@ -874,7 +502,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
874
502
  prev.clear();
875
503
  };
876
504
  }, [stagingFields]);
877
- useEffect4(() => {
505
+ useEffect3(() => {
878
506
  const timeouts = [];
879
507
  executedFields.forEach((fieldId) => {
880
508
  const els = document.querySelectorAll(`[data-modelnex-field-id="${fieldId}"]`);
@@ -895,7 +523,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
895
523
  }
896
524
 
897
525
  // src/overlay.tsx
898
- import React2, { useState as useState2, useEffect as useEffect5 } from "react";
526
+ import React2, { useState, useEffect as useEffect4 } from "react";
899
527
  var AIActivityOverlay = ({ activeActions }) => {
900
528
  if (activeActions.size === 0) return null;
901
529
  return React2.createElement(
@@ -1092,7 +720,7 @@ body.modelnex-highlight-actions [data-modelnex-action-id]::before {
1092
720
  `;
1093
721
 
1094
722
  // src/tag-store.ts
1095
- import { useState as useState3, useCallback as useCallback3, useEffect as useEffect6 } from "react";
723
+ import { useState as useState2, useCallback as useCallback2, useEffect as useEffect5 } from "react";
1096
724
  var STORAGE_KEY = "modelnex-tags";
1097
725
  function loadTags() {
1098
726
  try {
@@ -1116,10 +744,10 @@ function saveTags(tags) {
1116
744
  }
1117
745
  }
1118
746
  function useTagStore(options) {
1119
- const [tags, setTags] = useState3(/* @__PURE__ */ new Map());
747
+ const [tags, setTags] = useState2(/* @__PURE__ */ new Map());
1120
748
  const apiUrl = options?.serverUrl ? `${options.serverUrl.replace(/\/$/, "")}/api/tags` : null;
1121
749
  const websiteId = options?.websiteId;
1122
- useEffect6(() => {
750
+ useEffect5(() => {
1123
751
  const local = loadTags();
1124
752
  setTags(local);
1125
753
  if (apiUrl) {
@@ -1139,14 +767,14 @@ function useTagStore(options) {
1139
767
  }).catch((err) => console.warn("[ModelNex] Failed to fetch remote tags:", err));
1140
768
  }
1141
769
  }, [apiUrl]);
1142
- useEffect6(() => {
770
+ useEffect5(() => {
1143
771
  if (typeof window === "undefined") return;
1144
772
  saveTags(tags);
1145
773
  }, [tags]);
1146
- const getTag = useCallback3((fingerprint) => {
774
+ const getTag = useCallback2((fingerprint) => {
1147
775
  return tags.get(fingerprint);
1148
776
  }, [tags]);
1149
- const setTag = useCallback3((fingerprint, description, category, metadata, selector, patternId, behavior, sourcePage, displayContext, skipRemoteSync) => {
777
+ const setTag = useCallback2((fingerprint, description, category, metadata, selector, patternId, behavior, sourcePage, displayContext, skipRemoteSync) => {
1150
778
  setTags((prev) => {
1151
779
  const next = new Map(prev);
1152
780
  const key = selector ? `selector:${selector}` : fingerprint;
@@ -1178,7 +806,7 @@ function useTagStore(options) {
1178
806
  return next;
1179
807
  });
1180
808
  }, [apiUrl, websiteId]);
1181
- const setTagsBatch = useCallback3((newTags, skipRemoteSync) => {
809
+ const setTagsBatch = useCallback2((newTags, skipRemoteSync) => {
1182
810
  setTags((prev) => {
1183
811
  const next = new Map(prev);
1184
812
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -1206,24 +834,24 @@ function useTagStore(options) {
1206
834
  return next;
1207
835
  });
1208
836
  }, [apiUrl, websiteId]);
1209
- const deleteTag = useCallback3((fingerprint) => {
837
+ const deleteTag = useCallback2((fingerprint) => {
1210
838
  setTags((prev) => {
1211
839
  const next = new Map(prev);
1212
840
  next.delete(fingerprint);
1213
841
  return next;
1214
842
  });
1215
843
  }, []);
1216
- const getAllTags = useCallback3(() => {
844
+ const getAllTags = useCallback2(() => {
1217
845
  return Array.from(tags.values());
1218
846
  }, [tags]);
1219
- const exportTags = useCallback3(() => {
847
+ const exportTags = useCallback2(() => {
1220
848
  const obj = {};
1221
849
  tags.forEach((v, k) => {
1222
850
  obj[k] = v;
1223
851
  });
1224
852
  return JSON.stringify(obj, null, 2);
1225
853
  }, [tags]);
1226
- const importTags = useCallback3((json) => {
854
+ const importTags = useCallback2((json) => {
1227
855
  try {
1228
856
  const parsed = JSON.parse(json);
1229
857
  setTags((prev) => {
@@ -1239,7 +867,7 @@ function useTagStore(options) {
1239
867
  }
1240
868
 
1241
869
  // src/studio-mode.tsx
1242
- import { useState as useState4, useEffect as useEffect7, useRef as useRef5, useCallback as useCallback4 } from "react";
870
+ import { useState as useState3, useEffect as useEffect6, useRef as useRef4, useCallback as useCallback3 } from "react";
1243
871
  import { jsx, jsxs } from "react/jsx-runtime";
1244
872
  var CATEGORIES = [
1245
873
  { value: "button", label: "Button" },
@@ -1250,10 +878,10 @@ var CATEGORIES = [
1250
878
  { value: "other", label: "Other" }
1251
879
  ];
1252
880
  function TaggingPanel({ element, existingTag, onSave, onDelete, onClose }) {
1253
- const [description, setDescription] = useState4(existingTag?.description ?? "");
1254
- const [category, setCategory] = useState4(existingTag?.category ?? "other");
1255
- const inputRef = useRef5(null);
1256
- useEffect7(() => {
881
+ const [description, setDescription] = useState3(existingTag?.description ?? "");
882
+ const [category, setCategory] = useState3(existingTag?.category ?? "other");
883
+ const inputRef = useRef4(null);
884
+ useEffect6(() => {
1257
885
  inputRef.current?.focus();
1258
886
  }, []);
1259
887
  const handleSave = () => {
@@ -1480,10 +1108,10 @@ function findTagForElement(el, tagStore) {
1480
1108
  return void 0;
1481
1109
  }
1482
1110
  function StudioOverlay({ elements, tagStore }) {
1483
- const [selectedFingerprint, setSelectedFingerprint] = useState4(null);
1484
- const [positions, setPositions] = useState4(/* @__PURE__ */ new Map());
1485
- const liveElementsRef = useRef5(/* @__PURE__ */ new Map());
1486
- const updatePositions = useCallback4(() => {
1111
+ const [selectedFingerprint, setSelectedFingerprint] = useState3(null);
1112
+ const [positions, setPositions] = useState3(/* @__PURE__ */ new Map());
1113
+ const liveElementsRef = useRef4(/* @__PURE__ */ new Map());
1114
+ const updatePositions = useCallback3(() => {
1487
1115
  const newPositions = /* @__PURE__ */ new Map();
1488
1116
  const newLiveElements = /* @__PURE__ */ new Map();
1489
1117
  const knownFingerprints = new Set(elements.map((e) => e.fingerprint));
@@ -1518,7 +1146,7 @@ function StudioOverlay({ elements, tagStore }) {
1518
1146
  liveElementsRef.current = newLiveElements;
1519
1147
  setPositions(newPositions);
1520
1148
  }, [elements]);
1521
- useEffect7(() => {
1149
+ useEffect6(() => {
1522
1150
  updatePositions();
1523
1151
  const interval = setInterval(updatePositions, 1e3);
1524
1152
  window.addEventListener("scroll", updatePositions, { passive: true });
@@ -1662,7 +1290,7 @@ function StudioOverlay({ elements, tagStore }) {
1662
1290
  }
1663
1291
 
1664
1292
  // src/hooks/useBuiltinActions.ts
1665
- import { useEffect as useEffect8, useRef as useRef6 } from "react";
1293
+ import { useEffect as useEffect7, useRef as useRef5 } from "react";
1666
1294
  import { z as z2 } from "zod";
1667
1295
 
1668
1296
  // src/utils/screenshot.ts
@@ -2514,18 +2142,18 @@ var BUILTIN_ACTION_IDS = {
2514
2142
  startWorkflow: "start_workflow"
2515
2143
  };
2516
2144
  function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl, websiteId, toursApiBase, userProfile) {
2517
- const registeredRef = useRef6(false);
2518
- const tagStoreRef = useRef6(tagStore);
2145
+ const registeredRef = useRef5(false);
2146
+ const tagStoreRef = useRef5(tagStore);
2519
2147
  tagStoreRef.current = tagStore;
2520
- const serverUrlRef = useRef6(serverUrl);
2148
+ const serverUrlRef = useRef5(serverUrl);
2521
2149
  serverUrlRef.current = serverUrl;
2522
- const websiteIdRef = useRef6(websiteId);
2150
+ const websiteIdRef = useRef5(websiteId);
2523
2151
  websiteIdRef.current = websiteId;
2524
- const toursApiBaseRef = useRef6(toursApiBase);
2152
+ const toursApiBaseRef = useRef5(toursApiBase);
2525
2153
  toursApiBaseRef.current = toursApiBase;
2526
- const userProfileRef = useRef6(userProfile);
2154
+ const userProfileRef = useRef5(userProfile);
2527
2155
  userProfileRef.current = userProfile;
2528
- useEffect8(() => {
2156
+ useEffect7(() => {
2529
2157
  if (registeredRef.current) return;
2530
2158
  registeredRef.current = true;
2531
2159
  const getTagStore = () => tagStoreRef.current;
@@ -2880,7 +2508,7 @@ function readPreviewSessionSuppression() {
2880
2508
  }
2881
2509
 
2882
2510
  // src/hooks/useRunCommand.ts
2883
- import { useCallback as useCallback5, useContext as useContext2 } from "react";
2511
+ import { useCallback as useCallback4, useContext as useContext2 } from "react";
2884
2512
  function searchTaggedElementsForQuery(store, query, limit = 8) {
2885
2513
  const allTags = store.getAllTags();
2886
2514
  if (allTags.length === 0) return [];
@@ -2903,7 +2531,7 @@ function useRunCommand(serverUrlOverride) {
2903
2531
  const context = useContext2(ModelNexContext);
2904
2532
  const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
2905
2533
  const tagStore = context?.tagStore;
2906
- return useCallback5(
2534
+ return useCallback4(
2907
2535
  async (command, signal) => {
2908
2536
  const url = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/command` : `${baseUrl}/agent/command`;
2909
2537
  const relevantTaggedElements = tagStore ? searchTaggedElementsForQuery(tagStore, command) : void 0;
@@ -2931,7 +2559,7 @@ function useRunCommand(serverUrlOverride) {
2931
2559
  }
2932
2560
 
2933
2561
  // src/ui-state.tsx
2934
- import { createContext as createContext2, useContext as useContext3, useState as useState5, useCallback as useCallback6, useMemo as useMemo2 } from "react";
2562
+ import { createContext as createContext2, useContext as useContext3, useState as useState4, useCallback as useCallback5, useMemo as useMemo2 } from "react";
2935
2563
  import { jsx as jsx2 } from "react/jsx-runtime";
2936
2564
  var UIStateContext = createContext2(null);
2937
2565
  function UIStateProvider({
@@ -2940,8 +2568,8 @@ function UIStateProvider({
2940
2568
  type = "ui",
2941
2569
  initialState = {}
2942
2570
  }) {
2943
- const [state, setStateInternal] = useState5(initialState);
2944
- const setState = useCallback6((update) => {
2571
+ const [state, setStateInternal] = useState4(initialState);
2572
+ const setState = useCallback5((update) => {
2945
2573
  setStateInternal((prev) => ({ ...prev, ...update }));
2946
2574
  }, []);
2947
2575
  const value = useMemo2(() => ({ state, setState }), [state, setState]);
@@ -2954,7 +2582,7 @@ function useUIState() {
2954
2582
  }
2955
2583
 
2956
2584
  // src/viewport.ts
2957
- import { useEffect as useEffect10, useRef as useRef7, useState as useState6 } from "react";
2585
+ import { useEffect as useEffect9, useRef as useRef6, useState as useState5 } from "react";
2958
2586
  var visibleIds = /* @__PURE__ */ new Set();
2959
2587
  var listeners = /* @__PURE__ */ new Set();
2960
2588
  function updateVisibility(id, visible) {
@@ -2963,9 +2591,9 @@ function updateVisibility(id, visible) {
2963
2591
  listeners.forEach((fn) => fn());
2964
2592
  }
2965
2593
  function useViewportTrack(id) {
2966
- const ref = useRef7(null);
2967
- const [, setTick] = useState6(0);
2968
- useEffect10(() => {
2594
+ const ref = useRef6(null);
2595
+ const [, setTick] = useState5(0);
2596
+ useEffect9(() => {
2969
2597
  const el = ref.current;
2970
2598
  if (!el) return;
2971
2599
  const obs = new IntersectionObserver(
@@ -2980,7 +2608,7 @@ function useViewportTrack(id) {
2980
2608
  updateVisibility(id, false);
2981
2609
  };
2982
2610
  }, [id]);
2983
- useEffect10(() => {
2611
+ useEffect9(() => {
2984
2612
  const fn = () => setTick((t) => t + 1);
2985
2613
  listeners.add(fn);
2986
2614
  return () => {
@@ -2990,8 +2618,8 @@ function useViewportTrack(id) {
2990
2618
  return ref;
2991
2619
  }
2992
2620
  function useVisibleIds() {
2993
- const [ids, setIds] = useState6([]);
2994
- useEffect10(() => {
2621
+ const [ids, setIds] = useState5([]);
2622
+ useEffect9(() => {
2995
2623
  const fn = () => setIds(Array.from(visibleIds));
2996
2624
  fn();
2997
2625
  listeners.add(fn);
@@ -3008,11 +2636,11 @@ function useAgentViewport(options = {}) {
3008
2636
  }
3009
2637
 
3010
2638
  // src/chat-bubble.tsx
3011
- import { useState as useState13, useRef as useRef13, useEffect as useEffect17, useContext as useContext5, useCallback as useCallback12, useMemo as useMemo3 } from "react";
2639
+ import { useState as useState12, useRef as useRef12, useEffect as useEffect16, useContext as useContext5, useCallback as useCallback11, useMemo as useMemo3 } from "react";
3012
2640
  import { createPortal, flushSync } from "react-dom";
3013
2641
 
3014
2642
  // src/hooks/useExperiencePlaybackController.ts
3015
- import { useCallback as useCallback8, useEffect as useEffect12, useRef as useRef9, useState as useState8 } from "react";
2643
+ import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef8, useState as useState7 } from "react";
3016
2644
 
3017
2645
  // src/utils/locationSignature.ts
3018
2646
  function getLocationSignature(locationLike) {
@@ -3021,7 +2649,7 @@ function getLocationSignature(locationLike) {
3021
2649
  }
3022
2650
 
3023
2651
  // src/hooks/useTourPlayback.ts
3024
- import { useState as useState7, useRef as useRef8, useCallback as useCallback7, useEffect as useEffect11, useContext as useContext4 } from "react";
2652
+ import { useState as useState6, useRef as useRef7, useCallback as useCallback6, useEffect as useEffect10, useContext as useContext4 } from "react";
3025
2653
 
3026
2654
  // src/utils/retryLookup.ts
3027
2655
  var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -3787,58 +3415,58 @@ function useTourPlayback({
3787
3415
  enableAutoDiscovery = true
3788
3416
  }) {
3789
3417
  const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
3790
- const [isActive, setIsActive] = useState7(false);
3791
- const [currentStepIndex, setCurrentStepIndex] = useState7(0);
3792
- const [totalSteps, setTotalSteps] = useState7(0);
3793
- const [activeTour, setActiveTour] = useState7(null);
3794
- const [playbackState, setPlaybackState] = useState7("idle");
3795
- const [isReviewMode, setIsReviewMode] = useState7(false);
3796
- const [previewRunId, setPreviewRunId] = useState7(null);
3797
- const [reviewSubmitting, setReviewSubmitting] = useState7(false);
3798
- const [reviewStatusMessage, setReviewStatusMessage] = useState7(null);
3799
- const [pendingTour, setPendingTour] = useState7(null);
3800
- const [serverState, setServerState] = useState7(null);
3418
+ const [isActive, setIsActive] = useState6(false);
3419
+ const [currentStepIndex, setCurrentStepIndex] = useState6(0);
3420
+ const [totalSteps, setTotalSteps] = useState6(0);
3421
+ const [activeTour, setActiveTour] = useState6(null);
3422
+ const [playbackState, setPlaybackState] = useState6("idle");
3423
+ const [isReviewMode, setIsReviewMode] = useState6(false);
3424
+ const [previewRunId, setPreviewRunId] = useState6(null);
3425
+ const [reviewSubmitting, setReviewSubmitting] = useState6(false);
3426
+ const [reviewStatusMessage, setReviewStatusMessage] = useState6(null);
3427
+ const [pendingTour, setPendingTour] = useState6(null);
3428
+ const [serverState, setServerState] = useState6(null);
3801
3429
  const ctx = useContext4(ModelNexContext);
3802
3430
  const devMode = ctx?.devMode;
3803
- const devModeRef = useRef8(devMode);
3431
+ const devModeRef = useRef7(devMode);
3804
3432
  devModeRef.current = devMode;
3805
- const userProfileRef = useRef8(userProfile);
3433
+ const userProfileRef = useRef7(userProfile);
3806
3434
  userProfileRef.current = userProfile;
3807
- const experienceTypeRef = useRef8(experienceType);
3435
+ const experienceTypeRef = useRef7(experienceType);
3808
3436
  experienceTypeRef.current = experienceType;
3809
- const tourRef = useRef8(null);
3810
- const stepIndexRef = useRef8(0);
3811
- const skipRequestedRef = useRef8(false);
3812
- const advanceRequestedRef = useRef8(false);
3813
- const textInputResolveRef = useRef8(null);
3814
- const voiceInputResolveRef = useRef8(null);
3815
- const askOrFillRef = useRef8(null);
3816
- const pendingManualWaitCleanupRef = useRef8(null);
3817
- const pendingManualInputSyncRef = useRef8(null);
3818
- const llmRespondingRef = useRef8(false);
3819
- const interruptedForQuestionRef = useRef8(false);
3820
- const pendingInputBufRef = useRef8(null);
3821
- const activeExecutionTokenRef = useRef8(0);
3822
- const commandInFlightRef = useRef8(false);
3823
- const reviewModeRef = useRef8(false);
3824
- const previewRunIdRef = useRef8(null);
3825
- const toursApiBaseRef = useRef8(toursApiBase);
3826
- const pendingTourRef = useRef8(null);
3827
- const pendingTourOptionsRef = useRef8(null);
3828
- const showCaptionsRef = useRef8(showCaptions);
3829
- const initialPersistedTourSessionRef = useRef8(readPersistedActiveTourSession());
3830
- const runIdRef = useRef8(initialPersistedTourSessionRef.current?.runId ?? null);
3831
- const turnIdRef = useRef8(null);
3832
- const startRequestedRef = useRef8(false);
3833
- const playbackOwnerIdRef = useRef8(`playback-owner-${Math.random().toString(36).slice(2, 10)}`);
3834
- const claimedPlaybackOwnerKeyRef = useRef8(null);
3835
- const socketRef = useRef8(null);
3836
- const socketIdRef = useRef8(socketId);
3837
- const commandUrlRef = useRef8(commandUrl);
3838
- const websiteIdRef = useRef8(websiteId);
3839
- const onStepChangeRef = useRef8(onStepChange);
3840
- const isActiveRef = useRef8(false);
3841
- const activeCommandBatchIdRef = useRef8(null);
3437
+ const tourRef = useRef7(null);
3438
+ const stepIndexRef = useRef7(0);
3439
+ const skipRequestedRef = useRef7(false);
3440
+ const advanceRequestedRef = useRef7(false);
3441
+ const textInputResolveRef = useRef7(null);
3442
+ const voiceInputResolveRef = useRef7(null);
3443
+ const askOrFillRef = useRef7(null);
3444
+ const pendingManualWaitCleanupRef = useRef7(null);
3445
+ const pendingManualInputSyncRef = useRef7(null);
3446
+ const llmRespondingRef = useRef7(false);
3447
+ const interruptedForQuestionRef = useRef7(false);
3448
+ const pendingInputBufRef = useRef7(null);
3449
+ const activeExecutionTokenRef = useRef7(0);
3450
+ const commandInFlightRef = useRef7(false);
3451
+ const reviewModeRef = useRef7(false);
3452
+ const previewRunIdRef = useRef7(null);
3453
+ const toursApiBaseRef = useRef7(toursApiBase);
3454
+ const pendingTourRef = useRef7(null);
3455
+ const pendingTourOptionsRef = useRef7(null);
3456
+ const showCaptionsRef = useRef7(showCaptions);
3457
+ const initialPersistedTourSessionRef = useRef7(readPersistedActiveTourSession());
3458
+ const runIdRef = useRef7(initialPersistedTourSessionRef.current?.runId ?? null);
3459
+ const turnIdRef = useRef7(null);
3460
+ const startRequestedRef = useRef7(false);
3461
+ const playbackOwnerIdRef = useRef7(`playback-owner-${Math.random().toString(36).slice(2, 10)}`);
3462
+ const claimedPlaybackOwnerKeyRef = useRef7(null);
3463
+ const socketRef = useRef7(null);
3464
+ const socketIdRef = useRef7(socketId);
3465
+ const commandUrlRef = useRef7(commandUrl);
3466
+ const websiteIdRef = useRef7(websiteId);
3467
+ const onStepChangeRef = useRef7(onStepChange);
3468
+ const isActiveRef = useRef7(false);
3469
+ const activeCommandBatchIdRef = useRef7(null);
3842
3470
  socketIdRef.current = socketId;
3843
3471
  commandUrlRef.current = commandUrl;
3844
3472
  websiteIdRef.current = websiteId;
@@ -3849,13 +3477,13 @@ function useTourPlayback({
3849
3477
  toursApiBaseRef.current = toursApiBase;
3850
3478
  pendingTourRef.current = pendingTour;
3851
3479
  showCaptionsRef.current = showCaptions;
3852
- const releasePlaybackOwnership = useCallback7(() => {
3480
+ const releasePlaybackOwnership = useCallback6(() => {
3853
3481
  const claimedKey = claimedPlaybackOwnerKeyRef.current;
3854
3482
  if (!claimedKey) return;
3855
3483
  releaseTourPlaybackOwnership(claimedKey, playbackOwnerIdRef.current);
3856
3484
  claimedPlaybackOwnerKeyRef.current = null;
3857
3485
  }, []);
3858
- const emitTourInit = useCallback7((socket, currentWebsiteId, profile) => {
3486
+ const emitTourInit = useCallback6((socket, currentWebsiteId, profile) => {
3859
3487
  if (!currentWebsiteId || !profile?.type) return;
3860
3488
  const persistedRunId = runIdRef.current ?? readPersistedActiveTourSession()?.runId ?? null;
3861
3489
  const payload = {
@@ -3868,7 +3496,7 @@ function useTourPlayback({
3868
3496
  }
3869
3497
  emitSocketEvent(socket, "tour:init", payload);
3870
3498
  }, []);
3871
- useEffect11(() => {
3499
+ useEffect10(() => {
3872
3500
  if (disabled) return;
3873
3501
  if (typeof window === "undefined") return;
3874
3502
  const socket = tourSocketPool.acquire(serverUrl);
@@ -4017,7 +3645,7 @@ function useTourPlayback({
4017
3645
  resolve: async () => {
4018
3646
  let targetEl = null;
4019
3647
  if (params.uid) {
4020
- const { getElementByUid } = await import("./aom-LJNCLNXL.mjs");
3648
+ const { getElementByUid } = await import("./aom-SP2LMWQI.mjs");
4021
3649
  targetEl = getElementByUid(params.uid);
4022
3650
  }
4023
3651
  if (!targetEl) {
@@ -4495,7 +4123,7 @@ function useTourPlayback({
4495
4123
  void recordTourEvent(serverUrl, toursApiBaseRef.current, tour.id, userProfile.userId, "started", websiteId);
4496
4124
  }
4497
4125
  try {
4498
- const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
4126
+ const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-SP2LMWQI.mjs");
4499
4127
  const aom = generateMinifiedAOM2();
4500
4128
  if (socketRef.current === socket) {
4501
4129
  emitSocketEvent(socket, "tour:sync_dom", {
@@ -4579,7 +4207,7 @@ function useTourPlayback({
4579
4207
  tourSocketPool.release(serverUrl, toClose);
4580
4208
  };
4581
4209
  }, [serverUrl, disabled, emitTourInit, releasePlaybackOwnership]);
4582
- useEffect11(() => {
4210
+ useEffect10(() => {
4583
4211
  if (disabled) return;
4584
4212
  const s = socketRef.current;
4585
4213
  const profile = userProfile;
@@ -4589,12 +4217,12 @@ function useTourPlayback({
4589
4217
  }, 150);
4590
4218
  return () => clearTimeout(timer);
4591
4219
  }, [disabled, emitTourInit, websiteId, userProfile?.userId, userProfile?.type]);
4592
- useEffect11(() => {
4220
+ useEffect10(() => {
4593
4221
  if (!showCaptions || !isReviewMode) {
4594
4222
  removeCaption();
4595
4223
  }
4596
4224
  }, [showCaptions, isReviewMode]);
4597
- useEffect11(() => {
4225
+ useEffect10(() => {
4598
4226
  if (!isActiveRef.current) return;
4599
4227
  emitSocketEvent(socketRef.current, "tour:client_state", {
4600
4228
  runId: runIdRef.current,
@@ -4608,9 +4236,9 @@ function useTourPlayback({
4608
4236
  awaitingVoiceResolve: Boolean(voiceInputResolveRef.current)
4609
4237
  });
4610
4238
  }, [isActive, playbackState, voice.isListening, voice.isSpeaking]);
4611
- const syncAOM = useCallback7(async () => {
4239
+ const syncAOM = useCallback6(async () => {
4612
4240
  if (!isActiveRef.current) return;
4613
- const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
4241
+ const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-SP2LMWQI.mjs");
4614
4242
  const aom = generateMinifiedAOM2();
4615
4243
  emitSocketEvent(socketRef.current, "tour:sync_dom", {
4616
4244
  url: window.location.pathname + window.location.search + window.location.hash,
@@ -4618,7 +4246,7 @@ function useTourPlayback({
4618
4246
  domSummary: captureDomSummary()
4619
4247
  });
4620
4248
  }, []);
4621
- const scheduleManualInputSync = useCallback7(() => {
4249
+ const scheduleManualInputSync = useCallback6(() => {
4622
4250
  if (pendingManualInputSyncRef.current) {
4623
4251
  clearTimeout(pendingManualInputSyncRef.current);
4624
4252
  }
@@ -4630,13 +4258,13 @@ function useTourPlayback({
4630
4258
  await syncAOM();
4631
4259
  }, 150);
4632
4260
  }, [syncAOM]);
4633
- const clearPendingManualInputSync = useCallback7(() => {
4261
+ const clearPendingManualInputSync = useCallback6(() => {
4634
4262
  if (pendingManualInputSyncRef.current) {
4635
4263
  clearTimeout(pendingManualInputSyncRef.current);
4636
4264
  pendingManualInputSyncRef.current = null;
4637
4265
  }
4638
4266
  }, []);
4639
- const interruptExecution = useCallback7((transcript) => {
4267
+ const interruptExecution = useCallback6((transcript) => {
4640
4268
  if (!isSocketWritable(socketRef.current) || !isActiveRef.current) return false;
4641
4269
  if (!commandInFlightRef.current && !voice.isSpeaking) return false;
4642
4270
  interruptedForQuestionRef.current = true;
@@ -4664,7 +4292,7 @@ function useTourPlayback({
4664
4292
  setPlaybackState("thinking");
4665
4293
  return true;
4666
4294
  }, [voice]);
4667
- const stopTour = useCallback7(() => {
4295
+ const stopTour = useCallback6(() => {
4668
4296
  skipRequestedRef.current = true;
4669
4297
  isActiveRef.current = false;
4670
4298
  startRequestedRef.current = false;
@@ -4715,7 +4343,7 @@ function useTourPlayback({
4715
4343
  pendingInputBufRef.current = null;
4716
4344
  onTourEnd?.();
4717
4345
  }, [voice, onTourEnd, serverUrl, websiteId, releasePlaybackOwnership]);
4718
- const handleTourEnd = useCallback7(() => {
4346
+ const handleTourEnd = useCallback6(() => {
4719
4347
  const endingTourId = tourRef.current?.id;
4720
4348
  const endingPreviewRunId = previewRunIdRef.current;
4721
4349
  const endingStepOrder = stepIndexRef.current;
@@ -4762,7 +4390,7 @@ function useTourPlayback({
4762
4390
  }
4763
4391
  onTourEnd?.();
4764
4392
  }, [experienceType, userProfile, serverUrl, voice, onTourEnd, websiteId, releasePlaybackOwnership]);
4765
- const runTour = useCallback7(async (tour, options) => {
4393
+ const runTour = useCallback6(async (tour, options) => {
4766
4394
  if (!shouldAcceptTourStart({
4767
4395
  isPlaybackActive: isActiveRef.current,
4768
4396
  startRequested: startRequestedRef.current
@@ -4827,7 +4455,7 @@ function useTourPlayback({
4827
4455
  tourContext: compactTourForTransport(tour)
4828
4456
  });
4829
4457
  }, [serverUrl, websiteId]);
4830
- useEffect11(() => {
4458
+ useEffect10(() => {
4831
4459
  if (!shouldRunTourAutoDiscovery({
4832
4460
  enableAutoDiscovery,
4833
4461
  disabled,
@@ -4891,7 +4519,7 @@ function useTourPlayback({
4891
4519
  cancelled = true;
4892
4520
  };
4893
4521
  }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery, locationSignature]);
4894
- useEffect11(() => {
4522
+ useEffect10(() => {
4895
4523
  if (!shouldRunTourAutoDiscovery({
4896
4524
  enableAutoDiscovery,
4897
4525
  disabled,
@@ -4938,22 +4566,22 @@ function useTourPlayback({
4938
4566
  clearTimeout(timer);
4939
4567
  };
4940
4568
  }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery, locationSignature]);
4941
- useEffect11(() => {
4569
+ useEffect10(() => {
4942
4570
  if (!disabled || !isActiveRef.current) return;
4943
4571
  stopTour();
4944
4572
  }, [disabled, stopTour]);
4945
- const startTour = useCallback7((tour, options) => {
4573
+ const startTour = useCallback6((tour, options) => {
4946
4574
  if (disabled) return;
4947
4575
  void runTour(tour, options);
4948
4576
  }, [disabled, runTour]);
4949
- const acceptPendingTour = useCallback7(() => {
4577
+ const acceptPendingTour = useCallback6(() => {
4950
4578
  const tour = pendingTourRef.current;
4951
4579
  if (!tour || disabled) return;
4952
4580
  const opts = pendingTourOptionsRef.current;
4953
4581
  pendingTourOptionsRef.current = null;
4954
4582
  void runTour(tour, opts ?? void 0);
4955
4583
  }, [disabled, runTour]);
4956
- const dismissPendingTour = useCallback7(() => {
4584
+ const dismissPendingTour = useCallback6(() => {
4957
4585
  const tour = pendingTourRef.current;
4958
4586
  setPendingTour(null);
4959
4587
  pendingTourRef.current = null;
@@ -4961,7 +4589,7 @@ function useTourPlayback({
4961
4589
  if (!tour || !userProfile?.userId) return;
4962
4590
  void markTourDismissed(serverUrl, toursApiBaseRef.current, tour.id, userProfile.userId, experienceType, websiteId);
4963
4591
  }, [experienceType, serverUrl, userProfile, websiteId]);
4964
- const submitReviewFeedbackAction = useCallback7(async (utterance, apply = false) => {
4592
+ const submitReviewFeedbackAction = useCallback6(async (utterance, apply = false) => {
4965
4593
  const trimmed = utterance.trim();
4966
4594
  const currentTour = tourRef.current;
4967
4595
  const currentPreviewRunId = previewRunIdRef.current;
@@ -5001,10 +4629,10 @@ function useTourPlayback({
5001
4629
  setReviewSubmitting(false);
5002
4630
  }
5003
4631
  }, [playbackState, serverUrl, websiteId]);
5004
- const advanceStep = useCallback7(() => {
4632
+ const advanceStep = useCallback6(() => {
5005
4633
  advanceRequestedRef.current = true;
5006
4634
  }, []);
5007
- const skipTour = useCallback7(() => {
4635
+ const skipTour = useCallback6(() => {
5008
4636
  skipRequestedRef.current = true;
5009
4637
  voiceInputResolveRef.current?.("");
5010
4638
  voiceInputResolveRef.current = null;
@@ -5014,19 +4642,19 @@ function useTourPlayback({
5014
4642
  askOrFillRef.current = null;
5015
4643
  stopTour();
5016
4644
  }, [stopTour]);
5017
- const pauseTour = useCallback7(() => {
4645
+ const pauseTour = useCallback6(() => {
5018
4646
  if (isSocketWritable(socketRef.current) && isActiveRef.current) {
5019
4647
  emitSocketEvent(socketRef.current, "tour:pause");
5020
4648
  setPlaybackState("paused");
5021
4649
  }
5022
4650
  }, []);
5023
- const resumeTour = useCallback7(() => {
4651
+ const resumeTour = useCallback6(() => {
5024
4652
  if (isSocketWritable(socketRef.current) && isActiveRef.current) {
5025
4653
  emitSocketEvent(socketRef.current, "tour:resume");
5026
4654
  setPlaybackState("executing");
5027
4655
  }
5028
4656
  }, []);
5029
- const repeatStep = useCallback7(() => {
4657
+ const repeatStep = useCallback6(() => {
5030
4658
  const tour = tourRef.current;
5031
4659
  const step = tour?.steps[stepIndexRef.current];
5032
4660
  if (step) {
@@ -5034,7 +4662,7 @@ function useTourPlayback({
5034
4662
  voice.speak(text, tour?.voice.ttsVoice);
5035
4663
  }
5036
4664
  }, [voice]);
5037
- const handleVoiceInput = useCallback7((transcript) => {
4665
+ const handleVoiceInput = useCallback6((transcript) => {
5038
4666
  const text = transcript.trim();
5039
4667
  emitSdkDebugLog("[TourAgent] Voice input received", {
5040
4668
  textLength: text.length
@@ -5062,7 +4690,7 @@ function useTourPlayback({
5062
4690
  pendingInputBufRef.current = text;
5063
4691
  }
5064
4692
  }, [interruptExecution]);
5065
- const handleTextInput = useCallback7((text) => {
4693
+ const handleTextInput = useCallback6((text) => {
5066
4694
  if (voiceInputResolveRef.current) {
5067
4695
  const resolve = voiceInputResolveRef.current;
5068
4696
  voiceInputResolveRef.current = null;
@@ -5075,7 +4703,7 @@ function useTourPlayback({
5075
4703
  handleVoiceInput(text.trim());
5076
4704
  }
5077
4705
  }, [handleVoiceInput]);
5078
- useEffect11(() => {
4706
+ useEffect10(() => {
5079
4707
  return () => {
5080
4708
  removeHighlight();
5081
4709
  removeCaption();
@@ -5156,14 +4784,14 @@ function useExperiencePlaybackController({
5156
4784
  initialExperienceType = "tour"
5157
4785
  }) {
5158
4786
  const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
5159
- const [activeExperienceType, setActiveExperienceType] = useState8(initialExperienceType);
5160
- const [startingExperienceType, setStartingExperienceType] = useState8(null);
5161
- const [pendingPrompt, setPendingPrompt] = useState8(null);
5162
- const pendingPromptRef = useRef9(null);
5163
- const queuedStartRef = useRef9(null);
5164
- const bufferedVoiceInputsRef = useRef9([]);
5165
- const previewDiscoveryInFlightRef = useRef9(false);
5166
- const previewSessionRef = useRef9(readPreviewSessionSuppression());
4787
+ const [activeExperienceType, setActiveExperienceType] = useState7(initialExperienceType);
4788
+ const [startingExperienceType, setStartingExperienceType] = useState7(null);
4789
+ const [pendingPrompt, setPendingPrompt] = useState7(null);
4790
+ const pendingPromptRef = useRef8(null);
4791
+ const queuedStartRef = useRef8(null);
4792
+ const bufferedVoiceInputsRef = useRef8([]);
4793
+ const previewDiscoveryInFlightRef = useRef8(false);
4794
+ const previewSessionRef = useRef8(readPreviewSessionSuppression());
5167
4795
  pendingPromptRef.current = pendingPrompt;
5168
4796
  const playback = useTourPlayback({
5169
4797
  serverUrl,
@@ -5182,7 +4810,7 @@ function useExperiencePlaybackController({
5182
4810
  showCaptions,
5183
4811
  enableAutoDiscovery: false
5184
4812
  });
5185
- const queueExperienceStart = useCallback8((tour, experienceType, options) => {
4813
+ const queueExperienceStart = useCallback7((tour, experienceType, options) => {
5186
4814
  setPendingPrompt(null);
5187
4815
  pendingPromptRef.current = null;
5188
4816
  setStartingExperienceType(experienceType);
@@ -5197,17 +4825,17 @@ function useExperiencePlaybackController({
5197
4825
  }
5198
4826
  playback.startTour(tour, options);
5199
4827
  }, [activeExperienceType, playback]);
5200
- const startExperience = useCallback8((tour, experienceType, options) => {
4828
+ const startExperience = useCallback7((tour, experienceType, options) => {
5201
4829
  const resolvedExperienceType = experienceType ?? tour.type ?? activeExperienceType;
5202
4830
  queueExperienceStart(tour, resolvedExperienceType, options);
5203
4831
  }, [activeExperienceType, queueExperienceStart]);
5204
- const acceptPendingPrompt = useCallback8((experienceType) => {
4832
+ const acceptPendingPrompt = useCallback7((experienceType) => {
5205
4833
  const prompt = pendingPromptRef.current;
5206
4834
  if (!prompt) return;
5207
4835
  if (experienceType && prompt.experienceType !== experienceType) return;
5208
4836
  queueExperienceStart(prompt.tour, prompt.experienceType, prompt.options);
5209
4837
  }, [queueExperienceStart]);
5210
- const dismissPendingPrompt = useCallback8((experienceType) => {
4838
+ const dismissPendingPrompt = useCallback7((experienceType) => {
5211
4839
  const prompt = pendingPromptRef.current;
5212
4840
  if (!prompt) return;
5213
4841
  if (experienceType && prompt.experienceType !== experienceType) return;
@@ -5230,7 +4858,7 @@ function useExperiencePlaybackController({
5230
4858
  websiteId
5231
4859
  );
5232
4860
  }, [serverUrl, toursApiBase, userProfile, websiteId]);
5233
- const handleVoiceInput = useCallback8((transcript, experienceType) => {
4861
+ const handleVoiceInput = useCallback7((transcript, experienceType) => {
5234
4862
  const trimmed = transcript.trim();
5235
4863
  if (!trimmed) return;
5236
4864
  const targetExperienceType = experienceType ?? activeExperienceType;
@@ -5250,12 +4878,12 @@ function useExperiencePlaybackController({
5250
4878
  }
5251
4879
  playback.handleVoiceInput(trimmed);
5252
4880
  }, [activeExperienceType, playback]);
5253
- useEffect12(() => {
4881
+ useEffect11(() => {
5254
4882
  if (playback.isActive && startingExperienceType !== null) {
5255
4883
  setStartingExperienceType(null);
5256
4884
  }
5257
4885
  }, [playback.isActive, startingExperienceType]);
5258
- useEffect12(() => {
4886
+ useEffect11(() => {
5259
4887
  const queuedStart = queuedStartRef.current;
5260
4888
  if (!queuedStart) return;
5261
4889
  if (playback.isActive) return;
@@ -5263,14 +4891,14 @@ function useExperiencePlaybackController({
5263
4891
  queuedStartRef.current = null;
5264
4892
  playback.startTour(queuedStart.tour, queuedStart.options);
5265
4893
  }, [activeExperienceType, playback]);
5266
- useEffect12(() => {
4894
+ useEffect11(() => {
5267
4895
  if (!playback.isActive) return;
5268
4896
  const readyInputs = bufferedVoiceInputsRef.current.filter((item) => item.experienceType === activeExperienceType);
5269
4897
  if (readyInputs.length === 0) return;
5270
4898
  bufferedVoiceInputsRef.current = bufferedVoiceInputsRef.current.filter((item) => item.experienceType !== activeExperienceType);
5271
4899
  readyInputs.forEach((item) => playback.handleVoiceInput(item.transcript));
5272
4900
  }, [activeExperienceType, playback]);
5273
- useEffect12(() => {
4901
+ useEffect11(() => {
5274
4902
  if (!shouldDiscoverDraftPreview({
5275
4903
  disabled,
5276
4904
  hasPendingPrompt: Boolean(pendingPromptRef.current),
@@ -5352,7 +4980,7 @@ function useExperiencePlaybackController({
5352
4980
  previewDiscoveryInFlightRef.current = false;
5353
4981
  };
5354
4982
  }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId, locationSignature]);
5355
- useEffect12(() => {
4983
+ useEffect11(() => {
5356
4984
  if (!shouldDiscoverEligibleTours({
5357
4985
  disabled,
5358
4986
  hasPendingPrompt: Boolean(pendingPromptRef.current),
@@ -5416,7 +5044,7 @@ function useExperiencePlaybackController({
5416
5044
  }
5417
5045
 
5418
5046
  // src/hooks/useVoice.ts
5419
- import { useState as useState9, useRef as useRef10, useCallback as useCallback9, useEffect as useEffect13 } from "react";
5047
+ import { useState as useState8, useRef as useRef9, useCallback as useCallback8, useEffect as useEffect12 } from "react";
5420
5048
 
5421
5049
  // src/utils/webrtc-aec.ts
5422
5050
  function isWebRtcAecSupported() {
@@ -5785,36 +5413,36 @@ function isFatalSpeechError(error) {
5785
5413
  return error === "not-allowed" || error === "service-not-allowed" || error === "audio-capture";
5786
5414
  }
5787
5415
  function useVoice(serverUrl) {
5788
- const [isSpeaking, setIsSpeaking] = useState9(false);
5789
- const [isListening, setIsListening] = useState9(false);
5790
- const [isMuted, setIsMuted] = useState9(false);
5791
- const audioRef = useRef10(null);
5792
- const audioBlobUrlRef = useRef10(null);
5793
- const speakResolveRef = useRef10(null);
5794
- const recognitionRef = useRef10(null);
5795
- const isMutedRef = useRef10(false);
5796
- const sttCallbacksRef = useRef10(null);
5797
- const stripIndicesRef = useRef10({});
5798
- const accumulatedRef = useRef10([]);
5799
- const interimDebounceRef = useRef10(null);
5800
- const lastInterimRef = useRef10("");
5801
- const lastDeliveredRef = useRef10("");
5802
- const isSpeakingRef = useRef10(false);
5803
- const speechEndTimeRef = useRef10(0);
5804
- const recentTtsRef = useRef10([]);
5805
- const prefetchedSpeechRef = useRef10(/* @__PURE__ */ new Map());
5806
- const nearEndTimeoutRef = useRef10(null);
5807
- const queuePromiseRef = useRef10(Promise.resolve());
5808
- const queueSeqRef = useRef10(0);
5809
- const lastStopSeqRef = useRef10(0);
5810
- const listeningSessionIdRef = useRef10(null);
5811
- const listeningStartedAtRef = useRef10(0);
5812
- const loopbackRef = useRef10(null);
5813
- const aecActiveRef = useRef10(false);
5814
- const mediaRecorderRef = useRef10(null);
5815
- const micStreamRef = useRef10(null);
5816
- const sttSocketRef = useRef10(null);
5817
- const stopLiveSttTransport = useCallback9(() => {
5416
+ const [isSpeaking, setIsSpeaking] = useState8(false);
5417
+ const [isListening, setIsListening] = useState8(false);
5418
+ const [isMuted, setIsMuted] = useState8(false);
5419
+ const audioRef = useRef9(null);
5420
+ const audioBlobUrlRef = useRef9(null);
5421
+ const speakResolveRef = useRef9(null);
5422
+ const recognitionRef = useRef9(null);
5423
+ const isMutedRef = useRef9(false);
5424
+ const sttCallbacksRef = useRef9(null);
5425
+ const stripIndicesRef = useRef9({});
5426
+ const accumulatedRef = useRef9([]);
5427
+ const interimDebounceRef = useRef9(null);
5428
+ const lastInterimRef = useRef9("");
5429
+ const lastDeliveredRef = useRef9("");
5430
+ const isSpeakingRef = useRef9(false);
5431
+ const speechEndTimeRef = useRef9(0);
5432
+ const recentTtsRef = useRef9([]);
5433
+ const prefetchedSpeechRef = useRef9(/* @__PURE__ */ new Map());
5434
+ const nearEndTimeoutRef = useRef9(null);
5435
+ const queuePromiseRef = useRef9(Promise.resolve());
5436
+ const queueSeqRef = useRef9(0);
5437
+ const lastStopSeqRef = useRef9(0);
5438
+ const listeningSessionIdRef = useRef9(null);
5439
+ const listeningStartedAtRef = useRef9(0);
5440
+ const loopbackRef = useRef9(null);
5441
+ const aecActiveRef = useRef9(false);
5442
+ const mediaRecorderRef = useRef9(null);
5443
+ const micStreamRef = useRef9(null);
5444
+ const sttSocketRef = useRef9(null);
5445
+ const stopLiveSttTransport = useCallback8(() => {
5818
5446
  const socket = sttSocketRef.current;
5819
5447
  sttSocketRef.current = null;
5820
5448
  if (socket) {
@@ -5843,16 +5471,16 @@ function useVoice(serverUrl) {
5843
5471
  }
5844
5472
  mediaRecorderRef.current = null;
5845
5473
  }, []);
5846
- useEffect13(() => {
5474
+ useEffect12(() => {
5847
5475
  isMutedRef.current = isMuted;
5848
5476
  }, [isMuted]);
5849
- useEffect13(() => {
5477
+ useEffect12(() => {
5850
5478
  isSpeakingRef.current = isSpeaking;
5851
5479
  }, [isSpeaking]);
5852
5480
  const webSpeechSupported = typeof window !== "undefined" && !!(window.SpeechRecognition || window.webkitSpeechRecognition);
5853
5481
  const mediaCaptureSupported = typeof window !== "undefined" && typeof navigator !== "undefined" && !!navigator.mediaDevices?.getUserMedia && typeof MediaRecorder !== "undefined";
5854
5482
  const sttSupported = typeof window !== "undefined" && (mediaCaptureSupported || webSpeechSupported);
5855
- const stopSpeaking = useCallback9(() => {
5483
+ const stopSpeaking = useCallback8(() => {
5856
5484
  emitVoiceDebug("tts_stop", {
5857
5485
  queueSeq: queueSeqRef.current,
5858
5486
  wasSpeaking: isSpeakingRef.current
@@ -5879,8 +5507,8 @@ function useVoice(serverUrl) {
5879
5507
  speakResolveRef.current?.();
5880
5508
  speakResolveRef.current = null;
5881
5509
  }, []);
5882
- const getSpeechCacheKey = useCallback9((text, voiceId) => `${voiceId}::${text}`, []);
5883
- const loadAudioDurationMs = useCallback9(async (url, fallbackText) => {
5510
+ const getSpeechCacheKey = useCallback8((text, voiceId) => `${voiceId}::${text}`, []);
5511
+ const loadAudioDurationMs = useCallback8(async (url, fallbackText) => {
5884
5512
  try {
5885
5513
  const probe = new Audio();
5886
5514
  probe.preload = "metadata";
@@ -5902,7 +5530,7 @@ function useVoice(serverUrl) {
5902
5530
  return estimateSpeechDurationMs(fallbackText);
5903
5531
  }
5904
5532
  }, []);
5905
- const fetchSpeechClip = useCallback9(async (text, voiceId) => {
5533
+ const fetchSpeechClip = useCallback8(async (text, voiceId) => {
5906
5534
  const baseUrl = serverUrl.replace(/\/$/, "");
5907
5535
  const debugEnabled = isVoiceDebugEnabled();
5908
5536
  const requestId = createVoiceDebugId("tts");
@@ -5964,7 +5592,7 @@ function useVoice(serverUrl) {
5964
5592
  });
5965
5593
  return { url, durationMs, requestId, buffered: true };
5966
5594
  }, [loadAudioDurationMs, serverUrl]);
5967
- const createStreamingSpeechClipForPlayback = useCallback9((text, voiceId) => {
5595
+ const createStreamingSpeechClipForPlayback = useCallback8((text, voiceId) => {
5968
5596
  const requestId = createVoiceDebugId("tts");
5969
5597
  const clip = createStreamingSpeechClip(serverUrl, text, voiceId, {
5970
5598
  requestId,
@@ -5979,7 +5607,7 @@ function useVoice(serverUrl) {
5979
5607
  });
5980
5608
  return clip;
5981
5609
  }, [serverUrl]);
5982
- const prefetchSpeech = useCallback9(async (text, voiceId = DEFAULT_VOICE_ID) => {
5610
+ const prefetchSpeech = useCallback8(async (text, voiceId = DEFAULT_VOICE_ID) => {
5983
5611
  if (isMutedRef.current || !text.trim()) return;
5984
5612
  const key = getSpeechCacheKey(text, voiceId);
5985
5613
  if (!prefetchedSpeechRef.current.has(key)) {
@@ -5993,7 +5621,7 @@ function useVoice(serverUrl) {
5993
5621
  }
5994
5622
  await prefetchedSpeechRef.current.get(key);
5995
5623
  }, [fetchSpeechClip, getSpeechCacheKey]);
5996
- const playClipDirect = useCallback9(async (clip, timeoutMs) => {
5624
+ const playClipDirect = useCallback8(async (clip, timeoutMs) => {
5997
5625
  const { url } = clip;
5998
5626
  const audio = new Audio();
5999
5627
  audio.crossOrigin = "anonymous";
@@ -6089,7 +5717,7 @@ function useVoice(serverUrl) {
6089
5717
  });
6090
5718
  });
6091
5719
  }, []);
6092
- const speak = useCallback9(async (text, voiceId = DEFAULT_VOICE_ID, options = {}) => {
5720
+ const speak = useCallback8(async (text, voiceId = DEFAULT_VOICE_ID, options = {}) => {
6093
5721
  if (isMutedRef.current) return;
6094
5722
  const mySeq = ++queueSeqRef.current;
6095
5723
  const interrupt = options.interrupt === true;
@@ -6181,7 +5809,7 @@ function useVoice(serverUrl) {
6181
5809
  }
6182
5810
  return taskPromise;
6183
5811
  }, [createStreamingSpeechClipForPlayback, fetchSpeechClip, getSpeechCacheKey, playClipDirect, stopSpeaking]);
6184
- const stopListening = useCallback9(() => {
5812
+ const stopListening = useCallback8(() => {
6185
5813
  emitVoiceDebug("stt_stop_listening", {
6186
5814
  listeningSessionId: listeningSessionIdRef.current,
6187
5815
  listeningMs: listeningStartedAtRef.current ? Math.round(performance.now() - listeningStartedAtRef.current) : null
@@ -6213,7 +5841,7 @@ function useVoice(serverUrl) {
6213
5841
  accumulatedRef.current = [];
6214
5842
  setIsListening(false);
6215
5843
  }, [stopLiveSttTransport]);
6216
- const startListening = useCallback9((onResult, onInterruption, onError, options = {}) => {
5844
+ const startListening = useCallback8((onResult, onInterruption, onError, options = {}) => {
6217
5845
  stopListening();
6218
5846
  listeningSessionIdRef.current = createVoiceDebugId("stt");
6219
5847
  listeningStartedAtRef.current = performance.now();
@@ -6497,7 +6125,7 @@ function useVoice(serverUrl) {
6497
6125
  }
6498
6126
  fallbackToWebSpeech();
6499
6127
  }, [serverUrl, stopListening, stopSpeaking, stopLiveSttTransport]);
6500
- const toggleMute = useCallback9(() => {
6128
+ const toggleMute = useCallback8(() => {
6501
6129
  setIsMuted((prev) => {
6502
6130
  const next = !prev;
6503
6131
  if (next) {
@@ -6509,7 +6137,7 @@ function useVoice(serverUrl) {
6509
6137
  return next;
6510
6138
  });
6511
6139
  }, []);
6512
- useEffect13(() => {
6140
+ useEffect12(() => {
6513
6141
  return () => {
6514
6142
  stopSpeaking();
6515
6143
  stopListening();
@@ -6538,18 +6166,18 @@ function useVoice(serverUrl) {
6538
6166
  }
6539
6167
 
6540
6168
  // src/hooks/useAudioLevel.ts
6541
- import { useState as useState10, useEffect as useEffect14, useRef as useRef11 } from "react";
6169
+ import { useState as useState9, useEffect as useEffect13, useRef as useRef10 } from "react";
6542
6170
  var BAR_COUNT = 9;
6543
6171
  var SENSITIVITY = 2.8;
6544
6172
  var FLOOR = 0.08;
6545
6173
  function useAudioLevel(active) {
6546
- const [levels, setLevels] = useState10(() => Array(BAR_COUNT).fill(FLOOR));
6547
- const streamRef = useRef11(null);
6548
- const ctxRef = useRef11(null);
6549
- const analyserRef = useRef11(null);
6550
- const rafRef = useRef11(0);
6551
- const timeDataRef = useRef11(null);
6552
- useEffect14(() => {
6174
+ const [levels, setLevels] = useState9(() => Array(BAR_COUNT).fill(FLOOR));
6175
+ const streamRef = useRef10(null);
6176
+ const ctxRef = useRef10(null);
6177
+ const analyserRef = useRef10(null);
6178
+ const rafRef = useRef10(0);
6179
+ const timeDataRef = useRef10(null);
6180
+ useEffect13(() => {
6553
6181
  if (!active || typeof window === "undefined") {
6554
6182
  setLevels(Array(BAR_COUNT).fill(FLOOR));
6555
6183
  return;
@@ -6621,7 +6249,7 @@ function useAudioLevel(active) {
6621
6249
  }
6622
6250
 
6623
6251
  // src/hooks/useRecordingMode.ts
6624
- import { useState as useState11, useRef as useRef12, useCallback as useCallback10, useEffect as useEffect15 } from "react";
6252
+ import { useState as useState10, useRef as useRef11, useCallback as useCallback9, useEffect as useEffect14 } from "react";
6625
6253
 
6626
6254
  // src/utils/tourStepTypes.ts
6627
6255
  function isAskDrivenInputStepType(stepType) {
@@ -6902,46 +6530,46 @@ function useRecordingMode({
6902
6530
  onPreview,
6903
6531
  experienceType = "tour"
6904
6532
  }) {
6905
- const restoredSessionRef = useRef12(void 0);
6533
+ const restoredSessionRef = useRef11(void 0);
6906
6534
  if (restoredSessionRef.current === void 0) {
6907
6535
  restoredSessionRef.current = readPersistedRecordingSession();
6908
6536
  }
6909
6537
  const restoredSession = restoredSessionRef.current;
6910
6538
  const restoredPhase = restoredSession ? "active" : "idle";
6911
- const [phase, setPhase] = useState11(restoredPhase);
6912
- const [steps, setSteps] = useState11(() => restoredSession?.steps ?? []);
6913
- const [selectedElement, setSelectedElement] = useState11(null);
6914
- const [selectedStepType, setSelectedStepType] = useState11(() => restoredSession?.selectedStepType ?? "ask_or_fill");
6915
- const [pendingNarration, setPendingNarration] = useState11("");
6916
- const [polishedNarration, setPolishedNarration] = useState11("");
6917
- const [captureEvents, setCaptureEvents] = useState11(() => restoredSession?.captureEvents ?? []);
6918
- const [capturedTranscript, setCapturedTranscript] = useState11(() => restoredSession?.capturedTranscript ?? "");
6919
- const [isVoiceCaptureActive, setIsVoiceCaptureActive] = useState11(false);
6920
- const stepsRef = useRef12([]);
6539
+ const [phase, setPhase] = useState10(restoredPhase);
6540
+ const [steps, setSteps] = useState10(() => restoredSession?.steps ?? []);
6541
+ const [selectedElement, setSelectedElement] = useState10(null);
6542
+ const [selectedStepType, setSelectedStepType] = useState10(() => restoredSession?.selectedStepType ?? "ask_or_fill");
6543
+ const [pendingNarration, setPendingNarration] = useState10("");
6544
+ const [polishedNarration, setPolishedNarration] = useState10("");
6545
+ const [captureEvents, setCaptureEvents] = useState10(() => restoredSession?.captureEvents ?? []);
6546
+ const [capturedTranscript, setCapturedTranscript] = useState10(() => restoredSession?.capturedTranscript ?? "");
6547
+ const [isVoiceCaptureActive, setIsVoiceCaptureActive] = useState10(false);
6548
+ const stepsRef = useRef11([]);
6921
6549
  stepsRef.current = steps;
6922
- const captureEventsRef = useRef12([]);
6923
- const capturedTranscriptRef = useRef12(capturedTranscript);
6550
+ const captureEventsRef = useRef11([]);
6551
+ const capturedTranscriptRef = useRef11(capturedTranscript);
6924
6552
  capturedTranscriptRef.current = capturedTranscript;
6925
- const phaseRef = useRef12(phase);
6553
+ const phaseRef = useRef11(phase);
6926
6554
  phaseRef.current = phase;
6927
- const safeSpeak = useCallback10((text) => {
6555
+ const safeSpeak = useCallback9((text) => {
6928
6556
  void voice.speak(text).catch((err) => {
6929
6557
  console.warn("[Recording] Voice playback unavailable:", err);
6930
6558
  });
6931
6559
  }, [voice]);
6932
6560
  captureEventsRef.current = captureEvents;
6933
- const pendingClicksRef = useRef12(restoredSession?.pendingClicks ?? []);
6934
- const shouldKeepVoiceCaptureRef = useRef12(restoredSession?.voiceCaptureEnabled === true);
6935
- const resumeVoiceAfterNarrationRef = useRef12(false);
6936
- const lastAutoNoteRef = useRef12("");
6937
- const lastHoverKeyRef = useRef12("");
6938
- const lastHoverAtRef = useRef12(0);
6939
- const selectedStepTypeRef = useRef12("ask_or_fill");
6561
+ const pendingClicksRef = useRef11(restoredSession?.pendingClicks ?? []);
6562
+ const shouldKeepVoiceCaptureRef = useRef11(restoredSession?.voiceCaptureEnabled === true);
6563
+ const resumeVoiceAfterNarrationRef = useRef11(false);
6564
+ const lastAutoNoteRef = useRef11("");
6565
+ const lastHoverKeyRef = useRef11("");
6566
+ const lastHoverAtRef = useRef11(0);
6567
+ const selectedStepTypeRef = useRef11("ask_or_fill");
6940
6568
  selectedStepTypeRef.current = selectedStepType;
6941
6569
  const isRecording = phase !== "idle";
6942
6570
  const stepCount = steps.length;
6943
6571
  const captureEventCount = captureEvents.length;
6944
- const persistSnapshot = useCallback10((overrides) => {
6572
+ const persistSnapshot = useCallback9((overrides) => {
6945
6573
  const nextPhase = overrides?.phase ?? phaseRef.current;
6946
6574
  const nextSteps = overrides?.steps ?? stepsRef.current;
6947
6575
  const nextCaptureEvents = overrides?.captureEvents ?? captureEventsRef.current;
@@ -6964,7 +6592,7 @@ function useRecordingMode({
6964
6592
  voiceCaptureEnabled: nextVoiceCaptureEnabled
6965
6593
  });
6966
6594
  }, [experienceType]);
6967
- const appendCaptureEvent = useCallback10((event) => {
6595
+ const appendCaptureEvent = useCallback9((event) => {
6968
6596
  const nextEvent = {
6969
6597
  id: event.id || newCaptureId(event.type),
6970
6598
  order: captureEventsRef.current.length,
@@ -6976,7 +6604,7 @@ function useRecordingMode({
6976
6604
  setCaptureEvents(nextCaptureEvents);
6977
6605
  persistSnapshot({ captureEvents: nextCaptureEvents });
6978
6606
  }, [persistSnapshot]);
6979
- const updateCaptureEvent = useCallback10((id, metadataPatch) => {
6607
+ const updateCaptureEvent = useCallback9((id, metadataPatch) => {
6980
6608
  const nextCaptureEvents = captureEventsRef.current.map((event) => {
6981
6609
  if (event.id === id) {
6982
6610
  return {
@@ -6993,7 +6621,7 @@ function useRecordingMode({
6993
6621
  setCaptureEvents(nextCaptureEvents);
6994
6622
  persistSnapshot({ captureEvents: nextCaptureEvents });
6995
6623
  }, [persistSnapshot]);
6996
- const appendVoiceNote = useCallback10((transcript) => {
6624
+ const appendVoiceNote = useCallback9((transcript) => {
6997
6625
  const text = transcript.trim();
6998
6626
  if (!text) return;
6999
6627
  if (lastAutoNoteRef.current === text) return;
@@ -7054,11 +6682,11 @@ function useRecordingMode({
7054
6682
  }
7055
6683
  });
7056
6684
  }, [appendCaptureEvent, persistSnapshot]);
7057
- const stopBackgroundVoiceCapture = useCallback10(() => {
6685
+ const stopBackgroundVoiceCapture = useCallback9(() => {
7058
6686
  voice.stopListening();
7059
6687
  setIsVoiceCaptureActive(false);
7060
6688
  }, [voice]);
7061
- const startBackgroundVoiceCapture = useCallback10(() => {
6689
+ const startBackgroundVoiceCapture = useCallback9(() => {
7062
6690
  if (!shouldKeepVoiceCaptureRef.current) return;
7063
6691
  if (!isRecording) return;
7064
6692
  if (phase === "narrating" || phase === "reviewing") return;
@@ -7075,7 +6703,7 @@ function useRecordingMode({
7075
6703
  );
7076
6704
  setIsVoiceCaptureActive(true);
7077
6705
  }, [appendVoiceNote, isRecording, phase, voice]);
7078
- const startRecording = useCallback10(() => {
6706
+ const startRecording = useCallback9(() => {
7079
6707
  const nextPhase = "active";
7080
6708
  const nextCaptureEvents = [{
7081
6709
  id: newCaptureId("session_start"),
@@ -7107,34 +6735,34 @@ function useRecordingMode({
7107
6735
  voiceCaptureEnabled: false
7108
6736
  });
7109
6737
  }, [persistSnapshot]);
7110
- const markStep = useCallback10(() => {
6738
+ const markStep = useCallback9(() => {
7111
6739
  if (phase !== "active") return;
7112
6740
  setPhase("selecting");
7113
6741
  }, [phase]);
7114
- const selectElement = useCallback10((recorded) => {
6742
+ const selectElement = useCallback9((recorded) => {
7115
6743
  setSelectedElement(recorded);
7116
6744
  setPhase("configuring");
7117
6745
  const isFormField = ["INPUT", "SELECT", "TEXTAREA"].includes(recorded.el.tagName);
7118
6746
  setSelectedStepType(isFormField ? "ask_or_fill" : "narrate");
7119
6747
  }, []);
7120
- const selectPageLevel = useCallback10(() => {
6748
+ const selectPageLevel = useCallback9(() => {
7121
6749
  setSelectedElement(null);
7122
6750
  setSelectedStepType("narrate");
7123
6751
  setPhase("configuring");
7124
6752
  }, []);
7125
- const cancelSelection = useCallback10(() => {
6753
+ const cancelSelection = useCallback9(() => {
7126
6754
  setSelectedElement(null);
7127
6755
  setPhase("active");
7128
6756
  }, []);
7129
- const setStepType = useCallback10((type) => {
6757
+ const setStepType = useCallback9((type) => {
7130
6758
  setSelectedStepType(type);
7131
6759
  }, []);
7132
- const runPolishAndReview = useCallback10(async (transcript) => {
6760
+ const runPolishAndReview = useCallback9(async (transcript) => {
7133
6761
  setPolishedNarration(transcript);
7134
6762
  setPhase("reviewing");
7135
6763
  }, []);
7136
- const pendingNarrationRef = useRef12("");
7137
- const startNarration = useCallback10(() => {
6764
+ const pendingNarrationRef = useRef11("");
6765
+ const startNarration = useCallback9(() => {
7138
6766
  resumeVoiceAfterNarrationRef.current = shouldKeepVoiceCaptureRef.current && isVoiceCaptureActive;
7139
6767
  if (isVoiceCaptureActive) {
7140
6768
  stopBackgroundVoiceCapture();
@@ -7156,7 +6784,7 @@ function useRecordingMode({
7156
6784
  { continuous: true }
7157
6785
  );
7158
6786
  }, [isVoiceCaptureActive, stopBackgroundVoiceCapture, voice]);
7159
- const finishNarration = useCallback10(async () => {
6787
+ const finishNarration = useCallback9(async () => {
7160
6788
  if (phase !== "narrating") return;
7161
6789
  voice.stopListening();
7162
6790
  const text = pendingNarrationRef.current;
@@ -7171,13 +6799,13 @@ function useRecordingMode({
7171
6799
  }
7172
6800
  }
7173
6801
  }, [phase, runPolishAndReview, startBackgroundVoiceCapture, voice]);
7174
- const submitTextNarration = useCallback10(async (text) => {
6802
+ const submitTextNarration = useCallback9(async (text) => {
7175
6803
  if (phase !== "narrating" || !text.trim()) return;
7176
6804
  voice.stopListening();
7177
6805
  setPendingNarration(text);
7178
6806
  await runPolishAndReview(text);
7179
6807
  }, [phase, voice, runPolishAndReview]);
7180
- const approveNarration = useCallback10(() => {
6808
+ const approveNarration = useCallback9(() => {
7181
6809
  if (phase !== "reviewing") return;
7182
6810
  const el = selectedElement;
7183
6811
  const narration = polishedNarration || pendingNarration;
@@ -7267,17 +6895,17 @@ function useRecordingMode({
7267
6895
  }, 0);
7268
6896
  }
7269
6897
  }, [appendCaptureEvent, phase, polishedNarration, pendingNarration, persistSnapshot, selectedElement, selectedStepType, startBackgroundVoiceCapture, voice]);
7270
- const redoNarration = useCallback10(() => {
6898
+ const redoNarration = useCallback9(() => {
7271
6899
  if (phase !== "reviewing") return;
7272
6900
  setPendingNarration("");
7273
6901
  setPolishedNarration("");
7274
6902
  startNarration();
7275
6903
  }, [phase, startNarration]);
7276
- const editNarration = useCallback10((text) => {
6904
+ const editNarration = useCallback9((text) => {
7277
6905
  setPendingNarration(text);
7278
6906
  setPolishedNarration(text);
7279
6907
  }, []);
7280
- const continueRecording = useCallback10(() => {
6908
+ const continueRecording = useCallback9(() => {
7281
6909
  phaseRef.current = "active";
7282
6910
  setPhase("active");
7283
6911
  persistSnapshot({ phase: "active" });
@@ -7287,7 +6915,7 @@ function useRecordingMode({
7287
6915
  }, 0);
7288
6916
  }
7289
6917
  }, [persistSnapshot, startBackgroundVoiceCapture]);
7290
- const undoLastStep = useCallback10(() => {
6918
+ const undoLastStep = useCallback9(() => {
7291
6919
  const previous = stepsRef.current;
7292
6920
  const nextSteps = previous.slice(0, -1);
7293
6921
  stepsRef.current = nextSteps;
@@ -7299,7 +6927,7 @@ function useRecordingMode({
7299
6927
  setPhase("active");
7300
6928
  persistSnapshot({ steps: nextSteps, phase: "active" });
7301
6929
  }, [persistSnapshot, voice]);
7302
- const previewSteps = useCallback10(() => {
6930
+ const previewSteps = useCallback9(() => {
7303
6931
  if (steps.length === 0) {
7304
6932
  safeSpeak("No steps recorded yet.");
7305
6933
  return;
@@ -7307,13 +6935,13 @@ function useRecordingMode({
7307
6935
  onPreview?.(steps);
7308
6936
  safeSpeak(`Previewing ${steps.length} step${steps.length !== 1 ? "s" : ""}.`);
7309
6937
  }, [onPreview, safeSpeak, steps]);
7310
- const prepareToStopRecording = useCallback10(() => {
6938
+ const prepareToStopRecording = useCallback9(() => {
7311
6939
  shouldKeepVoiceCaptureRef.current = false;
7312
6940
  resumeVoiceAfterNarrationRef.current = false;
7313
6941
  stopBackgroundVoiceCapture();
7314
6942
  persistSnapshot({ voiceCaptureEnabled: false });
7315
6943
  }, [persistSnapshot, stopBackgroundVoiceCapture]);
7316
- const cancelRecording = useCallback10(() => {
6944
+ const cancelRecording = useCallback9(() => {
7317
6945
  shouldKeepVoiceCaptureRef.current = false;
7318
6946
  stopBackgroundVoiceCapture();
7319
6947
  phaseRef.current = "idle";
@@ -7331,7 +6959,7 @@ function useRecordingMode({
7331
6959
  clearPersistedRecordingSession();
7332
6960
  safeSpeak("Recording cancelled.");
7333
6961
  }, [safeSpeak, stopBackgroundVoiceCapture]);
7334
- useEffect15(() => {
6962
+ useEffect14(() => {
7335
6963
  if (!isRecording || typeof document === "undefined") return;
7336
6964
  const handleMouseMove = (event) => {
7337
6965
  const target = event.target;
@@ -7441,7 +7069,7 @@ function useRecordingMode({
7441
7069
  window.clearInterval(routePoll);
7442
7070
  };
7443
7071
  }, [appendCaptureEvent, isRecording]);
7444
- useEffect15(() => {
7072
+ useEffect14(() => {
7445
7073
  if (!isRecording || typeof window === "undefined") return;
7446
7074
  const flushRecordingSession = () => {
7447
7075
  persistSnapshot();
@@ -7453,7 +7081,7 @@ function useRecordingMode({
7453
7081
  window.removeEventListener("beforeunload", flushRecordingSession);
7454
7082
  };
7455
7083
  }, [isRecording, persistSnapshot]);
7456
- const stopRecording = useCallback10(async (tourName, targetUserTypes) => {
7084
+ const stopRecording = useCallback9(async (tourName, targetUserTypes) => {
7457
7085
  phaseRef.current = "finishing";
7458
7086
  setPhase("finishing");
7459
7087
  shouldKeepVoiceCaptureRef.current = false;
@@ -7527,7 +7155,7 @@ function useRecordingMode({
7527
7155
  return null;
7528
7156
  }
7529
7157
  }, [capturedTranscript, experienceType, persistSnapshot, safeSpeak, serverUrl, stopBackgroundVoiceCapture, steps, toursApiBase, websiteId]);
7530
- const toggleVoiceCapture = useCallback10(() => {
7158
+ const toggleVoiceCapture = useCallback9(() => {
7531
7159
  if (isVoiceCaptureActive || shouldKeepVoiceCaptureRef.current) {
7532
7160
  shouldKeepVoiceCaptureRef.current = false;
7533
7161
  stopBackgroundVoiceCapture();
@@ -7538,7 +7166,7 @@ function useRecordingMode({
7538
7166
  persistSnapshot({ voiceCaptureEnabled: true });
7539
7167
  startBackgroundVoiceCapture();
7540
7168
  }, [isVoiceCaptureActive, persistSnapshot, startBackgroundVoiceCapture, stopBackgroundVoiceCapture]);
7541
- useEffect15(() => {
7169
+ useEffect14(() => {
7542
7170
  if (!isRecording) return;
7543
7171
  if (phase === "active" && shouldKeepVoiceCaptureRef.current && !isVoiceCaptureActive) {
7544
7172
  startBackgroundVoiceCapture();
@@ -7547,7 +7175,7 @@ function useRecordingMode({
7547
7175
  stopBackgroundVoiceCapture();
7548
7176
  }
7549
7177
  }, [isRecording, isVoiceCaptureActive, phase, startBackgroundVoiceCapture, stopBackgroundVoiceCapture]);
7550
- const handleVoiceCommand = useCallback10((transcript) => {
7178
+ const handleVoiceCommand = useCallback9((transcript) => {
7551
7179
  const lower = transcript.toLowerCase().trim();
7552
7180
  if (!isRecording) return;
7553
7181
  if (lower.includes("mark step") && phase === "active") {
@@ -7609,7 +7237,7 @@ function useRecordingMode({
7609
7237
  }
7610
7238
 
7611
7239
  // src/components/RecordingOverlay.tsx
7612
- import { useEffect as useEffect16, useState as useState12, useCallback as useCallback11 } from "react";
7240
+ import { useEffect as useEffect15, useState as useState11, useCallback as useCallback10 } from "react";
7613
7241
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
7614
7242
  function buildFingerprint(el) {
7615
7243
  const tag = el.tagName.toLowerCase();
@@ -7637,8 +7265,8 @@ var panelBase = {
7637
7265
  color: "#18181b"
7638
7266
  };
7639
7267
  function ActiveHUD({ stepCount, captureEventCount, isVoiceCaptureActive, minimized, onToggleVoiceCapture, onToggleMinimized, onStop, onCancel }) {
7640
- const [hasActivatedVoiceCapture, setHasActivatedVoiceCapture] = useState12(isVoiceCaptureActive);
7641
- useEffect16(() => {
7268
+ const [hasActivatedVoiceCapture, setHasActivatedVoiceCapture] = useState11(isVoiceCaptureActive);
7269
+ useEffect15(() => {
7642
7270
  if (isVoiceCaptureActive) {
7643
7271
  setHasActivatedVoiceCapture(true);
7644
7272
  }
@@ -7883,8 +7511,8 @@ var STEP_TYPES_ADVANCED = [
7883
7511
  ];
7884
7512
  function StepPopover({ element, stepIndex, onConfirm, onCancel }) {
7885
7513
  const defaultType = element && ["INPUT", "SELECT", "TEXTAREA"].includes(element.el.tagName) ? "ask_or_fill" : "narrate";
7886
- const [selected, setSelected] = useState12(defaultType);
7887
- const [showAdvanced, setShowAdvanced] = useState12(false);
7514
+ const [selected, setSelected] = useState11(defaultType);
7515
+ const [showAdvanced, setShowAdvanced] = useState11(false);
7888
7516
  const hasTestId = !!element?.testId;
7889
7517
  const allTypes = showAdvanced ? [...STEP_TYPES_PRIMARY, ...STEP_TYPES_ADVANCED] : STEP_TYPES_PRIMARY;
7890
7518
  const popoverStyle = {
@@ -8028,8 +7656,8 @@ function StepPopover({ element, stepIndex, onConfirm, onCancel }) {
8028
7656
  ] });
8029
7657
  }
8030
7658
  function NarrationPanel({ stepIndex, stepCount, pendingNarration, isListening, onSubmitText, onCancel, onStopRecording }) {
8031
- const [textInput, setTextInput] = useState12("");
8032
- const [showTextInput, setShowTextInput] = useState12(false);
7659
+ const [textInput, setTextInput] = useState11("");
7660
+ const [showTextInput, setShowTextInput] = useState11(false);
8033
7661
  const audioLevels = useAudioLevel(isListening);
8034
7662
  return /* @__PURE__ */ jsxs2(
8035
7663
  "div",
@@ -8196,8 +7824,8 @@ function NarrationPanel({ stepIndex, stepCount, pendingNarration, isListening, o
8196
7824
  );
8197
7825
  }
8198
7826
  function ReviewPanel({ stepIndex, stepCount, polishedNarration, rawNarration, onApprove, onRedo, onEdit }) {
8199
- const [editMode, setEditMode] = useState12(false);
8200
- const [editText, setEditText] = useState12(polishedNarration || rawNarration);
7827
+ const [editMode, setEditMode] = useState11(false);
7828
+ const [editText, setEditText] = useState11(polishedNarration || rawNarration);
8201
7829
  const displayText = polishedNarration || rawNarration;
8202
7830
  return /* @__PURE__ */ jsxs2(
8203
7831
  "div",
@@ -8453,7 +8081,7 @@ function FinishingPanel() {
8453
8081
  }
8454
8082
  );
8455
8083
  }
8456
- var INTERACTIVE_SELECTOR2 = [
8084
+ var INTERACTIVE_SELECTOR = [
8457
8085
  "button",
8458
8086
  "a[href]",
8459
8087
  'input:not([type="hidden"])',
@@ -8491,19 +8119,19 @@ function RecordingOverlay({
8491
8119
  onCancelRecording,
8492
8120
  onStopRecording
8493
8121
  }) {
8494
- const [hoveredEl, setHoveredEl] = useState12(null);
8495
- const [pendingElement, setPendingElement] = useState12(null);
8496
- const [showPopover, setShowPopover] = useState12(false);
8497
- const [hudMinimized, setHudMinimized] = useState12(false);
8498
- const [voicePanelMinimized, setVoicePanelMinimized] = useState12(false);
8122
+ const [hoveredEl, setHoveredEl] = useState11(null);
8123
+ const [pendingElement, setPendingElement] = useState11(null);
8124
+ const [showPopover, setShowPopover] = useState11(false);
8125
+ const [hudMinimized, setHudMinimized] = useState11(false);
8126
+ const [voicePanelMinimized, setVoicePanelMinimized] = useState11(false);
8499
8127
  const isSelecting = phase === "selecting";
8500
- const handleMouseMove = useCallback11((e) => {
8501
- const target = e.target.closest(INTERACTIVE_SELECTOR2);
8128
+ const handleMouseMove = useCallback10((e) => {
8129
+ const target = e.target.closest(INTERACTIVE_SELECTOR);
8502
8130
  setHoveredEl(target);
8503
8131
  }, []);
8504
- const handleClick = useCallback11((e) => {
8132
+ const handleClick = useCallback10((e) => {
8505
8133
  if (e.target.closest("[data-modelnex-internal]")) return;
8506
- const target = e.target.closest(INTERACTIVE_SELECTOR2);
8134
+ const target = e.target.closest(INTERACTIVE_SELECTOR);
8507
8135
  if (target) {
8508
8136
  e.preventDefault();
8509
8137
  e.stopPropagation();
@@ -8526,7 +8154,7 @@ function RecordingOverlay({
8526
8154
  setShowPopover(true);
8527
8155
  }
8528
8156
  }, []);
8529
- useEffect16(() => {
8157
+ useEffect15(() => {
8530
8158
  if (!isSelecting) return;
8531
8159
  document.addEventListener("mousemove", handleMouseMove, true);
8532
8160
  document.addEventListener("click", handleClick, true);
@@ -8538,14 +8166,14 @@ function RecordingOverlay({
8538
8166
  document.body.style.cursor = prev;
8539
8167
  };
8540
8168
  }, [isSelecting, handleMouseMove, handleClick]);
8541
- useEffect16(() => {
8169
+ useEffect15(() => {
8542
8170
  if (isSelecting) {
8543
8171
  setShowPopover(false);
8544
8172
  setPendingElement(null);
8545
8173
  setHoveredEl(null);
8546
8174
  }
8547
8175
  }, [isSelecting]);
8548
- const handlePopoverConfirm = useCallback11((type) => {
8176
+ const handlePopoverConfirm = useCallback10((type) => {
8549
8177
  setShowPopover(false);
8550
8178
  if (pendingElement) {
8551
8179
  onElementSelected(pendingElement);
@@ -8555,7 +8183,7 @@ function RecordingOverlay({
8555
8183
  onStepTypeConfirmed(type);
8556
8184
  onStartNarration();
8557
8185
  }, [pendingElement, onElementSelected, onPageLevelStep, onStepTypeConfirmed, onStartNarration]);
8558
- const handlePopoverCancel = useCallback11(() => {
8186
+ const handlePopoverCancel = useCallback10(() => {
8559
8187
  setShowPopover(false);
8560
8188
  setPendingElement(null);
8561
8189
  }, []);
@@ -9102,8 +8730,8 @@ function getViewportHeight() {
9102
8730
  return layoutViewportHeight;
9103
8731
  }
9104
8732
  function useViewportHeight() {
9105
- const [viewportHeight, setViewportHeight] = useState13(() => getViewportHeight());
9106
- useEffect17(() => {
8733
+ const [viewportHeight, setViewportHeight] = useState12(() => getViewportHeight());
8734
+ useEffect16(() => {
9107
8735
  if (typeof window === "undefined") return;
9108
8736
  const updateViewportHeight = () => {
9109
8737
  setViewportHeight(getViewportHeight());
@@ -9122,8 +8750,8 @@ function useViewportHeight() {
9122
8750
  return viewportHeight;
9123
8751
  }
9124
8752
  function useMediaQuery(query) {
9125
- const [matches, setMatches] = useState13(false);
9126
- useEffect17(() => {
8753
+ const [matches, setMatches] = useState12(false);
8754
+ useEffect16(() => {
9127
8755
  const media = window.matchMedia(query);
9128
8756
  if (media.matches !== matches) setMatches(media.matches);
9129
8757
  const listener = () => setMatches(media.matches);
@@ -9195,8 +8823,8 @@ var GLOBAL_STYLES = `
9195
8823
  }
9196
8824
  `;
9197
8825
  function Tooltip({ children, title }) {
9198
- const [show, setShow] = useState13(false);
9199
- const ref = useRef13(null);
8826
+ const [show, setShow] = useState12(false);
8827
+ const ref = useRef12(null);
9200
8828
  const handleShow = () => setShow(true);
9201
8829
  const handleHide = () => setShow(false);
9202
8830
  return /* @__PURE__ */ jsxs3(
@@ -9290,11 +8918,11 @@ var TrashIcon = () => /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16",
9290
8918
  var StopIcon = () => /* @__PURE__ */ jsx4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) });
9291
8919
  var ChevronDown = ({ open }) => /* @__PURE__ */ jsx4("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { transform: open ? "rotate(180deg)" : "none", transition: "transform 0.2s" }, children: /* @__PURE__ */ jsx4("path", { d: "m6 9 6 6 6-6" }) });
9292
8920
  function AgentTraces({ debug, command, defaultExpanded = true }) {
9293
- const [expanded, setExpanded] = useState13(defaultExpanded);
9294
- const [expandedSteps, setExpandedSteps] = useState13(/* @__PURE__ */ new Set());
8921
+ const [expanded, setExpanded] = useState12(defaultExpanded);
8922
+ const [expandedSteps, setExpandedSteps] = useState12(/* @__PURE__ */ new Set());
9295
8923
  const traces = debug.traces ?? [];
9296
8924
  const hasTraceContent = traces.length > 0 || debug.llmInput || (debug.llmOutput?.length ?? 0) > 0 || (debug.actions?.length ?? 0) > 0;
9297
- useEffect17(() => {
8925
+ useEffect16(() => {
9298
8926
  setExpandedSteps(new Set(traces.map((t) => t.step)));
9299
8927
  }, [debug]);
9300
8928
  const toggleStep = (step) => {
@@ -9455,21 +9083,21 @@ function ModelNexChatBubble({
9455
9083
  }) {
9456
9084
  const onCommand = void 0;
9457
9085
  const recordingExperienceType = "tour";
9458
- const noop = useCallback12(() => void 0, []);
9459
- const noopAsync = useCallback12(async () => void 0, []);
9086
+ const noop = useCallback11(() => void 0, []);
9087
+ const noopAsync = useCallback11(async () => void 0, []);
9460
9088
  const runCommand = useRunCommand();
9461
9089
  const ctx = useContext5(ModelNexContext);
9462
- const [hydrated, setHydrated] = useState13(false);
9463
- const [expanded, setExpanded] = useState13(false);
9464
- const [docked, setDocked] = useState13(false);
9465
- const [input, setInput] = useState13("");
9090
+ const [hydrated, setHydrated] = useState12(false);
9091
+ const [expanded, setExpanded] = useState12(false);
9092
+ const [docked, setDocked] = useState12(false);
9093
+ const [input, setInput] = useState12("");
9466
9094
  const messages = ctx?.chatMessages ?? [];
9467
9095
  const setMessages = ctx?.setChatMessages ?? (() => {
9468
9096
  });
9469
- const [loading, setLoading] = useState13(false);
9470
- const messagesEndRef = useRef13(null);
9471
- const abortControllerRef = useRef13(null);
9472
- const panelRef = useRef13(null);
9097
+ const [loading, setLoading] = useState12(false);
9098
+ const messagesEndRef = useRef12(null);
9099
+ const abortControllerRef = useRef12(null);
9100
+ const panelRef = useRef12(null);
9473
9101
  const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
9474
9102
  const voice = useVoice(serverUrl);
9475
9103
  const audioLevels = useAudioLevel(voice.isListening);
@@ -9478,13 +9106,13 @@ function ModelNexChatBubble({
9478
9106
  });
9479
9107
  const devMode = ctx?.devMode ?? false;
9480
9108
  const authoringMode = ctx?.authoringMode ?? devMode;
9481
- const [recordingTourName, setRecordingTourName] = useState13("");
9482
- const [recordingTargetTypes, setRecordingTargetTypes] = useState13("admin");
9483
- const [showStopModal, setShowStopModal] = useState13(false);
9484
- const [savedDraft, setSavedDraft] = useState13(null);
9485
- const [reviewDraft, setReviewDraft] = useState13("");
9486
- const [tourLiveTranscript, setTourLiveTranscript] = useState13("");
9487
- const [activeRecordingExperienceType, setActiveRecordingExperienceType] = useState13(
9109
+ const [recordingTourName, setRecordingTourName] = useState12("");
9110
+ const [recordingTargetTypes, setRecordingTargetTypes] = useState12("admin");
9111
+ const [showStopModal, setShowStopModal] = useState12(false);
9112
+ const [savedDraft, setSavedDraft] = useState12(null);
9113
+ const [reviewDraft, setReviewDraft] = useState12("");
9114
+ const [tourLiveTranscript, setTourLiveTranscript] = useState12("");
9115
+ const [activeRecordingExperienceType, setActiveRecordingExperienceType] = useState12(
9488
9116
  () => readPersistedRecordingExperienceType() ?? recordingExperienceType
9489
9117
  );
9490
9118
  const recording = useRecordingMode({
@@ -9496,7 +9124,7 @@ function ModelNexChatBubble({
9496
9124
  });
9497
9125
  const isGeneratingDraft = isRecordingDraftGenerating(recording.phase);
9498
9126
  const showRecordingOverlay = recordingMode && shouldShowRecordingOverlay(recording.phase);
9499
- useEffect17(() => {
9127
+ useEffect16(() => {
9500
9128
  const shouldBeRecording = recording.phase !== "idle";
9501
9129
  if (shouldBeRecording && !recordingMode) {
9502
9130
  setRecordingMode(true);
@@ -9529,12 +9157,12 @@ function ModelNexChatBubble({
9529
9157
  const activePlayback = playbackController.playback;
9530
9158
  const activeExperienceType = playbackController.activeExperienceType;
9531
9159
  const startingExperienceType = playbackController.startingExperienceType;
9532
- useEffect17(() => {
9160
+ useEffect16(() => {
9533
9161
  return registerExperienceToolBridge({
9534
9162
  startExperience: playbackController.startExperience
9535
9163
  });
9536
9164
  }, [playbackController.startExperience]);
9537
- const createPlaybackView = useCallback12((experienceType) => {
9165
+ const createPlaybackView = useCallback11((experienceType) => {
9538
9166
  const isActiveExperience = activePlayback.isActive && activeExperienceType === experienceType;
9539
9167
  const pendingTour = playbackController.pendingPrompt?.experienceType === experienceType ? playbackController.pendingPrompt.tour : null;
9540
9168
  return {
@@ -9566,8 +9194,8 @@ function ModelNexChatBubble({
9566
9194
  const onboardingPlayback = useMemo3(() => createPlaybackView("onboarding"), [createPlaybackView]);
9567
9195
  const tourReviewToggle = getReviewModeToggleConfig(tourPlayback.playbackState);
9568
9196
  const tourReviewModeEnabled = isReviewModeEnabled(devMode, tourPlayback.isReviewMode);
9569
- const lastAutoTaggedUrlRef = useRef13(null);
9570
- const handleAutoTag = useCallback12(async () => {
9197
+ const lastAutoTaggedUrlRef = useRef12(null);
9198
+ const handleAutoTag = useCallback11(async () => {
9571
9199
  if (!ctx) return;
9572
9200
  const { extractedElements, tagStore, commandUrl, serverUrl: serverUrl2, websiteId } = ctx;
9573
9201
  if (extractedElements.length === 0) return;
@@ -9606,7 +9234,7 @@ function ModelNexChatBubble({
9606
9234
  console.warn("[ModelNex] Auto-tag error:", err);
9607
9235
  }
9608
9236
  }, [ctx]);
9609
- useEffect17(() => {
9237
+ useEffect16(() => {
9610
9238
  if (authoringMode && ctx?.extractedElements.length) {
9611
9239
  const timer = setTimeout(handleAutoTag, 1e3);
9612
9240
  return () => clearTimeout(timer);
@@ -9628,7 +9256,7 @@ function ModelNexChatBubble({
9628
9256
  recordingMode,
9629
9257
  pendingNotificationType
9630
9258
  });
9631
- useEffect17(() => {
9259
+ useEffect16(() => {
9632
9260
  setHydrated(true);
9633
9261
  try {
9634
9262
  setExpanded(sessionStorage.getItem(BUBBLE_EXPANDED_STORAGE_KEY) === "true");
@@ -9638,18 +9266,18 @@ function ModelNexChatBubble({
9638
9266
  setDocked(false);
9639
9267
  }
9640
9268
  }, []);
9641
- const sttActiveRef = useRef13(false);
9642
- const [tourListenReady, setTourListenReady] = useState13(false);
9643
- const [tourSttError, setTourSttError] = useState13(null);
9644
- const previousTourActiveRef = useRef13(false);
9645
- const tourListenReadyRef = useRef13(false);
9646
- const tourSttErrorRef = useRef13(null);
9647
- const updateTourListenReady = useCallback12((next) => {
9269
+ const sttActiveRef = useRef12(false);
9270
+ const [tourListenReady, setTourListenReady] = useState12(false);
9271
+ const [tourSttError, setTourSttError] = useState12(null);
9272
+ const previousTourActiveRef = useRef12(false);
9273
+ const tourListenReadyRef = useRef12(false);
9274
+ const tourSttErrorRef = useRef12(null);
9275
+ const updateTourListenReady = useCallback11((next) => {
9648
9276
  if (tourListenReadyRef.current === next) return;
9649
9277
  tourListenReadyRef.current = next;
9650
9278
  setTourListenReady(next);
9651
9279
  }, []);
9652
- const updateTourSttError = useCallback12((next) => {
9280
+ const updateTourSttError = useCallback11((next) => {
9653
9281
  if (tourSttErrorRef.current === next) return;
9654
9282
  tourSttErrorRef.current = next;
9655
9283
  setTourSttError(next);
@@ -9658,7 +9286,7 @@ function ModelNexChatBubble({
9658
9286
  () => buildTranscriptPreviewLines(tourLiveTranscript, { maxCharsPerLine: 36, maxLines: 2 }),
9659
9287
  [tourLiveTranscript]
9660
9288
  );
9661
- useEffect17(() => {
9289
+ useEffect16(() => {
9662
9290
  const shouldShowFloatingTranscript = (tourPlayback.isActive || onboardingPlayback.isActive) && tourListenReady && voice.isListening;
9663
9291
  if (shouldShowFloatingTranscript) {
9664
9292
  showFloatingLiveTranscript({
@@ -9680,10 +9308,10 @@ function ModelNexChatBubble({
9680
9308
  tourPlayback.isActive,
9681
9309
  voice.isListening
9682
9310
  ]);
9683
- useEffect17(() => () => {
9311
+ useEffect16(() => () => {
9684
9312
  hideFloatingLiveTranscript();
9685
9313
  }, []);
9686
- const setExpandedState = useCallback12((next, opts) => {
9314
+ const setExpandedState = useCallback11((next, opts) => {
9687
9315
  setExpanded(next);
9688
9316
  try {
9689
9317
  sessionStorage.setItem(BUBBLE_EXPANDED_STORAGE_KEY, String(next));
@@ -9695,14 +9323,14 @@ function ModelNexChatBubble({
9695
9323
  } catch {
9696
9324
  }
9697
9325
  }, [tourPlayback.isActive, onboardingPlayback.isActive]);
9698
- const setDockedState = useCallback12((next) => {
9326
+ const setDockedState = useCallback11((next) => {
9699
9327
  setDocked(next);
9700
9328
  try {
9701
9329
  sessionStorage.setItem(BUBBLE_DOCKED_STORAGE_KEY, String(next));
9702
9330
  } catch {
9703
9331
  }
9704
9332
  }, []);
9705
- useEffect17(() => {
9333
+ useEffect16(() => {
9706
9334
  if (shouldAutoExpandForPendingPrompt({
9707
9335
  pendingPrompt,
9708
9336
  isPlaybackActive,
@@ -9712,8 +9340,8 @@ function ModelNexChatBubble({
9712
9340
  setExpandedState(true);
9713
9341
  }
9714
9342
  }, [isPlaybackActive, pendingNotificationType, pendingPrompt, recordingMode, setExpandedState]);
9715
- const preferredListeningExperienceRef = useRef13(null);
9716
- const playbackVoiceRoutingRef = useRef13({
9343
+ const preferredListeningExperienceRef = useRef12(null);
9344
+ const playbackVoiceRoutingRef = useRef12({
9717
9345
  activeExperienceType,
9718
9346
  isActive: activePlayback.isActive,
9719
9347
  isReviewMode: activePlayback.isReviewMode,
@@ -9721,7 +9349,7 @@ function ModelNexChatBubble({
9721
9349
  playbackState: activePlayback.playbackState,
9722
9350
  handleVoiceInput: playbackController.handleVoiceInput
9723
9351
  });
9724
- useEffect17(() => {
9352
+ useEffect16(() => {
9725
9353
  playbackVoiceRoutingRef.current = {
9726
9354
  activeExperienceType,
9727
9355
  isActive: activePlayback.isActive,
@@ -9738,7 +9366,7 @@ function ModelNexChatBubble({
9738
9366
  playbackController.handleVoiceInput,
9739
9367
  playbackController.pendingPrompt?.experienceType
9740
9368
  ]);
9741
- const handleVoiceTourInput = useCallback12(createSinglePlaybackTranscriptRouter(
9369
+ const handleVoiceTourInput = useCallback11(createSinglePlaybackTranscriptRouter(
9742
9370
  () => ({
9743
9371
  isReviewMode: playbackVoiceRoutingRef.current.isReviewMode,
9744
9372
  playbackState: playbackVoiceRoutingRef.current.playbackState
@@ -9753,7 +9381,7 @@ function ModelNexChatBubble({
9753
9381
  }
9754
9382
  }
9755
9383
  ), []);
9756
- const startTourListening = useCallback12((preferredExperience) => {
9384
+ const startTourListening = useCallback11((preferredExperience) => {
9757
9385
  const listeningState = {
9758
9386
  isTourActive: tourPlayback.isActive,
9759
9387
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9808,7 +9436,7 @@ function ModelNexChatBubble({
9808
9436
  updateTourListenReady,
9809
9437
  updateTourSttError
9810
9438
  ]);
9811
- useEffect17(() => {
9439
+ useEffect16(() => {
9812
9440
  const isPlaybackActive2 = isTourListeningSessionActive({
9813
9441
  isTourActive: tourPlayback.isActive,
9814
9442
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9831,12 +9459,12 @@ function ModelNexChatBubble({
9831
9459
  }
9832
9460
  }
9833
9461
  }, [tourPlayback.isActive, onboardingPlayback.isActive, setExpandedState, startingExperienceType, updateTourSttError]);
9834
- useEffect17(() => {
9462
+ useEffect16(() => {
9835
9463
  if (!tourPlayback.isReviewMode && !onboardingPlayback.isReviewMode) {
9836
9464
  setReviewDraft("");
9837
9465
  }
9838
9466
  }, [tourPlayback.isReviewMode, onboardingPlayback.isReviewMode]);
9839
- useEffect17(() => {
9467
+ useEffect16(() => {
9840
9468
  if (!isTourListeningSessionActive({
9841
9469
  isTourActive: tourPlayback.isActive,
9842
9470
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9845,12 +9473,12 @@ function ModelNexChatBubble({
9845
9473
  preferredListeningExperienceRef.current = null;
9846
9474
  }
9847
9475
  }, [tourPlayback.isActive, onboardingPlayback.isActive, startingExperienceType]);
9848
- useEffect17(() => {
9476
+ useEffect16(() => {
9849
9477
  if (recordingMode) {
9850
9478
  setExpandedState(false);
9851
9479
  }
9852
9480
  }, [recordingMode, setExpandedState]);
9853
- useEffect17(() => {
9481
+ useEffect16(() => {
9854
9482
  const isPlaybackActive2 = isTourListeningSessionActive({
9855
9483
  isTourActive: tourPlayback.isActive,
9856
9484
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9864,7 +9492,7 @@ function ModelNexChatBubble({
9864
9492
  }
9865
9493
  updateTourListenReady(Boolean(voice.isListening && sttActiveRef.current));
9866
9494
  }, [tourPlayback.isActive, onboardingPlayback.isActive, voice.isListening, startingExperienceType, updateTourListenReady]);
9867
- useEffect17(() => {
9495
+ useEffect16(() => {
9868
9496
  const isPlaybackActive2 = isTourListeningSessionActive({
9869
9497
  isTourActive: tourPlayback.isActive,
9870
9498
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9879,7 +9507,7 @@ function ModelNexChatBubble({
9879
9507
  voice.stopListening();
9880
9508
  }
9881
9509
  }, [tourPlayback.isActive, onboardingPlayback.isActive, voice, startingExperienceType, updateTourListenReady, updateTourSttError]);
9882
- useEffect17(() => {
9510
+ useEffect16(() => {
9883
9511
  const isPlaybackActive2 = isTourListeningSessionActive({
9884
9512
  isTourActive: tourPlayback.isActive,
9885
9513
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9901,8 +9529,8 @@ function ModelNexChatBubble({
9901
9529
  window.removeEventListener("keydown", enableTourListeningFromGesture, true);
9902
9530
  };
9903
9531
  }, [tourPlayback.isActive, onboardingPlayback.isActive, tourListenReady, tourSttError, voice.sttSupported, startTourListening, startingExperienceType]);
9904
- const [voiceInputMode, setVoiceInputMode] = useState13(false);
9905
- const toggleVoiceInput = useCallback12(() => {
9532
+ const [voiceInputMode, setVoiceInputMode] = useState12(false);
9533
+ const toggleVoiceInput = useCallback11(() => {
9906
9534
  if (voiceInputMode) {
9907
9535
  voice.stopListening();
9908
9536
  setVoiceInputMode(false);
@@ -9925,7 +9553,7 @@ function ModelNexChatBubble({
9925
9553
  );
9926
9554
  }
9927
9555
  }, [voiceInputMode, voice, recordingMode, recording]);
9928
- useEffect17(() => {
9556
+ useEffect16(() => {
9929
9557
  const panel = panelRef.current;
9930
9558
  if (!panel) return;
9931
9559
  const stopKeyPropagation = (e) => {
@@ -9949,7 +9577,7 @@ function ModelNexChatBubble({
9949
9577
  const tourCompletionRatio = tourPlayback.totalSteps > 0 ? Math.min(tourPlayback.currentStepIndex / tourPlayback.totalSteps, 1) : 0;
9950
9578
  const tourCurrentStep = tourPlayback.activeTour?.steps?.[tourPlayback.currentStepIndex] || null;
9951
9579
  const scrollToBottom = () => messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
9952
- useEffect17(() => {
9580
+ useEffect16(() => {
9953
9581
  if (messages.length > 0) scrollToBottom();
9954
9582
  }, [messages, loading]);
9955
9583
  const runAgent = async () => {
@@ -10006,7 +9634,7 @@ function ModelNexChatBubble({
10006
9634
  const clearChat = () => {
10007
9635
  setMessages([]);
10008
9636
  };
10009
- const startRecordingSession = useCallback12((experienceType) => {
9637
+ const startRecordingSession = useCallback11((experienceType) => {
10010
9638
  abortControllerRef.current?.abort();
10011
9639
  abortControllerRef.current = null;
10012
9640
  setLoading(false);
@@ -11259,7 +10887,7 @@ function ModelNexChatBubble({
11259
10887
  }
11260
10888
 
11261
10889
  // src/onboarding-panel.tsx
11262
- import { useCallback as useCallback13, useContext as useContext6, useEffect as useEffect18, useMemo as useMemo4, useRef as useRef14, useState as useState14 } from "react";
10890
+ import { useCallback as useCallback12, useContext as useContext6, useEffect as useEffect17, useMemo as useMemo4, useRef as useRef13, useState as useState13 } from "react";
11263
10891
  import { createPortal as createPortal2 } from "react-dom";
11264
10892
 
11265
10893
  // src/hooks/useOnboardingPlayback.ts
@@ -11294,14 +10922,14 @@ function ModelNexOnboardingPanel({
11294
10922
  const devMode = ctx?.devMode ?? false;
11295
10923
  const voice = useVoice(serverUrl);
11296
10924
  const audioLevels = useAudioLevel(voice.isListening);
11297
- const [input, setInput] = useState14("");
11298
- const [reviewDraft, setReviewDraft] = useState14("");
11299
- const [open, setOpen] = useState14(true);
11300
- const [currentStepIndex, setCurrentStepIndex] = useState14(0);
11301
- const [liveTranscript, setLiveTranscript] = useState14("");
11302
- const [voiceEnabled, setVoiceEnabled] = useState14(false);
11303
- const [sttError, setSttError] = useState14(null);
11304
- const voiceEnabledRef = useRef14(false);
10925
+ const [input, setInput] = useState13("");
10926
+ const [reviewDraft, setReviewDraft] = useState13("");
10927
+ const [open, setOpen] = useState13(true);
10928
+ const [currentStepIndex, setCurrentStepIndex] = useState13(0);
10929
+ const [liveTranscript, setLiveTranscript] = useState13("");
10930
+ const [voiceEnabled, setVoiceEnabled] = useState13(false);
10931
+ const [sttError, setSttError] = useState13(null);
10932
+ const voiceEnabledRef = useRef13(false);
11305
10933
  const playback = useOnboardingPlayback({
11306
10934
  serverUrl,
11307
10935
  commandUrl: ctx?.commandUrl,
@@ -11321,26 +10949,26 @@ function ModelNexOnboardingPanel({
11321
10949
  voiceEnabledRef.current = false;
11322
10950
  }
11323
10951
  });
11324
- const playbackVoiceRoutingRef = useRef14({
10952
+ const playbackVoiceRoutingRef = useRef13({
11325
10953
  isReviewMode: false,
11326
10954
  playbackState: playback.playbackState,
11327
10955
  handleVoiceInput: playback.handleVoiceInput
11328
10956
  });
11329
10957
  const reviewToggle = getReviewModeToggleConfig(playback.playbackState);
11330
10958
  const reviewModeEnabled = isReviewModeEnabled(devMode, playback.isReviewMode);
11331
- useEffect18(() => {
10959
+ useEffect17(() => {
11332
10960
  playbackVoiceRoutingRef.current = {
11333
10961
  isReviewMode: playback.isReviewMode,
11334
10962
  playbackState: playback.playbackState,
11335
10963
  handleVoiceInput: playback.handleVoiceInput
11336
10964
  };
11337
10965
  }, [playback.isReviewMode, playback.playbackState, playback.handleVoiceInput]);
11338
- useEffect18(() => {
10966
+ useEffect17(() => {
11339
10967
  if (playback.isActive && !playback.isReviewMode) {
11340
10968
  setOpen(true);
11341
10969
  }
11342
10970
  }, [playback.activeTour?.id, playback.isActive, playback.isReviewMode]);
11343
- const startVoiceListening = useCallback13(() => {
10971
+ const startVoiceListening = useCallback12(() => {
11344
10972
  if (voiceEnabledRef.current || !voice.sttSupported) return;
11345
10973
  voiceEnabledRef.current = true;
11346
10974
  setVoiceEnabled(true);
@@ -11387,7 +11015,7 @@ function ModelNexOnboardingPanel({
11387
11015
  }
11388
11016
  );
11389
11017
  }, [playback.isActive, voice]);
11390
- useEffect18(() => {
11018
+ useEffect17(() => {
11391
11019
  if (!playback.isActive || voiceEnabledRef.current || !voice.sttSupported) return;
11392
11020
  const startOnGesture = (event) => {
11393
11021
  if (shouldIgnorePanelGestureStart(event.target)) {
@@ -11402,7 +11030,7 @@ function ModelNexOnboardingPanel({
11402
11030
  window.removeEventListener("keydown", startOnGesture, true);
11403
11031
  };
11404
11032
  }, [playback.isActive, voice.sttSupported, startVoiceListening]);
11405
- useEffect18(() => {
11033
+ useEffect17(() => {
11406
11034
  if (!playback.isActive && voiceEnabledRef.current) {
11407
11035
  voiceEnabledRef.current = false;
11408
11036
  setVoiceEnabled(false);
@@ -11422,7 +11050,7 @@ function ModelNexOnboardingPanel({
11422
11050
  () => buildTranscriptPreviewLines(liveTranscript, { maxCharsPerLine: 34, maxLines: 2 }),
11423
11051
  [liveTranscript]
11424
11052
  );
11425
- useEffect18(() => {
11053
+ useEffect17(() => {
11426
11054
  if (voiceEnabled && voice.isListening) {
11427
11055
  showFloatingLiveTranscript({
11428
11056
  levels: audioLevels,
@@ -11436,7 +11064,7 @@ function ModelNexOnboardingPanel({
11436
11064
  }
11437
11065
  hideFloatingLiveTranscript();
11438
11066
  }, [audioLevels, liveTranscriptLines, voiceEnabled, voice.isListening]);
11439
- useEffect18(() => () => {
11067
+ useEffect17(() => () => {
11440
11068
  hideFloatingLiveTranscript();
11441
11069
  }, []);
11442
11070
  const actionButtonStyle = {
@@ -12001,7 +11629,7 @@ var ModelNexProvider = ({
12001
11629
  const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
12002
11630
  const commandUrl = void 0;
12003
11631
  const disableSocket = false;
12004
- useEffect19(() => {
11632
+ useEffect18(() => {
12005
11633
  if (process.env.NODE_ENV !== "production" && !serverUrlProp) {
12006
11634
  console.warn(
12007
11635
  `[ModelNex SDK] ModelNexProvider is using the default server URL (${DEFAULT_MODELNEX_SERVER_URL}). Pass \`serverUrl\` explicitly in local development to avoid accidentally targeting the hosted backend.`
@@ -12009,21 +11637,21 @@ var ModelNexProvider = ({
12009
11637
  }
12010
11638
  }, [serverUrlProp]);
12011
11639
  const renderedChildren = children;
12012
- const [activeAgentActions, setActiveAgentActions] = useState15(/* @__PURE__ */ new Set());
12013
- const [stagingFields, setStagingFields] = useState15(/* @__PURE__ */ new Set());
12014
- const [executedFields, setExecutedFields] = useState15(/* @__PURE__ */ new Set());
12015
- const [highlightActions, setHighlightActions] = useState15(false);
12016
- const [studioMode, setStudioMode] = useState15(false);
12017
- const [recordingMode, setRecordingMode] = useState15(() => hasPersistedRecordingSession());
12018
- const [voiceMuted, setVoiceMuted] = useState15(false);
12019
- const [socketId, setSocketId] = useState15(null);
12020
- const [actions, setActions] = useState15(/* @__PURE__ */ new Map());
12021
- const [validatedBrowserDevMode, setValidatedBrowserDevMode] = useState15(false);
12022
- const [resolvedDevModeKey, setResolvedDevModeKey] = useState15(() => resolveInjectedDevModeKey());
12023
- const [previewRuntimeMode, setPreviewRuntimeMode] = useState15(() => hasDraftPreviewModeSignal());
12024
- useEffect19(() => observeInjectedDevModeKey(setResolvedDevModeKey), []);
12025
- useEffect19(() => observeDraftPreviewModeSignal(setPreviewRuntimeMode), []);
12026
- useEffect19(() => {
11640
+ const [activeAgentActions, setActiveAgentActions] = useState14(/* @__PURE__ */ new Set());
11641
+ const [stagingFields, setStagingFields] = useState14(/* @__PURE__ */ new Set());
11642
+ const [executedFields, setExecutedFields] = useState14(/* @__PURE__ */ new Set());
11643
+ const [highlightActions, setHighlightActions] = useState14(false);
11644
+ const [studioMode, setStudioMode] = useState14(false);
11645
+ const [recordingMode, setRecordingMode] = useState14(() => hasPersistedRecordingSession());
11646
+ const [voiceMuted, setVoiceMuted] = useState14(false);
11647
+ const [socketId, setSocketId] = useState14(null);
11648
+ const [actions, setActions] = useState14(/* @__PURE__ */ new Map());
11649
+ const [validatedBrowserDevMode, setValidatedBrowserDevMode] = useState14(false);
11650
+ const [resolvedDevModeKey, setResolvedDevModeKey] = useState14(() => resolveInjectedDevModeKey());
11651
+ const [previewRuntimeMode, setPreviewRuntimeMode] = useState14(() => hasDraftPreviewModeSignal());
11652
+ useEffect18(() => observeInjectedDevModeKey(setResolvedDevModeKey), []);
11653
+ useEffect18(() => observeDraftPreviewModeSignal(setPreviewRuntimeMode), []);
11654
+ useEffect18(() => {
12027
11655
  let cancelled = false;
12028
11656
  if (!websiteId || !resolvedDevModeKey) {
12029
11657
  setValidatedBrowserDevMode(false);
@@ -12040,14 +11668,14 @@ var ModelNexProvider = ({
12040
11668
  };
12041
11669
  }, [resolvedDevModeKey, serverUrl, websiteId]);
12042
11670
  const effectiveDevMode = validatedBrowserDevMode || previewRuntimeMode;
12043
- const registerAction = useCallback14((action) => {
11671
+ const registerAction = useCallback13((action) => {
12044
11672
  setActions((prev) => {
12045
11673
  const next = new Map(prev);
12046
11674
  next.set(action.id, action);
12047
11675
  return next;
12048
11676
  });
12049
11677
  }, []);
12050
- const unregisterAction = useCallback14((id) => {
11678
+ const unregisterAction = useCallback13((id) => {
12051
11679
  setActions((prev) => {
12052
11680
  const next = new Map(prev);
12053
11681
  next.delete(id);
@@ -12058,8 +11686,8 @@ var ModelNexProvider = ({
12058
11686
  const tagStore = useTagStore({ serverUrl, websiteId });
12059
11687
  useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl, websiteId, toursApiBase, userProfile);
12060
11688
  const CHAT_STORAGE_KEY = "modelnex-chat-messages";
12061
- const [chatMessages, setChatMessagesRaw] = useState15([]);
12062
- useEffect19(() => {
11689
+ const [chatMessages, setChatMessagesRaw] = useState14([]);
11690
+ useEffect18(() => {
12063
11691
  try {
12064
11692
  const stored = sessionStorage.getItem(CHAT_STORAGE_KEY);
12065
11693
  if (stored) {
@@ -12068,7 +11696,7 @@ var ModelNexProvider = ({
12068
11696
  } catch {
12069
11697
  }
12070
11698
  }, [effectiveDevMode]);
12071
- useEffect19(() => {
11699
+ useEffect18(() => {
12072
11700
  setChatMessagesRaw((prev) => {
12073
11701
  const next = sanitizeChatMessages(prev, effectiveDevMode);
12074
11702
  try {
@@ -12078,7 +11706,7 @@ var ModelNexProvider = ({
12078
11706
  return next;
12079
11707
  });
12080
11708
  }, [effectiveDevMode]);
12081
- const setChatMessages = useCallback14((action) => {
11709
+ const setChatMessages = useCallback13((action) => {
12082
11710
  setChatMessagesRaw((prev) => {
12083
11711
  const resolved = typeof action === "function" ? action(prev) : action;
12084
11712
  const next = sanitizeChatMessages(resolved, effectiveDevMode);
@@ -12104,14 +11732,14 @@ var ModelNexProvider = ({
12104
11732
  devMode: effectiveDevMode
12105
11733
  });
12106
11734
  useFieldHighlight(stagingFields, executedFields, setExecutedFields);
12107
- useEffect19(() => {
11735
+ useEffect18(() => {
12108
11736
  document.body.classList.toggle("modelnex-highlight-actions", highlightActions);
12109
11737
  return () => {
12110
11738
  document.body.classList.remove("modelnex-highlight-actions");
12111
11739
  };
12112
11740
  }, [highlightActions]);
12113
- const [mounted, setMounted] = useState15(false);
12114
- useEffect19(() => {
11741
+ const [mounted, setMounted] = useState14(false);
11742
+ useEffect18(() => {
12115
11743
  setMounted(true);
12116
11744
  }, []);
12117
11745
  const value = useMemo5(