@modelnex/sdk 0.5.44 → 0.5.46

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);
@@ -677,6 +305,157 @@ function serializeContexts(contexts) {
677
305
  return Array.from(contexts.values());
678
306
  }
679
307
 
308
+ // src/utils/debug-tools.ts
309
+ var lastActionEffect = null;
310
+ function normalizeText(value) {
311
+ return String(value || "").replace(/\s+/g, " ").trim();
312
+ }
313
+ function isElementVisible(el) {
314
+ if (!(el instanceof HTMLElement)) return false;
315
+ const style = window.getComputedStyle(el);
316
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
317
+ return false;
318
+ }
319
+ const rect = el.getBoundingClientRect();
320
+ return rect.width > 0 && rect.height > 0;
321
+ }
322
+ function safeQueryAll2(selector) {
323
+ try {
324
+ return Array.from(document.querySelectorAll(selector)).filter(
325
+ (el) => el instanceof HTMLElement
326
+ );
327
+ } catch {
328
+ return [];
329
+ }
330
+ }
331
+ function classifyLevel(el, text) {
332
+ const levelHint = `${el.getAttribute("data-variant") || ""} ${el.className || ""} ${text}`.toLowerCase();
333
+ if (/\berror|danger|invalid|failed|required\b/.test(levelHint)) return "error";
334
+ if (/\bwarn|warning|caution\b/.test(levelHint)) return "warning";
335
+ return "info";
336
+ }
337
+ function classifySource(el) {
338
+ const role = (el.getAttribute("role") || "").toLowerCase();
339
+ if (role === "alert") return "alert";
340
+ if (role === "status") return "status";
341
+ if (el.hasAttribute("aria-live")) return "aria-live";
342
+ const classHint = String(el.className || "").toLowerCase();
343
+ if (/\bbanner\b/.test(classHint)) return "banner";
344
+ return "inline";
345
+ }
346
+ function selectorHintFor(el) {
347
+ if (el.id) return `#${el.id}`;
348
+ if (el.getAttribute("data-testid")) return `[data-testid="${el.getAttribute("data-testid")}"]`;
349
+ const role = el.getAttribute("role");
350
+ return role ? `${el.tagName.toLowerCase()}[role="${role}"]` : el.tagName.toLowerCase();
351
+ }
352
+ function collectUiMessages(options) {
353
+ const includeHidden = Boolean(options?.includeHidden);
354
+ const maxItems = Math.max(1, Math.min(Number(options?.maxItems || 10), 20));
355
+ const selectors = [
356
+ '[role="alert"]',
357
+ '[role="status"]',
358
+ "[aria-live]",
359
+ '[aria-invalid="true"]',
360
+ "[data-error]",
361
+ "[data-warning]",
362
+ ".error",
363
+ ".warning",
364
+ ".alert",
365
+ ".toast",
366
+ ".banner"
367
+ ];
368
+ const seen = /* @__PURE__ */ new Set();
369
+ const results = [];
370
+ for (const selector of selectors) {
371
+ for (const el of safeQueryAll2(selector)) {
372
+ const visible = isElementVisible(el);
373
+ if (!includeHidden && !visible) continue;
374
+ const text = normalizeText(el.textContent);
375
+ if (!text || text.length < 2) continue;
376
+ const key = `${selector}:${text.toLowerCase()}`;
377
+ if (seen.has(key)) continue;
378
+ seen.add(key);
379
+ results.push({
380
+ id: `ui_${results.length + 1}`,
381
+ level: classifyLevel(el, text),
382
+ text,
383
+ source: classifySource(el),
384
+ visible,
385
+ selectorHint: selectorHintFor(el)
386
+ });
387
+ if (results.length >= maxItems) return results;
388
+ }
389
+ }
390
+ return results;
391
+ }
392
+ function captureDebugSnapshot() {
393
+ return {
394
+ route: `${window.location.pathname}${window.location.search}${window.location.hash}`,
395
+ title: document.title || "",
396
+ uiMessages: collectUiMessages({ maxItems: 6 }),
397
+ timestamp: Date.now()
398
+ };
399
+ }
400
+ function diffUiMessages(before, after) {
401
+ const beforeKeys = new Set(before.map((entry) => `${entry.level}:${entry.text}`));
402
+ return after.filter((entry) => !beforeKeys.has(`${entry.level}:${entry.text}`));
403
+ }
404
+ function summarizeEffect(record) {
405
+ const routeChanged = record.before.route !== record.after.route;
406
+ const titleChanged = record.before.title !== record.after.title;
407
+ const newMessages = diffUiMessages(record.before.uiMessages, record.after.uiMessages);
408
+ const changed = routeChanged || titleChanged || newMessages.length > 0 || !record.success || record.before.timestamp !== record.after.timestamp;
409
+ const parts = [];
410
+ if (routeChanged) parts.push(`route changed from ${record.before.route} to ${record.after.route}`);
411
+ if (titleChanged) parts.push("page title changed");
412
+ if (newMessages.length > 0) parts.push(`new UI messages: ${newMessages.map((entry) => entry.text).join(" | ")}`);
413
+ if (!record.success && record.error) parts.push(`action failed: ${record.error}`);
414
+ if (parts.length === 0) parts.push("no obvious route/title/message change detected");
415
+ return {
416
+ summary: parts.join("; "),
417
+ changed
418
+ };
419
+ }
420
+ function recordLastActionEffect(record) {
421
+ const summary = summarizeEffect(record);
422
+ lastActionEffect = {
423
+ ...record,
424
+ ...summary
425
+ };
426
+ return lastActionEffect;
427
+ }
428
+ function getLastActionEffectRecord() {
429
+ return lastActionEffect;
430
+ }
431
+ function inspectDomElementState(el) {
432
+ const rect = el.getBoundingClientRect();
433
+ const describedByIds = normalizeText(el.getAttribute("aria-describedby")).split(/\s+/).filter(Boolean);
434
+ const describedByText = describedByIds.map((id) => normalizeText(document.getElementById(id)?.textContent)).filter(Boolean).join(" | ");
435
+ const labelText = normalizeText(
436
+ el.labels?.[0]?.textContent || el.getAttribute("aria-label") || el.getAttribute("name") || el.getAttribute("id") || el.textContent
437
+ );
438
+ return {
439
+ tag: el.tagName.toLowerCase(),
440
+ label: labelText || null,
441
+ text: normalizeText(el.textContent).slice(0, 300) || null,
442
+ value: "value" in el ? normalizeText(String(el.value || "")) || null : null,
443
+ visible: isElementVisible(el),
444
+ enabled: !el.hasAttribute("disabled") && el.getAttribute("aria-disabled") !== "true",
445
+ focused: document.activeElement === el,
446
+ ariaInvalid: el.getAttribute("aria-invalid") === "true",
447
+ describedByText: describedByText || null,
448
+ role: el.getAttribute("role") || null,
449
+ selectorHint: selectorHintFor(el),
450
+ rect: {
451
+ x: Math.round(rect.x),
452
+ y: Math.round(rect.y),
453
+ width: Math.round(rect.width),
454
+ height: Math.round(rect.height)
455
+ }
456
+ };
457
+ }
458
+
680
459
  // src/hooks/useModelNexSocket.ts
