@modelnex/sdk 0.5.43 → 0.5.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{aom-LJNCLNXL.mjs → aom-SP2LMWQI.mjs} +1 -1
- package/dist/chunk-SXGINP3O.mjs +683 -0
- package/dist/index.js +863 -708
- package/dist/index.mjs +494 -793
- package/package.json +1 -1
- package/dist/chunk-H4LUY7LI.mjs +0 -243
package/dist/index.js
CHANGED
|
@@ -30,763 +30,829 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
));
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
|
-
// src/utils/
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return
|
|
33
|
+
// src/utils/dev-logging.ts
|
|
34
|
+
function isSdkDebugEnabled(devMode) {
|
|
35
|
+
if (devMode) return true;
|
|
36
|
+
if (typeof window !== "undefined" && Boolean(window.MODELNEX_DEBUG)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return process.env.NODE_ENV === "development";
|
|
40
40
|
}
|
|
41
|
-
function
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
41
|
+
function emitSdkDebugLog(message, payload, options) {
|
|
42
|
+
if (!isSdkDebugEnabled(options?.devMode)) return;
|
|
43
|
+
if (payload && Object.keys(payload).length > 0) {
|
|
44
|
+
console.log(message, payload);
|
|
45
|
+
} else {
|
|
46
|
+
console.log(message);
|
|
47
|
+
}
|
|
48
|
+
if (options?.dispatchEvent && typeof window !== "undefined") {
|
|
49
|
+
window.dispatchEvent(new CustomEvent("modelnex-debug", { detail: { msg: message, data: payload } }));
|
|
45
50
|
}
|
|
46
|
-
return null;
|
|
47
51
|
}
|
|
48
|
-
function
|
|
49
|
-
if (!
|
|
50
|
-
|
|
51
|
-
if (inputCtor && element instanceof inputCtor) return true;
|
|
52
|
-
const textareaCtor = typeof HTMLTextAreaElement !== "undefined" ? HTMLTextAreaElement : null;
|
|
53
|
-
if (textareaCtor && element instanceof textareaCtor) return true;
|
|
54
|
-
const selectCtor = typeof HTMLSelectElement !== "undefined" ? HTMLSelectElement : null;
|
|
55
|
-
if (selectCtor && element instanceof selectCtor) return true;
|
|
56
|
-
return ["input", "textarea", "select"].includes(getTagName(element));
|
|
52
|
+
function sanitizeActionList(actions) {
|
|
53
|
+
if (!Array.isArray(actions) || actions.length === 0) return void 0;
|
|
54
|
+
return actions.map(({ actionId }) => ({ actionId }));
|
|
57
55
|
}
|
|
58
|
-
function
|
|
59
|
-
if (!
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
56
|
+
function sanitizeAgentDebug(debug) {
|
|
57
|
+
if (!debug) return void 0;
|
|
58
|
+
const actions = sanitizeActionList(debug.actions);
|
|
59
|
+
const traces = Array.isArray(debug.traces) && debug.traces.length > 0 ? debug.traces.map((trace) => ({
|
|
60
|
+
step: trace.step,
|
|
61
|
+
actions: sanitizeActionList(trace.actions) ?? [],
|
|
62
|
+
results: Array.isArray(trace.results) && trace.results.length > 0 ? trace.results.map(({ actionId, success }) => ({ actionId, success })) : void 0
|
|
63
|
+
})) : void 0;
|
|
64
|
+
if ((!actions || actions.length === 0) && (!traces || traces.length === 0)) {
|
|
65
|
+
return void 0;
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
return {
|
|
68
|
+
...actions ? { actions } : {},
|
|
69
|
+
...traces ? { traces } : {}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function sanitizeChatMessages(messages, devMode) {
|
|
73
|
+
const includeDebug = isSdkDebugEnabled(devMode);
|
|
74
|
+
return messages.map((message) => {
|
|
75
|
+
if (message.role !== "assistant") {
|
|
76
|
+
return message;
|
|
70
77
|
}
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
return {
|
|
79
|
+
...message,
|
|
80
|
+
debug: includeDebug ? sanitizeAgentDebug(message.debug) : void 0
|
|
81
|
+
};
|
|
82
|
+
});
|
|
73
83
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return resolveEditableControlElement(labelControl);
|
|
84
|
+
var init_dev_logging = __esm({
|
|
85
|
+
"src/utils/dev-logging.ts"() {
|
|
86
|
+
"use strict";
|
|
78
87
|
}
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// src/auto-extract.ts
|
|
91
|
+
function simpleHash(str) {
|
|
92
|
+
let hash = 0;
|
|
93
|
+
for (let i = 0; i < str.length; i++) {
|
|
94
|
+
const char = str.charCodeAt(i);
|
|
95
|
+
hash = (hash << 5) - hash + char;
|
|
96
|
+
hash |= 0;
|
|
81
97
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
99
|
+
}
|
|
100
|
+
function isStableDomId(id) {
|
|
101
|
+
if (!id) return false;
|
|
102
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
103
|
+
const REACT_USE_ID_RE = /^(?:radix-)?:[rR][^\s]*$/;
|
|
104
|
+
if (REACT_USE_ID_RE.test(id)) return false;
|
|
105
|
+
if (/^\d+$/.test(id)) return false;
|
|
106
|
+
if (UUID_RE.test(id)) return false;
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
function getNearestHeading(el) {
|
|
110
|
+
const shellContainer = el.closest('nav, aside, header, [role="navigation"], [role="complementary"], [role="banner"]');
|
|
111
|
+
const boundary = shellContainer || document.body;
|
|
112
|
+
let current = el;
|
|
113
|
+
while (current && current !== boundary) {
|
|
114
|
+
let sibling = current.previousElementSibling;
|
|
115
|
+
while (sibling) {
|
|
116
|
+
if (/^H[1-6]$/.test(sibling.tagName)) {
|
|
117
|
+
return sibling.textContent?.trim().slice(0, 100) || null;
|
|
118
|
+
}
|
|
119
|
+
const innerHeading = sibling.querySelector("h1, h2, h3, h4, h5, h6");
|
|
120
|
+
if (innerHeading) {
|
|
121
|
+
return innerHeading.textContent?.trim().slice(0, 100) || null;
|
|
122
|
+
}
|
|
123
|
+
sibling = sibling.previousElementSibling;
|
|
87
124
|
}
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return resolveEditableControlElement(nested);
|
|
125
|
+
const parentHeading = current.parentElement?.querySelector("h1, h2, h3, h4, h5, h6");
|
|
126
|
+
if (parentHeading && !current.contains(parentHeading)) {
|
|
127
|
+
return parentHeading.textContent?.trim().slice(0, 100) || null;
|
|
128
|
+
}
|
|
129
|
+
current = current.parentElement;
|
|
94
130
|
}
|
|
95
|
-
|
|
96
|
-
return shadowNested ?? element;
|
|
131
|
+
return null;
|
|
97
132
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
133
|
+
function getParentContainer(el) {
|
|
134
|
+
let current = el.parentElement;
|
|
135
|
+
while (current && current !== document.body) {
|
|
136
|
+
const role = current.getAttribute("role");
|
|
137
|
+
const tag = current.tagName.toLowerCase();
|
|
138
|
+
const state = current.getAttribute("data-state");
|
|
139
|
+
if (role === "dialog" || role === "alertdialog" || tag === "dialog") {
|
|
140
|
+
const title = current.querySelector('h2, h3, [class*="title"]');
|
|
141
|
+
const titleText = title?.textContent?.trim().slice(0, 60) || "";
|
|
142
|
+
return titleText ? `dialog:${titleText}` : "dialog";
|
|
105
143
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
144
|
+
if (role === "menu" || role === "listbox") {
|
|
145
|
+
return role;
|
|
146
|
+
}
|
|
147
|
+
if (current.hasAttribute("popover") || state === "open" && current.getAttribute("data-radix-popper-content-wrapper") !== null) {
|
|
148
|
+
return "popover";
|
|
149
|
+
}
|
|
150
|
+
if (current.getAttribute("data-radix-menu-content") !== null || role === "menubar") {
|
|
151
|
+
return "dropdown-menu";
|
|
152
|
+
}
|
|
153
|
+
if (role === "tabpanel") {
|
|
154
|
+
const label = current.getAttribute("aria-label") || current.getAttribute("aria-labelledby");
|
|
155
|
+
return label ? `tabpanel:${label.slice(0, 40)}` : "tabpanel";
|
|
156
|
+
}
|
|
157
|
+
if (tag === "nav" || role === "navigation") {
|
|
158
|
+
const label = current.getAttribute("aria-label");
|
|
159
|
+
return label ? `navigation:${label.slice(0, 40)}` : "navigation";
|
|
160
|
+
}
|
|
161
|
+
if (tag === "aside") {
|
|
162
|
+
return "sidebar";
|
|
163
|
+
}
|
|
164
|
+
if (tag === "header") {
|
|
165
|
+
return "header";
|
|
166
|
+
}
|
|
167
|
+
current = current.parentElement;
|
|
111
168
|
}
|
|
112
|
-
|
|
113
|
-
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function getRowContext(el) {
|
|
172
|
+
let current = el.parentElement;
|
|
173
|
+
while (current && current !== document.body) {
|
|
174
|
+
const tag = current.tagName.toLowerCase();
|
|
175
|
+
if (tag === "tr" || tag === "li" || current.getAttribute("role") === "row" || current.getAttribute("role") === "listitem") {
|
|
176
|
+
const rowText = current.textContent?.trim().replace(/\s+/g, " ").slice(0, 120) || "";
|
|
177
|
+
return rowText;
|
|
178
|
+
}
|
|
179
|
+
current = current.parentElement;
|
|
114
180
|
}
|
|
115
|
-
|
|
116
|
-
|
|
181
|
+
return "";
|
|
182
|
+
}
|
|
183
|
+
function getNearestAncestorId(el) {
|
|
184
|
+
let current = el.parentElement;
|
|
185
|
+
while (current && current !== document.body) {
|
|
186
|
+
const aid = current.id;
|
|
187
|
+
if (isStableDomId(aid)) {
|
|
188
|
+
return aid;
|
|
189
|
+
}
|
|
190
|
+
const ancestorTestId = current.getAttribute("data-testid");
|
|
191
|
+
if (ancestorTestId) return `[data-testid="${ancestorTestId}"]`;
|
|
192
|
+
current = current.parentElement;
|
|
117
193
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
function generateFingerprint(el) {
|
|
197
|
+
const tag = el.tagName.toLowerCase();
|
|
198
|
+
const testId = el.getAttribute("data-testid");
|
|
199
|
+
const id = el.id;
|
|
200
|
+
const name = el.getAttribute("name");
|
|
201
|
+
const ariaLabel = el.getAttribute("aria-label");
|
|
202
|
+
const type = el.type || "";
|
|
203
|
+
const text = el.textContent?.trim().slice(0, 80) || "";
|
|
204
|
+
if (testId) return `tid:${testId}`;
|
|
205
|
+
if (isStableDomId(id)) return `id:${id}`;
|
|
206
|
+
if (name) return `name:${tag}:${name}`;
|
|
207
|
+
if (ariaLabel) {
|
|
208
|
+
const rowCtx2 = getRowContext(el);
|
|
209
|
+
if (rowCtx2) {
|
|
210
|
+
return `aria:${simpleHash(ariaLabel + ":" + rowCtx2)}:${ariaLabel.slice(0, 40)}`;
|
|
211
|
+
}
|
|
212
|
+
return `aria:${simpleHash(ariaLabel)}:${ariaLabel.slice(0, 40)}`;
|
|
121
213
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
214
|
+
if (tag === "a") {
|
|
215
|
+
const href = el.getAttribute("href");
|
|
216
|
+
if (href && href !== "#" && !href.startsWith("javascript:")) {
|
|
217
|
+
return `href:${simpleHash(href + ":" + text)}:${text.slice(0, 30) || href.slice(0, 30)}`;
|
|
218
|
+
}
|
|
125
219
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const target = resolveEditableControlElement(element);
|
|
130
|
-
if (typeof target.placeholder === "string") {
|
|
131
|
-
return String(target.placeholder || "").trim().slice(0, 100);
|
|
220
|
+
const ancestorId = getNearestAncestorId(el);
|
|
221
|
+
if (ancestorId) {
|
|
222
|
+
return `anc:${simpleHash(ancestorId + ":" + tag + ":" + text)}:${text.slice(0, 30) || tag}`;
|
|
132
223
|
}
|
|
133
|
-
|
|
224
|
+
const heading = getNearestHeading(el) || "";
|
|
225
|
+
const rowCtx = getRowContext(el);
|
|
226
|
+
const raw = `${tag}:${type}:${text}:${heading}:${rowCtx}`;
|
|
227
|
+
return `hash:${simpleHash(raw)}:${text.slice(0, 30) || tag}`;
|
|
134
228
|
}
|
|
135
|
-
function
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return
|
|
142
|
-
|
|
143
|
-
|
|
229
|
+
function classifyRole(el) {
|
|
230
|
+
const tag = el.tagName.toLowerCase();
|
|
231
|
+
const role = el.getAttribute("role");
|
|
232
|
+
if (tag === "button" || role === "button") return "button";
|
|
233
|
+
if (tag === "a") return "link";
|
|
234
|
+
if (tag === "input") return "input";
|
|
235
|
+
if (tag === "textarea") return "textarea";
|
|
236
|
+
if (tag === "select") return "select";
|
|
237
|
+
if (tag === "form") return "form";
|
|
238
|
+
if (tag === "label") return "label";
|
|
239
|
+
if (role === "link") return "link";
|
|
240
|
+
if (role === "menuitem") return "menuitem";
|
|
241
|
+
if (role === "menuitemcheckbox") return "menuitem";
|
|
242
|
+
if (role === "menuitemradio") return "menuitem";
|
|
243
|
+
if (role === "tab") return "tab";
|
|
244
|
+
if (role === "checkbox") return "checkbox";
|
|
245
|
+
if (role === "radio") return "radio";
|
|
246
|
+
if (role === "switch") return "switch";
|
|
247
|
+
if (role === "slider") return "slider";
|
|
248
|
+
if (role === "combobox") return "combobox";
|
|
249
|
+
if (role === "option") return "option";
|
|
250
|
+
if (role === "treeitem") return "treeitem";
|
|
251
|
+
if (role === "gridcell") return "gridcell";
|
|
252
|
+
if (el.hasAttribute("tabindex") && el.getAttribute("tabindex") !== "-1") return "interactive";
|
|
253
|
+
if (el.hasAttribute("cmdk-item")) return "menuitem";
|
|
254
|
+
return null;
|
|
144
255
|
}
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
256
|
+
function isVisible(el) {
|
|
257
|
+
if (el.offsetParent === null) {
|
|
258
|
+
const computed = window.getComputedStyle(el);
|
|
259
|
+
if (computed.position !== "fixed" && computed.position !== "sticky") {
|
|
260
|
+
if (computed.display === "none" || computed.visibility === "hidden") {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
const rect2 = el.getBoundingClientRect();
|
|
264
|
+
if (rect2.width === 0 && rect2.height === 0) return false;
|
|
265
|
+
}
|
|
152
266
|
}
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
155
|
-
return
|
|
267
|
+
const style = window.getComputedStyle(el);
|
|
268
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
|
|
269
|
+
return false;
|
|
156
270
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
function isEditableControlDisabled(element) {
|
|
160
|
-
const target = resolveEditableControlElement(element);
|
|
161
|
-
const ariaDisabled = String(target.getAttribute("aria-disabled") || "").toLowerCase();
|
|
162
|
-
if (ariaDisabled === "true") return true;
|
|
163
|
-
return Boolean(target.disabled);
|
|
271
|
+
const rect = el.getBoundingClientRect();
|
|
272
|
+
return rect.width > 0 && rect.height > 0;
|
|
164
273
|
}
|
|
165
|
-
function
|
|
274
|
+
function extractInteractiveElements() {
|
|
275
|
+
const elements = [];
|
|
166
276
|
const seen = /* @__PURE__ */ new Set();
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
277
|
+
try {
|
|
278
|
+
const nodes = document.querySelectorAll(INTERACTIVE_SELECTOR);
|
|
279
|
+
nodes.forEach((node) => {
|
|
280
|
+
const el = node;
|
|
281
|
+
if (!isVisible(el)) return;
|
|
282
|
+
if (el.closest(".modelnex-chat-panel, .modelnex-studio-overlay, [data-modelnex-internal]")) return;
|
|
283
|
+
const role = classifyRole(el);
|
|
284
|
+
if (!role) return;
|
|
285
|
+
let fingerprint = generateFingerprint(el);
|
|
286
|
+
if (seen.has(fingerprint)) {
|
|
287
|
+
let idx = 2;
|
|
288
|
+
while (seen.has(`${fingerprint}#${idx}`)) idx++;
|
|
289
|
+
fingerprint = `${fingerprint}#${idx}`;
|
|
290
|
+
}
|
|
291
|
+
seen.add(fingerprint);
|
|
292
|
+
const rect = el.getBoundingClientRect();
|
|
293
|
+
const text = el.textContent?.trim().slice(0, 200) || "";
|
|
294
|
+
elements.push({
|
|
295
|
+
fingerprint,
|
|
296
|
+
tagName: el.tagName.toLowerCase(),
|
|
297
|
+
text,
|
|
298
|
+
role,
|
|
299
|
+
rect: {
|
|
300
|
+
top: rect.top,
|
|
301
|
+
left: rect.left,
|
|
302
|
+
width: rect.width,
|
|
303
|
+
height: rect.height
|
|
304
|
+
},
|
|
305
|
+
attributes: {
|
|
306
|
+
id: el.id || void 0,
|
|
307
|
+
name: el.getAttribute("name") || void 0,
|
|
308
|
+
type: el.type || void 0,
|
|
309
|
+
ariaLabel: el.getAttribute("aria-label") || void 0,
|
|
310
|
+
dataTestId: el.getAttribute("data-testid") || void 0,
|
|
311
|
+
href: el.href || void 0,
|
|
312
|
+
placeholder: el.placeholder || void 0
|
|
313
|
+
},
|
|
314
|
+
nearestHeading: getNearestHeading(el),
|
|
315
|
+
parentContainer: getParentContainer(el),
|
|
316
|
+
disabled: el.disabled || el.getAttribute("aria-disabled") === "true",
|
|
317
|
+
element: el
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
} catch (err) {
|
|
321
|
+
console.warn("[ModelNex] Auto-extraction error:", err);
|
|
176
322
|
}
|
|
177
|
-
return
|
|
323
|
+
return elements;
|
|
178
324
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
325
|
+
function useAutoExtract(devMode) {
|
|
326
|
+
const [elements, setElements] = (0, import_react2.useState)([]);
|
|
327
|
+
const timerRef = (0, import_react2.useRef)(null);
|
|
328
|
+
const lastSnapshotRef = (0, import_react2.useRef)("");
|
|
329
|
+
const scan = (0, import_react2.useCallback)(() => {
|
|
330
|
+
if (typeof document === "undefined") return;
|
|
331
|
+
const extracted = extractInteractiveElements();
|
|
332
|
+
const snapshot = JSON.stringify(extracted.map((e) => ({
|
|
333
|
+
fingerprint: e.fingerprint,
|
|
334
|
+
role: e.role,
|
|
335
|
+
text: e.text,
|
|
336
|
+
rect: e.rect,
|
|
337
|
+
disabled: e.disabled,
|
|
338
|
+
nearestHeading: e.nearestHeading,
|
|
339
|
+
parentContainer: e.parentContainer
|
|
340
|
+
})));
|
|
341
|
+
if (snapshot === lastSnapshotRef.current) return;
|
|
342
|
+
lastSnapshotRef.current = snapshot;
|
|
343
|
+
emitSdkDebugLog("[ModelNex AutoExtract] Scan complete", {
|
|
344
|
+
elementCount: extracted.length
|
|
345
|
+
}, { devMode });
|
|
346
|
+
setElements(extracted);
|
|
347
|
+
}, [devMode]);
|
|
348
|
+
(0, import_react2.useEffect)(() => {
|
|
349
|
+
const initialTimer = setTimeout(scan, 300);
|
|
350
|
+
const observer = new MutationObserver((mutations) => {
|
|
351
|
+
const hasRelevantMutation = mutations.some((mutation) => {
|
|
352
|
+
const target = mutation.target;
|
|
353
|
+
if (target?.closest?.(".modelnex-chat-panel, .modelnex-studio-overlay, [data-modelnex-internal]")) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
return true;
|
|
357
|
+
});
|
|
358
|
+
if (!hasRelevantMutation) return;
|
|
359
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
360
|
+
timerRef.current = setTimeout(scan, 500);
|
|
361
|
+
});
|
|
362
|
+
observer.observe(document.body, {
|
|
363
|
+
childList: true,
|
|
364
|
+
subtree: true,
|
|
365
|
+
attributes: true,
|
|
366
|
+
attributeFilter: ["disabled", "aria-disabled", "hidden", "style", "class"]
|
|
367
|
+
});
|
|
368
|
+
const handlePositionChange = () => {
|
|
369
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
370
|
+
timerRef.current = setTimeout(scan, 200);
|
|
371
|
+
};
|
|
372
|
+
window.addEventListener("scroll", handlePositionChange, { passive: true });
|
|
373
|
+
window.addEventListener("resize", handlePositionChange, { passive: true });
|
|
374
|
+
return () => {
|
|
375
|
+
clearTimeout(initialTimer);
|
|
376
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
377
|
+
observer.disconnect();
|
|
378
|
+
window.removeEventListener("scroll", handlePositionChange);
|
|
379
|
+
window.removeEventListener("resize", handlePositionChange);
|
|
380
|
+
};
|
|
381
|
+
}, [scan]);
|
|
382
|
+
return elements;
|
|
383
|
+
}
|
|
384
|
+
var import_react2, INTERACTIVE_SELECTOR;
|
|
385
|
+
var init_auto_extract = __esm({
|
|
386
|
+
"src/auto-extract.ts"() {
|
|
182
387
|
"use strict";
|
|
183
|
-
|
|
184
|
-
|
|
388
|
+
import_react2 = require("react");
|
|
389
|
+
init_dev_logging();
|
|
390
|
+
INTERACTIVE_SELECTOR = [
|
|
391
|
+
"button",
|
|
392
|
+
"a",
|
|
393
|
+
// All anchor tags (SPA links may not have href)
|
|
185
394
|
'input:not([type="hidden"])',
|
|
186
395
|
"textarea",
|
|
187
396
|
"select",
|
|
188
|
-
|
|
189
|
-
'[role="
|
|
190
|
-
'[role="
|
|
397
|
+
"label[for]",
|
|
398
|
+
'[role="button"]',
|
|
399
|
+
'[role="link"]',
|
|
400
|
+
'[role="menuitem"]',
|
|
401
|
+
'[role="menuitemcheckbox"]',
|
|
402
|
+
'[role="menuitemradio"]',
|
|
403
|
+
'[role="tab"]',
|
|
404
|
+
'[role="checkbox"]',
|
|
405
|
+
'[role="radio"]',
|
|
406
|
+
'[role="switch"]',
|
|
407
|
+
'[role="slider"]',
|
|
408
|
+
'[role="combobox"]',
|
|
409
|
+
'[role="option"]',
|
|
410
|
+
'[role="treeitem"]',
|
|
411
|
+
'[role="gridcell"]',
|
|
412
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
413
|
+
"[data-discover]",
|
|
414
|
+
// React Router links
|
|
415
|
+
"[cmdk-item]",
|
|
416
|
+
// cmdk menu items
|
|
417
|
+
"form"
|
|
191
418
|
].join(", ");
|
|
192
419
|
}
|
|
193
420
|
});
|
|
194
421
|
|
|
195
|
-
// src/utils/
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
422
|
+
// src/utils/editable-controls.ts
|
|
423
|
+
function getTagName(element) {
|
|
424
|
+
return String(element?.tagName || "").toLowerCase();
|
|
425
|
+
}
|
|
426
|
+
function getRole(element) {
|
|
427
|
+
const role = element && typeof element.getAttribute === "function" ? element.getAttribute("role") : null;
|
|
428
|
+
return String(role || "").toLowerCase();
|
|
429
|
+
}
|
|
430
|
+
function getLabelControl(element) {
|
|
431
|
+
const labelCtor = typeof HTMLLabelElement !== "undefined" ? HTMLLabelElement : null;
|
|
432
|
+
if (labelCtor && element instanceof labelCtor && element.control instanceof HTMLElement) {
|
|
433
|
+
return element.control;
|
|
434
|
+
}
|
|
435
|
+
return null;
|
|
436
|
+
}
|
|
437
|
+
function isValueBearingElement(element) {
|
|
438
|
+
if (!element) return false;
|
|
439
|
+
const inputCtor = typeof HTMLInputElement !== "undefined" ? HTMLInputElement : null;
|
|
440
|
+
if (inputCtor && element instanceof inputCtor) return true;
|
|
441
|
+
const textareaCtor = typeof HTMLTextAreaElement !== "undefined" ? HTMLTextAreaElement : null;
|
|
442
|
+
if (textareaCtor && element instanceof textareaCtor) return true;
|
|
443
|
+
const selectCtor = typeof HTMLSelectElement !== "undefined" ? HTMLSelectElement : null;
|
|
444
|
+
if (selectCtor && element instanceof selectCtor) return true;
|
|
445
|
+
return ["input", "textarea", "select"].includes(getTagName(element));
|
|
446
|
+
}
|
|
447
|
+
function findEditableControlInShadowRoot(root) {
|
|
448
|
+
if (!root) return null;
|
|
449
|
+
if (root.shadowRoot) {
|
|
450
|
+
const found = root.shadowRoot.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
451
|
+
if (found) {
|
|
452
|
+
return resolveEditableControlElement(found);
|
|
217
453
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
454
|
+
}
|
|
455
|
+
for (const child of Array.from(root.children)) {
|
|
456
|
+
if (child instanceof HTMLElement) {
|
|
457
|
+
const found = findEditableControlInShadowRoot(child);
|
|
458
|
+
if (found) return found;
|
|
221
459
|
}
|
|
222
|
-
if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
const uid = `node:${nextUid++}`;
|
|
226
|
-
uidMap.set(uid, el);
|
|
227
|
-
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
228
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
229
|
-
const placeholder = el.getAttribute("placeholder");
|
|
230
|
-
const value = readEditableControlValue(el, { maskPasswords: false }) || void 0;
|
|
231
|
-
let role = el.tagName.toLowerCase();
|
|
232
|
-
if (el.hasAttribute("role")) {
|
|
233
|
-
role = el.getAttribute("role");
|
|
234
|
-
} else if (role === "a") {
|
|
235
|
-
role = "link";
|
|
236
|
-
} else if (el.tagName.toLowerCase() === "input") {
|
|
237
|
-
const inputType = el.type;
|
|
238
|
-
role = inputType ? `input[${inputType}]` : "input";
|
|
239
|
-
}
|
|
240
|
-
const node = { uid, role };
|
|
241
|
-
const displayLabel = ariaLabel || text || placeholder;
|
|
242
|
-
if (displayLabel) {
|
|
243
|
-
node.text = displayLabel.substring(0, 100);
|
|
244
|
-
}
|
|
245
|
-
const controlName = readEditableControlName(el);
|
|
246
|
-
if (controlName) {
|
|
247
|
-
node.name = controlName;
|
|
248
|
-
}
|
|
249
|
-
if (value) {
|
|
250
|
-
node.value = value.substring(0, 100);
|
|
251
|
-
}
|
|
252
|
-
if (el instanceof HTMLAnchorElement && el.href) {
|
|
253
|
-
try {
|
|
254
|
-
const url = new URL(el.href);
|
|
255
|
-
node.href = url.pathname + url.search + url.hash;
|
|
256
|
-
} catch {
|
|
257
|
-
node.href = el.getAttribute("href");
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
nodes.push(node);
|
|
261
|
-
});
|
|
262
|
-
return { nodes };
|
|
263
|
-
}
|
|
264
|
-
function getElementByUid(uid) {
|
|
265
|
-
return uidMap.get(uid) || null;
|
|
266
|
-
}
|
|
267
|
-
function clearAOMMap() {
|
|
268
|
-
uidMap.clear();
|
|
269
|
-
nextUid = 1;
|
|
270
|
-
}
|
|
271
|
-
var uidMap, nextUid;
|
|
272
|
-
var init_aom = __esm({
|
|
273
|
-
"src/utils/aom.ts"() {
|
|
274
|
-
"use strict";
|
|
275
|
-
init_editable_controls();
|
|
276
|
-
uidMap = /* @__PURE__ */ new Map();
|
|
277
|
-
nextUid = 1;
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// src/utils/dom-sync.ts
|
|
282
|
-
var dom_sync_exports = {};
|
|
283
|
-
__export(dom_sync_exports, {
|
|
284
|
-
waitForDomSettle: () => waitForDomSettle
|
|
285
|
-
});
|
|
286
|
-
function waitForDomSettle(options = {}) {
|
|
287
|
-
const { timeoutMs = 5e3, debounceMs = 400, minWaitMs = 100 } = options;
|
|
288
|
-
return new Promise((resolve) => {
|
|
289
|
-
let debounceTimer = null;
|
|
290
|
-
let resolved = false;
|
|
291
|
-
const maxTimer = setTimeout(() => {
|
|
292
|
-
if (!resolved) {
|
|
293
|
-
resolved = true;
|
|
294
|
-
cleanup();
|
|
295
|
-
resolve();
|
|
296
|
-
}
|
|
297
|
-
}, Math.max(timeoutMs, minWaitMs));
|
|
298
|
-
const finish = () => {
|
|
299
|
-
if (!resolved) {
|
|
300
|
-
resolved = true;
|
|
301
|
-
cleanup();
|
|
302
|
-
resolve();
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
const observer = new MutationObserver((mutations) => {
|
|
306
|
-
const hasSignificantMutations = mutations.some((m) => {
|
|
307
|
-
if (m.target instanceof HTMLElement) {
|
|
308
|
-
if (m.target.hasAttribute("data-modelnex-tour-highlight")) return false;
|
|
309
|
-
if (m.target.hasAttribute("data-modelnex-caption")) return false;
|
|
310
|
-
if (m.target.closest("#modelnex-studio-root")) return false;
|
|
311
|
-
if (m.target.closest("#modelnex-active-agent-root")) return false;
|
|
312
|
-
}
|
|
313
|
-
return true;
|
|
314
|
-
});
|
|
315
|
-
if (!hasSignificantMutations) return;
|
|
316
|
-
if (debounceTimer) clearTimeout(debounceTimer);
|
|
317
|
-
debounceTimer = setTimeout(finish, debounceMs);
|
|
318
|
-
});
|
|
319
|
-
const cleanup = () => {
|
|
320
|
-
observer.disconnect();
|
|
321
|
-
if (debounceTimer) clearTimeout(debounceTimer);
|
|
322
|
-
clearTimeout(maxTimer);
|
|
323
|
-
};
|
|
324
|
-
setTimeout(() => {
|
|
325
|
-
if (resolved) return;
|
|
326
|
-
observer.observe(document.body, {
|
|
327
|
-
childList: true,
|
|
328
|
-
subtree: true,
|
|
329
|
-
attributes: true,
|
|
330
|
-
characterData: true
|
|
331
|
-
});
|
|
332
|
-
debounceTimer = setTimeout(finish, debounceMs);
|
|
333
|
-
}, minWaitMs);
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
var init_dom_sync = __esm({
|
|
337
|
-
"src/utils/dom-sync.ts"() {
|
|
338
|
-
"use strict";
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
// src/index.ts
|
|
343
|
-
var index_exports = {};
|
|
344
|
-
__export(index_exports, {
|
|
345
|
-
DEFAULT_MODELNEX_SERVER_URL: () => DEFAULT_MODELNEX_SERVER_URL,
|
|
346
|
-
ModelNexChatBubble: () => ModelNexChatBubble,
|
|
347
|
-
ModelNexOnboardingPanel: () => ModelNexOnboardingPanel,
|
|
348
|
-
ModelNexProvider: () => ModelNexProvider,
|
|
349
|
-
RecordingOverlay: () => RecordingOverlay,
|
|
350
|
-
StudioOverlay: () => StudioOverlay,
|
|
351
|
-
TourProgressPanel: () => TourProgressPanel,
|
|
352
|
-
UIStateProvider: () => UIStateProvider,
|
|
353
|
-
buildDraftPreviewUrl: () => buildDraftPreviewUrl,
|
|
354
|
-
buildRecordingCapturePayload: () => buildRecordingCapturePayload,
|
|
355
|
-
buildRecordingStepGoal: () => buildRecordingStepGoal,
|
|
356
|
-
clearActiveDraftPreview: () => clearActiveDraftPreview,
|
|
357
|
-
extractInteractiveElements: () => extractInteractiveElements,
|
|
358
|
-
generateFingerprint: () => generateFingerprint,
|
|
359
|
-
getPreviewQueryParamName: () => getPreviewQueryParamName,
|
|
360
|
-
getRecordingDraftActionLabel: () => getRecordingDraftActionLabel,
|
|
361
|
-
getRecordingDraftStatusMessage: () => getRecordingDraftStatusMessage,
|
|
362
|
-
hasDraftPreviewModeSignal: () => hasDraftPreviewModeSignal,
|
|
363
|
-
inferOnboardingMetadataForStep: () => inferOnboardingMetadataForStep,
|
|
364
|
-
isAskDrivenInputStepType: () => isAskDrivenInputStepType,
|
|
365
|
-
isInteractiveInputStepType: () => isInteractiveInputStepType,
|
|
366
|
-
isManualOnboardingStep: () => isManualOnboardingStep,
|
|
367
|
-
isRecordingDraftGenerating: () => isRecordingDraftGenerating,
|
|
368
|
-
observeDraftPreviewModeSignal: () => observeDraftPreviewModeSignal,
|
|
369
|
-
persistActiveDraftPreview: () => persistActiveDraftPreview,
|
|
370
|
-
readActiveDraftPreview: () => readActiveDraftPreview,
|
|
371
|
-
shouldPromptForPreviewStart: () => shouldPromptForPreviewStart,
|
|
372
|
-
shouldShowRecordingOverlay: () => shouldShowRecordingOverlay,
|
|
373
|
-
useActionHighlight: () => useActionHighlight,
|
|
374
|
-
useAgentViewport: () => useAgentViewport,
|
|
375
|
-
useAutoExtract: () => useAutoExtract,
|
|
376
|
-
useExperiencePlayback: () => useExperiencePlayback,
|
|
377
|
-
useOnboardingPlayback: () => useOnboardingPlayback,
|
|
378
|
-
useRecordingMode: () => useRecordingMode,
|
|
379
|
-
useRunCommand: () => useRunCommand,
|
|
380
|
-
useTagStore: () => useTagStore,
|
|
381
|
-
useTourPlayback: () => useTourPlayback,
|
|
382
|
-
useUIState: () => useUIState,
|
|
383
|
-
useViewportTrack: () => useViewportTrack,
|
|
384
|
-
useVisibleIds: () => useVisibleIds,
|
|
385
|
-
useVoice: () => useVoice
|
|
386
|
-
});
|
|
387
|
-
module.exports = __toCommonJS(index_exports);
|
|
388
|
-
var import_react21 = __toESM(require("react"));
|
|
389
|
-
|
|
390
|
-
// src/context.ts
|
|
391
|
-
var import_react = require("react");
|
|
392
|
-
var ModelNexContext = (0, import_react.createContext)(null);
|
|
393
|
-
|
|
394
|
-
// src/hooks/useModelNexSocket.ts
|
|
395
|
-
var import_react3 = require("react");
|
|
396
|
-
var import_socket = require("socket.io-client");
|
|
397
|
-
|
|
398
|
-
// src/utils/socket-io-transports.ts
|
|
399
|
-
function resolveSocketIoTransports(serverUrl, order) {
|
|
400
|
-
try {
|
|
401
|
-
const host = new URL(serverUrl).hostname.toLowerCase();
|
|
402
|
-
if (host.endsWith("awsapprunner.com")) {
|
|
403
|
-
return ["websocket"];
|
|
404
|
-
}
|
|
405
|
-
} catch {
|
|
406
460
|
}
|
|
407
|
-
return
|
|
461
|
+
return null;
|
|
408
462
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
// src/utils/dev-logging.ts
|
|
414
|
-
function isSdkDebugEnabled(devMode) {
|
|
415
|
-
if (devMode) return true;
|
|
416
|
-
if (typeof window !== "undefined" && Boolean(window.MODELNEX_DEBUG)) {
|
|
417
|
-
return true;
|
|
463
|
+
function resolveEditableControlElement(element) {
|
|
464
|
+
const labelControl = getLabelControl(element);
|
|
465
|
+
if (labelControl) {
|
|
466
|
+
return resolveEditableControlElement(labelControl);
|
|
418
467
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
function emitSdkDebugLog(message, payload, options) {
|
|
422
|
-
if (!isSdkDebugEnabled(options?.devMode)) return;
|
|
423
|
-
if (payload && Object.keys(payload).length > 0) {
|
|
424
|
-
console.log(message, payload);
|
|
425
|
-
} else {
|
|
426
|
-
console.log(message);
|
|
468
|
+
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
469
|
+
return element;
|
|
427
470
|
}
|
|
428
|
-
|
|
429
|
-
|
|
471
|
+
const role = getRole(element);
|
|
472
|
+
if (EDITABLE_ROLES.has(role)) {
|
|
473
|
+
const nested2 = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
474
|
+
if (nested2 && nested2 !== element) {
|
|
475
|
+
return resolveEditableControlElement(nested2);
|
|
476
|
+
}
|
|
477
|
+
const shadowNested2 = findEditableControlInShadowRoot(element);
|
|
478
|
+
return shadowNested2 ?? element;
|
|
430
479
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
return actions.map(({ actionId }) => ({ actionId }));
|
|
435
|
-
}
|
|
436
|
-
function sanitizeAgentDebug(debug) {
|
|
437
|
-
if (!debug) return void 0;
|
|
438
|
-
const actions = sanitizeActionList(debug.actions);
|
|
439
|
-
const traces = Array.isArray(debug.traces) && debug.traces.length > 0 ? debug.traces.map((trace) => ({
|
|
440
|
-
step: trace.step,
|
|
441
|
-
actions: sanitizeActionList(trace.actions) ?? [],
|
|
442
|
-
results: Array.isArray(trace.results) && trace.results.length > 0 ? trace.results.map(({ actionId, success }) => ({ actionId, success })) : void 0
|
|
443
|
-
})) : void 0;
|
|
444
|
-
if ((!actions || actions.length === 0) && (!traces || traces.length === 0)) {
|
|
445
|
-
return void 0;
|
|
480
|
+
const nested = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
481
|
+
if (nested) {
|
|
482
|
+
return resolveEditableControlElement(nested);
|
|
446
483
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
...traces ? { traces } : {}
|
|
450
|
-
};
|
|
484
|
+
const shadowNested = findEditableControlInShadowRoot(element);
|
|
485
|
+
return shadowNested ?? element;
|
|
451
486
|
}
|
|
452
|
-
function
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
487
|
+
function readEditableControlValue(element, options = {}) {
|
|
488
|
+
const target = resolveEditableControlElement(element);
|
|
489
|
+
const maskPasswords = options.maskPasswords !== false;
|
|
490
|
+
if (isValueBearingElement(target)) {
|
|
491
|
+
const type = String(target.type || "").toLowerCase();
|
|
492
|
+
if (maskPasswords && type === "password") {
|
|
493
|
+
return "***";
|
|
457
494
|
}
|
|
458
|
-
return
|
|
459
|
-
...message,
|
|
460
|
-
debug: includeDebug ? sanitizeAgentDebug(message.debug) : void 0
|
|
461
|
-
};
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/auto-extract.ts
|
|
466
|
-
function simpleHash(str) {
|
|
467
|
-
let hash = 0;
|
|
468
|
-
for (let i = 0; i < str.length; i++) {
|
|
469
|
-
const char = str.charCodeAt(i);
|
|
470
|
-
hash = (hash << 5) - hash + char;
|
|
471
|
-
hash |= 0;
|
|
495
|
+
return String(target.value || "").trim().slice(0, 100);
|
|
472
496
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if (!id) return false;
|
|
477
|
-
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
478
|
-
const REACT_USE_ID_RE = /^(?:radix-)?:[rR][^\s]*$/;
|
|
479
|
-
if (REACT_USE_ID_RE.test(id)) return false;
|
|
480
|
-
if (/^\d+$/.test(id)) return false;
|
|
481
|
-
if (UUID_RE.test(id)) return false;
|
|
482
|
-
return true;
|
|
483
|
-
}
|
|
484
|
-
function getNearestHeading(el) {
|
|
485
|
-
const shellContainer = el.closest('nav, aside, header, [role="navigation"], [role="complementary"], [role="banner"]');
|
|
486
|
-
const boundary = shellContainer || document.body;
|
|
487
|
-
let current = el;
|
|
488
|
-
while (current && current !== boundary) {
|
|
489
|
-
let sibling = current.previousElementSibling;
|
|
490
|
-
while (sibling) {
|
|
491
|
-
if (/^H[1-6]$/.test(sibling.tagName)) {
|
|
492
|
-
return sibling.textContent?.trim().slice(0, 100) || null;
|
|
493
|
-
}
|
|
494
|
-
const innerHeading = sibling.querySelector("h1, h2, h3, h4, h5, h6");
|
|
495
|
-
if (innerHeading) {
|
|
496
|
-
return innerHeading.textContent?.trim().slice(0, 100) || null;
|
|
497
|
-
}
|
|
498
|
-
sibling = sibling.previousElementSibling;
|
|
499
|
-
}
|
|
500
|
-
const parentHeading = current.parentElement?.querySelector("h1, h2, h3, h4, h5, h6");
|
|
501
|
-
if (parentHeading && !current.contains(parentHeading)) {
|
|
502
|
-
return parentHeading.textContent?.trim().slice(0, 100) || null;
|
|
503
|
-
}
|
|
504
|
-
current = current.parentElement;
|
|
497
|
+
const genericValue = target.value;
|
|
498
|
+
if (typeof genericValue === "string") {
|
|
499
|
+
return genericValue.trim().slice(0, 100);
|
|
505
500
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
const role = current.getAttribute("role");
|
|
512
|
-
const tag = current.tagName.toLowerCase();
|
|
513
|
-
const state = current.getAttribute("data-state");
|
|
514
|
-
if (role === "dialog" || role === "alertdialog" || tag === "dialog") {
|
|
515
|
-
const title = current.querySelector('h2, h3, [class*="title"]');
|
|
516
|
-
const titleText = title?.textContent?.trim().slice(0, 60) || "";
|
|
517
|
-
return titleText ? `dialog:${titleText}` : "dialog";
|
|
518
|
-
}
|
|
519
|
-
if (role === "menu" || role === "listbox") {
|
|
520
|
-
return role;
|
|
521
|
-
}
|
|
522
|
-
if (current.hasAttribute("popover") || state === "open" && current.getAttribute("data-radix-popper-content-wrapper") !== null) {
|
|
523
|
-
return "popover";
|
|
524
|
-
}
|
|
525
|
-
if (current.getAttribute("data-radix-menu-content") !== null || role === "menubar") {
|
|
526
|
-
return "dropdown-menu";
|
|
527
|
-
}
|
|
528
|
-
if (role === "tabpanel") {
|
|
529
|
-
const label = current.getAttribute("aria-label") || current.getAttribute("aria-labelledby");
|
|
530
|
-
return label ? `tabpanel:${label.slice(0, 40)}` : "tabpanel";
|
|
531
|
-
}
|
|
532
|
-
if (tag === "nav" || role === "navigation") {
|
|
533
|
-
const label = current.getAttribute("aria-label");
|
|
534
|
-
return label ? `navigation:${label.slice(0, 40)}` : "navigation";
|
|
535
|
-
}
|
|
536
|
-
if (tag === "aside") {
|
|
537
|
-
return "sidebar";
|
|
538
|
-
}
|
|
539
|
-
if (tag === "header") {
|
|
540
|
-
return "header";
|
|
541
|
-
}
|
|
542
|
-
current = current.parentElement;
|
|
501
|
+
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
502
|
+
return String(genericValue).trim().slice(0, 100);
|
|
503
|
+
}
|
|
504
|
+
if (target.isContentEditable) {
|
|
505
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
543
506
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
let current = el.parentElement;
|
|
548
|
-
while (current && current !== document.body) {
|
|
549
|
-
const tag = current.tagName.toLowerCase();
|
|
550
|
-
if (tag === "tr" || tag === "li" || current.getAttribute("role") === "row" || current.getAttribute("role") === "listitem") {
|
|
551
|
-
const rowText = current.textContent?.trim().replace(/\s+/g, " ").slice(0, 120) || "";
|
|
552
|
-
return rowText;
|
|
553
|
-
}
|
|
554
|
-
current = current.parentElement;
|
|
507
|
+
const ariaValueText = target.getAttribute("aria-valuetext");
|
|
508
|
+
if (ariaValueText?.trim()) {
|
|
509
|
+
return ariaValueText.trim().slice(0, 100);
|
|
555
510
|
}
|
|
556
|
-
|
|
511
|
+
const ariaValueNow = target.getAttribute("aria-valuenow");
|
|
512
|
+
if (ariaValueNow?.trim()) {
|
|
513
|
+
return ariaValueNow.trim().slice(0, 100);
|
|
514
|
+
}
|
|
515
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
557
516
|
}
|
|
558
|
-
function
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
if (isStableDomId(aid)) {
|
|
563
|
-
return aid;
|
|
564
|
-
}
|
|
565
|
-
const ancestorTestId = current.getAttribute("data-testid");
|
|
566
|
-
if (ancestorTestId) return `[data-testid="${ancestorTestId}"]`;
|
|
567
|
-
current = current.parentElement;
|
|
517
|
+
function readEditableControlPlaceholder(element) {
|
|
518
|
+
const target = resolveEditableControlElement(element);
|
|
519
|
+
if (typeof target.placeholder === "string") {
|
|
520
|
+
return String(target.placeholder || "").trim().slice(0, 100);
|
|
568
521
|
}
|
|
569
|
-
return
|
|
522
|
+
return String(target.getAttribute("placeholder") || "").trim().slice(0, 100);
|
|
570
523
|
}
|
|
571
|
-
function
|
|
572
|
-
const
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
577
|
-
const type = el.type || "";
|
|
578
|
-
const text = el.textContent?.trim().slice(0, 80) || "";
|
|
579
|
-
if (testId) return `tid:${testId}`;
|
|
580
|
-
if (isStableDomId(id)) return `id:${id}`;
|
|
581
|
-
if (name) return `name:${tag}:${name}`;
|
|
582
|
-
if (ariaLabel) {
|
|
583
|
-
const rowCtx2 = getRowContext(el);
|
|
584
|
-
if (rowCtx2) {
|
|
585
|
-
return `aria:${simpleHash(ariaLabel + ":" + rowCtx2)}:${ariaLabel.slice(0, 40)}`;
|
|
586
|
-
}
|
|
587
|
-
return `aria:${simpleHash(ariaLabel)}:${ariaLabel.slice(0, 40)}`;
|
|
524
|
+
function readEditableControlName(element) {
|
|
525
|
+
const target = resolveEditableControlElement(element);
|
|
526
|
+
const explicitName = target.name;
|
|
527
|
+
if (typeof explicitName === "string" && explicitName.trim()) {
|
|
528
|
+
return explicitName.trim().slice(0, 100);
|
|
588
529
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
530
|
+
return String(
|
|
531
|
+
target.getAttribute("name") || target.getAttribute("id") || target.getAttribute("aria-label") || ""
|
|
532
|
+
).trim().slice(0, 100);
|
|
533
|
+
}
|
|
534
|
+
function readEditableControlType(element) {
|
|
535
|
+
const target = resolveEditableControlElement(element);
|
|
536
|
+
const role = getRole(target);
|
|
537
|
+
if (role) return role;
|
|
538
|
+
const explicitType = target.type;
|
|
539
|
+
if (typeof explicitType === "string" && explicitType.trim()) {
|
|
540
|
+
return explicitType.trim().toLowerCase().slice(0, 50);
|
|
594
541
|
}
|
|
595
|
-
const
|
|
596
|
-
if (
|
|
597
|
-
return
|
|
542
|
+
const attributeType = target.getAttribute("type");
|
|
543
|
+
if (attributeType?.trim()) {
|
|
544
|
+
return attributeType.trim().toLowerCase().slice(0, 50);
|
|
598
545
|
}
|
|
599
|
-
|
|
600
|
-
const rowCtx = getRowContext(el);
|
|
601
|
-
const raw = `${tag}:${type}:${text}:${heading}:${rowCtx}`;
|
|
602
|
-
return `hash:${simpleHash(raw)}:${text.slice(0, 30) || tag}`;
|
|
546
|
+
return getTagName(target);
|
|
603
547
|
}
|
|
604
|
-
function
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
if (
|
|
608
|
-
|
|
609
|
-
if (tag === "input") return "input";
|
|
610
|
-
if (tag === "textarea") return "textarea";
|
|
611
|
-
if (tag === "select") return "select";
|
|
612
|
-
if (tag === "form") return "form";
|
|
613
|
-
if (tag === "label") return "label";
|
|
614
|
-
if (role === "link") return "link";
|
|
615
|
-
if (role === "menuitem") return "menuitem";
|
|
616
|
-
if (role === "menuitemcheckbox") return "menuitem";
|
|
617
|
-
if (role === "menuitemradio") return "menuitem";
|
|
618
|
-
if (role === "tab") return "tab";
|
|
619
|
-
if (role === "checkbox") return "checkbox";
|
|
620
|
-
if (role === "radio") return "radio";
|
|
621
|
-
if (role === "switch") return "switch";
|
|
622
|
-
if (role === "slider") return "slider";
|
|
623
|
-
if (role === "combobox") return "combobox";
|
|
624
|
-
if (role === "option") return "option";
|
|
625
|
-
if (role === "treeitem") return "treeitem";
|
|
626
|
-
if (role === "gridcell") return "gridcell";
|
|
627
|
-
if (el.hasAttribute("tabindex") && el.getAttribute("tabindex") !== "-1") return "interactive";
|
|
628
|
-
if (el.hasAttribute("cmdk-item")) return "menuitem";
|
|
629
|
-
return null;
|
|
548
|
+
function isEditableControlDisabled(element) {
|
|
549
|
+
const target = resolveEditableControlElement(element);
|
|
550
|
+
const ariaDisabled = String(target.getAttribute("aria-disabled") || "").toLowerCase();
|
|
551
|
+
if (ariaDisabled === "true") return true;
|
|
552
|
+
return Boolean(target.disabled);
|
|
630
553
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
'[role="button"]',
|
|
640
|
-
'[role="link"]',
|
|
641
|
-
'[role="menuitem"]',
|
|
642
|
-
'[role="menuitemcheckbox"]',
|
|
643
|
-
'[role="menuitemradio"]',
|
|
644
|
-
'[role="tab"]',
|
|
645
|
-
'[role="checkbox"]',
|
|
646
|
-
'[role="radio"]',
|
|
647
|
-
'[role="switch"]',
|
|
648
|
-
'[role="slider"]',
|
|
649
|
-
'[role="combobox"]',
|
|
650
|
-
'[role="option"]',
|
|
651
|
-
'[role="treeitem"]',
|
|
652
|
-
'[role="gridcell"]',
|
|
653
|
-
'[tabindex]:not([tabindex="-1"])',
|
|
654
|
-
"[data-discover]",
|
|
655
|
-
// React Router links
|
|
656
|
-
"[cmdk-item]",
|
|
657
|
-
// cmdk menu items
|
|
658
|
-
"form"
|
|
659
|
-
].join(", ");
|
|
660
|
-
function isVisible(el) {
|
|
661
|
-
if (el.offsetParent === null) {
|
|
662
|
-
const computed = window.getComputedStyle(el);
|
|
663
|
-
if (computed.position !== "fixed" && computed.position !== "sticky") {
|
|
664
|
-
if (computed.display === "none" || computed.visibility === "hidden") {
|
|
665
|
-
return false;
|
|
666
|
-
}
|
|
667
|
-
const rect2 = el.getBoundingClientRect();
|
|
668
|
-
if (rect2.width === 0 && rect2.height === 0) return false;
|
|
554
|
+
function collectEditableControls(scope) {
|
|
555
|
+
const seen = /* @__PURE__ */ new Set();
|
|
556
|
+
const controls = [];
|
|
557
|
+
for (const rawElement of Array.from(scope.querySelectorAll(EDITABLE_CONTROL_SELECTOR))) {
|
|
558
|
+
const resolved = resolveEditableControlElement(rawElement);
|
|
559
|
+
if (seen.has(resolved)) continue;
|
|
560
|
+
if (isValueBearingElement(resolved) && String(resolved.type || "").toLowerCase() === "hidden") {
|
|
561
|
+
continue;
|
|
669
562
|
}
|
|
563
|
+
seen.add(resolved);
|
|
564
|
+
controls.push(resolved);
|
|
670
565
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
566
|
+
return controls;
|
|
567
|
+
}
|
|
568
|
+
var EDITABLE_ROLES, EDITABLE_CONTROL_SELECTOR;
|
|
569
|
+
var init_editable_controls = __esm({
|
|
570
|
+
"src/utils/editable-controls.ts"() {
|
|
571
|
+
"use strict";
|
|
572
|
+
EDITABLE_ROLES = /* @__PURE__ */ new Set(["textbox", "combobox"]);
|
|
573
|
+
EDITABLE_CONTROL_SELECTOR = [
|
|
574
|
+
'input:not([type="hidden"])',
|
|
575
|
+
"textarea",
|
|
576
|
+
"select",
|
|
577
|
+
'[contenteditable="true"]',
|
|
578
|
+
'[role="textbox"]',
|
|
579
|
+
'[role="combobox"]'
|
|
580
|
+
].join(", ");
|
|
674
581
|
}
|
|
675
|
-
|
|
676
|
-
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// src/utils/aom.ts
|
|
585
|
+
var aom_exports = {};
|
|
586
|
+
__export(aom_exports, {
|
|
587
|
+
clearAOMMap: () => clearAOMMap,
|
|
588
|
+
generateMinifiedAOM: () => generateMinifiedAOM,
|
|
589
|
+
getElementByUid: () => getElementByUid
|
|
590
|
+
});
|
|
591
|
+
function normalizeUidText(value) {
|
|
592
|
+
return String(value || "").replace(/\s+/g, " ").trim().slice(0, 120);
|
|
677
593
|
}
|
|
678
|
-
function
|
|
679
|
-
const
|
|
680
|
-
const
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
594
|
+
function buildStableUidLocator(el) {
|
|
595
|
+
const tag = el.tagName.toLowerCase();
|
|
596
|
+
const role = normalizeUidText(el.getAttribute("role"));
|
|
597
|
+
const testId = normalizeUidText(el.getAttribute("data-testid"));
|
|
598
|
+
const fingerprint = normalizeUidText(generateFingerprint(el));
|
|
599
|
+
const controlName = normalizeUidText(readEditableControlName(el));
|
|
600
|
+
const ariaLabel = normalizeUidText(el.getAttribute("aria-label"));
|
|
601
|
+
const placeholder = normalizeUidText(readEditableControlPlaceholder(el));
|
|
602
|
+
const inputType = normalizeUidText(el.type || el.getAttribute("type"));
|
|
603
|
+
const href = el instanceof HTMLAnchorElement ? normalizeUidText(el.getAttribute("href")) : "";
|
|
604
|
+
return [
|
|
605
|
+
tag,
|
|
606
|
+
role,
|
|
607
|
+
testId,
|
|
608
|
+
fingerprint,
|
|
609
|
+
controlName,
|
|
610
|
+
ariaLabel,
|
|
611
|
+
placeholder,
|
|
612
|
+
inputType,
|
|
613
|
+
href
|
|
614
|
+
].join("::");
|
|
615
|
+
}
|
|
616
|
+
function allocateUid() {
|
|
617
|
+
return `node:${nextUid++}`;
|
|
618
|
+
}
|
|
619
|
+
function resolveStableUid(el, activeUids) {
|
|
620
|
+
const existingElementUid = elementUidMap.get(el);
|
|
621
|
+
if (existingElementUid && !activeUids.has(existingElementUid)) {
|
|
622
|
+
return existingElementUid;
|
|
623
|
+
}
|
|
624
|
+
const locatorKey = buildStableUidLocator(el);
|
|
625
|
+
const existingLocatorUid = locatorUidMap.get(locatorKey);
|
|
626
|
+
if (existingLocatorUid && !activeUids.has(existingLocatorUid)) {
|
|
627
|
+
elementUidMap.set(el, existingLocatorUid);
|
|
628
|
+
return existingLocatorUid;
|
|
629
|
+
}
|
|
630
|
+
const uid = allocateUid();
|
|
631
|
+
elementUidMap.set(el, uid);
|
|
632
|
+
if (locatorKey) {
|
|
633
|
+
locatorUidMap.set(locatorKey, uid);
|
|
634
|
+
}
|
|
635
|
+
return uid;
|
|
636
|
+
}
|
|
637
|
+
function generateMinifiedAOM() {
|
|
638
|
+
const interactiveSet = /* @__PURE__ */ new Set();
|
|
639
|
+
const activeUids = /* @__PURE__ */ new Set();
|
|
640
|
+
const nextUidMap = /* @__PURE__ */ new Map();
|
|
641
|
+
const interactiveCandidates = [
|
|
642
|
+
...Array.from(document.querySelectorAll(
|
|
643
|
+
'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], [role="textbox"], [role="combobox"], [contenteditable="true"]'
|
|
644
|
+
)),
|
|
645
|
+
...collectEditableControls(document)
|
|
646
|
+
];
|
|
647
|
+
const nodes = [];
|
|
648
|
+
interactiveCandidates.forEach((candidate) => {
|
|
649
|
+
const el = resolveEditableControlElement(candidate);
|
|
650
|
+
if (interactiveSet.has(el)) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
interactiveSet.add(el);
|
|
654
|
+
if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const uid = resolveStableUid(el, activeUids);
|
|
661
|
+
activeUids.add(uid);
|
|
662
|
+
nextUidMap.set(uid, el);
|
|
663
|
+
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
664
|
+
const ariaLabel = el.getAttribute("aria-label");
|
|
665
|
+
const placeholder = el.getAttribute("placeholder");
|
|
666
|
+
const value = readEditableControlValue(el, { maskPasswords: false }) || void 0;
|
|
667
|
+
let role = el.tagName.toLowerCase();
|
|
668
|
+
if (el.hasAttribute("role")) {
|
|
669
|
+
role = el.getAttribute("role");
|
|
670
|
+
} else if (role === "a") {
|
|
671
|
+
role = "link";
|
|
672
|
+
} else if (el.tagName.toLowerCase() === "input") {
|
|
673
|
+
const inputType = el.type;
|
|
674
|
+
role = inputType ? `input[${inputType}]` : "input";
|
|
675
|
+
}
|
|
676
|
+
const node = { uid, role };
|
|
677
|
+
const displayLabel = ariaLabel || text || placeholder;
|
|
678
|
+
if (displayLabel) {
|
|
679
|
+
node.text = displayLabel.substring(0, 100);
|
|
680
|
+
}
|
|
681
|
+
const controlName = readEditableControlName(el);
|
|
682
|
+
if (controlName) {
|
|
683
|
+
node.name = controlName;
|
|
684
|
+
}
|
|
685
|
+
if (value) {
|
|
686
|
+
node.value = value.substring(0, 100);
|
|
687
|
+
}
|
|
688
|
+
if (el instanceof HTMLAnchorElement && el.href) {
|
|
689
|
+
try {
|
|
690
|
+
const url = new URL(el.href);
|
|
691
|
+
node.href = url.pathname + url.search + url.hash;
|
|
692
|
+
} catch {
|
|
693
|
+
node.href = el.getAttribute("href");
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
nodes.push(node);
|
|
697
|
+
});
|
|
698
|
+
uidMap.clear();
|
|
699
|
+
for (const [uid, el] of nextUidMap.entries()) {
|
|
700
|
+
uidMap.set(uid, el);
|
|
726
701
|
}
|
|
727
|
-
return
|
|
702
|
+
return { nodes };
|
|
728
703
|
}
|
|
729
|
-
function
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
704
|
+
function getElementByUid(uid) {
|
|
705
|
+
return uidMap.get(uid) || null;
|
|
706
|
+
}
|
|
707
|
+
function clearAOMMap() {
|
|
708
|
+
uidMap.clear();
|
|
709
|
+
locatorUidMap.clear();
|
|
710
|
+
nextUid = 1;
|
|
711
|
+
}
|
|
712
|
+
var uidMap, elementUidMap, locatorUidMap, nextUid;
|
|
713
|
+
var init_aom = __esm({
|
|
714
|
+
"src/utils/aom.ts"() {
|
|
715
|
+
"use strict";
|
|
716
|
+
init_editable_controls();
|
|
717
|
+
init_auto_extract();
|
|
718
|
+
uidMap = /* @__PURE__ */ new Map();
|
|
719
|
+
elementUidMap = /* @__PURE__ */ new WeakMap();
|
|
720
|
+
locatorUidMap = /* @__PURE__ */ new Map();
|
|
721
|
+
nextUid = 1;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
// src/utils/dom-sync.ts
|
|
726
|
+
var dom_sync_exports = {};
|
|
727
|
+
__export(dom_sync_exports, {
|
|
728
|
+
waitForDomSettle: () => waitForDomSettle
|
|
729
|
+
});
|
|
730
|
+
function waitForDomSettle(options = {}) {
|
|
731
|
+
const { timeoutMs = 5e3, debounceMs = 400, minWaitMs = 100 } = options;
|
|
732
|
+
return new Promise((resolve) => {
|
|
733
|
+
let debounceTimer = null;
|
|
734
|
+
let resolved = false;
|
|
735
|
+
const maxTimer = setTimeout(() => {
|
|
736
|
+
if (!resolved) {
|
|
737
|
+
resolved = true;
|
|
738
|
+
cleanup();
|
|
739
|
+
resolve();
|
|
740
|
+
}
|
|
741
|
+
}, Math.max(timeoutMs, minWaitMs));
|
|
742
|
+
const finish = () => {
|
|
743
|
+
if (!resolved) {
|
|
744
|
+
resolved = true;
|
|
745
|
+
cleanup();
|
|
746
|
+
resolve();
|
|
747
|
+
}
|
|
748
|
+
};
|
|
754
749
|
const observer = new MutationObserver((mutations) => {
|
|
755
|
-
const
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
return false;
|
|
750
|
+
const hasSignificantMutations = mutations.some((m) => {
|
|
751
|
+
if (m.target instanceof HTMLElement) {
|
|
752
|
+
if (m.target.hasAttribute("data-modelnex-tour-highlight")) return false;
|
|
753
|
+
if (m.target.hasAttribute("data-modelnex-caption")) return false;
|
|
754
|
+
if (m.target.closest("#modelnex-studio-root")) return false;
|
|
755
|
+
if (m.target.closest("#modelnex-active-agent-root")) return false;
|
|
759
756
|
}
|
|
760
757
|
return true;
|
|
761
758
|
});
|
|
762
|
-
if (!
|
|
763
|
-
if (
|
|
764
|
-
|
|
765
|
-
});
|
|
766
|
-
observer.observe(document.body, {
|
|
767
|
-
childList: true,
|
|
768
|
-
subtree: true,
|
|
769
|
-
attributes: true,
|
|
770
|
-
attributeFilter: ["disabled", "aria-disabled", "hidden", "style", "class"]
|
|
759
|
+
if (!hasSignificantMutations) return;
|
|
760
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
761
|
+
debounceTimer = setTimeout(finish, debounceMs);
|
|
771
762
|
});
|
|
772
|
-
const
|
|
773
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
774
|
-
timerRef.current = setTimeout(scan, 200);
|
|
775
|
-
};
|
|
776
|
-
window.addEventListener("scroll", handlePositionChange, { passive: true });
|
|
777
|
-
window.addEventListener("resize", handlePositionChange, { passive: true });
|
|
778
|
-
return () => {
|
|
779
|
-
clearTimeout(initialTimer);
|
|
780
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
763
|
+
const cleanup = () => {
|
|
781
764
|
observer.disconnect();
|
|
782
|
-
|
|
783
|
-
|
|
765
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
766
|
+
clearTimeout(maxTimer);
|
|
784
767
|
};
|
|
785
|
-
|
|
786
|
-
|
|
768
|
+
setTimeout(() => {
|
|
769
|
+
if (resolved) return;
|
|
770
|
+
observer.observe(document.body, {
|
|
771
|
+
childList: true,
|
|
772
|
+
subtree: true,
|
|
773
|
+
attributes: true,
|
|
774
|
+
characterData: true
|
|
775
|
+
});
|
|
776
|
+
debounceTimer = setTimeout(finish, debounceMs);
|
|
777
|
+
}, minWaitMs);
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
var init_dom_sync = __esm({
|
|
781
|
+
"src/utils/dom-sync.ts"() {
|
|
782
|
+
"use strict";
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// src/index.ts
|
|
787
|
+
var index_exports = {};
|
|
788
|
+
__export(index_exports, {
|
|
789
|
+
DEFAULT_MODELNEX_SERVER_URL: () => DEFAULT_MODELNEX_SERVER_URL,
|
|
790
|
+
ModelNexChatBubble: () => ModelNexChatBubble,
|
|
791
|
+
ModelNexOnboardingPanel: () => ModelNexOnboardingPanel,
|
|
792
|
+
ModelNexProvider: () => ModelNexProvider,
|
|
793
|
+
RecordingOverlay: () => RecordingOverlay,
|
|
794
|
+
StudioOverlay: () => StudioOverlay,
|
|
795
|
+
TourProgressPanel: () => TourProgressPanel,
|
|
796
|
+
UIStateProvider: () => UIStateProvider,
|
|
797
|
+
buildDraftPreviewUrl: () => buildDraftPreviewUrl,
|
|
798
|
+
buildRecordingCapturePayload: () => buildRecordingCapturePayload,
|
|
799
|
+
buildRecordingStepGoal: () => buildRecordingStepGoal,
|
|
800
|
+
clearActiveDraftPreview: () => clearActiveDraftPreview,
|
|
801
|
+
extractInteractiveElements: () => extractInteractiveElements,
|
|
802
|
+
generateFingerprint: () => generateFingerprint,
|
|
803
|
+
getPreviewQueryParamName: () => getPreviewQueryParamName,
|
|
804
|
+
getRecordingDraftActionLabel: () => getRecordingDraftActionLabel,
|
|
805
|
+
getRecordingDraftStatusMessage: () => getRecordingDraftStatusMessage,
|
|
806
|
+
hasDraftPreviewModeSignal: () => hasDraftPreviewModeSignal,
|
|
807
|
+
inferOnboardingMetadataForStep: () => inferOnboardingMetadataForStep,
|
|
808
|
+
isAskDrivenInputStepType: () => isAskDrivenInputStepType,
|
|
809
|
+
isInteractiveInputStepType: () => isInteractiveInputStepType,
|
|
810
|
+
isManualOnboardingStep: () => isManualOnboardingStep,
|
|
811
|
+
isRecordingDraftGenerating: () => isRecordingDraftGenerating,
|
|
812
|
+
observeDraftPreviewModeSignal: () => observeDraftPreviewModeSignal,
|
|
813
|
+
persistActiveDraftPreview: () => persistActiveDraftPreview,
|
|
814
|
+
readActiveDraftPreview: () => readActiveDraftPreview,
|
|
815
|
+
shouldPromptForPreviewStart: () => shouldPromptForPreviewStart,
|
|
816
|
+
shouldShowRecordingOverlay: () => shouldShowRecordingOverlay,
|
|
817
|
+
useActionHighlight: () => useActionHighlight,
|
|
818
|
+
useAgentViewport: () => useAgentViewport,
|
|
819
|
+
useAutoExtract: () => useAutoExtract,
|
|
820
|
+
useExperiencePlayback: () => useExperiencePlayback,
|
|
821
|
+
useOnboardingPlayback: () => useOnboardingPlayback,
|
|
822
|
+
useRecordingMode: () => useRecordingMode,
|
|
823
|
+
useRunCommand: () => useRunCommand,
|
|
824
|
+
useTagStore: () => useTagStore,
|
|
825
|
+
useTourPlayback: () => useTourPlayback,
|
|
826
|
+
useUIState: () => useUIState,
|
|
827
|
+
useViewportTrack: () => useViewportTrack,
|
|
828
|
+
useVisibleIds: () => useVisibleIds,
|
|
829
|
+
useVoice: () => useVoice
|
|
830
|
+
});
|
|
831
|
+
module.exports = __toCommonJS(index_exports);
|
|
832
|
+
var import_react21 = __toESM(require("react"));
|
|
833
|
+
|
|
834
|
+
// src/context.ts
|
|
835
|
+
var import_react = require("react");
|
|
836
|
+
var ModelNexContext = (0, import_react.createContext)(null);
|
|
837
|
+
|
|
838
|
+
// src/hooks/useModelNexSocket.ts
|
|
839
|
+
var import_react3 = require("react");
|
|
840
|
+
var import_socket = require("socket.io-client");
|
|
841
|
+
|
|
842
|
+
// src/utils/socket-io-transports.ts
|
|
843
|
+
function resolveSocketIoTransports(serverUrl, order) {
|
|
844
|
+
try {
|
|
845
|
+
const host = new URL(serverUrl).hostname.toLowerCase();
|
|
846
|
+
if (host.endsWith("awsapprunner.com")) {
|
|
847
|
+
return ["websocket"];
|
|
848
|
+
}
|
|
849
|
+
} catch {
|
|
850
|
+
}
|
|
851
|
+
return ["websocket", "polling"];
|
|
787
852
|
}
|
|
788
853
|
|
|
789
854
|
// src/utils/dom-summary.ts
|
|
855
|
+
init_auto_extract();
|
|
790
856
|
init_editable_controls();
|
|
791
857
|
function textOf(el) {
|
|
792
858
|
return el?.textContent?.trim().slice(0, 200) ?? "";
|
|
@@ -1052,6 +1118,7 @@ function serializeContexts(contexts) {
|
|
|
1052
1118
|
}
|
|
1053
1119
|
|
|
1054
1120
|
// src/hooks/useModelNexSocket.ts
|
|
1121
|
+
init_dev_logging();
|
|
1055
1122
|
function useModelNexSocket({
|
|
1056
1123
|
serverUrl,
|
|
1057
1124
|
actions,
|
|
@@ -1270,6 +1337,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
|
|
|
1270
1337
|
|
|
1271
1338
|
// src/overlay.tsx
|
|
1272
1339
|
var import_react5 = __toESM(require("react"));
|
|
1340
|
+
init_auto_extract();
|
|
1273
1341
|
var AIActivityOverlay = ({ activeActions }) => {
|
|
1274
1342
|
if (activeActions.size === 0) return null;
|
|
1275
1343
|
return import_react5.default.createElement(
|
|
@@ -1465,6 +1533,9 @@ body.modelnex-highlight-actions [data-modelnex-action-id]::before {
|
|
|
1465
1533
|
}
|
|
1466
1534
|
`;
|
|
1467
1535
|
|
|
1536
|
+
// src/index.ts
|
|
1537
|
+
init_auto_extract();
|
|
1538
|
+
|
|
1468
1539
|
// src/tag-store.ts
|
|
1469
1540
|
var import_react6 = require("react");
|
|
1470
1541
|
var STORAGE_KEY = "modelnex-tags";
|
|
@@ -1614,6 +1685,7 @@ function useTagStore(options) {
|
|
|
1614
1685
|
|
|
1615
1686
|
// src/studio-mode.tsx
|
|
1616
1687
|
var import_react7 = require("react");
|
|
1688
|
+
init_auto_extract();
|
|
1617
1689
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1618
1690
|
var CATEGORIES = [
|
|
1619
1691
|
{ value: "button", label: "Button" },
|
|
@@ -2038,10 +2110,22 @@ function StudioOverlay({ elements, tagStore }) {
|
|
|
2038
2110
|
// src/hooks/useBuiltinActions.ts
|
|
2039
2111
|
var import_react8 = require("react");
|
|
2040
2112
|
var import_zod2 = require("zod");
|
|
2113
|
+
init_auto_extract();
|
|
2041
2114
|
|
|
2042
2115
|
// src/utils/screenshot.ts
|
|
2043
2116
|
var import_html2canvas = __toESM(require("html2canvas"));
|
|
2044
|
-
|
|
2117
|
+
var SCREENSHOT_SCALE_BY_RESOLUTION = {
|
|
2118
|
+
low: 0.75,
|
|
2119
|
+
medium: 1.25,
|
|
2120
|
+
high: 2
|
|
2121
|
+
};
|
|
2122
|
+
function normalizeScreenshotResolution(resolution) {
|
|
2123
|
+
return resolution === "low" || resolution === "high" || resolution === "medium" ? resolution : "medium";
|
|
2124
|
+
}
|
|
2125
|
+
function resolveScreenshotScale(resolution) {
|
|
2126
|
+
return SCREENSHOT_SCALE_BY_RESOLUTION[normalizeScreenshotResolution(resolution)];
|
|
2127
|
+
}
|
|
2128
|
+
async function captureScreenshot(selector, resolution) {
|
|
2045
2129
|
const target = selector ? document.querySelector(selector) : document.documentElement;
|
|
2046
2130
|
if (!target || !(target instanceof HTMLElement)) {
|
|
2047
2131
|
throw new Error(`Screenshot target not found: ${selector ?? "document"}`);
|
|
@@ -2049,7 +2133,7 @@ async function captureScreenshot(selector) {
|
|
|
2049
2133
|
const canvas = await (0, import_html2canvas.default)(target, {
|
|
2050
2134
|
useCORS: true,
|
|
2051
2135
|
allowTaint: true,
|
|
2052
|
-
scale:
|
|
2136
|
+
scale: resolveScreenshotScale(resolution),
|
|
2053
2137
|
width: window.innerWidth,
|
|
2054
2138
|
height: window.innerHeight,
|
|
2055
2139
|
x: window.scrollX,
|
|
@@ -2512,14 +2596,15 @@ async function resolveWorkflowFromInput(getters, params) {
|
|
|
2512
2596
|
return { workflow: ranked[0].workflow };
|
|
2513
2597
|
}
|
|
2514
2598
|
var screenshotSchema = import_zod2.z.object({
|
|
2515
|
-
selector: import_zod2.z.string().optional().describe("Optional CSS selector to capture a specific element. Omit to capture the full viewport.")
|
|
2599
|
+
selector: import_zod2.z.string().optional().describe("Optional CSS selector to capture a specific element. Omit to capture the full viewport."),
|
|
2600
|
+
resolution: import_zod2.z.enum(["low", "medium", "high"]).optional().describe("Optional screenshot resolution. Use low for smaller/faster captures, medium for the default balance, or high for extra detail.")
|
|
2516
2601
|
});
|
|
2517
2602
|
var BUILTIN_SCREENSHOT_ACTION = {
|
|
2518
2603
|
id: "take_screenshot",
|
|
2519
2604
|
description: "Take a screenshot of the current page (or a specific element via CSS selector). Returns a base64 PNG image. Use when you need to see the current UI state, verify a visual change, or when the user asks you to look at the screen.",
|
|
2520
2605
|
schema: screenshotSchema,
|
|
2521
2606
|
execute: async (params) => {
|
|
2522
|
-
return await captureScreenshot(params.selector);
|
|
2607
|
+
return await captureScreenshot(params.selector, params.resolution);
|
|
2523
2608
|
}
|
|
2524
2609
|
};
|
|
2525
2610
|
var clickElementSchema = import_zod2.z.object({
|
|
@@ -2928,6 +3013,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
|
|
|
2928
3013
|
// src/constants.ts
|
|
2929
3014
|
var DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
|
|
2930
3015
|
|
|
3016
|
+
// src/index.ts
|
|
3017
|
+
init_dev_logging();
|
|
3018
|
+
|
|
2931
3019
|
// src/utils/dev-mode.ts
|
|
2932
3020
|
var DEV_MODE_KEY_GLOBAL_NAMES = ["__MODELNEX_DEV_MODE_KEY__", "MODELNEX_DEV_MODE_KEY"];
|
|
2933
3021
|
var devModeValidationCache = /* @__PURE__ */ new Map();
|
|
@@ -3243,6 +3331,7 @@ function readPreviewSessionSuppression() {
|
|
|
3243
3331
|
|
|
3244
3332
|
// src/hooks/useRunCommand.ts
|
|
3245
3333
|
var import_react9 = require("react");
|
|
3334
|
+
init_dev_logging();
|
|
3246
3335
|
function searchTaggedElementsForQuery(store, query, limit = 8) {
|
|
3247
3336
|
const allTags = store.getAllTags();
|
|
3248
3337
|
if (allTags.length === 0) return [];
|
|
@@ -3529,6 +3618,54 @@ function compactTourForTransport(tour) {
|
|
|
3529
3618
|
};
|
|
3530
3619
|
}
|
|
3531
3620
|
|
|
3621
|
+
// src/utils/tourSessionPersistence.ts
|
|
3622
|
+
var ACTIVE_TOUR_SESSION_STORAGE_KEY = "modelnex-active-tour-session";
|
|
3623
|
+
var ACTIVE_TOUR_SESSION_VERSION = 1;
|
|
3624
|
+
var ACTIVE_TOUR_SESSION_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
3625
|
+
function canUseSessionStorage2() {
|
|
3626
|
+
return typeof window !== "undefined" && typeof window.sessionStorage !== "undefined";
|
|
3627
|
+
}
|
|
3628
|
+
function persistActiveTourSession(runId) {
|
|
3629
|
+
if (!canUseSessionStorage2() || !Number.isFinite(runId)) return;
|
|
3630
|
+
const session = {
|
|
3631
|
+
version: ACTIVE_TOUR_SESSION_VERSION,
|
|
3632
|
+
runId,
|
|
3633
|
+
savedAt: Date.now()
|
|
3634
|
+
};
|
|
3635
|
+
try {
|
|
3636
|
+
window.sessionStorage.setItem(ACTIVE_TOUR_SESSION_STORAGE_KEY, JSON.stringify(session));
|
|
3637
|
+
} catch {
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
function clearPersistedActiveTourSession() {
|
|
3641
|
+
if (!canUseSessionStorage2()) return;
|
|
3642
|
+
try {
|
|
3643
|
+
window.sessionStorage.removeItem(ACTIVE_TOUR_SESSION_STORAGE_KEY);
|
|
3644
|
+
} catch {
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
function readPersistedActiveTourSession() {
|
|
3648
|
+
if (!canUseSessionStorage2()) return null;
|
|
3649
|
+
try {
|
|
3650
|
+
const raw = window.sessionStorage.getItem(ACTIVE_TOUR_SESSION_STORAGE_KEY);
|
|
3651
|
+
if (!raw) return null;
|
|
3652
|
+
const parsed = JSON.parse(raw);
|
|
3653
|
+
const isValid = parsed && parsed.version === ACTIVE_TOUR_SESSION_VERSION && typeof parsed.runId === "number" && Number.isFinite(parsed.runId) && typeof parsed.savedAt === "number" && Number.isFinite(parsed.savedAt);
|
|
3654
|
+
if (!isValid) {
|
|
3655
|
+
clearPersistedActiveTourSession();
|
|
3656
|
+
return null;
|
|
3657
|
+
}
|
|
3658
|
+
if (Date.now() - parsed.savedAt > ACTIVE_TOUR_SESSION_MAX_AGE_MS) {
|
|
3659
|
+
clearPersistedActiveTourSession();
|
|
3660
|
+
return null;
|
|
3661
|
+
}
|
|
3662
|
+
return parsed;
|
|
3663
|
+
} catch {
|
|
3664
|
+
clearPersistedActiveTourSession();
|
|
3665
|
+
return null;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3532
3669
|
// src/hooks/useTourPlayback.ts
|
|
3533
3670
|
init_editable_controls();
|
|
3534
3671
|
|
|
@@ -3578,6 +3715,7 @@ function releaseTourPlaybackOwnership(key, ownerId) {
|
|
|
3578
3715
|
}
|
|
3579
3716
|
|
|
3580
3717
|
// src/hooks/useTourPlayback.ts
|
|
3718
|
+
init_dev_logging();
|
|
3581
3719
|
function resolveElement(step) {
|
|
3582
3720
|
const el = step.element;
|
|
3583
3721
|
if (!el) return null;
|
|
@@ -4143,7 +4281,8 @@ function useTourPlayback({
|
|
|
4143
4281
|
const pendingTourRef = (0, import_react12.useRef)(null);
|
|
4144
4282
|
const pendingTourOptionsRef = (0, import_react12.useRef)(null);
|
|
4145
4283
|
const showCaptionsRef = (0, import_react12.useRef)(showCaptions);
|
|
4146
|
-
const
|
|
4284
|
+
const initialPersistedTourSessionRef = (0, import_react12.useRef)(readPersistedActiveTourSession());
|
|
4285
|
+
const runIdRef = (0, import_react12.useRef)(initialPersistedTourSessionRef.current?.runId ?? null);
|
|
4147
4286
|
const turnIdRef = (0, import_react12.useRef)(null);
|
|
4148
4287
|
const startRequestedRef = (0, import_react12.useRef)(false);
|
|
4149
4288
|
const playbackOwnerIdRef = (0, import_react12.useRef)(`playback-owner-${Math.random().toString(36).slice(2, 10)}`);
|
|
@@ -4171,6 +4310,19 @@ function useTourPlayback({
|
|
|
4171
4310
|
releaseTourPlaybackOwnership(claimedKey, playbackOwnerIdRef.current);
|
|
4172
4311
|
claimedPlaybackOwnerKeyRef.current = null;
|
|
4173
4312
|
}, []);
|
|
4313
|
+
const emitTourInit = (0, import_react12.useCallback)((socket, currentWebsiteId, profile) => {
|
|
4314
|
+
if (!currentWebsiteId || !profile?.type) return;
|
|
4315
|
+
const persistedRunId = runIdRef.current ?? readPersistedActiveTourSession()?.runId ?? null;
|
|
4316
|
+
const payload = {
|
|
4317
|
+
websiteId: currentWebsiteId,
|
|
4318
|
+
userId: profile.userId,
|
|
4319
|
+
userType: profile.type
|
|
4320
|
+
};
|
|
4321
|
+
if (typeof persistedRunId === "number") {
|
|
4322
|
+
payload.resumeRunId = persistedRunId;
|
|
4323
|
+
}
|
|
4324
|
+
emitSocketEvent(socket, "tour:init", payload);
|
|
4325
|
+
}, []);
|
|
4174
4326
|
(0, import_react12.useEffect)(() => {
|
|
4175
4327
|
if (disabled) return;
|
|
4176
4328
|
if (typeof window === "undefined") return;
|
|
@@ -4182,9 +4334,7 @@ function useTourPlayback({
|
|
|
4182
4334
|
}, { devMode: devModeRef.current });
|
|
4183
4335
|
const profile = userProfileRef.current;
|
|
4184
4336
|
const currentWebsiteId = websiteIdRef.current;
|
|
4185
|
-
|
|
4186
|
-
emitSocketEvent(socket, "tour:init", { websiteId: currentWebsiteId, userId: profile.userId, userType: profile.type });
|
|
4187
|
-
}
|
|
4337
|
+
emitTourInit(socket, currentWebsiteId, profile);
|
|
4188
4338
|
};
|
|
4189
4339
|
const handleServerState = (payload) => {
|
|
4190
4340
|
if (typeof payload?.runId === "number") {
|
|
@@ -4193,6 +4343,11 @@ function useTourPlayback({
|
|
|
4193
4343
|
if (typeof payload?.turnId === "string" || payload?.turnId === null) {
|
|
4194
4344
|
turnIdRef.current = payload.turnId ?? null;
|
|
4195
4345
|
}
|
|
4346
|
+
if (payload?.isActive && typeof payload?.runId === "number") {
|
|
4347
|
+
persistActiveTourSession(payload.runId);
|
|
4348
|
+
} else if (payload?.isActive === false) {
|
|
4349
|
+
clearPersistedActiveTourSession();
|
|
4350
|
+
}
|
|
4196
4351
|
setServerState(payload);
|
|
4197
4352
|
};
|
|
4198
4353
|
const handleCommandCancel = (payload) => {
|
|
@@ -4456,19 +4611,9 @@ function useTourPlayback({
|
|
|
4456
4611
|
return { result: value };
|
|
4457
4612
|
}
|
|
4458
4613
|
if (action.type === "take_screenshot") {
|
|
4459
|
-
const
|
|
4460
|
-
const
|
|
4461
|
-
|
|
4462
|
-
useCORS: true,
|
|
4463
|
-
allowTaint: true,
|
|
4464
|
-
scale: Math.min(window.devicePixelRatio, 2),
|
|
4465
|
-
width: window.innerWidth,
|
|
4466
|
-
height: window.innerHeight,
|
|
4467
|
-
x: window.scrollX,
|
|
4468
|
-
y: window.scrollY,
|
|
4469
|
-
logging: false
|
|
4470
|
-
});
|
|
4471
|
-
return { result: canvas.toDataURL("image/png") };
|
|
4614
|
+
const selector = typeof action.params?.selector === "string" ? action.params.selector : void 0;
|
|
4615
|
+
const resolution = typeof action.params?.resolution === "string" ? action.params.resolution : void 0;
|
|
4616
|
+
return { result: await captureScreenshot(selector, resolution) };
|
|
4472
4617
|
}
|
|
4473
4618
|
if (action.type === "navigate_to_url") {
|
|
4474
4619
|
const nextUrl = typeof action.params?.url === "string" ? action.params.url : "";
|
|
@@ -4760,6 +4905,9 @@ function useTourPlayback({
|
|
|
4760
4905
|
const handleTourStart = async (tourData) => {
|
|
4761
4906
|
if (isActiveRef.current) return;
|
|
4762
4907
|
runIdRef.current = typeof tourData.runId === "number" ? tourData.runId : runIdRef.current;
|
|
4908
|
+
if (typeof runIdRef.current === "number") {
|
|
4909
|
+
persistActiveTourSession(runIdRef.current);
|
|
4910
|
+
}
|
|
4763
4911
|
const tour = tourData.tourContext ?? tourRef.current;
|
|
4764
4912
|
const expType = experienceTypeRef.current;
|
|
4765
4913
|
if (tour?.type && tour.type !== expType) {
|
|
@@ -4835,6 +4983,7 @@ function useTourPlayback({
|
|
|
4835
4983
|
}
|
|
4836
4984
|
};
|
|
4837
4985
|
const handleTourEndEvent = () => {
|
|
4986
|
+
clearPersistedActiveTourSession();
|
|
4838
4987
|
setServerState((prev) => prev ? { ...prev, isActive: false, phase: "completed" } : prev);
|
|
4839
4988
|
handleTourEnd();
|
|
4840
4989
|
};
|
|
@@ -4884,17 +5033,17 @@ function useTourPlayback({
|
|
|
4884
5033
|
releasePlaybackOwnership();
|
|
4885
5034
|
tourSocketPool.release(serverUrl, toClose);
|
|
4886
5035
|
};
|
|
4887
|
-
}, [serverUrl, disabled, releasePlaybackOwnership]);
|
|
5036
|
+
}, [serverUrl, disabled, emitTourInit, releasePlaybackOwnership]);
|
|
4888
5037
|
(0, import_react12.useEffect)(() => {
|
|
4889
5038
|
if (disabled) return;
|
|
4890
5039
|
const s = socketRef.current;
|
|
4891
5040
|
const profile = userProfile;
|
|
4892
5041
|
if (!websiteId || !profile?.type) return;
|
|
4893
5042
|
const timer = setTimeout(() => {
|
|
4894
|
-
|
|
5043
|
+
emitTourInit(s, websiteId, profile);
|
|
4895
5044
|
}, 150);
|
|
4896
5045
|
return () => clearTimeout(timer);
|
|
4897
|
-
}, [disabled, websiteId, userProfile?.userId, userProfile?.type]);
|
|
5046
|
+
}, [disabled, emitTourInit, websiteId, userProfile?.userId, userProfile?.type]);
|
|
4898
5047
|
(0, import_react12.useEffect)(() => {
|
|
4899
5048
|
if (!showCaptions || !isReviewMode) {
|
|
4900
5049
|
removeCaption();
|
|
@@ -5013,6 +5162,7 @@ function useTourPlayback({
|
|
|
5013
5162
|
tourRef.current = null;
|
|
5014
5163
|
setPlaybackState("idle");
|
|
5015
5164
|
setServerState(null);
|
|
5165
|
+
clearPersistedActiveTourSession();
|
|
5016
5166
|
runIdRef.current = null;
|
|
5017
5167
|
turnIdRef.current = null;
|
|
5018
5168
|
setPreviewRunId(null);
|
|
@@ -5042,6 +5192,7 @@ function useTourPlayback({
|
|
|
5042
5192
|
tourRef.current = null;
|
|
5043
5193
|
setPlaybackState("idle");
|
|
5044
5194
|
setServerState(null);
|
|
5195
|
+
clearPersistedActiveTourSession();
|
|
5045
5196
|
runIdRef.current = null;
|
|
5046
5197
|
turnIdRef.current = null;
|
|
5047
5198
|
setPreviewRunId(null);
|
|
@@ -6926,6 +7077,7 @@ function useAudioLevel(active) {
|
|
|
6926
7077
|
|
|
6927
7078
|
// src/hooks/useRecordingMode.ts
|
|
6928
7079
|
var import_react16 = require("react");
|
|
7080
|
+
init_auto_extract();
|
|
6929
7081
|
|
|
6930
7082
|
// src/utils/tourStepTypes.ts
|
|
6931
7083
|
function isAskDrivenInputStepType(stepType) {
|
|
@@ -12225,6 +12377,9 @@ function useActionHighlight() {
|
|
|
12225
12377
|
};
|
|
12226
12378
|
}
|
|
12227
12379
|
|
|
12380
|
+
// src/index.ts
|
|
12381
|
+
init_auto_extract();
|
|
12382
|
+
|
|
12228
12383
|
// src/hooks/useExperiencePlayback.ts
|
|
12229
12384
|
function useExperiencePlayback(...args) {
|
|
12230
12385
|
return useTourPlayback(...args);
|