@modelnex/sdk 0.5.44 → 0.5.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{aom-LJNCLNXL.mjs → aom-SP2LMWQI.mjs} +1 -1
- package/dist/chunk-SXGINP3O.mjs +683 -0
- package/dist/index.js +755 -673
- package/dist/index.mjs +400 -772
- package/package.json +1 -1
- package/dist/chunk-H4LUY7LI.mjs +0 -243
package/dist/index.js
CHANGED
|
@@ -30,200 +30,636 @@ 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
|
-
|
|
460
|
+
}
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
function resolveEditableControlElement(element) {
|
|
464
|
+
const labelControl = getLabelControl(element);
|
|
465
|
+
if (labelControl) {
|
|
466
|
+
return resolveEditableControlElement(labelControl);
|
|
467
|
+
}
|
|
468
|
+
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
469
|
+
return element;
|
|
470
|
+
}
|
|
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;
|
|
479
|
+
}
|
|
480
|
+
const nested = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
481
|
+
if (nested) {
|
|
482
|
+
return resolveEditableControlElement(nested);
|
|
483
|
+
}
|
|
484
|
+
const shadowNested = findEditableControlInShadowRoot(element);
|
|
485
|
+
return shadowNested ?? element;
|
|
486
|
+
}
|
|
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 "***";
|
|
494
|
+
}
|
|
495
|
+
return String(target.value || "").trim().slice(0, 100);
|
|
496
|
+
}
|
|
497
|
+
const genericValue = target.value;
|
|
498
|
+
if (typeof genericValue === "string") {
|
|
499
|
+
return genericValue.trim().slice(0, 100);
|
|
500
|
+
}
|
|
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);
|
|
506
|
+
}
|
|
507
|
+
const ariaValueText = target.getAttribute("aria-valuetext");
|
|
508
|
+
if (ariaValueText?.trim()) {
|
|
509
|
+
return ariaValueText.trim().slice(0, 100);
|
|
510
|
+
}
|
|
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);
|
|
516
|
+
}
|
|
517
|
+
function readEditableControlPlaceholder(element) {
|
|
518
|
+
const target = resolveEditableControlElement(element);
|
|
519
|
+
if (typeof target.placeholder === "string") {
|
|
520
|
+
return String(target.placeholder || "").trim().slice(0, 100);
|
|
521
|
+
}
|
|
522
|
+
return String(target.getAttribute("placeholder") || "").trim().slice(0, 100);
|
|
523
|
+
}
|
|
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);
|
|
529
|
+
}
|
|
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);
|
|
541
|
+
}
|
|
542
|
+
const attributeType = target.getAttribute("type");
|
|
543
|
+
if (attributeType?.trim()) {
|
|
544
|
+
return attributeType.trim().toLowerCase().slice(0, 50);
|
|
545
|
+
}
|
|
546
|
+
return getTagName(target);
|
|
547
|
+
}
|
|
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);
|
|
553
|
+
}
|
|
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;
|
|
562
|
+
}
|
|
563
|
+
seen.add(resolved);
|
|
564
|
+
controls.push(resolved);
|
|
565
|
+
}
|
|
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(", ");
|
|
581
|
+
}
|
|
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);
|
|
593
|
+
}
|
|
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)) {
|
|
223
651
|
return;
|
|
224
652
|
}
|
|
225
|
-
|
|
226
|
-
|
|
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);
|
|
227
663
|
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
228
664
|
const ariaLabel = el.getAttribute("aria-label");
|
|
229
665
|
const placeholder = el.getAttribute("placeholder");
|
|
@@ -254,539 +690,169 @@ function generateMinifiedAOM() {
|
|
|
254
690
|
const url = new URL(el.href);
|
|
255
691
|
node.href = url.pathname + url.search + url.hash;
|
|
256
692
|
} 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
|
-
}
|
|
407
|
-
return ["websocket", "polling"];
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// src/auto-extract.ts
|
|
411
|
-
var import_react2 = require("react");
|
|
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;
|
|
418
|
-
}
|
|
419
|
-
return process.env.NODE_ENV === "development";
|
|
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);
|
|
427
|
-
}
|
|
428
|
-
if (options?.dispatchEvent && typeof window !== "undefined") {
|
|
429
|
-
window.dispatchEvent(new CustomEvent("modelnex-debug", { detail: { msg: message, data: payload } }));
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function sanitizeActionList(actions) {
|
|
433
|
-
if (!Array.isArray(actions) || actions.length === 0) return void 0;
|
|
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;
|
|
446
|
-
}
|
|
447
|
-
return {
|
|
448
|
-
...actions ? { actions } : {},
|
|
449
|
-
...traces ? { traces } : {}
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
function sanitizeChatMessages(messages, devMode) {
|
|
453
|
-
const includeDebug = isSdkDebugEnabled(devMode);
|
|
454
|
-
return messages.map((message) => {
|
|
455
|
-
if (message.role !== "assistant") {
|
|
456
|
-
return message;
|
|
457
|
-
}
|
|
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;
|
|
472
|
-
}
|
|
473
|
-
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
474
|
-
}
|
|
475
|
-
function isStableDomId(id) {
|
|
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;
|
|
505
|
-
}
|
|
506
|
-
return null;
|
|
507
|
-
}
|
|
508
|
-
function getParentContainer(el) {
|
|
509
|
-
let current = el.parentElement;
|
|
510
|
-
while (current && current !== document.body) {
|
|
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;
|
|
543
|
-
}
|
|
544
|
-
return null;
|
|
545
|
-
}
|
|
546
|
-
function getRowContext(el) {
|
|
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;
|
|
555
|
-
}
|
|
556
|
-
return "";
|
|
557
|
-
}
|
|
558
|
-
function getNearestAncestorId(el) {
|
|
559
|
-
let current = el.parentElement;
|
|
560
|
-
while (current && current !== document.body) {
|
|
561
|
-
const aid = current.id;
|
|
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;
|
|
568
|
-
}
|
|
569
|
-
return null;
|
|
570
|
-
}
|
|
571
|
-
function generateFingerprint(el) {
|
|
572
|
-
const tag = el.tagName.toLowerCase();
|
|
573
|
-
const testId = el.getAttribute("data-testid");
|
|
574
|
-
const id = el.id;
|
|
575
|
-
const name = el.getAttribute("name");
|
|
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)}`;
|
|
588
|
-
}
|
|
589
|
-
if (tag === "a") {
|
|
590
|
-
const href = el.getAttribute("href");
|
|
591
|
-
if (href && href !== "#" && !href.startsWith("javascript:")) {
|
|
592
|
-
return `href:${simpleHash(href + ":" + text)}:${text.slice(0, 30) || href.slice(0, 30)}`;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
const ancestorId = getNearestAncestorId(el);
|
|
596
|
-
if (ancestorId) {
|
|
597
|
-
return `anc:${simpleHash(ancestorId + ":" + tag + ":" + text)}:${text.slice(0, 30) || tag}`;
|
|
598
|
-
}
|
|
599
|
-
const heading = getNearestHeading(el) || "";
|
|
600
|
-
const rowCtx = getRowContext(el);
|
|
601
|
-
const raw = `${tag}:${type}:${text}:${heading}:${rowCtx}`;
|
|
602
|
-
return `hash:${simpleHash(raw)}:${text.slice(0, 30) || tag}`;
|
|
603
|
-
}
|
|
604
|
-
function classifyRole(el) {
|
|
605
|
-
const tag = el.tagName.toLowerCase();
|
|
606
|
-
const role = el.getAttribute("role");
|
|
607
|
-
if (tag === "button" || role === "button") return "button";
|
|
608
|
-
if (tag === "a") return "link";
|
|
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;
|
|
630
|
-
}
|
|
631
|
-
var INTERACTIVE_SELECTOR = [
|
|
632
|
-
"button",
|
|
633
|
-
"a",
|
|
634
|
-
// All anchor tags (SPA links may not have href)
|
|
635
|
-
'input:not([type="hidden"])',
|
|
636
|
-
"textarea",
|
|
637
|
-
"select",
|
|
638
|
-
"label[for]",
|
|
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;
|
|
693
|
+
node.href = el.getAttribute("href");
|
|
666
694
|
}
|
|
667
|
-
const rect2 = el.getBoundingClientRect();
|
|
668
|
-
if (rect2.width === 0 && rect2.height === 0) return false;
|
|
669
695
|
}
|
|
696
|
+
nodes.push(node);
|
|
697
|
+
});
|
|
698
|
+
uidMap.clear();
|
|
699
|
+
for (const [uid, el] of nextUidMap.entries()) {
|
|
700
|
+
uidMap.set(uid, el);
|
|
670
701
|
}
|
|
671
|
-
|
|
672
|
-
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
|
|
673
|
-
return false;
|
|
674
|
-
}
|
|
675
|
-
const rect = el.getBoundingClientRect();
|
|
676
|
-
return rect.width > 0 && rect.height > 0;
|
|
702
|
+
return { nodes };
|
|
677
703
|
}
|
|
678
|
-
function
|
|
679
|
-
|
|
680
|
-
const seen = /* @__PURE__ */ new Set();
|
|
681
|
-
try {
|
|
682
|
-
const nodes = document.querySelectorAll(INTERACTIVE_SELECTOR);
|
|
683
|
-
nodes.forEach((node) => {
|
|
684
|
-
const el = node;
|
|
685
|
-
if (!isVisible(el)) return;
|
|
686
|
-
if (el.closest(".modelnex-chat-panel, .modelnex-studio-overlay, [data-modelnex-internal]")) return;
|
|
687
|
-
const role = classifyRole(el);
|
|
688
|
-
if (!role) return;
|
|
689
|
-
let fingerprint = generateFingerprint(el);
|
|
690
|
-
if (seen.has(fingerprint)) {
|
|
691
|
-
let idx = 2;
|
|
692
|
-
while (seen.has(`${fingerprint}#${idx}`)) idx++;
|
|
693
|
-
fingerprint = `${fingerprint}#${idx}`;
|
|
694
|
-
}
|
|
695
|
-
seen.add(fingerprint);
|
|
696
|
-
const rect = el.getBoundingClientRect();
|
|
697
|
-
const text = el.textContent?.trim().slice(0, 200) || "";
|
|
698
|
-
elements.push({
|
|
699
|
-
fingerprint,
|
|
700
|
-
tagName: el.tagName.toLowerCase(),
|
|
701
|
-
text,
|
|
702
|
-
role,
|
|
703
|
-
rect: {
|
|
704
|
-
top: rect.top,
|
|
705
|
-
left: rect.left,
|
|
706
|
-
width: rect.width,
|
|
707
|
-
height: rect.height
|
|
708
|
-
},
|
|
709
|
-
attributes: {
|
|
710
|
-
id: el.id || void 0,
|
|
711
|
-
name: el.getAttribute("name") || void 0,
|
|
712
|
-
type: el.type || void 0,
|
|
713
|
-
ariaLabel: el.getAttribute("aria-label") || void 0,
|
|
714
|
-
dataTestId: el.getAttribute("data-testid") || void 0,
|
|
715
|
-
href: el.href || void 0,
|
|
716
|
-
placeholder: el.placeholder || void 0
|
|
717
|
-
},
|
|
718
|
-
nearestHeading: getNearestHeading(el),
|
|
719
|
-
parentContainer: getParentContainer(el),
|
|
720
|
-
disabled: el.disabled || el.getAttribute("aria-disabled") === "true",
|
|
721
|
-
element: el
|
|
722
|
-
});
|
|
723
|
-
});
|
|
724
|
-
} catch (err) {
|
|
725
|
-
console.warn("[ModelNex] Auto-extraction error:", err);
|
|
726
|
-
}
|
|
727
|
-
return elements;
|
|
704
|
+
function getElementByUid(uid) {
|
|
705
|
+
return uidMap.get(uid) || null;
|
|
728
706
|
}
|
|
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
|
-
|
|
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,6 +2110,7 @@ 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"));
|
|
@@ -2940,6 +3013,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
|
|
|
2940
3013
|
// src/constants.ts
|
|
2941
3014
|
var DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
|
|
2942
3015
|
|
|
3016
|
+
// src/index.ts
|
|
3017
|
+
init_dev_logging();
|
|
3018
|
+
|
|
2943
3019
|
// src/utils/dev-mode.ts
|
|
2944
3020
|
var DEV_MODE_KEY_GLOBAL_NAMES = ["__MODELNEX_DEV_MODE_KEY__", "MODELNEX_DEV_MODE_KEY"];
|
|
2945
3021
|
var devModeValidationCache = /* @__PURE__ */ new Map();
|
|
@@ -3255,6 +3331,7 @@ function readPreviewSessionSuppression() {
|
|
|
3255
3331
|
|
|
3256
3332
|
// src/hooks/useRunCommand.ts
|
|
3257
3333
|
var import_react9 = require("react");
|
|
3334
|
+
init_dev_logging();
|
|
3258
3335
|
function searchTaggedElementsForQuery(store, query, limit = 8) {
|
|
3259
3336
|
const allTags = store.getAllTags();
|
|
3260
3337
|
if (allTags.length === 0) return [];
|
|
@@ -3638,6 +3715,7 @@ function releaseTourPlaybackOwnership(key, ownerId) {
|
|
|
3638
3715
|
}
|
|
3639
3716
|
|
|
3640
3717
|
// src/hooks/useTourPlayback.ts
|
|
3718
|
+
init_dev_logging();
|
|
3641
3719
|
function resolveElement(step) {
|
|
3642
3720
|
const el = step.element;
|
|
3643
3721
|
if (!el) return null;
|
|
@@ -6999,6 +7077,7 @@ function useAudioLevel(active) {
|
|
|
6999
7077
|
|
|
7000
7078
|
// src/hooks/useRecordingMode.ts
|
|
7001
7079
|
var import_react16 = require("react");
|
|
7080
|
+
init_auto_extract();
|
|
7002
7081
|
|
|
7003
7082
|
// src/utils/tourStepTypes.ts
|
|
7004
7083
|
function isAskDrivenInputStepType(stepType) {
|
|
@@ -12298,6 +12377,9 @@ function useActionHighlight() {
|
|
|
12298
12377
|
};
|
|
12299
12378
|
}
|
|
12300
12379
|
|
|
12380
|
+
// src/index.ts
|
|
12381
|
+
init_auto_extract();
|
|
12382
|
+
|
|
12301
12383
|
// src/hooks/useExperiencePlayback.ts
|
|
12302
12384
|
function useExperiencePlayback(...args) {
|
|
12303
12385
|
return useTourPlayback(...args);
|