681
460
  function useModelNexSocket({
682
461
  serverUrl,
@@ -692,16 +471,16 @@ function useModelNexSocket({
692
471
  websiteId,
693
472
  devMode
694
473
  }) {
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);
474
+ const socketRef = useRef2(null);
475
+ const actionsRef = useRef2(actions);
476
+ const contextsRef = useRef2(contexts);
477
+ const documentationRef = useRef2(documentation);
478
+ const tagsRef = useRef2(tags);
700
479
  actionsRef.current = actions;
701
480
  contextsRef.current = contexts;
702
481
  documentationRef.current = documentation;
703
482
  tagsRef.current = tags;
704
- useEffect3(() => {
483
+ useEffect2(() => {
705
484
  if (disabled) {
706
485
  socketRef.current = null;
707
486
  onSocketId?.(null);
@@ -775,11 +554,22 @@ function useModelNexSocket({
775
554
  const NAV_ACTION_IDS = ["navigate_to_documents", "navigate_to_templates", "navigate_to_inbox", "navigate_to_settings", "navigate_to_template", "navigate_to_document", "navigate_to_folder", "navigate_editor_step"];
776
555
  const action = currentActions.get(actionId);
777
556
  if (action) {
557
+ const beforeSnapshot = captureDebugSnapshot();
558
+ const startedAt = Date.now();
778
559
  try {
779
560
  const validatedParams = action.schema.parse(params);
780
561
  log("[SDK] Executing action", { actionId });
781
562
  const execResult = await action.execute(validatedParams);
782
563
  log("[SDK] Action completed", { actionId });
564
+ recordLastActionEffect({
565
+ actionId,
566
+ success: true,
567
+ error: null,
568
+ startedAt,
569
+ finishedAt: Date.now(),
570
+ before: beforeSnapshot,
571
+ after: captureDebugSnapshot()
572
+ });
783
573
  sendResult(true, execResult);
784
574
  if (NAV_ACTION_IDS.includes(actionId)) {
785
575
  requestAnimationFrame(() => {
@@ -804,6 +594,15 @@ function useModelNexSocket({
804
594
  } catch (err) {
805
595
  const errMsg = err instanceof Error ? err.message : String(err);
806
596
  console.error(`[ModelNex SDK] Execution failed for ${actionId}: ${errMsg}`);
597
+ recordLastActionEffect({
598
+ actionId,
599
+ success: false,
600
+ error: errMsg,
601
+ startedAt,
602
+ finishedAt: Date.now(),
603
+ before: beforeSnapshot,
604
+ after: captureDebugSnapshot()
605
+ });
807
606
  if (isSdkDebugEnabled(devMode)) {
808
607
  window.dispatchEvent(
809
608
  new CustomEvent("modelnex-debug", {
@@ -834,7 +633,7 @@ function useModelNexSocket({
834
633
  socket.disconnect();
835
634
  };
836
635
  }, [disabled, onSocketId, serverUrl]);
837
- useEffect3(() => {
636
+ useEffect2(() => {
838
637
  if (disabled) {
839
638
  return;
840
639
  }
@@ -852,10 +651,10 @@ function useModelNexSocket({
852
651
  }
853
652
 
854
653
  // src/hooks/useFieldHighlight.ts
855
- import { useEffect as useEffect4, useRef as useRef4 } from "react";
654
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
856
655
  function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
857
- const highlightedRef = useRef4(/* @__PURE__ */ new Map());
858
- useEffect4(() => {
656
+ const highlightedRef = useRef3(/* @__PURE__ */ new Map());
657
+ useEffect3(() => {
859
658
  const prev = highlightedRef.current;
860
659
  prev.forEach((_, fieldId) => {
861
660
  if (!stagingFields.has(fieldId)) {
@@ -874,7 +673,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
874
673
  prev.clear();
875
674
  };
876
675
  }, [stagingFields]);
877
- useEffect4(() => {
676
+ useEffect3(() => {
878
677
  const timeouts = [];
879
678
  executedFields.forEach((fieldId) => {
880
679
  const els = document.querySelectorAll(`[data-modelnex-field-id="${fieldId}"]`);
@@ -895,7 +694,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
895
694
  }
896
695
 
897
696
  // src/overlay.tsx
898
- import React2, { useState as useState2, useEffect as useEffect5 } from "react";
697
+ import React2, { useState, useEffect as useEffect4 } from "react";
899
698
  var AIActivityOverlay = ({ activeActions }) => {
900
699
  if (activeActions.size === 0) return null;
901
700
  return React2.createElement(
@@ -1092,7 +891,7 @@ body.modelnex-highlight-actions [data-modelnex-action-id]::before {
1092
891
  `;
1093
892
 
1094
893
  // src/tag-store.ts
1095
- import { useState as useState3, useCallback as useCallback3, useEffect as useEffect6 } from "react";
894
+ import { useState as useState2, useCallback as useCallback2, useEffect as useEffect5 } from "react";
1096
895
  var STORAGE_KEY = "modelnex-tags";
1097
896
  function loadTags() {
1098
897
  try {
@@ -1116,10 +915,10 @@ function saveTags(tags) {
1116
915
  }
1117
916
  }
1118
917
  function useTagStore(options) {
1119
- const [tags, setTags] = useState3(/* @__PURE__ */ new Map());
918
+ const [tags, setTags] = useState2(/* @__PURE__ */ new Map());
1120
919
  const apiUrl = options?.serverUrl ? `${options.serverUrl.replace(/\/$/, "")}/api/tags` : null;
1121
920
  const websiteId = options?.websiteId;
1122
- useEffect6(() => {
921
+ useEffect5(() => {
1123
922
  const local = loadTags();
1124
923
  setTags(local);
1125
924
  if (apiUrl) {
@@ -1139,14 +938,14 @@ function useTagStore(options) {
1139
938
  }).catch((err) => console.warn("[ModelNex] Failed to fetch remote tags:", err));
1140
939
  }
1141
940
  }, [apiUrl]);
1142
- useEffect6(() => {
941
+ useEffect5(() => {
1143
942
  if (typeof window === "undefined") return;
1144
943
  saveTags(tags);
1145
944
  }, [tags]);
1146
- const getTag = useCallback3((fingerprint) => {
945
+ const getTag = useCallback2((fingerprint) => {
1147
946
  return tags.get(fingerprint);
1148
947
  }, [tags]);
1149
- const setTag = useCallback3((fingerprint, description, category, metadata, selector, patternId, behavior, sourcePage, displayContext, skipRemoteSync) => {
948
+ const setTag = useCallback2((fingerprint, description, category, metadata, selector, patternId, behavior, sourcePage, displayContext, skipRemoteSync) => {
1150
949
  setTags((prev) => {
1151
950
  const next = new Map(prev);
1152
951
  const key = selector ? `selector:${selector}` : fingerprint;
@@ -1178,7 +977,7 @@ function useTagStore(options) {
1178
977
  return next;
1179
978
  });
1180
979
  }, [apiUrl, websiteId]);
1181
- const setTagsBatch = useCallback3((newTags, skipRemoteSync) => {
980
+ const setTagsBatch = useCallback2((newTags, skipRemoteSync) => {
1182
981
  setTags((prev) => {
1183
982
  const next = new Map(prev);
1184
983
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -1206,24 +1005,24 @@ function useTagStore(options) {
1206
1005
  return next;
1207
1006
  });
1208
1007
  }, [apiUrl, websiteId]);
1209
- const deleteTag = useCallback3((fingerprint) => {
1008
+ const deleteTag = useCallback2((fingerprint) => {
1210
1009
  setTags((prev) => {
1211
1010
  const next = new Map(prev);
1212
1011
  next.delete(fingerprint);
1213
1012
  return next;
1214
1013
  });
1215
1014
  }, []);
1216
- const getAllTags = useCallback3(() => {
1015
+ const getAllTags = useCallback2(() => {
1217
1016
  return Array.from(tags.values());
1218
1017
  }, [tags]);
1219
- const exportTags = useCallback3(() => {
1018
+ const exportTags = useCallback2(() => {
1220
1019
  const obj = {};
1221
1020
  tags.forEach((v, k) => {
1222
1021
  obj[k] = v;
1223
1022
  });
1224
1023
  return JSON.stringify(obj, null, 2);
1225
1024
  }, [tags]);
1226
- const importTags = useCallback3((json) => {
1025
+ const importTags = useCallback2((json) => {
1227
1026
  try {
1228
1027
  const parsed = JSON.parse(json);
1229
1028
  setTags((prev) => {
@@ -1239,7 +1038,7 @@ function useTagStore(options) {
1239
1038
  }
1240
1039
 
1241
1040
  // src/studio-mode.tsx
1242
- import { useState as useState4, useEffect as useEffect7, useRef as useRef5, useCallback as useCallback4 } from "react";
1041
+ import { useState as useState3, useEffect as useEffect6, useRef as useRef4, useCallback as useCallback3 } from "react";
1243
1042
  import { jsx, jsxs } from "react/jsx-runtime";
1244
1043
  var CATEGORIES = [
1245
1044
  { value: "button", label: "Button" },
@@ -1250,10 +1049,10 @@ var CATEGORIES = [
1250
1049
  { value: "other", label: "Other" }
1251
1050
  ];
1252
1051
  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(() => {
1052
+ const [description, setDescription] = useState3(existingTag?.description ?? "");
1053
+ const [category, setCategory] = useState3(existingTag?.category ?? "other");
1054
+ const inputRef = useRef4(null);
1055
+ useEffect6(() => {
1257
1056
  inputRef.current?.focus();
1258
1057
  }, []);
1259
1058
  const handleSave = () => {
@@ -1480,10 +1279,10 @@ function findTagForElement(el, tagStore) {
1480
1279
  return void 0;
1481
1280
  }
1482
1281
  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(() => {
1282
+ const [selectedFingerprint, setSelectedFingerprint] = useState3(null);
1283
+ const [positions, setPositions] = useState3(/* @__PURE__ */ new Map());
1284
+ const liveElementsRef = useRef4(/* @__PURE__ */ new Map());
1285
+ const updatePositions = useCallback3(() => {
1487
1286
  const newPositions = /* @__PURE__ */ new Map();
1488
1287
  const newLiveElements = /* @__PURE__ */ new Map();
1489
1288
  const knownFingerprints = new Set(elements.map((e) => e.fingerprint));
@@ -1518,7 +1317,7 @@ function StudioOverlay({ elements, tagStore }) {
1518
1317
  liveElementsRef.current = newLiveElements;
1519
1318
  setPositions(newPositions);
1520
1319
  }, [elements]);
1521
- useEffect7(() => {
1320
+ useEffect6(() => {
1522
1321
  updatePositions();
1523
1322
  const interval = setInterval(updatePositions, 1e3);
1524
1323
  window.addEventListener("scroll", updatePositions, { passive: true });
@@ -1662,7 +1461,7 @@ function StudioOverlay({ elements, tagStore }) {
1662
1461
  }
1663
1462
 
1664
1463
  // src/hooks/useBuiltinActions.ts
1665
- import { useEffect as useEffect8, useRef as useRef6 } from "react";
1464
+ import { useEffect as useEffect7, useRef as useRef5 } from "react";
1666
1465
  import { z as z2 } from "zod";
1667
1466
 
1668
1467
  // src/utils/screenshot.ts
@@ -1843,7 +1642,7 @@ function isTourEligible(tour, userProfile) {
1843
1642
  var resolutionCache = /* @__PURE__ */ new Map();
1844
1643
  var DEFAULT_WORKFLOW_SEARCH_LIMIT = 5;
1845
1644
  var WORKFLOW_TYPES = ["onboarding", "tour"];
1846
- function safeQueryAll2(selector) {
1645
+ function safeQueryAll3(selector) {
1847
1646
  try {
1848
1647
  return Array.from(document.querySelectorAll(selector)).filter(
1849
1648
  (el) => el instanceof HTMLElement
@@ -1852,6 +1651,9 @@ function safeQueryAll2(selector) {
1852
1651
  return [];
1853
1652
  }
1854
1653
  }
1654
+ function safeQueryOne(selector) {
1655
+ return safeQueryAll3(selector)[0] || null;
1656
+ }
1855
1657
  var ROW_SELECTORS = 'tr, [role="row"], [role="listitem"], li, [data-row], [class*="row"], [class*="card"], article, section';
1856
1658
  function getRowText(el) {
1857
1659
  const row = el.closest(ROW_SELECTORS);
@@ -1883,6 +1685,20 @@ function makeTarget(el, via) {
1883
1685
  resolvedVia: via
1884
1686
  };
1885
1687
  }
1688
+ function resolveInspectableElement(params, getTagStore) {
1689
+ if (params.selector) {
1690
+ const bySelector = safeQueryOne(params.selector);
1691
+ if (bySelector) return makeTarget(bySelector, "single-selector");
1692
+ }
1693
+ if (params.fingerprint) {
1694
+ return resolveTargetElement(
1695
+ params.fingerprint,
1696
+ { patternId: params.patternId, textContaining: params.textContaining },
1697
+ getTagStore()
1698
+ );
1699
+ }
1700
+ return null;
1701
+ }
1886
1702
  function resolveTargetElement(fingerprint, options, tagStore) {
1887
1703
  const elements = extractInteractiveElements();
1888
1704
  const byFp = elements.find((e) => e.fingerprint === fingerprint);
@@ -1891,7 +1707,7 @@ function resolveTargetElement(fingerprint, options, tagStore) {
1891
1707
  if (cached) {
1892
1708
  const cachedEl = elements.find((e) => e.fingerprint === cached.resolvedFingerprint);
1893
1709
  if (cachedEl?.element) return makeTarget(cachedEl.element, "cache");
1894
- const selectorMatches = safeQueryAll2(cached.selector);
1710
+ const selectorMatches = safeQueryAll3(cached.selector);
1895
1711
  if (selectorMatches.length === 1) {
1896
1712
  return makeTarget(selectorMatches[0], "cache");
1897
1713
  }
@@ -1910,7 +1726,7 @@ function resolveTargetElement(fingerprint, options, tagStore) {
1910
1726
  const fallbackTags = patternId ? selectorTags.filter((t) => t.patternId !== patternId) : [];
1911
1727
  for (const tagSet of [candidateTags, fallbackTags]) {
1912
1728
  for (const tag of tagSet) {
1913
- const matched = safeQueryAll2(tag.selector);
1729
+ const matched = safeQueryAll3(tag.selector);
1914
1730
  if (matched.length === 0) continue;
1915
1731
  for (const el of matched) {
1916
1732
  const fp = generateFingerprint(el);
@@ -1996,7 +1812,7 @@ function lastResortScan(fingerprint, options, elements) {
1996
1812
  }
1997
1813
  if (bestEl) return makeTarget(bestEl, "fuzzy");
1998
1814
  if (fpTextHint) {
1999
- const ariaMatches = safeQueryAll2(`[aria-label*="${CSS.escape(fpTextHint)}"], [data-testid*="${CSS.escape(fpTextHint)}"]`);
1815
+ const ariaMatches = safeQueryAll3(`[aria-label*="${CSS.escape(fpTextHint)}"], [data-testid*="${CSS.escape(fpTextHint)}"]`);
2000
1816
  if (textContaining && ariaMatches.length > 1) {
2001
1817
  let best = null;
2002
1818
  let bestS = 0;
@@ -2338,6 +2154,68 @@ function createWaitAction(getTagStore) {
2338
2154
  }
2339
2155
  };
2340
2156
  }
2157
+ var getUiMessagesSchema = z2.object({
2158
+ includeHidden: z2.boolean().optional().describe("Include currently hidden UI messages when true. Defaults to false."),
2159
+ maxItems: z2.number().int().min(1).max(20).optional().describe("Maximum number of messages to return. Defaults to 10.")
2160
+ });
2161
+ function createGetUiMessagesAction() {
2162
+ return {
2163
+ id: "get_ui_messages",
2164
+ description: "Return current UI-facing messages such as alerts, warnings, toasts, banners, and inline validation text.",
2165
+ schema: getUiMessagesSchema,
2166
+ execute: async (params) => {
2167
+ const messages = collectUiMessages(params);
2168
+ return {
2169
+ messages,
2170
+ total: messages.length,
2171
+ capturedAt: Date.now()
2172
+ };
2173
+ }
2174
+ };
2175
+ }
2176
+ var getLastActionEffectSchema = z2.object({});
2177
+ function createGetLastActionEffectAction() {
2178
+ return {
2179
+ id: "get_last_action_effect",
2180
+ description: "Return a compact summary of what changed after the most recent agent action.",
2181
+ schema: getLastActionEffectSchema,
2182
+ execute: async () => {
2183
+ return {
2184
+ effect: getLastActionEffectRecord()
2185
+ };
2186
+ }
2187
+ };
2188
+ }
2189
+ var inspectElementStateSchema = z2.object({
2190
+ fingerprint: z2.string().optional().describe("Fingerprint of the target element to inspect."),
2191
+ selector: z2.string().optional().describe("Optional CSS selector for direct inspection when a fingerprint is unavailable."),
2192
+ patternId: z2.string().optional().describe("Optional patternId from tagged elements for disambiguation."),
2193
+ textContaining: z2.string().optional().describe("Optional row or label text used to disambiguate similar elements.")
2194
+ });
2195
+ function createInspectElementStateAction(getTagStore) {
2196
+ return {
2197
+ id: "inspect_element_state",
2198
+ description: "Inspect one specific element and return its current visibility, enabled state, value/text, aria state, and associated error/help text.",
2199
+ schema: inspectElementStateSchema,
2200
+ execute: async (params) => {
2201
+ const target = resolveInspectableElement(params, getTagStore);
2202
+ if (!target) {
2203
+ return {
2204
+ found: false,
2205
+ reason: "Element not found from the provided fingerprint or selector."
2206
+ };
2207
+ }
2208
+ return {
2209
+ found: true,
2210
+ target: {
2211
+ fingerprint: target.fingerprint,
2212
+ resolvedVia: target.resolvedVia
2213
+ },
2214
+ element: inspectDomElementState(target.element)
2215
+ };
2216
+ }
2217
+ };
2218
+ }
2341
2219
  var searchDocsSchema = z2.object({
2342
2220
  query: z2.string().describe("The search query to find relevant documentation."),
2343
2221
  limit: z2.number().optional().describe("Maximum number of results to return (default: 5).")
@@ -2507,6 +2385,9 @@ var BUILTIN_ACTION_IDS = {
2507
2385
  click: "click_element",
2508
2386
  fill: "fill_input",
2509
2387
  wait: "request_user_action",
2388
+ getUiMessages: "get_ui_messages",
2389
+ getLastActionEffect: "get_last_action_effect",
2390
+ inspectElementState: "inspect_element_state",
2510
2391
  searchDocs: "search_docs",
2511
2392
  searchTaggedElements: "search_tagged_elements",
2512
2393
  searchWorkflows: "search_workflows",
@@ -2514,18 +2395,18 @@ var BUILTIN_ACTION_IDS = {
2514
2395
  startWorkflow: "start_workflow"
2515
2396
  };
2516
2397
  function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl, websiteId, toursApiBase, userProfile) {
2517
- const registeredRef = useRef6(false);
2518
- const tagStoreRef = useRef6(tagStore);
2398
+ const registeredRef = useRef5(false);
2399
+ const tagStoreRef = useRef5(tagStore);
2519
2400
  tagStoreRef.current = tagStore;
2520
- const serverUrlRef = useRef6(serverUrl);
2401
+ const serverUrlRef = useRef5(serverUrl);
2521
2402
  serverUrlRef.current = serverUrl;
2522
- const websiteIdRef = useRef6(websiteId);
2403
+ const websiteIdRef = useRef5(websiteId);
2523
2404
  websiteIdRef.current = websiteId;
2524
- const toursApiBaseRef = useRef6(toursApiBase);
2405
+ const toursApiBaseRef = useRef5(toursApiBase);
2525
2406
  toursApiBaseRef.current = toursApiBase;
2526
- const userProfileRef = useRef6(userProfile);
2407
+ const userProfileRef = useRef5(userProfile);
2527
2408
  userProfileRef.current = userProfile;
2528
- useEffect8(() => {
2409
+ useEffect7(() => {
2529
2410
  if (registeredRef.current) return;
2530
2411
  registeredRef.current = true;
2531
2412
  const getTagStore = () => tagStoreRef.current;
@@ -2543,6 +2424,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
2543
2424
  registerAction(createClickAction(getTagStore));
2544
2425
  registerAction(createFillAction(getTagStore));
2545
2426
  registerAction(createWaitAction(getTagStore));
2427
+ registerAction(createGetUiMessagesAction());
2428
+ registerAction(createGetLastActionEffectAction());
2429
+ registerAction(createInspectElementStateAction(getTagStore));
2546
2430
  registerAction(createSearchDocsAction(getServerUrl, getWebsiteId));
2547
2431
  registerAction(createSearchTaggedElementsAction(getTagStore));
2548
2432
  registerAction(createSearchWorkflowsAction(workflowToolGetters));
@@ -2553,6 +2437,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
2553
2437
  unregisterAction(BUILTIN_ACTION_IDS.click);
2554
2438
  unregisterAction(BUILTIN_ACTION_IDS.fill);
2555
2439
  unregisterAction(BUILTIN_ACTION_IDS.wait);
2440
+ unregisterAction(BUILTIN_ACTION_IDS.getUiMessages);
2441
+ unregisterAction(BUILTIN_ACTION_IDS.getLastActionEffect);
2442
+ unregisterAction(BUILTIN_ACTION_IDS.inspectElementState);
2556
2443
  unregisterAction(BUILTIN_ACTION_IDS.searchDocs);
2557
2444
  unregisterAction(BUILTIN_ACTION_IDS.searchTaggedElements);
2558
2445
  unregisterAction(BUILTIN_ACTION_IDS.searchWorkflows);
@@ -2880,7 +2767,7 @@ function readPreviewSessionSuppression() {
2880
2767
  }
2881
2768
 
2882
2769
  // src/hooks/useRunCommand.ts
2883
- import { useCallback as useCallback5, useContext as useContext2 } from "react";
2770
+ import { useCallback as useCallback4, useContext as useContext2 } from "react";
2884
2771
  function searchTaggedElementsForQuery(store, query, limit = 8) {
2885
2772
  const allTags = store.getAllTags();
2886
2773
  if (allTags.length === 0) return [];
@@ -2903,7 +2790,7 @@ function useRunCommand(serverUrlOverride) {
2903
2790
  const context = useContext2(ModelNexContext);
2904
2791
  const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
2905
2792
  const tagStore = context?.tagStore;
2906
- return useCallback5(
2793
+ return useCallback4(
2907
2794
  async (command, signal) => {
2908
2795
  const url = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/command` : `${baseUrl}/agent/command`;
2909
2796
  const relevantTaggedElements = tagStore ? searchTaggedElementsForQuery(tagStore, command) : void 0;
@@ -2931,7 +2818,7 @@ function useRunCommand(serverUrlOverride) {
2931
2818
  }
2932
2819
 
2933
2820
  // src/ui-state.tsx
2934
- import { createContext as createContext2, useContext as useContext3, useState as useState5, useCallback as useCallback6, useMemo as useMemo2 } from "react";
2821
+ import { createContext as createContext2, useContext as useContext3, useState as useState4, useCallback as useCallback5, useMemo as useMemo2 } from "react";
2935
2822
  import { jsx as jsx2 } from "react/jsx-runtime";
2936
2823
  var UIStateContext = createContext2(null);
2937
2824
  function UIStateProvider({
@@ -2940,8 +2827,8 @@ function UIStateProvider({
2940
2827
  type = "ui",
2941
2828
  initialState = {}
2942
2829
  }) {
2943
- const [state, setStateInternal] = useState5(initialState);
2944
- const setState = useCallback6((update) => {
2830
+ const [state, setStateInternal] = useState4(initialState);
2831
+ const setState = useCallback5((update) => {
2945
2832
  setStateInternal((prev) => ({ ...prev, ...update }));
2946
2833
  }, []);
2947
2834
  const value = useMemo2(() => ({ state, setState }), [state, setState]);
@@ -2954,7 +2841,7 @@ function useUIState() {
2954
2841
  }
2955
2842
 
2956
2843
  // src/viewport.ts
2957
- import { useEffect as useEffect10, useRef as useRef7, useState as useState6 } from "react";
2844
+ import { useEffect as useEffect9, useRef as useRef6, useState as useState5 } from "react";
2958
2845
  var visibleIds = /* @__PURE__ */ new Set();
2959
2846
  var listeners = /* @__PURE__ */ new Set();
2960
2847
  function updateVisibility(id, visible) {
@@ -2963,9 +2850,9 @@ function updateVisibility(id, visible) {
2963
2850
  listeners.forEach((fn) => fn());
2964
2851
  }
2965
2852
  function useViewportTrack(id) {
2966
- const ref = useRef7(null);
2967
- const [, setTick] = useState6(0);
2968
- useEffect10(() => {
2853
+ const ref = useRef6(null);
2854
+ const [, setTick] = useState5(0);
2855
+ useEffect9(() => {
2969
2856
  const el = ref.current;
2970
2857
  if (!el) return;
2971
2858
  const obs = new IntersectionObserver(
@@ -2980,7 +2867,7 @@ function useViewportTrack(id) {
2980
2867
  updateVisibility(id, false);
2981
2868
  };
2982
2869
  }, [id]);
2983
- useEffect10(() => {
2870
+ useEffect9(() => {
2984
2871
  const fn = () => setTick((t) => t + 1);
2985
2872
  listeners.add(fn);
2986
2873
  return () => {
@@ -2990,8 +2877,8 @@ function useViewportTrack(id) {
2990
2877
  return ref;
2991
2878
  }
2992
2879
  function useVisibleIds() {
2993
- const [ids, setIds] = useState6([]);
2994
- useEffect10(() => {
2880
+ const [ids, setIds] = useState5([]);
2881
+ useEffect9(() => {
2995
2882
  const fn = () => setIds(Array.from(visibleIds));
2996
2883
  fn();
2997
2884
  listeners.add(fn);
@@ -3008,11 +2895,11 @@ function useAgentViewport(options = {}) {
3008
2895
  }
3009
2896
 
3010
2897
  // 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";
2898
+ import { useState as useState12, useRef as useRef12, useEffect as useEffect16, useContext as useContext5, useCallback as useCallback11, useMemo as useMemo3 } from "react";
3012
2899
  import { createPortal, flushSync } from "react-dom";
3013
2900
 
3014
2901
  // src/hooks/useExperiencePlaybackController.ts
3015
- import { useCallback as useCallback8, useEffect as useEffect12, useRef as useRef9, useState as useState8 } from "react";
2902
+ import { useCallback as useCallback7, useEffect as useEffect11, useRef as useRef8, useState as useState7 } from "react";
3016
2903
 
3017
2904
  // src/utils/locationSignature.ts
3018
2905
  function getLocationSignature(locationLike) {
@@ -3021,7 +2908,7 @@ function getLocationSignature(locationLike) {
3021
2908
  }
3022
2909
 
3023
2910
  // src/hooks/useTourPlayback.ts
3024
- import { useState as useState7, useRef as useRef8, useCallback as useCallback7, useEffect as useEffect11, useContext as useContext4 } from "react";
2911
+ import { useState as useState6, useRef as useRef7, useCallback as useCallback6, useEffect as useEffect10, useContext as useContext4 } from "react";
3025
2912
 
3026
2913
  // src/utils/retryLookup.ts
3027
2914
  var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
@@ -3787,58 +3674,58 @@ function useTourPlayback({
3787
3674
  enableAutoDiscovery = true
3788
3675
  }) {
3789
3676
  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);
3677
+ const [isActive, setIsActive] = useState6(false);
3678
+ const [currentStepIndex, setCurrentStepIndex] = useState6(0);
3679
+ const [totalSteps, setTotalSteps] = useState6(0);
3680
+ const [activeTour, setActiveTour] = useState6(null);
3681
+ const [playbackState, setPlaybackState] = useState6("idle");
3682
+ const [isReviewMode, setIsReviewMode] = useState6(false);
3683
+ const [previewRunId, setPreviewRunId] = useState6(null);
3684
+ const [reviewSubmitting, setReviewSubmitting] = useState6(false);
3685
+ const [reviewStatusMessage, setReviewStatusMessage] = useState6(null);
3686
+ const [pendingTour, setPendingTour] = useState6(null);
3687
+ const [serverState, setServerState] = useState6(null);
3801
3688
  const ctx = useContext4(ModelNexContext);
3802
3689
  const devMode = ctx?.devMode;
3803
- const devModeRef = useRef8(devMode);
3690
+ const devModeRef = useRef7(devMode);
3804
3691
  devModeRef.current = devMode;
3805
- const userProfileRef = useRef8(userProfile);
3692
+ const userProfileRef = useRef7(userProfile);
3806
3693
  userProfileRef.current = userProfile;
3807
- const experienceTypeRef = useRef8(experienceType);
3694
+ const experienceTypeRef = useRef7(experienceType);
3808
3695
  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);
3696
+ const tourRef = useRef7(null);
3697
+ const stepIndexRef = useRef7(0);
3698
+ const skipRequestedRef = useRef7(false);
3699
+ const advanceRequestedRef = useRef7(false);
3700
+ const textInputResolveRef = useRef7(null);
3701
+ const voiceInputResolveRef = useRef7(null);
3702
+ const askOrFillRef = useRef7(null);
3703
+ const pendingManualWaitCleanupRef = useRef7(null);
3704
+ const pendingManualInputSyncRef = useRef7(null);
3705
+ const llmRespondingRef = useRef7(false);
3706
+ const interruptedForQuestionRef = useRef7(false);
3707
+ const pendingInputBufRef = useRef7(null);
3708
+ const activeExecutionTokenRef = useRef7(0);
3709
+ const commandInFlightRef = useRef7(false);
3710
+ const reviewModeRef = useRef7(false);
3711
+ const previewRunIdRef = useRef7(null);
3712
+ const toursApiBaseRef = useRef7(toursApiBase);
3713
+ const pendingTourRef = useRef7(null);
3714
+ const pendingTourOptionsRef = useRef7(null);
3715
+ const showCaptionsRef = useRef7(showCaptions);
3716
+ const initialPersistedTourSessionRef = useRef7(readPersistedActiveTourSession());
3717
+ const runIdRef = useRef7(initialPersistedTourSessionRef.current?.runId ?? null);
3718
+ const turnIdRef = useRef7(null);
3719
+ const startRequestedRef = useRef7(false);
3720
+ const playbackOwnerIdRef = useRef7(`playback-owner-${Math.random().toString(36).slice(2, 10)}`);
3721
+ const claimedPlaybackOwnerKeyRef = useRef7(null);
3722
+ const socketRef = useRef7(null);
3723
+ const socketIdRef = useRef7(socketId);
3724
+ const commandUrlRef = useRef7(commandUrl);
3725
+ const websiteIdRef = useRef7(websiteId);
3726
+ const onStepChangeRef = useRef7(onStepChange);
3727
+ const isActiveRef = useRef7(false);
3728
+ const activeCommandBatchIdRef = useRef7(null);
3842
3729
  socketIdRef.current = socketId;
3843
3730
  commandUrlRef.current = commandUrl;
3844
3731
  websiteIdRef.current = websiteId;
@@ -3849,13 +3736,13 @@ function useTourPlayback({
3849
3736
  toursApiBaseRef.current = toursApiBase;
3850
3737
  pendingTourRef.current = pendingTour;
3851
3738
  showCaptionsRef.current = showCaptions;
3852
- const releasePlaybackOwnership = useCallback7(() => {
3739
+ const releasePlaybackOwnership = useCallback6(() => {
3853
3740
  const claimedKey = claimedPlaybackOwnerKeyRef.current;
3854
3741
  if (!claimedKey) return;
3855
3742
  releaseTourPlaybackOwnership(claimedKey, playbackOwnerIdRef.current);
3856
3743
  claimedPlaybackOwnerKeyRef.current = null;
3857
3744
  }, []);
3858
- const emitTourInit = useCallback7((socket, currentWebsiteId, profile) => {
3745
+ const emitTourInit = useCallback6((socket, currentWebsiteId, profile) => {
3859
3746
  if (!currentWebsiteId || !profile?.type) return;
3860
3747
  const persistedRunId = runIdRef.current ?? readPersistedActiveTourSession()?.runId ?? null;
3861
3748
  const payload = {
@@ -3868,7 +3755,7 @@ function useTourPlayback({
3868
3755
  }
3869
3756
  emitSocketEvent(socket, "tour:init", payload);
3870
3757
  }, []);
3871
- useEffect11(() => {
3758
+ useEffect10(() => {
3872
3759
  if (disabled) return;
3873
3760
  if (typeof window === "undefined") return;
3874
3761
  const socket = tourSocketPool.acquire(serverUrl);
@@ -4017,7 +3904,7 @@ function useTourPlayback({
4017
3904
  resolve: async () => {
4018
3905
  let targetEl = null;
4019
3906
  if (params.uid) {
4020
- const { getElementByUid } = await import("./aom-LJNCLNXL.mjs");
3907
+ const { getElementByUid } = await import("./aom-SP2LMWQI.mjs");
4021
3908
  targetEl = getElementByUid(params.uid);
4022
3909
  }
4023
3910
  if (!targetEl) {
@@ -4495,7 +4382,7 @@ function useTourPlayback({
4495
4382
  void recordTourEvent(serverUrl, toursApiBaseRef.current, tour.id, userProfile.userId, "started", websiteId);
4496
4383
  }
4497
4384
  try {
4498
- const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
4385
+ const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-SP2LMWQI.mjs");
4499
4386
  const aom = generateMinifiedAOM2();
4500
4387
  if (socketRef.current === socket) {
4501
4388
  emitSocketEvent(socket, "tour:sync_dom", {
@@ -4579,7 +4466,7 @@ function useTourPlayback({
4579
4466
  tourSocketPool.release(serverUrl, toClose);
4580
4467
  };
4581
4468
  }, [serverUrl, disabled, emitTourInit, releasePlaybackOwnership]);
4582
- useEffect11(() => {
4469
+ useEffect10(() => {
4583
4470
  if (disabled) return;
4584
4471
  const s = socketRef.current;
4585
4472
  const profile = userProfile;
@@ -4589,12 +4476,12 @@ function useTourPlayback({
4589
4476
  }, 150);
4590
4477
  return () => clearTimeout(timer);
4591
4478
  }, [disabled, emitTourInit, websiteId, userProfile?.userId, userProfile?.type]);
4592
- useEffect11(() => {
4479
+ useEffect10(() => {
4593
4480
  if (!showCaptions || !isReviewMode) {
4594
4481
  removeCaption();
4595
4482
  }
4596
4483
  }, [showCaptions, isReviewMode]);
4597
- useEffect11(() => {
4484
+ useEffect10(() => {
4598
4485
  if (!isActiveRef.current) return;
4599
4486
  emitSocketEvent(socketRef.current, "tour:client_state", {
4600
4487
  runId: runIdRef.current,
@@ -4608,9 +4495,9 @@ function useTourPlayback({
4608
4495
  awaitingVoiceResolve: Boolean(voiceInputResolveRef.current)
4609
4496
  });
4610
4497
  }, [isActive, playbackState, voice.isListening, voice.isSpeaking]);
4611
- const syncAOM = useCallback7(async () => {
4498
+ const syncAOM = useCallback6(async () => {
4612
4499
  if (!isActiveRef.current) return;
4613
- const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
4500
+ const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-SP2LMWQI.mjs");
4614
4501
  const aom = generateMinifiedAOM2();
4615
4502
  emitSocketEvent(socketRef.current, "tour:sync_dom", {
4616
4503
  url: window.location.pathname + window.location.search + window.location.hash,
@@ -4618,7 +4505,7 @@ function useTourPlayback({
4618
4505
  domSummary: captureDomSummary()
4619
4506
  });
4620
4507
  }, []);
4621
- const scheduleManualInputSync = useCallback7(() => {
4508
+ const scheduleManualInputSync = useCallback6(() => {
4622
4509
  if (pendingManualInputSyncRef.current) {
4623
4510
  clearTimeout(pendingManualInputSyncRef.current);
4624
4511
  }
@@ -4630,13 +4517,13 @@ function useTourPlayback({
4630
4517
  await syncAOM();
4631
4518
  }, 150);
4632
4519
  }, [syncAOM]);
4633
- const clearPendingManualInputSync = useCallback7(() => {
4520
+ const clearPendingManualInputSync = useCallback6(() => {
4634
4521
  if (pendingManualInputSyncRef.current) {
4635
4522
  clearTimeout(pendingManualInputSyncRef.current);
4636
4523
  pendingManualInputSyncRef.current = null;
4637
4524
  }
4638
4525
  }, []);
4639
- const interruptExecution = useCallback7((transcript) => {
4526
+ const interruptExecution = useCallback6((transcript) => {
4640
4527
  if (!isSocketWritable(socketRef.current) || !isActiveRef.current) return false;
4641
4528
  if (!commandInFlightRef.current && !voice.isSpeaking) return false;
4642
4529
  interruptedForQuestionRef.current = true;
@@ -4664,7 +4551,7 @@ function useTourPlayback({
4664
4551
  setPlaybackState("thinking");
4665
4552
  return true;
4666
4553
  }, [voice]);
4667
- const stopTour = useCallback7(() => {
4554
+ const stopTour = useCallback6(() => {
4668
4555
  skipRequestedRef.current = true;
4669
4556
  isActiveRef.current = false;
4670
4557
  startRequestedRef.current = false;
@@ -4715,7 +4602,7 @@ function useTourPlayback({
4715
4602
  pendingInputBufRef.current = null;
4716
4603
  onTourEnd?.();
4717
4604
  }, [voice, onTourEnd, serverUrl, websiteId, releasePlaybackOwnership]);
4718
- const handleTourEnd = useCallback7(() => {
4605
+ const handleTourEnd = useCallback6(() => {
4719
4606
  const endingTourId = tourRef.current?.id;
4720
4607
  const endingPreviewRunId = previewRunIdRef.current;
4721
4608
  const endingStepOrder = stepIndexRef.current;
@@ -4762,7 +4649,7 @@ function useTourPlayback({
4762
4649
  }
4763
4650
  onTourEnd?.();
4764
4651
  }, [experienceType, userProfile, serverUrl, voice, onTourEnd, websiteId, releasePlaybackOwnership]);
4765
- const runTour = useCallback7(async (tour, options) => {
4652
+ const runTour = useCallback6(async (tour, options) => {
4766
4653
  if (!shouldAcceptTourStart({
4767
4654
  isPlaybackActive: isActiveRef.current,
4768
4655
  startRequested: startRequestedRef.current
@@ -4827,7 +4714,7 @@ function useTourPlayback({
4827
4714
  tourContext: compactTourForTransport(tour)
4828
4715
  });
4829
4716
  }, [serverUrl, websiteId]);
4830
- useEffect11(() => {
4717
+ useEffect10(() => {
4831
4718
  if (!shouldRunTourAutoDiscovery({
4832
4719
  enableAutoDiscovery,
4833
4720
  disabled,
@@ -4891,7 +4778,7 @@ function useTourPlayback({
4891
4778
  cancelled = true;
4892
4779
  };
4893
4780
  }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery, locationSignature]);
4894
- useEffect11(() => {
4781
+ useEffect10(() => {
4895
4782
  if (!shouldRunTourAutoDiscovery({
4896
4783
  enableAutoDiscovery,
4897
4784
  disabled,
@@ -4938,22 +4825,22 @@ function useTourPlayback({
4938
4825
  clearTimeout(timer);
4939
4826
  };
4940
4827
  }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery, locationSignature]);
4941
- useEffect11(() => {
4828
+ useEffect10(() => {
4942
4829
  if (!disabled || !isActiveRef.current) return;
4943
4830
  stopTour();
4944
4831
  }, [disabled, stopTour]);
4945
- const startTour = useCallback7((tour, options) => {
4832
+ const startTour = useCallback6((tour, options) => {
4946
4833
  if (disabled) return;
4947
4834
  void runTour(tour, options);
4948
4835
  }, [disabled, runTour]);
4949
- const acceptPendingTour = useCallback7(() => {
4836
+ const acceptPendingTour = useCallback6(() => {
4950
4837
  const tour = pendingTourRef.current;
4951
4838
  if (!tour || disabled) return;
4952
4839
  const opts = pendingTourOptionsRef.current;
4953
4840
  pendingTourOptionsRef.current = null;
4954
4841
  void runTour(tour, opts ?? void 0);
4955
4842
  }, [disabled, runTour]);
4956
- const dismissPendingTour = useCallback7(() => {
4843
+ const dismissPendingTour = useCallback6(() => {
4957
4844
  const tour = pendingTourRef.current;
4958
4845
  setPendingTour(null);
4959
4846
  pendingTourRef.current = null;
@@ -4961,7 +4848,7 @@ function useTourPlayback({
4961
4848
  if (!tour || !userProfile?.userId) return;
4962
4849
  void markTourDismissed(serverUrl, toursApiBaseRef.current, tour.id, userProfile.userId, experienceType, websiteId);
4963
4850
  }, [experienceType, serverUrl, userProfile, websiteId]);
4964
- const submitReviewFeedbackAction = useCallback7(async (utterance, apply = false) => {
4851
+ const submitReviewFeedbackAction = useCallback6(async (utterance, apply = false) => {
4965
4852
  const trimmed = utterance.trim();
4966
4853
  const currentTour = tourRef.current;
4967
4854
  const currentPreviewRunId = previewRunIdRef.current;
@@ -5001,10 +4888,10 @@ function useTourPlayback({
5001
4888
  setReviewSubmitting(false);
5002
4889
  }
5003
4890
  }, [playbackState, serverUrl, websiteId]);
5004
- const advanceStep = useCallback7(() => {
4891
+ const advanceStep = useCallback6(() => {
5005
4892
  advanceRequestedRef.current = true;
5006
4893
  }, []);
5007
- const skipTour = useCallback7(() => {
4894
+ const skipTour = useCallback6(() => {
5008
4895
  skipRequestedRef.current = true;
5009
4896
  voiceInputResolveRef.current?.("");
5010
4897
  voiceInputResolveRef.current = null;
@@ -5014,19 +4901,19 @@ function useTourPlayback({
5014
4901
  askOrFillRef.current = null;
5015
4902
  stopTour();
5016
4903
  }, [stopTour]);
5017
- const pauseTour = useCallback7(() => {
4904
+ const pauseTour = useCallback6(() => {
5018
4905
  if (isSocketWritable(socketRef.current) && isActiveRef.current) {
5019
4906
  emitSocketEvent(socketRef.current, "tour:pause");
5020
4907
  setPlaybackState("paused");
5021
4908
  }
5022
4909
  }, []);
5023
- const resumeTour = useCallback7(() => {
4910
+ const resumeTour = useCallback6(() => {
5024
4911
  if (isSocketWritable(socketRef.current) && isActiveRef.current) {
5025
4912
  emitSocketEvent(socketRef.current, "tour:resume");
5026
4913
  setPlaybackState("executing");
5027
4914
  }
5028
4915
  }, []);
5029
- const repeatStep = useCallback7(() => {
4916
+ const repeatStep = useCallback6(() => {
5030
4917
  const tour = tourRef.current;
5031
4918
  const step = tour?.steps[stepIndexRef.current];
5032
4919
  if (step) {
@@ -5034,7 +4921,7 @@ function useTourPlayback({
5034
4921
  voice.speak(text, tour?.voice.ttsVoice);
5035
4922
  }
5036
4923
  }, [voice]);
5037
- const handleVoiceInput = useCallback7((transcript) => {
4924
+ const handleVoiceInput = useCallback6((transcript) => {
5038
4925
  const text = transcript.trim();
5039
4926
  emitSdkDebugLog("[TourAgent] Voice input received", {
5040
4927
  textLength: text.length
@@ -5062,7 +4949,7 @@ function useTourPlayback({
5062
4949
  pendingInputBufRef.current = text;
5063
4950
  }
5064
4951
  }, [interruptExecution]);
5065
- const handleTextInput = useCallback7((text) => {
4952
+ const handleTextInput = useCallback6((text) => {
5066
4953
  if (voiceInputResolveRef.current) {
5067
4954
  const resolve = voiceInputResolveRef.current;
5068
4955
  voiceInputResolveRef.current = null;
@@ -5075,7 +4962,7 @@ function useTourPlayback({
5075
4962
  handleVoiceInput(text.trim());
5076
4963
  }
5077
4964
  }, [handleVoiceInput]);
5078
- useEffect11(() => {
4965
+ useEffect10(() => {
5079
4966
  return () => {
5080
4967
  removeHighlight();
5081
4968
  removeCaption();
@@ -5156,14 +5043,14 @@ function useExperiencePlaybackController({
5156
5043
  initialExperienceType = "tour"
5157
5044
  }) {
5158
5045
  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());
5046
+ const [activeExperienceType, setActiveExperienceType] = useState7(initialExperienceType);
5047
+ const [startingExperienceType, setStartingExperienceType] = useState7(null);
5048
+ const [pendingPrompt, setPendingPrompt] = useState7(null);
5049
+ const pendingPromptRef = useRef8(null);
5050
+ const queuedStartRef = useRef8(null);
5051
+ const bufferedVoiceInputsRef = useRef8([]);
5052
+ const previewDiscoveryInFlightRef = useRef8(false);
5053
+ const previewSessionRef = useRef8(readPreviewSessionSuppression());
5167
5054
  pendingPromptRef.current = pendingPrompt;
5168
5055
  const playback = useTourPlayback({
5169
5056
  serverUrl,
@@ -5182,7 +5069,7 @@ function useExperiencePlaybackController({
5182
5069
  showCaptions,
5183
5070
  enableAutoDiscovery: false
5184
5071
  });
5185
- const queueExperienceStart = useCallback8((tour, experienceType, options) => {
5072
+ const queueExperienceStart = useCallback7((tour, experienceType, options) => {
5186
5073
  setPendingPrompt(null);
5187
5074
  pendingPromptRef.current = null;
5188
5075
  setStartingExperienceType(experienceType);
@@ -5197,17 +5084,17 @@ function useExperiencePlaybackController({
5197
5084
  }
5198
5085
  playback.startTour(tour, options);
5199
5086
  }, [activeExperienceType, playback]);
5200
- const startExperience = useCallback8((tour, experienceType, options) => {
5087
+ const startExperience = useCallback7((tour, experienceType, options) => {
5201
5088
  const resolvedExperienceType = experienceType ?? tour.type ?? activeExperienceType;
5202
5089
  queueExperienceStart(tour, resolvedExperienceType, options);
5203
5090
  }, [activeExperienceType, queueExperienceStart]);
5204
- const acceptPendingPrompt = useCallback8((experienceType) => {
5091
+ const acceptPendingPrompt = useCallback7((experienceType) => {
5205
5092
  const prompt = pendingPromptRef.current;
5206
5093
  if (!prompt) return;
5207
5094
  if (experienceType && prompt.experienceType !== experienceType) return;
5208
5095
  queueExperienceStart(prompt.tour, prompt.experienceType, prompt.options);
5209
5096
  }, [queueExperienceStart]);
5210
- const dismissPendingPrompt = useCallback8((experienceType) => {
5097
+ const dismissPendingPrompt = useCallback7((experienceType) => {
5211
5098
  const prompt = pendingPromptRef.current;
5212
5099
  if (!prompt) return;
5213
5100
  if (experienceType && prompt.experienceType !== experienceType) return;
@@ -5230,7 +5117,7 @@ function useExperiencePlaybackController({
5230
5117
  websiteId
5231
5118
  );
5232
5119
  }, [serverUrl, toursApiBase, userProfile, websiteId]);
5233
- const handleVoiceInput = useCallback8((transcript, experienceType) => {
5120
+ const handleVoiceInput = useCallback7((transcript, experienceType) => {
5234
5121
  const trimmed = transcript.trim();
5235
5122
  if (!trimmed) return;
5236
5123
  const targetExperienceType = experienceType ?? activeExperienceType;
@@ -5250,12 +5137,12 @@ function useExperiencePlaybackController({
5250
5137
  }
5251
5138
  playback.handleVoiceInput(trimmed);
5252
5139
  }, [activeExperienceType, playback]);
5253
- useEffect12(() => {
5140
+ useEffect11(() => {
5254
5141
  if (playback.isActive && startingExperienceType !== null) {
5255
5142
  setStartingExperienceType(null);
5256
5143
  }
5257
5144
  }, [playback.isActive, startingExperienceType]);
5258
- useEffect12(() => {
5145
+ useEffect11(() => {
5259
5146
  const queuedStart = queuedStartRef.current;
5260
5147
  if (!queuedStart) return;
5261
5148
  if (playback.isActive) return;
@@ -5263,14 +5150,14 @@ function useExperiencePlaybackController({
5263
5150
  queuedStartRef.current = null;
5264
5151
  playback.startTour(queuedStart.tour, queuedStart.options);
5265
5152
  }, [activeExperienceType, playback]);
5266
- useEffect12(() => {
5153
+ useEffect11(() => {
5267
5154
  if (!playback.isActive) return;
5268
5155
  const readyInputs = bufferedVoiceInputsRef.current.filter((item) => item.experienceType === activeExperienceType);
5269
5156
  if (readyInputs.length === 0) return;
5270
5157
  bufferedVoiceInputsRef.current = bufferedVoiceInputsRef.current.filter((item) => item.experienceType !== activeExperienceType);
5271
5158
  readyInputs.forEach((item) => playback.handleVoiceInput(item.transcript));
5272
5159
  }, [activeExperienceType, playback]);
5273
- useEffect12(() => {
5160
+ useEffect11(() => {
5274
5161
  if (!shouldDiscoverDraftPreview({
5275
5162
  disabled,
5276
5163
  hasPendingPrompt: Boolean(pendingPromptRef.current),
@@ -5352,7 +5239,7 @@ function useExperiencePlaybackController({
5352
5239
  previewDiscoveryInFlightRef.current = false;
5353
5240
  };
5354
5241
  }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId, locationSignature]);
5355
- useEffect12(() => {
5242
+ useEffect11(() => {
5356
5243
  if (!shouldDiscoverEligibleTours({
5357
5244
  disabled,
5358
5245
  hasPendingPrompt: Boolean(pendingPromptRef.current),
@@ -5416,7 +5303,7 @@ function useExperiencePlaybackController({
5416
5303
  }
5417
5304
 
5418
5305
  // src/hooks/useVoice.ts
5419
- import { useState as useState9, useRef as useRef10, useCallback as useCallback9, useEffect as useEffect13 } from "react";
5306
+ import { useState as useState8, useRef as useRef9, useCallback as useCallback8, useEffect as useEffect12 } from "react";
5420
5307
 
5421
5308
  // src/utils/webrtc-aec.ts
5422
5309
  function isWebRtcAecSupported() {
@@ -5785,36 +5672,36 @@ function isFatalSpeechError(error) {
5785
5672
  return error === "not-allowed" || error === "service-not-allowed" || error === "audio-capture";
5786
5673
  }
5787
5674
  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(() => {
5675
+ const [isSpeaking, setIsSpeaking] = useState8(false);
5676
+ const [isListening, setIsListening] = useState8(false);
5677
+ const [isMuted, setIsMuted] = useState8(false);
5678
+ const audioRef = useRef9(null);
5679
+ const audioBlobUrlRef = useRef9(null);
5680
+ const speakResolveRef = useRef9(null);
5681
+ const recognitionRef = useRef9(null);
5682
+ const isMutedRef = useRef9(false);
5683
+ const sttCallbacksRef = useRef9(null);
5684
+ const stripIndicesRef = useRef9({});
5685
+ const accumulatedRef = useRef9([]);
5686
+ const interimDebounceRef = useRef9(null);
5687
+ const lastInterimRef = useRef9("");
5688
+ const lastDeliveredRef = useRef9("");
5689
+ const isSpeakingRef = useRef9(false);
5690
+ const speechEndTimeRef = useRef9(0);
5691
+ const recentTtsRef = useRef9([]);
5692
+ const prefetchedSpeechRef = useRef9(/* @__PURE__ */ new Map());
5693
+ const nearEndTimeoutRef = useRef9(null);
5694
+ const queuePromiseRef = useRef9(Promise.resolve());
5695
+ const queueSeqRef = useRef9(0);
5696
+ const lastStopSeqRef = useRef9(0);
5697
+ const listeningSessionIdRef = useRef9(null);
5698
+ const listeningStartedAtRef = useRef9(0);
5699
+ const loopbackRef = useRef9(null);
5700
+ const aecActiveRef = useRef9(false);
5701
+ const mediaRecorderRef = useRef9(null);
5702
+ const micStreamRef = useRef9(null);
5703
+ const sttSocketRef = useRef9(null);
5704
+ const stopLiveSttTransport = useCallback8(() => {
5818
5705
  const socket = sttSocketRef.current;
5819
5706
  sttSocketRef.current = null;
5820
5707
  if (socket) {
@@ -5843,16 +5730,16 @@ function useVoice(serverUrl) {
5843
5730
  }
5844
5731
  mediaRecorderRef.current = null;
5845
5732
  }, []);
5846
- useEffect13(() => {
5733
+ useEffect12(() => {
5847
5734
  isMutedRef.current = isMuted;
5848
5735
  }, [isMuted]);
5849
- useEffect13(() => {
5736
+ useEffect12(() => {
5850
5737
  isSpeakingRef.current = isSpeaking;
5851
5738
  }, [isSpeaking]);
5852
5739
  const webSpeechSupported = typeof window !== "undefined" && !!(window.SpeechRecognition || window.webkitSpeechRecognition);
5853
5740
  const mediaCaptureSupported = typeof window !== "undefined" && typeof navigator !== "undefined" && !!navigator.mediaDevices?.getUserMedia && typeof MediaRecorder !== "undefined";
5854
5741
  const sttSupported = typeof window !== "undefined" && (mediaCaptureSupported || webSpeechSupported);
5855
- const stopSpeaking = useCallback9(() => {
5742
+ const stopSpeaking = useCallback8(() => {
5856
5743
  emitVoiceDebug("tts_stop", {
5857
5744
  queueSeq: queueSeqRef.current,
5858
5745
  wasSpeaking: isSpeakingRef.current
@@ -5879,8 +5766,8 @@ function useVoice(serverUrl) {
5879
5766
  speakResolveRef.current?.();
5880
5767
  speakResolveRef.current = null;
5881
5768
  }, []);
5882
- const getSpeechCacheKey = useCallback9((text, voiceId) => `${voiceId}::${text}`, []);
5883
- const loadAudioDurationMs = useCallback9(async (url, fallbackText) => {
5769
+ const getSpeechCacheKey = useCallback8((text, voiceId) => `${voiceId}::${text}`, []);
5770
+ const loadAudioDurationMs = useCallback8(async (url, fallbackText) => {
5884
5771
  try {
5885
5772
  const probe = new Audio();
5886
5773
  probe.preload = "metadata";
@@ -5902,7 +5789,7 @@ function useVoice(serverUrl) {
5902
5789
  return estimateSpeechDurationMs(fallbackText);
5903
5790
  }
5904
5791
  }, []);
5905
- const fetchSpeechClip = useCallback9(async (text, voiceId) => {
5792
+ const fetchSpeechClip = useCallback8(async (text, voiceId) => {
5906
5793
  const baseUrl = serverUrl.replace(/\/$/, "");
5907
5794
  const debugEnabled = isVoiceDebugEnabled();
5908
5795
  const requestId = createVoiceDebugId("tts");
@@ -5964,7 +5851,7 @@ function useVoice(serverUrl) {
5964
5851
  });
5965
5852
  return { url, durationMs, requestId, buffered: true };
5966
5853
  }, [loadAudioDurationMs, serverUrl]);
5967
- const createStreamingSpeechClipForPlayback = useCallback9((text, voiceId) => {
5854
+ const createStreamingSpeechClipForPlayback = useCallback8((text, voiceId) => {
5968
5855
  const requestId = createVoiceDebugId("tts");
5969
5856
  const clip = createStreamingSpeechClip(serverUrl, text, voiceId, {
5970
5857
  requestId,
@@ -5979,7 +5866,7 @@ function useVoice(serverUrl) {
5979
5866
  });
5980
5867
  return clip;
5981
5868
  }, [serverUrl]);
5982
- const prefetchSpeech = useCallback9(async (text, voiceId = DEFAULT_VOICE_ID) => {
5869
+ const prefetchSpeech = useCallback8(async (text, voiceId = DEFAULT_VOICE_ID) => {
5983
5870
  if (isMutedRef.current || !text.trim()) return;
5984
5871
  const key = getSpeechCacheKey(text, voiceId);
5985
5872
  if (!prefetchedSpeechRef.current.has(key)) {
@@ -5993,7 +5880,7 @@ function useVoice(serverUrl) {
5993
5880
  }
5994
5881
  await prefetchedSpeechRef.current.get(key);
5995
5882
  }, [fetchSpeechClip, getSpeechCacheKey]);
5996
- const playClipDirect = useCallback9(async (clip, timeoutMs) => {
5883
+ const playClipDirect = useCallback8(async (clip, timeoutMs) => {
5997
5884
  const { url } = clip;
5998
5885
  const audio = new Audio();
5999
5886
  audio.crossOrigin = "anonymous";
@@ -6089,7 +5976,7 @@ function useVoice(serverUrl) {
6089
5976
  });
6090
5977
  });
6091
5978
  }, []);
6092
- const speak = useCallback9(async (text, voiceId = DEFAULT_VOICE_ID, options = {}) => {
5979
+ const speak = useCallback8(async (text, voiceId = DEFAULT_VOICE_ID, options = {}) => {
6093
5980
  if (isMutedRef.current) return;
6094
5981
  const mySeq = ++queueSeqRef.current;
6095
5982
  const interrupt = options.interrupt === true;
@@ -6181,7 +6068,7 @@ function useVoice(serverUrl) {
6181
6068
  }
6182
6069
  return taskPromise;
6183
6070
  }, [createStreamingSpeechClipForPlayback, fetchSpeechClip, getSpeechCacheKey, playClipDirect, stopSpeaking]);
6184
- const stopListening = useCallback9(() => {
6071
+ const stopListening = useCallback8(() => {
6185
6072
  emitVoiceDebug("stt_stop_listening", {
6186
6073
  listeningSessionId: listeningSessionIdRef.current,
6187
6074
  listeningMs: listeningStartedAtRef.current ? Math.round(performance.now() - listeningStartedAtRef.current) : null
@@ -6213,7 +6100,7 @@ function useVoice(serverUrl) {
6213
6100
  accumulatedRef.current = [];
6214
6101
  setIsListening(false);
6215
6102
  }, [stopLiveSttTransport]);
6216
- const startListening = useCallback9((onResult, onInterruption, onError, options = {}) => {
6103
+ const startListening = useCallback8((onResult, onInterruption, onError, options = {}) => {
6217
6104
  stopListening();
6218
6105
  listeningSessionIdRef.current = createVoiceDebugId("stt");
6219
6106
  listeningStartedAtRef.current = performance.now();
@@ -6497,7 +6384,7 @@ function useVoice(serverUrl) {
6497
6384
  }
6498
6385
  fallbackToWebSpeech();
6499
6386
  }, [serverUrl, stopListening, stopSpeaking, stopLiveSttTransport]);
6500
- const toggleMute = useCallback9(() => {
6387
+ const toggleMute = useCallback8(() => {
6501
6388
  setIsMuted((prev) => {
6502
6389
  const next = !prev;
6503
6390
  if (next) {
@@ -6509,7 +6396,7 @@ function useVoice(serverUrl) {
6509
6396
  return next;
6510
6397
  });
6511
6398
  }, []);
6512
- useEffect13(() => {
6399
+ useEffect12(() => {
6513
6400
  return () => {
6514
6401
  stopSpeaking();
6515
6402
  stopListening();
@@ -6538,18 +6425,18 @@ function useVoice(serverUrl) {
6538
6425
  }
6539
6426
 
6540
6427
  // src/hooks/useAudioLevel.ts
6541
- import { useState as useState10, useEffect as useEffect14, useRef as useRef11 } from "react";
6428
+ import { useState as useState9, useEffect as useEffect13, useRef as useRef10 } from "react";
6542
6429
  var BAR_COUNT = 9;
6543
6430
  var SENSITIVITY = 2.8;
6544
6431
  var FLOOR = 0.08;
6545
6432
  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(() => {
6433
+ const [levels, setLevels] = useState9(() => Array(BAR_COUNT).fill(FLOOR));
6434
+ const streamRef = useRef10(null);
6435
+ const ctxRef = useRef10(null);
6436
+ const analyserRef = useRef10(null);
6437
+ const rafRef = useRef10(0);
6438
+ const timeDataRef = useRef10(null);
6439
+ useEffect13(() => {
6553
6440
  if (!active || typeof window === "undefined") {
6554
6441
  setLevels(Array(BAR_COUNT).fill(FLOOR));
6555
6442
  return;
@@ -6621,7 +6508,7 @@ function useAudioLevel(active) {
6621
6508
  }
6622
6509
 
6623
6510
  // src/hooks/useRecordingMode.ts
6624
- import { useState as useState11, useRef as useRef12, useCallback as useCallback10, useEffect as useEffect15 } from "react";
6511
+ import { useState as useState10, useRef as useRef11, useCallback as useCallback9, useEffect as useEffect14 } from "react";
6625
6512
 
6626
6513
  // src/utils/tourStepTypes.ts
6627
6514
  function isAskDrivenInputStepType(stepType) {
@@ -6902,46 +6789,46 @@ function useRecordingMode({
6902
6789
  onPreview,
6903
6790
  experienceType = "tour"
6904
6791
  }) {
6905
- const restoredSessionRef = useRef12(void 0);
6792
+ const restoredSessionRef = useRef11(void 0);
6906
6793
  if (restoredSessionRef.current === void 0) {
6907
6794
  restoredSessionRef.current = readPersistedRecordingSession();
6908
6795
  }
6909
6796
  const restoredSession = restoredSessionRef.current;
6910
6797
  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([]);
6798
+ const [phase, setPhase] = useState10(restoredPhase);
6799
+ const [steps, setSteps] = useState10(() => restoredSession?.steps ?? []);
6800
+ const [selectedElement, setSelectedElement] = useState10(null);
6801
+ const [selectedStepType, setSelectedStepType] = useState10(() => restoredSession?.selectedStepType ?? "ask_or_fill");
6802
+ const [pendingNarration, setPendingNarration] = useState10("");
6803
+ const [polishedNarration, setPolishedNarration] = useState10("");
6804
+ const [captureEvents, setCaptureEvents] = useState10(() => restoredSession?.captureEvents ?? []);
6805
+ const [capturedTranscript, setCapturedTranscript] = useState10(() => restoredSession?.capturedTranscript ?? "");
6806
+ const [isVoiceCaptureActive, setIsVoiceCaptureActive] = useState10(false);
6807
+ const stepsRef = useRef11([]);
6921
6808
  stepsRef.current = steps;
6922
- const captureEventsRef = useRef12([]);
6923
- const capturedTranscriptRef = useRef12(capturedTranscript);
6809
+ const captureEventsRef = useRef11([]);
6810
+ const capturedTranscriptRef = useRef11(capturedTranscript);
6924
6811
  capturedTranscriptRef.current = capturedTranscript;
6925
- const phaseRef = useRef12(phase);
6812
+ const phaseRef = useRef11(phase);
6926
6813
  phaseRef.current = phase;
6927
- const safeSpeak = useCallback10((text) => {
6814
+ const safeSpeak = useCallback9((text) => {
6928
6815
  void voice.speak(text).catch((err) => {
6929
6816
  console.warn("[Recording] Voice playback unavailable:", err);
6930
6817
  });
6931
6818
  }, [voice]);
6932
6819
  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");
6820
+ const pendingClicksRef = useRef11(restoredSession?.pendingClicks ?? []);
6821
+ const shouldKeepVoiceCaptureRef = useRef11(restoredSession?.voiceCaptureEnabled === true);
6822
+ const resumeVoiceAfterNarrationRef = useRef11(false);
6823
+ const lastAutoNoteRef = useRef11("");
6824
+ const lastHoverKeyRef = useRef11("");
6825
+ const lastHoverAtRef = useRef11(0);
6826
+ const selectedStepTypeRef = useRef11("ask_or_fill");
6940
6827
  selectedStepTypeRef.current = selectedStepType;
6941
6828
  const isRecording = phase !== "idle";
6942
6829
  const stepCount = steps.length;
6943
6830
  const captureEventCount = captureEvents.length;
6944
- const persistSnapshot = useCallback10((overrides) => {
6831
+ const persistSnapshot = useCallback9((overrides) => {
6945
6832
  const nextPhase = overrides?.phase ?? phaseRef.current;
6946
6833
  const nextSteps = overrides?.steps ?? stepsRef.current;
6947
6834
  const nextCaptureEvents = overrides?.captureEvents ?? captureEventsRef.current;
@@ -6964,7 +6851,7 @@ function useRecordingMode({
6964
6851
  voiceCaptureEnabled: nextVoiceCaptureEnabled
6965
6852
  });
6966
6853
  }, [experienceType]);
6967
- const appendCaptureEvent = useCallback10((event) => {
6854
+ const appendCaptureEvent = useCallback9((event) => {
6968
6855
  const nextEvent = {
6969
6856
  id: event.id || newCaptureId(event.type),
6970
6857
  order: captureEventsRef.current.length,
@@ -6976,7 +6863,7 @@ function useRecordingMode({
6976
6863
  setCaptureEvents(nextCaptureEvents);
6977
6864
  persistSnapshot({ captureEvents: nextCaptureEvents });
6978
6865
  }, [persistSnapshot]);
6979
- const updateCaptureEvent = useCallback10((id, metadataPatch) => {
6866
+ const updateCaptureEvent = useCallback9((id, metadataPatch) => {
6980
6867
  const nextCaptureEvents = captureEventsRef.current.map((event) => {
6981
6868
  if (event.id === id) {
6982
6869
  return {
@@ -6993,7 +6880,7 @@ function useRecordingMode({
6993
6880
  setCaptureEvents(nextCaptureEvents);
6994
6881
  persistSnapshot({ captureEvents: nextCaptureEvents });
6995
6882
  }, [persistSnapshot]);
6996
- const appendVoiceNote = useCallback10((transcript) => {
6883
+ const appendVoiceNote = useCallback9((transcript) => {
6997
6884
  const text = transcript.trim();
6998
6885
  if (!text) return;
6999
6886
  if (lastAutoNoteRef.current === text) return;
@@ -7054,11 +6941,11 @@ function useRecordingMode({
7054
6941
  }
7055
6942
  });
7056
6943
  }, [appendCaptureEvent, persistSnapshot]);
7057
- const stopBackgroundVoiceCapture = useCallback10(() => {
6944
+ const stopBackgroundVoiceCapture = useCallback9(() => {
7058
6945
  voice.stopListening();
7059
6946
  setIsVoiceCaptureActive(false);
7060
6947
  }, [voice]);
7061
- const startBackgroundVoiceCapture = useCallback10(() => {
6948
+ const startBackgroundVoiceCapture = useCallback9(() => {
7062
6949
  if (!shouldKeepVoiceCaptureRef.current) return;
7063
6950
  if (!isRecording) return;
7064
6951
  if (phase === "narrating" || phase === "reviewing") return;
@@ -7075,7 +6962,7 @@ function useRecordingMode({
7075
6962
  );
7076
6963
  setIsVoiceCaptureActive(true);
7077
6964
  }, [appendVoiceNote, isRecording, phase, voice]);
7078
- const startRecording = useCallback10(() => {
6965
+ const startRecording = useCallback9(() => {
7079
6966
  const nextPhase = "active";
7080
6967
  const nextCaptureEvents = [{
7081
6968
  id: newCaptureId("session_start"),
@@ -7107,34 +6994,34 @@ function useRecordingMode({
7107
6994
  voiceCaptureEnabled: false
7108
6995
  });
7109
6996
  }, [persistSnapshot]);
7110
- const markStep = useCallback10(() => {
6997
+ const markStep = useCallback9(() => {
7111
6998
  if (phase !== "active") return;
7112
6999
  setPhase("selecting");
7113
7000
  }, [phase]);
7114
- const selectElement = useCallback10((recorded) => {
7001
+ const selectElement = useCallback9((recorded) => {
7115
7002
  setSelectedElement(recorded);
7116
7003
  setPhase("configuring");
7117
7004
  const isFormField = ["INPUT", "SELECT", "TEXTAREA"].includes(recorded.el.tagName);
7118
7005
  setSelectedStepType(isFormField ? "ask_or_fill" : "narrate");
7119
7006
  }, []);
7120
- const selectPageLevel = useCallback10(() => {
7007
+ const selectPageLevel = useCallback9(() => {
7121
7008
  setSelectedElement(null);
7122
7009
  setSelectedStepType("narrate");
7123
7010
  setPhase("configuring");
7124
7011
  }, []);
7125
- const cancelSelection = useCallback10(() => {
7012
+ const cancelSelection = useCallback9(() => {
7126
7013
  setSelectedElement(null);
7127
7014
  setPhase("active");
7128
7015
  }, []);
7129
- const setStepType = useCallback10((type) => {
7016
+ const setStepType = useCallback9((type) => {
7130
7017
  setSelectedStepType(type);
7131
7018
  }, []);
7132
- const runPolishAndReview = useCallback10(async (transcript) => {
7019
+ const runPolishAndReview = useCallback9(async (transcript) => {
7133
7020
  setPolishedNarration(transcript);
7134
7021
  setPhase("reviewing");
7135
7022
  }, []);
7136
- const pendingNarrationRef = useRef12("");
7137
- const startNarration = useCallback10(() => {
7023
+ const pendingNarrationRef = useRef11("");
7024
+ const startNarration = useCallback9(() => {
7138
7025
  resumeVoiceAfterNarrationRef.current = shouldKeepVoiceCaptureRef.current && isVoiceCaptureActive;
7139
7026
  if (isVoiceCaptureActive) {
7140
7027
  stopBackgroundVoiceCapture();
@@ -7156,7 +7043,7 @@ function useRecordingMode({
7156
7043
  { continuous: true }
7157
7044
  );
7158
7045
  }, [isVoiceCaptureActive, stopBackgroundVoiceCapture, voice]);
7159
- const finishNarration = useCallback10(async () => {
7046
+ const finishNarration = useCallback9(async () => {
7160
7047
  if (phase !== "narrating") return;
7161
7048
  voice.stopListening();
7162
7049
  const text = pendingNarrationRef.current;
@@ -7171,13 +7058,13 @@ function useRecordingMode({
7171
7058
  }
7172
7059
  }
7173
7060
  }, [phase, runPolishAndReview, startBackgroundVoiceCapture, voice]);
7174
- const submitTextNarration = useCallback10(async (text) => {
7061
+ const submitTextNarration = useCallback9(async (text) => {
7175
7062
  if (phase !== "narrating" || !text.trim()) return;
7176
7063
  voice.stopListening();
7177
7064
  setPendingNarration(text);
7178
7065
  await runPolishAndReview(text);
7179
7066
  }, [phase, voice, runPolishAndReview]);
7180
- const approveNarration = useCallback10(() => {
7067
+ const approveNarration = useCallback9(() => {
7181
7068
  if (phase !== "reviewing") return;
7182
7069
  const el = selectedElement;
7183
7070
  const narration = polishedNarration || pendingNarration;
@@ -7267,17 +7154,17 @@ function useRecordingMode({
7267
7154
  }, 0);
7268
7155
  }
7269
7156
  }, [appendCaptureEvent, phase, polishedNarration, pendingNarration, persistSnapshot, selectedElement, selectedStepType, startBackgroundVoiceCapture, voice]);
7270
- const redoNarration = useCallback10(() => {
7157
+ const redoNarration = useCallback9(() => {
7271
7158
  if (phase !== "reviewing") return;
7272
7159
  setPendingNarration("");
7273
7160
  setPolishedNarration("");
7274
7161
  startNarration();
7275
7162
  }, [phase, startNarration]);
7276
- const editNarration = useCallback10((text) => {
7163
+ const editNarration = useCallback9((text) => {
7277
7164
  setPendingNarration(text);
7278
7165
  setPolishedNarration(text);
7279
7166
  }, []);
7280
- const continueRecording = useCallback10(() => {
7167
+ const continueRecording = useCallback9(() => {
7281
7168
  phaseRef.current = "active";
7282
7169
  setPhase("active");
7283
7170
  persistSnapshot({ phase: "active" });
@@ -7287,7 +7174,7 @@ function useRecordingMode({
7287
7174
  }, 0);
7288
7175
  }
7289
7176
  }, [persistSnapshot, startBackgroundVoiceCapture]);
7290
- const undoLastStep = useCallback10(() => {
7177
+ const undoLastStep = useCallback9(() => {
7291
7178
  const previous = stepsRef.current;
7292
7179
  const nextSteps = previous.slice(0, -1);
7293
7180
  stepsRef.current = nextSteps;
@@ -7299,7 +7186,7 @@ function useRecordingMode({
7299
7186
  setPhase("active");
7300
7187
  persistSnapshot({ steps: nextSteps, phase: "active" });
7301
7188
  }, [persistSnapshot, voice]);
7302
- const previewSteps = useCallback10(() => {
7189
+ const previewSteps = useCallback9(() => {
7303
7190
  if (steps.length === 0) {
7304
7191
  safeSpeak("No steps recorded yet.");
7305
7192
  return;
@@ -7307,13 +7194,13 @@ function useRecordingMode({
7307
7194
  onPreview?.(steps);
7308
7195
  safeSpeak(`Previewing ${steps.length} step${steps.length !== 1 ? "s" : ""}.`);
7309
7196
  }, [onPreview, safeSpeak, steps]);
7310
- const prepareToStopRecording = useCallback10(() => {
7197
+ const prepareToStopRecording = useCallback9(() => {
7311
7198
  shouldKeepVoiceCaptureRef.current = false;
7312
7199
  resumeVoiceAfterNarrationRef.current = false;
7313
7200
  stopBackgroundVoiceCapture();
7314
7201
  persistSnapshot({ voiceCaptureEnabled: false });
7315
7202
  }, [persistSnapshot, stopBackgroundVoiceCapture]);
7316
- const cancelRecording = useCallback10(() => {
7203
+ const cancelRecording = useCallback9(() => {
7317
7204
  shouldKeepVoiceCaptureRef.current = false;
7318
7205
  stopBackgroundVoiceCapture();
7319
7206
  phaseRef.current = "idle";
@@ -7331,7 +7218,7 @@ function useRecordingMode({
7331
7218
  clearPersistedRecordingSession();
7332
7219
  safeSpeak("Recording cancelled.");
7333
7220
  }, [safeSpeak, stopBackgroundVoiceCapture]);
7334
- useEffect15(() => {
7221
+ useEffect14(() => {
7335
7222
  if (!isRecording || typeof document === "undefined") return;
7336
7223
  const handleMouseMove = (event) => {
7337
7224
  const target = event.target;
@@ -7441,7 +7328,7 @@ function useRecordingMode({
7441
7328
  window.clearInterval(routePoll);
7442
7329
  };
7443
7330
  }, [appendCaptureEvent, isRecording]);
7444
- useEffect15(() => {
7331
+ useEffect14(() => {
7445
7332
  if (!isRecording || typeof window === "undefined") return;
7446
7333
  const flushRecordingSession = () => {
7447
7334
  persistSnapshot();
@@ -7453,7 +7340,7 @@ function useRecordingMode({
7453
7340
  window.removeEventListener("beforeunload", flushRecordingSession);
7454
7341
  };
7455
7342
  }, [isRecording, persistSnapshot]);
7456
- const stopRecording = useCallback10(async (tourName, targetUserTypes) => {
7343
+ const stopRecording = useCallback9(async (tourName, targetUserTypes) => {
7457
7344
  phaseRef.current = "finishing";
7458
7345
  setPhase("finishing");
7459
7346
  shouldKeepVoiceCaptureRef.current = false;
@@ -7527,7 +7414,7 @@ function useRecordingMode({
7527
7414
  return null;
7528
7415
  }
7529
7416
  }, [capturedTranscript, experienceType, persistSnapshot, safeSpeak, serverUrl, stopBackgroundVoiceCapture, steps, toursApiBase, websiteId]);
7530
- const toggleVoiceCapture = useCallback10(() => {
7417
+ const toggleVoiceCapture = useCallback9(() => {
7531
7418
  if (isVoiceCaptureActive || shouldKeepVoiceCaptureRef.current) {
7532
7419
  shouldKeepVoiceCaptureRef.current = false;
7533
7420
  stopBackgroundVoiceCapture();
@@ -7538,7 +7425,7 @@ function useRecordingMode({
7538
7425
  persistSnapshot({ voiceCaptureEnabled: true });
7539
7426
  startBackgroundVoiceCapture();
7540
7427
  }, [isVoiceCaptureActive, persistSnapshot, startBackgroundVoiceCapture, stopBackgroundVoiceCapture]);
7541
- useEffect15(() => {
7428
+ useEffect14(() => {
7542
7429
  if (!isRecording) return;
7543
7430
  if (phase === "active" && shouldKeepVoiceCaptureRef.current && !isVoiceCaptureActive) {
7544
7431
  startBackgroundVoiceCapture();
@@ -7547,7 +7434,7 @@ function useRecordingMode({
7547
7434
  stopBackgroundVoiceCapture();
7548
7435
  }
7549
7436
  }, [isRecording, isVoiceCaptureActive, phase, startBackgroundVoiceCapture, stopBackgroundVoiceCapture]);
7550
- const handleVoiceCommand = useCallback10((transcript) => {
7437
+ const handleVoiceCommand = useCallback9((transcript) => {
7551
7438
  const lower = transcript.toLowerCase().trim();
7552
7439
  if (!isRecording) return;
7553
7440
  if (lower.includes("mark step") && phase === "active") {
@@ -7609,7 +7496,7 @@ function useRecordingMode({
7609
7496
  }
7610
7497
 
7611
7498
  // src/components/RecordingOverlay.tsx
7612
- import { useEffect as useEffect16, useState as useState12, useCallback as useCallback11 } from "react";
7499
+ import { useEffect as useEffect15, useState as useState11, useCallback as useCallback10 } from "react";
7613
7500
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
7614
7501
  function buildFingerprint(el) {
7615
7502
  const tag = el.tagName.toLowerCase();
@@ -7637,8 +7524,8 @@ var panelBase = {
7637
7524
  color: "#18181b"
7638
7525
  };
7639
7526
  function ActiveHUD({ stepCount, captureEventCount, isVoiceCaptureActive, minimized, onToggleVoiceCapture, onToggleMinimized, onStop, onCancel }) {
7640
- const [hasActivatedVoiceCapture, setHasActivatedVoiceCapture] = useState12(isVoiceCaptureActive);
7641
- useEffect16(() => {
7527
+ const [hasActivatedVoiceCapture, setHasActivatedVoiceCapture] = useState11(isVoiceCaptureActive);
7528
+ useEffect15(() => {
7642
7529
  if (isVoiceCaptureActive) {
7643
7530
  setHasActivatedVoiceCapture(true);
7644
7531
  }
@@ -7883,8 +7770,8 @@ var STEP_TYPES_ADVANCED = [
7883
7770
  ];
7884
7771
  function StepPopover({ element, stepIndex, onConfirm, onCancel }) {
7885
7772
  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);
7773
+ const [selected, setSelected] = useState11(defaultType);
7774
+ const [showAdvanced, setShowAdvanced] = useState11(false);
7888
7775
  const hasTestId = !!element?.testId;
7889
7776
  const allTypes = showAdvanced ? [...STEP_TYPES_PRIMARY, ...STEP_TYPES_ADVANCED] : STEP_TYPES_PRIMARY;
7890
7777
  const popoverStyle = {
@@ -8028,8 +7915,8 @@ function StepPopover({ element, stepIndex, onConfirm, onCancel }) {
8028
7915
  ] });
8029
7916
  }
8030
7917
  function NarrationPanel({ stepIndex, stepCount, pendingNarration, isListening, onSubmitText, onCancel, onStopRecording }) {
8031
- const [textInput, setTextInput] = useState12("");
8032
- const [showTextInput, setShowTextInput] = useState12(false);
7918
+ const [textInput, setTextInput] = useState11("");
7919
+ const [showTextInput, setShowTextInput] = useState11(false);
8033
7920
  const audioLevels = useAudioLevel(isListening);
8034
7921
  return /* @__PURE__ */ jsxs2(
8035
7922
  "div",
@@ -8196,8 +8083,8 @@ function NarrationPanel({ stepIndex, stepCount, pendingNarration, isListening, o
8196
8083
  );
8197
8084
  }
8198
8085
  function ReviewPanel({ stepIndex, stepCount, polishedNarration, rawNarration, onApprove, onRedo, onEdit }) {
8199
- const [editMode, setEditMode] = useState12(false);
8200
- const [editText, setEditText] = useState12(polishedNarration || rawNarration);
8086
+ const [editMode, setEditMode] = useState11(false);
8087
+ const [editText, setEditText] = useState11(polishedNarration || rawNarration);
8201
8088
  const displayText = polishedNarration || rawNarration;
8202
8089
  return /* @__PURE__ */ jsxs2(
8203
8090
  "div",
@@ -8453,7 +8340,7 @@ function FinishingPanel() {
8453
8340
  }
8454
8341
  );
8455
8342
  }
8456
- var INTERACTIVE_SELECTOR2 = [
8343
+ var INTERACTIVE_SELECTOR = [
8457
8344
  "button",
8458
8345
  "a[href]",
8459
8346
  'input:not([type="hidden"])',
@@ -8491,19 +8378,19 @@ function RecordingOverlay({
8491
8378
  onCancelRecording,
8492
8379
  onStopRecording
8493
8380
  }) {
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);
8381
+ const [hoveredEl, setHoveredEl] = useState11(null);
8382
+ const [pendingElement, setPendingElement] = useState11(null);
8383
+ const [showPopover, setShowPopover] = useState11(false);
8384
+ const [hudMinimized, setHudMinimized] = useState11(false);
8385
+ const [voicePanelMinimized, setVoicePanelMinimized] = useState11(false);
8499
8386
  const isSelecting = phase === "selecting";
8500
- const handleMouseMove = useCallback11((e) => {
8501
- const target = e.target.closest(INTERACTIVE_SELECTOR2);
8387
+ const handleMouseMove = useCallback10((e) => {
8388
+ const target = e.target.closest(INTERACTIVE_SELECTOR);
8502
8389
  setHoveredEl(target);
8503
8390
  }, []);
8504
- const handleClick = useCallback11((e) => {
8391
+ const handleClick = useCallback10((e) => {
8505
8392
  if (e.target.closest("[data-modelnex-internal]")) return;
8506
- const target = e.target.closest(INTERACTIVE_SELECTOR2);
8393
+ const target = e.target.closest(INTERACTIVE_SELECTOR);
8507
8394
  if (target) {
8508
8395
  e.preventDefault();
8509
8396
  e.stopPropagation();
@@ -8526,7 +8413,7 @@ function RecordingOverlay({
8526
8413
  setShowPopover(true);
8527
8414
  }
8528
8415
  }, []);
8529
- useEffect16(() => {
8416
+ useEffect15(() => {
8530
8417
  if (!isSelecting) return;
8531
8418
  document.addEventListener("mousemove", handleMouseMove, true);
8532
8419
  document.addEventListener("click", handleClick, true);
@@ -8538,14 +8425,14 @@ function RecordingOverlay({
8538
8425
  document.body.style.cursor = prev;
8539
8426
  };
8540
8427
  }, [isSelecting, handleMouseMove, handleClick]);
8541
- useEffect16(() => {
8428
+ useEffect15(() => {
8542
8429
  if (isSelecting) {
8543
8430
  setShowPopover(false);
8544
8431
  setPendingElement(null);
8545
8432
  setHoveredEl(null);
8546
8433
  }
8547
8434
  }, [isSelecting]);
8548
- const handlePopoverConfirm = useCallback11((type) => {
8435
+ const handlePopoverConfirm = useCallback10((type) => {
8549
8436
  setShowPopover(false);
8550
8437
  if (pendingElement) {
8551
8438
  onElementSelected(pendingElement);
@@ -8555,7 +8442,7 @@ function RecordingOverlay({
8555
8442
  onStepTypeConfirmed(type);
8556
8443
  onStartNarration();
8557
8444
  }, [pendingElement, onElementSelected, onPageLevelStep, onStepTypeConfirmed, onStartNarration]);
8558
- const handlePopoverCancel = useCallback11(() => {
8445
+ const handlePopoverCancel = useCallback10(() => {
8559
8446
  setShowPopover(false);
8560
8447
  setPendingElement(null);
8561
8448
  }, []);
@@ -9102,8 +8989,8 @@ function getViewportHeight() {
9102
8989
  return layoutViewportHeight;
9103
8990
  }
9104
8991
  function useViewportHeight() {
9105
- const [viewportHeight, setViewportHeight] = useState13(() => getViewportHeight());
9106
- useEffect17(() => {
8992
+ const [viewportHeight, setViewportHeight] = useState12(() => getViewportHeight());
8993
+ useEffect16(() => {
9107
8994
  if (typeof window === "undefined") return;
9108
8995
  const updateViewportHeight = () => {
9109
8996
  setViewportHeight(getViewportHeight());
@@ -9122,8 +9009,8 @@ function useViewportHeight() {
9122
9009
  return viewportHeight;
9123
9010
  }
9124
9011
  function useMediaQuery(query) {
9125
- const [matches, setMatches] = useState13(false);
9126
- useEffect17(() => {
9012
+ const [matches, setMatches] = useState12(false);
9013
+ useEffect16(() => {
9127
9014
  const media = window.matchMedia(query);
9128
9015
  if (media.matches !== matches) setMatches(media.matches);
9129
9016
  const listener = () => setMatches(media.matches);
@@ -9195,8 +9082,8 @@ var GLOBAL_STYLES = `
9195
9082
  }
9196
9083
  `;
9197
9084
  function Tooltip({ children, title }) {
9198
- const [show, setShow] = useState13(false);
9199
- const ref = useRef13(null);
9085
+ const [show, setShow] = useState12(false);
9086
+ const ref = useRef12(null);
9200
9087
  const handleShow = () => setShow(true);
9201
9088
  const handleHide = () => setShow(false);
9202
9089
  return /* @__PURE__ */ jsxs3(
@@ -9290,11 +9177,11 @@ var TrashIcon = () => /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16",
9290
9177
  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
9178
  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
9179
  function AgentTraces({ debug, command, defaultExpanded = true }) {
9293
- const [expanded, setExpanded] = useState13(defaultExpanded);
9294
- const [expandedSteps, setExpandedSteps] = useState13(/* @__PURE__ */ new Set());
9180
+ const [expanded, setExpanded] = useState12(defaultExpanded);
9181
+ const [expandedSteps, setExpandedSteps] = useState12(/* @__PURE__ */ new Set());
9295
9182
  const traces = debug.traces ?? [];
9296
9183
  const hasTraceContent = traces.length > 0 || debug.llmInput || (debug.llmOutput?.length ?? 0) > 0 || (debug.actions?.length ?? 0) > 0;
9297
- useEffect17(() => {
9184
+ useEffect16(() => {
9298
9185
  setExpandedSteps(new Set(traces.map((t) => t.step)));
9299
9186
  }, [debug]);
9300
9187
  const toggleStep = (step) => {
@@ -9455,21 +9342,21 @@ function ModelNexChatBubble({
9455
9342
  }) {
9456
9343
  const onCommand = void 0;
9457
9344
  const recordingExperienceType = "tour";
9458
- const noop = useCallback12(() => void 0, []);
9459
- const noopAsync = useCallback12(async () => void 0, []);
9345
+ const noop = useCallback11(() => void 0, []);
9346
+ const noopAsync = useCallback11(async () => void 0, []);
9460
9347
  const runCommand = useRunCommand();
9461
9348
  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("");
9349
+ const [hydrated, setHydrated] = useState12(false);
9350
+ const [expanded, setExpanded] = useState12(false);
9351
+ const [docked, setDocked] = useState12(false);
9352
+ const [input, setInput] = useState12("");
9466
9353
  const messages = ctx?.chatMessages ?? [];
9467
9354
  const setMessages = ctx?.setChatMessages ?? (() => {
9468
9355
  });
9469
- const [loading, setLoading] = useState13(false);
9470
- const messagesEndRef = useRef13(null);
9471
- const abortControllerRef = useRef13(null);
9472
- const panelRef = useRef13(null);
9356
+ const [loading, setLoading] = useState12(false);
9357
+ const messagesEndRef = useRef12(null);
9358
+ const abortControllerRef = useRef12(null);
9359
+ const panelRef = useRef12(null);
9473
9360
  const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
9474
9361
  const voice = useVoice(serverUrl);
9475
9362
  const audioLevels = useAudioLevel(voice.isListening);
@@ -9478,13 +9365,13 @@ function ModelNexChatBubble({
9478
9365
  });
9479
9366
  const devMode = ctx?.devMode ?? false;
9480
9367
  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(
9368
+ const [recordingTourName, setRecordingTourName] = useState12("");
9369
+ const [recordingTargetTypes, setRecordingTargetTypes] = useState12("admin");
9370
+ const [showStopModal, setShowStopModal] = useState12(false);
9371
+ const [savedDraft, setSavedDraft] = useState12(null);
9372
+ const [reviewDraft, setReviewDraft] = useState12("");
9373
+ const [tourLiveTranscript, setTourLiveTranscript] = useState12("");
9374
+ const [activeRecordingExperienceType, setActiveRecordingExperienceType] = useState12(
9488
9375
  () => readPersistedRecordingExperienceType() ?? recordingExperienceType
9489
9376
  );
9490
9377
  const recording = useRecordingMode({
@@ -9496,7 +9383,7 @@ function ModelNexChatBubble({
9496
9383
  });
9497
9384
  const isGeneratingDraft = isRecordingDraftGenerating(recording.phase);
9498
9385
  const showRecordingOverlay = recordingMode && shouldShowRecordingOverlay(recording.phase);
9499
- useEffect17(() => {
9386
+ useEffect16(() => {
9500
9387
  const shouldBeRecording = recording.phase !== "idle";
9501
9388
  if (shouldBeRecording && !recordingMode) {
9502
9389
  setRecordingMode(true);
@@ -9529,12 +9416,12 @@ function ModelNexChatBubble({
9529
9416
  const activePlayback = playbackController.playback;
9530
9417
  const activeExperienceType = playbackController.activeExperienceType;
9531
9418
  const startingExperienceType = playbackController.startingExperienceType;
9532
- useEffect17(() => {
9419
+ useEffect16(() => {
9533
9420
  return registerExperienceToolBridge({
9534
9421
  startExperience: playbackController.startExperience
9535
9422
  });
9536
9423
  }, [playbackController.startExperience]);
9537
- const createPlaybackView = useCallback12((experienceType) => {
9424
+ const createPlaybackView = useCallback11((experienceType) => {
9538
9425
  const isActiveExperience = activePlayback.isActive && activeExperienceType === experienceType;
9539
9426
  const pendingTour = playbackController.pendingPrompt?.experienceType === experienceType ? playbackController.pendingPrompt.tour : null;
9540
9427
  return {
@@ -9566,8 +9453,8 @@ function ModelNexChatBubble({
9566
9453
  const onboardingPlayback = useMemo3(() => createPlaybackView("onboarding"), [createPlaybackView]);
9567
9454
  const tourReviewToggle = getReviewModeToggleConfig(tourPlayback.playbackState);
9568
9455
  const tourReviewModeEnabled = isReviewModeEnabled(devMode, tourPlayback.isReviewMode);
9569
- const lastAutoTaggedUrlRef = useRef13(null);
9570
- const handleAutoTag = useCallback12(async () => {
9456
+ const lastAutoTaggedUrlRef = useRef12(null);
9457
+ const handleAutoTag = useCallback11(async () => {
9571
9458
  if (!ctx) return;
9572
9459
  const { extractedElements, tagStore, commandUrl, serverUrl: serverUrl2, websiteId } = ctx;
9573
9460
  if (extractedElements.length === 0) return;
@@ -9606,7 +9493,7 @@ function ModelNexChatBubble({
9606
9493
  console.warn("[ModelNex] Auto-tag error:", err);
9607
9494
  }
9608
9495
  }, [ctx]);
9609
- useEffect17(() => {
9496
+ useEffect16(() => {
9610
9497
  if (authoringMode && ctx?.extractedElements.length) {
9611
9498
  const timer = setTimeout(handleAutoTag, 1e3);
9612
9499
  return () => clearTimeout(timer);
@@ -9628,7 +9515,7 @@ function ModelNexChatBubble({
9628
9515
  recordingMode,
9629
9516
  pendingNotificationType
9630
9517
  });
9631
- useEffect17(() => {
9518
+ useEffect16(() => {
9632
9519
  setHydrated(true);
9633
9520
  try {
9634
9521
  setExpanded(sessionStorage.getItem(BUBBLE_EXPANDED_STORAGE_KEY) === "true");
@@ -9638,18 +9525,18 @@ function ModelNexChatBubble({
9638
9525
  setDocked(false);
9639
9526
  }
9640
9527
  }, []);
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) => {
9528
+ const sttActiveRef = useRef12(false);
9529
+ const [tourListenReady, setTourListenReady] = useState12(false);
9530
+ const [tourSttError, setTourSttError] = useState12(null);
9531
+ const previousTourActiveRef = useRef12(false);
9532
+ const tourListenReadyRef = useRef12(false);
9533
+ const tourSttErrorRef = useRef12(null);
9534
+ const updateTourListenReady = useCallback11((next) => {
9648
9535
  if (tourListenReadyRef.current === next) return;
9649
9536
  tourListenReadyRef.current = next;
9650
9537
  setTourListenReady(next);
9651
9538
  }, []);
9652
- const updateTourSttError = useCallback12((next) => {
9539
+ const updateTourSttError = useCallback11((next) => {
9653
9540
  if (tourSttErrorRef.current === next) return;
9654
9541
  tourSttErrorRef.current = next;
9655
9542
  setTourSttError(next);
@@ -9658,7 +9545,7 @@ function ModelNexChatBubble({
9658
9545
  () => buildTranscriptPreviewLines(tourLiveTranscript, { maxCharsPerLine: 36, maxLines: 2 }),
9659
9546
  [tourLiveTranscript]
9660
9547
  );
9661
- useEffect17(() => {
9548
+ useEffect16(() => {
9662
9549
  const shouldShowFloatingTranscript = (tourPlayback.isActive || onboardingPlayback.isActive) && tourListenReady && voice.isListening;
9663
9550
  if (shouldShowFloatingTranscript) {
9664
9551
  showFloatingLiveTranscript({
@@ -9680,10 +9567,10 @@ function ModelNexChatBubble({
9680
9567
  tourPlayback.isActive,
9681
9568
  voice.isListening
9682
9569
  ]);
9683
- useEffect17(() => () => {
9570
+ useEffect16(() => () => {
9684
9571
  hideFloatingLiveTranscript();
9685
9572
  }, []);
9686
- const setExpandedState = useCallback12((next, opts) => {
9573
+ const setExpandedState = useCallback11((next, opts) => {
9687
9574
  setExpanded(next);
9688
9575
  try {
9689
9576
  sessionStorage.setItem(BUBBLE_EXPANDED_STORAGE_KEY, String(next));
@@ -9695,14 +9582,14 @@ function ModelNexChatBubble({
9695
9582
  } catch {
9696
9583
  }
9697
9584
  }, [tourPlayback.isActive, onboardingPlayback.isActive]);
9698
- const setDockedState = useCallback12((next) => {
9585
+ const setDockedState = useCallback11((next) => {
9699
9586
  setDocked(next);
9700
9587
  try {
9701
9588
  sessionStorage.setItem(BUBBLE_DOCKED_STORAGE_KEY, String(next));
9702
9589
  } catch {
9703
9590
  }
9704
9591
  }, []);
9705
- useEffect17(() => {
9592
+ useEffect16(() => {
9706
9593
  if (shouldAutoExpandForPendingPrompt({
9707
9594
  pendingPrompt,
9708
9595
  isPlaybackActive,
@@ -9712,8 +9599,8 @@ function ModelNexChatBubble({
9712
9599
  setExpandedState(true);
9713
9600
  }
9714
9601
  }, [isPlaybackActive, pendingNotificationType, pendingPrompt, recordingMode, setExpandedState]);
9715
- const preferredListeningExperienceRef = useRef13(null);
9716
- const playbackVoiceRoutingRef = useRef13({
9602
+ const preferredListeningExperienceRef = useRef12(null);
9603
+ const playbackVoiceRoutingRef = useRef12({
9717
9604
  activeExperienceType,
9718
9605
  isActive: activePlayback.isActive,
9719
9606
  isReviewMode: activePlayback.isReviewMode,
@@ -9721,7 +9608,7 @@ function ModelNexChatBubble({
9721
9608
  playbackState: activePlayback.playbackState,
9722
9609
  handleVoiceInput: playbackController.handleVoiceInput
9723
9610
  });
9724
- useEffect17(() => {
9611
+ useEffect16(() => {
9725
9612
  playbackVoiceRoutingRef.current = {
9726
9613
  activeExperienceType,
9727
9614
  isActive: activePlayback.isActive,
@@ -9738,7 +9625,7 @@ function ModelNexChatBubble({
9738
9625
  playbackController.handleVoiceInput,
9739
9626
  playbackController.pendingPrompt?.experienceType
9740
9627
  ]);
9741
- const handleVoiceTourInput = useCallback12(createSinglePlaybackTranscriptRouter(
9628
+ const handleVoiceTourInput = useCallback11(createSinglePlaybackTranscriptRouter(
9742
9629
  () => ({
9743
9630
  isReviewMode: playbackVoiceRoutingRef.current.isReviewMode,
9744
9631
  playbackState: playbackVoiceRoutingRef.current.playbackState
@@ -9753,7 +9640,7 @@ function ModelNexChatBubble({
9753
9640
  }
9754
9641
  }
9755
9642
  ), []);
9756
- const startTourListening = useCallback12((preferredExperience) => {
9643
+ const startTourListening = useCallback11((preferredExperience) => {
9757
9644
  const listeningState = {
9758
9645
  isTourActive: tourPlayback.isActive,
9759
9646
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9808,7 +9695,7 @@ function ModelNexChatBubble({
9808
9695
  updateTourListenReady,
9809
9696
  updateTourSttError
9810
9697
  ]);
9811
- useEffect17(() => {
9698
+ useEffect16(() => {
9812
9699
  const isPlaybackActive2 = isTourListeningSessionActive({
9813
9700
  isTourActive: tourPlayback.isActive,
9814
9701
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9831,12 +9718,12 @@ function ModelNexChatBubble({
9831
9718
  }
9832
9719
  }
9833
9720
  }, [tourPlayback.isActive, onboardingPlayback.isActive, setExpandedState, startingExperienceType, updateTourSttError]);
9834
- useEffect17(() => {
9721
+ useEffect16(() => {
9835
9722
  if (!tourPlayback.isReviewMode && !onboardingPlayback.isReviewMode) {
9836
9723
  setReviewDraft("");
9837
9724
  }
9838
9725
  }, [tourPlayback.isReviewMode, onboardingPlayback.isReviewMode]);
9839
- useEffect17(() => {
9726
+ useEffect16(() => {
9840
9727
  if (!isTourListeningSessionActive({
9841
9728
  isTourActive: tourPlayback.isActive,
9842
9729
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9845,12 +9732,12 @@ function ModelNexChatBubble({
9845
9732
  preferredListeningExperienceRef.current = null;
9846
9733
  }
9847
9734
  }, [tourPlayback.isActive, onboardingPlayback.isActive, startingExperienceType]);
9848
- useEffect17(() => {
9735
+ useEffect16(() => {
9849
9736
  if (recordingMode) {
9850
9737
  setExpandedState(false);
9851
9738
  }
9852
9739
  }, [recordingMode, setExpandedState]);
9853
- useEffect17(() => {
9740
+ useEffect16(() => {
9854
9741
  const isPlaybackActive2 = isTourListeningSessionActive({
9855
9742
  isTourActive: tourPlayback.isActive,
9856
9743
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9864,7 +9751,7 @@ function ModelNexChatBubble({
9864
9751
  }
9865
9752
  updateTourListenReady(Boolean(voice.isListening && sttActiveRef.current));
9866
9753
  }, [tourPlayback.isActive, onboardingPlayback.isActive, voice.isListening, startingExperienceType, updateTourListenReady]);
9867
- useEffect17(() => {
9754
+ useEffect16(() => {
9868
9755
  const isPlaybackActive2 = isTourListeningSessionActive({
9869
9756
  isTourActive: tourPlayback.isActive,
9870
9757
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9879,7 +9766,7 @@ function ModelNexChatBubble({
9879
9766
  voice.stopListening();
9880
9767
  }
9881
9768
  }, [tourPlayback.isActive, onboardingPlayback.isActive, voice, startingExperienceType, updateTourListenReady, updateTourSttError]);
9882
- useEffect17(() => {
9769
+ useEffect16(() => {
9883
9770
  const isPlaybackActive2 = isTourListeningSessionActive({
9884
9771
  isTourActive: tourPlayback.isActive,
9885
9772
  isOnboardingActive: onboardingPlayback.isActive,
@@ -9901,8 +9788,8 @@ function ModelNexChatBubble({
9901
9788
  window.removeEventListener("keydown", enableTourListeningFromGesture, true);
9902
9789
  };
9903
9790
  }, [tourPlayback.isActive, onboardingPlayback.isActive, tourListenReady, tourSttError, voice.sttSupported, startTourListening, startingExperienceType]);
9904
- const [voiceInputMode, setVoiceInputMode] = useState13(false);
9905
- const toggleVoiceInput = useCallback12(() => {
9791
+ const [voiceInputMode, setVoiceInputMode] = useState12(false);
9792
+ const toggleVoiceInput = useCallback11(() => {
9906
9793
  if (voiceInputMode) {
9907
9794
  voice.stopListening();
9908
9795
  setVoiceInputMode(false);
@@ -9925,7 +9812,7 @@ function ModelNexChatBubble({
9925
9812
  );
9926
9813
  }
9927
9814
  }, [voiceInputMode, voice, recordingMode, recording]);
9928
- useEffect17(() => {
9815
+ useEffect16(() => {
9929
9816
  const panel = panelRef.current;
9930
9817
  if (!panel) return;
9931
9818
  const stopKeyPropagation = (e) => {
@@ -9949,7 +9836,7 @@ function ModelNexChatBubble({
9949
9836
  const tourCompletionRatio = tourPlayback.totalSteps > 0 ? Math.min(tourPlayback.currentStepIndex / tourPlayback.totalSteps, 1) : 0;
9950
9837
  const tourCurrentStep = tourPlayback.activeTour?.steps?.[tourPlayback.currentStepIndex] || null;
9951
9838
  const scrollToBottom = () => messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
9952
- useEffect17(() => {
9839
+ useEffect16(() => {
9953
9840
  if (messages.length > 0) scrollToBottom();
9954
9841
  }, [messages, loading]);
9955
9842
  const runAgent = async () => {
@@ -10006,7 +9893,7 @@ function ModelNexChatBubble({
10006
9893
  const clearChat = () => {
10007
9894
  setMessages([]);
10008
9895
  };
10009
- const startRecordingSession = useCallback12((experienceType) => {
9896
+ const startRecordingSession = useCallback11((experienceType) => {
10010
9897
  abortControllerRef.current?.abort();
10011
9898
  abortControllerRef.current = null;
10012
9899
  setLoading(false);
@@ -11259,7 +11146,7 @@ function ModelNexChatBubble({
11259
11146
  }
11260
11147
 
11261
11148
  // 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";
11149
+ import { useCallback as useCallback12, useContext as useContext6, useEffect as useEffect17, useMemo as useMemo4, useRef as useRef13, useState as useState13 } from "react";
11263
11150
  import { createPortal as createPortal2 } from "react-dom";
11264
11151
 
11265
11152
  // src/hooks/useOnboardingPlayback.ts
@@ -11294,14 +11181,14 @@ function ModelNexOnboardingPanel({
11294
11181
  const devMode = ctx?.devMode ?? false;
11295
11182
  const voice = useVoice(serverUrl);
11296
11183
  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);
11184
+ const [input, setInput] = useState13("");
11185
+ const [reviewDraft, setReviewDraft] = useState13("");
11186
+ const [open, setOpen] = useState13(true);
11187
+ const [currentStepIndex, setCurrentStepIndex] = useState13(0);
11188
+ const [liveTranscript, setLiveTranscript] = useState13("");
11189
+ const [voiceEnabled, setVoiceEnabled] = useState13(false);
11190
+ const [sttError, setSttError] = useState13(null);
11191
+ const voiceEnabledRef = useRef13(false);
11305
11192
  const playback = useOnboardingPlayback({
11306
11193
  serverUrl,
11307
11194
  commandUrl: ctx?.commandUrl,
@@ -11321,26 +11208,26 @@ function ModelNexOnboardingPanel({
11321
11208
  voiceEnabledRef.current = false;
11322
11209
  }
11323
11210
  });
11324
- const playbackVoiceRoutingRef = useRef14({
11211
+ const playbackVoiceRoutingRef = useRef13({
11325
11212
  isReviewMode: false,
11326
11213
  playbackState: playback.playbackState,
11327
11214
  handleVoiceInput: playback.handleVoiceInput
11328
11215
  });
11329
11216
  const reviewToggle = getReviewModeToggleConfig(playback.playbackState);
11330
11217
  const reviewModeEnabled = isReviewModeEnabled(devMode, playback.isReviewMode);
11331
- useEffect18(() => {
11218
+ useEffect17(() => {
11332
11219
  playbackVoiceRoutingRef.current = {
11333
11220
  isReviewMode: playback.isReviewMode,
11334
11221
  playbackState: playback.playbackState,
11335
11222
  handleVoiceInput: playback.handleVoiceInput
11336
11223
  };
11337
11224
  }, [playback.isReviewMode, playback.playbackState, playback.handleVoiceInput]);
11338
- useEffect18(() => {
11225
+ useEffect17(() => {
11339
11226
  if (playback.isActive && !playback.isReviewMode) {
11340
11227
  setOpen(true);
11341
11228
  }
11342
11229
  }, [playback.activeTour?.id, playback.isActive, playback.isReviewMode]);
11343
- const startVoiceListening = useCallback13(() => {
11230
+ const startVoiceListening = useCallback12(() => {
11344
11231
  if (voiceEnabledRef.current || !voice.sttSupported) return;
11345
11232
  voiceEnabledRef.current = true;
11346
11233
  setVoiceEnabled(true);
@@ -11387,7 +11274,7 @@ function ModelNexOnboardingPanel({
11387
11274
  }
11388
11275
  );
11389
11276
  }, [playback.isActive, voice]);
11390
- useEffect18(() => {
11277
+ useEffect17(() => {
11391
11278
  if (!playback.isActive || voiceEnabledRef.current || !voice.sttSupported) return;
11392
11279
  const startOnGesture = (event) => {
11393
11280
  if (shouldIgnorePanelGestureStart(event.target)) {
@@ -11402,7 +11289,7 @@ function ModelNexOnboardingPanel({
11402
11289
  window.removeEventListener("keydown", startOnGesture, true);
11403
11290
  };
11404
11291
  }, [playback.isActive, voice.sttSupported, startVoiceListening]);
11405
- useEffect18(() => {
11292
+ useEffect17(() => {
11406
11293
  if (!playback.isActive && voiceEnabledRef.current) {
11407
11294
  voiceEnabledRef.current = false;
11408
11295
  setVoiceEnabled(false);
@@ -11422,7 +11309,7 @@ function ModelNexOnboardingPanel({
11422
11309
  () => buildTranscriptPreviewLines(liveTranscript, { maxCharsPerLine: 34, maxLines: 2 }),
11423
11310
  [liveTranscript]
11424
11311
  );
11425
- useEffect18(() => {
11312
+ useEffect17(() => {
11426
11313
  if (voiceEnabled && voice.isListening) {
11427
11314
  showFloatingLiveTranscript({
11428
11315
  levels: audioLevels,
@@ -11436,7 +11323,7 @@ function ModelNexOnboardingPanel({
11436
11323
  }
11437
11324
  hideFloatingLiveTranscript();
11438
11325
  }, [audioLevels, liveTranscriptLines, voiceEnabled, voice.isListening]);
11439
- useEffect18(() => () => {
11326
+ useEffect17(() => () => {
11440
11327
  hideFloatingLiveTranscript();
11441
11328
  }, []);
11442
11329
  const actionButtonStyle = {
@@ -12001,7 +11888,7 @@ var ModelNexProvider = ({
12001
11888
  const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
12002
11889
  const commandUrl = void 0;
12003
11890
  const disableSocket = false;
12004
- useEffect19(() => {
11891
+ useEffect18(() => {
12005
11892
  if (process.env.NODE_ENV !== "production" && !serverUrlProp) {
12006
11893
  console.warn(
12007
11894
  `[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 +11896,21 @@ var ModelNexProvider = ({
12009
11896
  }
12010
11897
  }, [serverUrlProp]);
12011
11898
  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(() => {
11899
+ const [activeAgentActions, setActiveAgentActions] = useState14(/* @__PURE__ */ new Set());
11900
+ const [stagingFields, setStagingFields] = useState14(/* @__PURE__ */ new Set());
11901
+ const [executedFields, setExecutedFields] = useState14(/* @__PURE__ */ new Set());
11902
+ const [highlightActions, setHighlightActions] = useState14(false);
11903
+ const [studioMode, setStudioMode] = useState14(false);
11904
+ const [recordingMode, setRecordingMode] = useState14(() => hasPersistedRecordingSession());
11905
+ const [voiceMuted, setVoiceMuted] = useState14(false);
11906
+ const [socketId, setSocketId] = useState14(null);
11907
+ const [actions, setActions] = useState14(/* @__PURE__ */ new Map());
11908
+ const [validatedBrowserDevMode, setValidatedBrowserDevMode] = useState14(false);
11909
+ const [resolvedDevModeKey, setResolvedDevModeKey] = useState14(() => resolveInjectedDevModeKey());
11910
+ const [previewRuntimeMode, setPreviewRuntimeMode] = useState14(() => hasDraftPreviewModeSignal());
11911
+ useEffect18(() => observeInjectedDevModeKey(setResolvedDevModeKey), []);
11912
+ useEffect18(() => observeDraftPreviewModeSignal(setPreviewRuntimeMode), []);
11913
+ useEffect18(() => {
12027
11914
  let cancelled = false;
12028
11915
  if (!websiteId || !resolvedDevModeKey) {
12029
11916
  setValidatedBrowserDevMode(false);
@@ -12040,14 +11927,14 @@ var ModelNexProvider = ({
12040
11927
  };
12041
11928
  }, [resolvedDevModeKey, serverUrl, websiteId]);
12042
11929
  const effectiveDevMode = validatedBrowserDevMode || previewRuntimeMode;
12043
- const registerAction = useCallback14((action) => {
11930
+ const registerAction = useCallback13((action) => {
12044
11931
  setActions((prev) => {
12045
11932
  const next = new Map(prev);
12046
11933
  next.set(action.id, action);
12047
11934
  return next;
12048
11935
  });
12049
11936
  }, []);
12050
- const unregisterAction = useCallback14((id) => {
11937
+ const unregisterAction = useCallback13((id) => {
12051
11938
  setActions((prev) => {
12052
11939
  const next = new Map(prev);
12053
11940
  next.delete(id);
@@ -12058,8 +11945,8 @@ var ModelNexProvider = ({
12058
11945
  const tagStore = useTagStore({ serverUrl, websiteId });
12059
11946
  useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl, websiteId, toursApiBase, userProfile);
12060
11947
  const CHAT_STORAGE_KEY = "modelnex-chat-messages";
12061
- const [chatMessages, setChatMessagesRaw] = useState15([]);
12062
- useEffect19(() => {
11948
+ const [chatMessages, setChatMessagesRaw] = useState14([]);
11949
+ useEffect18(() => {
12063
11950
  try {
12064
11951
  const stored = sessionStorage.getItem(CHAT_STORAGE_KEY);
12065
11952
  if (stored) {
@@ -12068,7 +11955,7 @@ var ModelNexProvider = ({
12068
11955
  } catch {
12069
11956
  }
12070
11957
  }, [effectiveDevMode]);
12071
- useEffect19(() => {
11958
+ useEffect18(() => {
12072
11959
  setChatMessagesRaw((prev) => {
12073
11960
  const next = sanitizeChatMessages(prev, effectiveDevMode);
12074
11961
  try {
@@ -12078,7 +11965,7 @@ var ModelNexProvider = ({
12078
11965
  return next;
12079
11966
  });
12080
11967
  }, [effectiveDevMode]);
12081
- const setChatMessages = useCallback14((action) => {
11968
+ const setChatMessages = useCallback13((action) => {
12082
11969
  setChatMessagesRaw((prev) => {
12083
11970
  const resolved = typeof action === "function" ? action(prev) : action;
12084
11971
  const next = sanitizeChatMessages(resolved, effectiveDevMode);
@@ -12104,14 +11991,14 @@ var ModelNexProvider = ({
12104
11991
  devMode: effectiveDevMode
12105
11992
  });
12106
11993
  useFieldHighlight(stagingFields, executedFields, setExecutedFields);
12107
- useEffect19(() => {
11994
+ useEffect18(() => {
12108
11995
  document.body.classList.toggle("modelnex-highlight-actions", highlightActions);
12109
11996
  return () => {
12110
11997
  document.body.classList.remove("modelnex-highlight-actions");
12111
11998
  };
12112
11999
  }, [highlightActions]);
12113
- const [mounted, setMounted] = useState15(false);
12114
- useEffect19(() => {
12000
+ const [mounted, setMounted] = useState14(false);
12001
+ useEffect18(() => {
12115
12002
  setMounted(true);
12116
12003
  }, []);
12117
12004
  const value = useMemo5(