@modelnex/sdk 0.5.44 → 0.5.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{aom-LJNCLNXL.mjs → aom-SP2LMWQI.mjs} +1 -1
- package/dist/chunk-SXGINP3O.mjs +683 -0
- package/dist/index.js +1023 -680
- package/dist/index.mjs +663 -776
- 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");
|
|
@@ -256,537 +692,167 @@ function generateMinifiedAOM() {
|
|
|
256
692
|
} catch {
|
|
257
693
|
node.href = el.getAttribute("href");
|
|
258
694
|
}
|
|
259
|
-
}
|
|
260
|
-
nodes.push(node);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
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;
|
|
666
|
-
}
|
|
667
|
-
const rect2 = el.getBoundingClientRect();
|
|
668
|
-
if (rect2.width === 0 && rect2.height === 0) return false;
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
const style = window.getComputedStyle(el);
|
|
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;
|
|
677
|
-
}
|
|
678
|
-
function extractInteractiveElements() {
|
|
679
|
-
const elements = [];
|
|
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;
|
|
728
|
-
}
|
|
729
|
-
function useAutoExtract(devMode) {
|
|
730
|
-
const [elements, setElements] = (0, import_react2.useState)([]);
|
|
731
|
-
const timerRef = (0, import_react2.useRef)(null);
|
|
732
|
-
const lastSnapshotRef = (0, import_react2.useRef)("");
|
|
733
|
-
const scan = (0, import_react2.useCallback)(() => {
|
|
734
|
-
if (typeof document === "undefined") return;
|
|
735
|
-
const extracted = extractInteractiveElements();
|
|
736
|
-
const snapshot = JSON.stringify(extracted.map((e) => ({
|
|
737
|
-
fingerprint: e.fingerprint,
|
|
738
|
-
role: e.role,
|
|
739
|
-
text: e.text,
|
|
740
|
-
rect: e.rect,
|
|
741
|
-
disabled: e.disabled,
|
|
742
|
-
nearestHeading: e.nearestHeading,
|
|
743
|
-
parentContainer: e.parentContainer
|
|
744
|
-
})));
|
|
745
|
-
if (snapshot === lastSnapshotRef.current) return;
|
|
746
|
-
lastSnapshotRef.current = snapshot;
|
|
747
|
-
emitSdkDebugLog("[ModelNex AutoExtract] Scan complete", {
|
|
748
|
-
elementCount: extracted.length
|
|
749
|
-
}, { devMode });
|
|
750
|
-
setElements(extracted);
|
|
751
|
-
}, [devMode]);
|
|
752
|
-
(0, import_react2.useEffect)(() => {
|
|
753
|
-
const initialTimer = setTimeout(scan, 300);
|
|
695
|
+
}
|
|
696
|
+
nodes.push(node);
|
|
697
|
+
});
|
|
698
|
+
uidMap.clear();
|
|
699
|
+
for (const [uid, el] of nextUidMap.entries()) {
|
|
700
|
+
uidMap.set(uid, el);
|
|
701
|
+
}
|
|
702
|
+
return { nodes };
|
|
703
|
+
}
|
|
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) ?? "";
|
|
@@ -1051,6 +1117,160 @@ function serializeContexts(contexts) {
|
|
|
1051
1117
|
return Array.from(contexts.values());
|
|
1052
1118
|
}
|
|
1053
1119
|
|
|
1120
|
+
// src/hooks/useModelNexSocket.ts
|
|
1121
|
+
init_dev_logging();
|
|
1122
|
+
|
|
1123
|
+
// src/utils/debug-tools.ts
|
|
1124
|
+
var lastActionEffect = null;
|
|
1125
|
+
function normalizeText(value) {
|
|
1126
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
1127
|
+
}
|
|
1128
|
+
function isElementVisible(el) {
|
|
1129
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
1130
|
+
const style = window.getComputedStyle(el);
|
|
1131
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") {
|
|
1132
|
+
return false;
|
|
1133
|
+
}
|
|
1134
|
+
const rect = el.getBoundingClientRect();
|
|
1135
|
+
return rect.width > 0 && rect.height > 0;
|
|
1136
|
+
}
|
|
1137
|
+
function safeQueryAll2(selector) {
|
|
1138
|
+
try {
|
|
1139
|
+
return Array.from(document.querySelectorAll(selector)).filter(
|
|
1140
|
+
(el) => el instanceof HTMLElement
|
|
1141
|
+
);
|
|
1142
|
+
} catch {
|
|
1143
|
+
return [];
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
function classifyLevel(el, text) {
|
|
1147
|
+
const levelHint = `${el.getAttribute("data-variant") || ""} ${el.className || ""} ${text}`.toLowerCase();
|
|
1148
|
+
if (/\berror|danger|invalid|failed|required\b/.test(levelHint)) return "error";
|
|
1149
|
+
if (/\bwarn|warning|caution\b/.test(levelHint)) return "warning";
|
|
1150
|
+
return "info";
|
|
1151
|
+
}
|
|
1152
|
+
function classifySource(el) {
|
|
1153
|
+
const role = (el.getAttribute("role") || "").toLowerCase();
|
|
1154
|
+
if (role === "alert") return "alert";
|
|
1155
|
+
if (role === "status") return "status";
|
|
1156
|
+
if (el.hasAttribute("aria-live")) return "aria-live";
|
|
1157
|
+
const classHint = String(el.className || "").toLowerCase();
|
|
1158
|
+
if (/\bbanner\b/.test(classHint)) return "banner";
|
|
1159
|
+
return "inline";
|
|
1160
|
+
}
|
|
1161
|
+
function selectorHintFor(el) {
|
|
1162
|
+
if (el.id) return `#${el.id}`;
|
|
1163
|
+
if (el.getAttribute("data-testid")) return `[data-testid="${el.getAttribute("data-testid")}"]`;
|
|
1164
|
+
const role = el.getAttribute("role");
|
|
1165
|
+
return role ? `${el.tagName.toLowerCase()}[role="${role}"]` : el.tagName.toLowerCase();
|
|
1166
|
+
}
|
|
1167
|
+
function collectUiMessages(options) {
|
|
1168
|
+
const includeHidden = Boolean(options?.includeHidden);
|
|
1169
|
+
const maxItems = Math.max(1, Math.min(Number(options?.maxItems || 10), 20));
|
|
1170
|
+
const selectors = [
|
|
1171
|
+
'[role="alert"]',
|
|
1172
|
+
'[role="status"]',
|
|
1173
|
+
"[aria-live]",
|
|
1174
|
+
'[aria-invalid="true"]',
|
|
1175
|
+
"[data-error]",
|
|
1176
|
+
"[data-warning]",
|
|
1177
|
+
".error",
|
|
1178
|
+
".warning",
|
|
1179
|
+
".alert",
|
|
1180
|
+
".toast",
|
|
1181
|
+
".banner"
|
|
1182
|
+
];
|
|
1183
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1184
|
+
const results = [];
|
|
1185
|
+
for (const selector of selectors) {
|
|
1186
|
+
for (const el of safeQueryAll2(selector)) {
|
|
1187
|
+
const visible = isElementVisible(el);
|
|
1188
|
+
if (!includeHidden && !visible) continue;
|
|
1189
|
+
const text = normalizeText(el.textContent);
|
|
1190
|
+
if (!text || text.length < 2) continue;
|
|
1191
|
+
const key = `${selector}:${text.toLowerCase()}`;
|
|
1192
|
+
if (seen.has(key)) continue;
|
|
1193
|
+
seen.add(key);
|
|
1194
|
+
results.push({
|
|
1195
|
+
id: `ui_${results.length + 1}`,
|
|
1196
|
+
level: classifyLevel(el, text),
|
|
1197
|
+
text,
|
|
1198
|
+
source: classifySource(el),
|
|
1199
|
+
visible,
|
|
1200
|
+
selectorHint: selectorHintFor(el)
|
|
1201
|
+
});
|
|
1202
|
+
if (results.length >= maxItems) return results;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
return results;
|
|
1206
|
+
}
|
|
1207
|
+
function captureDebugSnapshot() {
|
|
1208
|
+
return {
|
|
1209
|
+
route: `${window.location.pathname}${window.location.search}${window.location.hash}`,
|
|
1210
|
+
title: document.title || "",
|
|
1211
|
+
uiMessages: collectUiMessages({ maxItems: 6 }),
|
|
1212
|
+
timestamp: Date.now()
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
function diffUiMessages(before, after) {
|
|
1216
|
+
const beforeKeys = new Set(before.map((entry) => `${entry.level}:${entry.text}`));
|
|
1217
|
+
return after.filter((entry) => !beforeKeys.has(`${entry.level}:${entry.text}`));
|
|
1218
|
+
}
|
|
1219
|
+
function summarizeEffect(record) {
|
|
1220
|
+
const routeChanged = record.before.route !== record.after.route;
|
|
1221
|
+
const titleChanged = record.before.title !== record.after.title;
|
|
1222
|
+
const newMessages = diffUiMessages(record.before.uiMessages, record.after.uiMessages);
|
|
1223
|
+
const changed = routeChanged || titleChanged || newMessages.length > 0 || !record.success || record.before.timestamp !== record.after.timestamp;
|
|
1224
|
+
const parts = [];
|
|
1225
|
+
if (routeChanged) parts.push(`route changed from ${record.before.route} to ${record.after.route}`);
|
|
1226
|
+
if (titleChanged) parts.push("page title changed");
|
|
1227
|
+
if (newMessages.length > 0) parts.push(`new UI messages: ${newMessages.map((entry) => entry.text).join(" | ")}`);
|
|
1228
|
+
if (!record.success && record.error) parts.push(`action failed: ${record.error}`);
|
|
1229
|
+
if (parts.length === 0) parts.push("no obvious route/title/message change detected");
|
|
1230
|
+
return {
|
|
1231
|
+
summary: parts.join("; "),
|
|
1232
|
+
changed
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
function recordLastActionEffect(record) {
|
|
1236
|
+
const summary = summarizeEffect(record);
|
|
1237
|
+
lastActionEffect = {
|
|
1238
|
+
...record,
|
|
1239
|
+
...summary
|
|
1240
|
+
};
|
|
1241
|
+
return lastActionEffect;
|
|
1242
|
+
}
|
|
1243
|
+
function getLastActionEffectRecord() {
|
|
1244
|
+
return lastActionEffect;
|
|
1245
|
+
}
|
|
1246
|
+
function inspectDomElementState(el) {
|
|
1247
|
+
const rect = el.getBoundingClientRect();
|
|
1248
|
+
const describedByIds = normalizeText(el.getAttribute("aria-describedby")).split(/\s+/).filter(Boolean);
|
|
1249
|
+
const describedByText = describedByIds.map((id) => normalizeText(document.getElementById(id)?.textContent)).filter(Boolean).join(" | ");
|
|
1250
|
+
const labelText = normalizeText(
|
|
1251
|
+
el.labels?.[0]?.textContent || el.getAttribute("aria-label") || el.getAttribute("name") || el.getAttribute("id") || el.textContent
|
|
1252
|
+
);
|
|
1253
|
+
return {
|
|
1254
|
+
tag: el.tagName.toLowerCase(),
|
|
1255
|
+
label: labelText || null,
|
|
1256
|
+
text: normalizeText(el.textContent).slice(0, 300) || null,
|
|
1257
|
+
value: "value" in el ? normalizeText(String(el.value || "")) || null : null,
|
|
1258
|
+
visible: isElementVisible(el),
|
|
1259
|
+
enabled: !el.hasAttribute("disabled") && el.getAttribute("aria-disabled") !== "true",
|
|
1260
|
+
focused: document.activeElement === el,
|
|
1261
|
+
ariaInvalid: el.getAttribute("aria-invalid") === "true",
|
|
1262
|
+
describedByText: describedByText || null,
|
|
1263
|
+
role: el.getAttribute("role") || null,
|
|
1264
|
+
selectorHint: selectorHintFor(el),
|
|
1265
|
+
rect: {
|
|
1266
|
+
x: Math.round(rect.x),
|
|
1267
|
+
y: Math.round(rect.y),
|
|
1268
|
+
width: Math.round(rect.width),
|
|
1269
|
+
height: Math.round(rect.height)
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1054
1274
|
// src/hooks/useModelNexSocket.ts
|
|
1055
1275
|
function useModelNexSocket({
|
|
1056
1276
|
serverUrl,
|
|
@@ -1149,11 +1369,22 @@ function useModelNexSocket({
|
|
|
1149
1369
|
const NAV_ACTION_IDS = ["navigate_to_documents", "navigate_to_templates", "navigate_to_inbox", "navigate_to_settings", "navigate_to_template", "navigate_to_document", "navigate_to_folder", "navigate_editor_step"];
|
|
1150
1370
|
const action = currentActions.get(actionId);
|
|
1151
1371
|
if (action) {
|
|
1372
|
+
const beforeSnapshot = captureDebugSnapshot();
|
|
1373
|
+
const startedAt = Date.now();
|
|
1152
1374
|
try {
|
|
1153
1375
|
const validatedParams = action.schema.parse(params);
|
|
1154
1376
|
log("[SDK] Executing action", { actionId });
|
|
1155
1377
|
const execResult = await action.execute(validatedParams);
|
|
1156
1378
|
log("[SDK] Action completed", { actionId });
|
|
1379
|
+
recordLastActionEffect({
|
|
1380
|
+
actionId,
|
|
1381
|
+
success: true,
|
|
1382
|
+
error: null,
|
|
1383
|
+
startedAt,
|
|
1384
|
+
finishedAt: Date.now(),
|
|
1385
|
+
before: beforeSnapshot,
|
|
1386
|
+
after: captureDebugSnapshot()
|
|
1387
|
+
});
|
|
1157
1388
|
sendResult(true, execResult);
|
|
1158
1389
|
if (NAV_ACTION_IDS.includes(actionId)) {
|
|
1159
1390
|
requestAnimationFrame(() => {
|
|
@@ -1178,6 +1409,15 @@ function useModelNexSocket({
|
|
|
1178
1409
|
} catch (err) {
|
|
1179
1410
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
1180
1411
|
console.error(`[ModelNex SDK] Execution failed for ${actionId}: ${errMsg}`);
|
|
1412
|
+
recordLastActionEffect({
|
|
1413
|
+
actionId,
|
|
1414
|
+
success: false,
|
|
1415
|
+
error: errMsg,
|
|
1416
|
+
startedAt,
|
|
1417
|
+
finishedAt: Date.now(),
|
|
1418
|
+
before: beforeSnapshot,
|
|
1419
|
+
after: captureDebugSnapshot()
|
|
1420
|
+
});
|
|
1181
1421
|
if (isSdkDebugEnabled(devMode)) {
|
|
1182
1422
|
window.dispatchEvent(
|
|
1183
1423
|
new CustomEvent("modelnex-debug", {
|
|
@@ -1270,6 +1510,7 @@ function useFieldHighlight(stagingFields, executedFields, setExecutedFields) {
|
|
|
1270
1510
|
|
|
1271
1511
|
// src/overlay.tsx
|
|
1272
1512
|
var import_react5 = __toESM(require("react"));
|
|
1513
|
+
init_auto_extract();
|
|
1273
1514
|
var AIActivityOverlay = ({ activeActions }) => {
|
|
1274
1515
|
if (activeActions.size === 0) return null;
|
|
1275
1516
|
return import_react5.default.createElement(
|
|
@@ -1465,6 +1706,9 @@ body.modelnex-highlight-actions [data-modelnex-action-id]::before {
|
|
|
1465
1706
|
}
|
|
1466
1707
|
`;
|
|
1467
1708
|
|
|
1709
|
+
// src/index.ts
|
|
1710
|
+
init_auto_extract();
|
|
1711
|
+
|
|
1468
1712
|
// src/tag-store.ts
|
|
1469
1713
|
var import_react6 = require("react");
|
|
1470
1714
|
var STORAGE_KEY = "modelnex-tags";
|
|
@@ -1614,6 +1858,7 @@ function useTagStore(options) {
|
|
|
1614
1858
|
|
|
1615
1859
|
// src/studio-mode.tsx
|
|
1616
1860
|
var import_react7 = require("react");
|
|
1861
|
+
init_auto_extract();
|
|
1617
1862
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1618
1863
|
var CATEGORIES = [
|
|
1619
1864
|
{ value: "button", label: "Button" },
|
|
@@ -2038,6 +2283,7 @@ function StudioOverlay({ elements, tagStore }) {
|
|
|
2038
2283
|
// src/hooks/useBuiltinActions.ts
|
|
2039
2284
|
var import_react8 = require("react");
|
|
2040
2285
|
var import_zod2 = require("zod");
|
|
2286
|
+
init_auto_extract();
|
|
2041
2287
|
|
|
2042
2288
|
// src/utils/screenshot.ts
|
|
2043
2289
|
var import_html2canvas = __toESM(require("html2canvas"));
|
|
@@ -2217,7 +2463,7 @@ function isTourEligible(tour, userProfile) {
|
|
|
2217
2463
|
var resolutionCache = /* @__PURE__ */ new Map();
|
|
2218
2464
|
var DEFAULT_WORKFLOW_SEARCH_LIMIT = 5;
|
|
2219
2465
|
var WORKFLOW_TYPES = ["onboarding", "tour"];
|
|
2220
|
-
function
|
|
2466
|
+
function safeQueryAll3(selector) {
|
|
2221
2467
|
try {
|
|
2222
2468
|
return Array.from(document.querySelectorAll(selector)).filter(
|
|
2223
2469
|
(el) => el instanceof HTMLElement
|
|
@@ -2226,6 +2472,9 @@ function safeQueryAll2(selector) {
|
|
|
2226
2472
|
return [];
|
|
2227
2473
|
}
|
|
2228
2474
|
}
|
|
2475
|
+
function safeQueryOne(selector) {
|
|
2476
|
+
return safeQueryAll3(selector)[0] || null;
|
|
2477
|
+
}
|
|
2229
2478
|
var ROW_SELECTORS = 'tr, [role="row"], [role="listitem"], li, [data-row], [class*="row"], [class*="card"], article, section';
|
|
2230
2479
|
function getRowText(el) {
|
|
2231
2480
|
const row = el.closest(ROW_SELECTORS);
|
|
@@ -2257,6 +2506,20 @@ function makeTarget(el, via) {
|
|
|
2257
2506
|
resolvedVia: via
|
|
2258
2507
|
};
|
|
2259
2508
|
}
|
|
2509
|
+
function resolveInspectableElement(params, getTagStore) {
|
|
2510
|
+
if (params.selector) {
|
|
2511
|
+
const bySelector = safeQueryOne(params.selector);
|
|
2512
|
+
if (bySelector) return makeTarget(bySelector, "single-selector");
|
|
2513
|
+
}
|
|
2514
|
+
if (params.fingerprint) {
|
|
2515
|
+
return resolveTargetElement(
|
|
2516
|
+
params.fingerprint,
|
|
2517
|
+
{ patternId: params.patternId, textContaining: params.textContaining },
|
|
2518
|
+
getTagStore()
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
return null;
|
|
2522
|
+
}
|
|
2260
2523
|
function resolveTargetElement(fingerprint, options, tagStore) {
|
|
2261
2524
|
const elements = extractInteractiveElements();
|
|
2262
2525
|
const byFp = elements.find((e) => e.fingerprint === fingerprint);
|
|
@@ -2265,7 +2528,7 @@ function resolveTargetElement(fingerprint, options, tagStore) {
|
|
|
2265
2528
|
if (cached) {
|
|
2266
2529
|
const cachedEl = elements.find((e) => e.fingerprint === cached.resolvedFingerprint);
|
|
2267
2530
|
if (cachedEl?.element) return makeTarget(cachedEl.element, "cache");
|
|
2268
|
-
const selectorMatches =
|
|
2531
|
+
const selectorMatches = safeQueryAll3(cached.selector);
|
|
2269
2532
|
if (selectorMatches.length === 1) {
|
|
2270
2533
|
return makeTarget(selectorMatches[0], "cache");
|
|
2271
2534
|
}
|
|
@@ -2284,7 +2547,7 @@ function resolveTargetElement(fingerprint, options, tagStore) {
|
|
|
2284
2547
|
const fallbackTags = patternId ? selectorTags.filter((t) => t.patternId !== patternId) : [];
|
|
2285
2548
|
for (const tagSet of [candidateTags, fallbackTags]) {
|
|
2286
2549
|
for (const tag of tagSet) {
|
|
2287
|
-
const matched =
|
|
2550
|
+
const matched = safeQueryAll3(tag.selector);
|
|
2288
2551
|
if (matched.length === 0) continue;
|
|
2289
2552
|
for (const el of matched) {
|
|
2290
2553
|
const fp = generateFingerprint(el);
|
|
@@ -2370,7 +2633,7 @@ function lastResortScan(fingerprint, options, elements) {
|
|
|
2370
2633
|
}
|
|
2371
2634
|
if (bestEl) return makeTarget(bestEl, "fuzzy");
|
|
2372
2635
|
if (fpTextHint) {
|
|
2373
|
-
const ariaMatches =
|
|
2636
|
+
const ariaMatches = safeQueryAll3(`[aria-label*="${CSS.escape(fpTextHint)}"], [data-testid*="${CSS.escape(fpTextHint)}"]`);
|
|
2374
2637
|
if (textContaining && ariaMatches.length > 1) {
|
|
2375
2638
|
let best = null;
|
|
2376
2639
|
let bestS = 0;
|
|
@@ -2712,6 +2975,68 @@ function createWaitAction(getTagStore) {
|
|
|
2712
2975
|
}
|
|
2713
2976
|
};
|
|
2714
2977
|
}
|
|
2978
|
+
var getUiMessagesSchema = import_zod2.z.object({
|
|
2979
|
+
includeHidden: import_zod2.z.boolean().optional().describe("Include currently hidden UI messages when true. Defaults to false."),
|
|
2980
|
+
maxItems: import_zod2.z.number().int().min(1).max(20).optional().describe("Maximum number of messages to return. Defaults to 10.")
|
|
2981
|
+
});
|
|
2982
|
+
function createGetUiMessagesAction() {
|
|
2983
|
+
return {
|
|
2984
|
+
id: "get_ui_messages",
|
|
2985
|
+
description: "Return current UI-facing messages such as alerts, warnings, toasts, banners, and inline validation text.",
|
|
2986
|
+
schema: getUiMessagesSchema,
|
|
2987
|
+
execute: async (params) => {
|
|
2988
|
+
const messages = collectUiMessages(params);
|
|
2989
|
+
return {
|
|
2990
|
+
messages,
|
|
2991
|
+
total: messages.length,
|
|
2992
|
+
capturedAt: Date.now()
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
var getLastActionEffectSchema = import_zod2.z.object({});
|
|
2998
|
+
function createGetLastActionEffectAction() {
|
|
2999
|
+
return {
|
|
3000
|
+
id: "get_last_action_effect",
|
|
3001
|
+
description: "Return a compact summary of what changed after the most recent agent action.",
|
|
3002
|
+
schema: getLastActionEffectSchema,
|
|
3003
|
+
execute: async () => {
|
|
3004
|
+
return {
|
|
3005
|
+
effect: getLastActionEffectRecord()
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
};
|
|
3009
|
+
}
|
|
3010
|
+
var inspectElementStateSchema = import_zod2.z.object({
|
|
3011
|
+
fingerprint: import_zod2.z.string().optional().describe("Fingerprint of the target element to inspect."),
|
|
3012
|
+
selector: import_zod2.z.string().optional().describe("Optional CSS selector for direct inspection when a fingerprint is unavailable."),
|
|
3013
|
+
patternId: import_zod2.z.string().optional().describe("Optional patternId from tagged elements for disambiguation."),
|
|
3014
|
+
textContaining: import_zod2.z.string().optional().describe("Optional row or label text used to disambiguate similar elements.")
|
|
3015
|
+
});
|
|
3016
|
+
function createInspectElementStateAction(getTagStore) {
|
|
3017
|
+
return {
|
|
3018
|
+
id: "inspect_element_state",
|
|
3019
|
+
description: "Inspect one specific element and return its current visibility, enabled state, value/text, aria state, and associated error/help text.",
|
|
3020
|
+
schema: inspectElementStateSchema,
|
|
3021
|
+
execute: async (params) => {
|
|
3022
|
+
const target = resolveInspectableElement(params, getTagStore);
|
|
3023
|
+
if (!target) {
|
|
3024
|
+
return {
|
|
3025
|
+
found: false,
|
|
3026
|
+
reason: "Element not found from the provided fingerprint or selector."
|
|
3027
|
+
};
|
|
3028
|
+
}
|
|
3029
|
+
return {
|
|
3030
|
+
found: true,
|
|
3031
|
+
target: {
|
|
3032
|
+
fingerprint: target.fingerprint,
|
|
3033
|
+
resolvedVia: target.resolvedVia
|
|
3034
|
+
},
|
|
3035
|
+
element: inspectDomElementState(target.element)
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
};
|
|
3039
|
+
}
|
|
2715
3040
|
var searchDocsSchema = import_zod2.z.object({
|
|
2716
3041
|
query: import_zod2.z.string().describe("The search query to find relevant documentation."),
|
|
2717
3042
|
limit: import_zod2.z.number().optional().describe("Maximum number of results to return (default: 5).")
|
|
@@ -2881,6 +3206,9 @@ var BUILTIN_ACTION_IDS = {
|
|
|
2881
3206
|
click: "click_element",
|
|
2882
3207
|
fill: "fill_input",
|
|
2883
3208
|
wait: "request_user_action",
|
|
3209
|
+
getUiMessages: "get_ui_messages",
|
|
3210
|
+
getLastActionEffect: "get_last_action_effect",
|
|
3211
|
+
inspectElementState: "inspect_element_state",
|
|
2884
3212
|
searchDocs: "search_docs",
|
|
2885
3213
|
searchTaggedElements: "search_tagged_elements",
|
|
2886
3214
|
searchWorkflows: "search_workflows",
|
|
@@ -2917,6 +3245,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
|
|
|
2917
3245
|
registerAction(createClickAction(getTagStore));
|
|
2918
3246
|
registerAction(createFillAction(getTagStore));
|
|
2919
3247
|
registerAction(createWaitAction(getTagStore));
|
|
3248
|
+
registerAction(createGetUiMessagesAction());
|
|
3249
|
+
registerAction(createGetLastActionEffectAction());
|
|
3250
|
+
registerAction(createInspectElementStateAction(getTagStore));
|
|
2920
3251
|
registerAction(createSearchDocsAction(getServerUrl, getWebsiteId));
|
|
2921
3252
|
registerAction(createSearchTaggedElementsAction(getTagStore));
|
|
2922
3253
|
registerAction(createSearchWorkflowsAction(workflowToolGetters));
|
|
@@ -2927,6 +3258,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
|
|
|
2927
3258
|
unregisterAction(BUILTIN_ACTION_IDS.click);
|
|
2928
3259
|
unregisterAction(BUILTIN_ACTION_IDS.fill);
|
|
2929
3260
|
unregisterAction(BUILTIN_ACTION_IDS.wait);
|
|
3261
|
+
unregisterAction(BUILTIN_ACTION_IDS.getUiMessages);
|
|
3262
|
+
unregisterAction(BUILTIN_ACTION_IDS.getLastActionEffect);
|
|
3263
|
+
unregisterAction(BUILTIN_ACTION_IDS.inspectElementState);
|
|
2930
3264
|
unregisterAction(BUILTIN_ACTION_IDS.searchDocs);
|
|
2931
3265
|
unregisterAction(BUILTIN_ACTION_IDS.searchTaggedElements);
|
|
2932
3266
|
unregisterAction(BUILTIN_ACTION_IDS.searchWorkflows);
|
|
@@ -2940,6 +3274,9 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
|
|
|
2940
3274
|
// src/constants.ts
|
|
2941
3275
|
var DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
|
|
2942
3276
|
|
|
3277
|
+
// src/index.ts
|
|
3278
|
+
init_dev_logging();
|
|
3279
|
+
|
|
2943
3280
|
// src/utils/dev-mode.ts
|
|
2944
3281
|
var DEV_MODE_KEY_GLOBAL_NAMES = ["__MODELNEX_DEV_MODE_KEY__", "MODELNEX_DEV_MODE_KEY"];
|
|
2945
3282
|
var devModeValidationCache = /* @__PURE__ */ new Map();
|
|
@@ -3255,6 +3592,7 @@ function readPreviewSessionSuppression() {
|
|
|
3255
3592
|
|
|
3256
3593
|
// src/hooks/useRunCommand.ts
|
|
3257
3594
|
var import_react9 = require("react");
|
|
3595
|
+
init_dev_logging();
|
|
3258
3596
|
function searchTaggedElementsForQuery(store, query, limit = 8) {
|
|
3259
3597
|
const allTags = store.getAllTags();
|
|
3260
3598
|
if (allTags.length === 0) return [];
|
|
@@ -3638,6 +3976,7 @@ function releaseTourPlaybackOwnership(key, ownerId) {
|
|
|
3638
3976
|
}
|
|
3639
3977
|
|
|
3640
3978
|
// src/hooks/useTourPlayback.ts
|
|
3979
|
+
init_dev_logging();
|
|
3641
3980
|
function resolveElement(step) {
|
|
3642
3981
|
const el = step.element;
|
|
3643
3982
|
if (!el) return null;
|
|
@@ -6999,6 +7338,7 @@ function useAudioLevel(active) {
|
|
|
6999
7338
|
|
|
7000
7339
|
// src/hooks/useRecordingMode.ts
|
|
7001
7340
|
var import_react16 = require("react");
|
|
7341
|
+
init_auto_extract();
|
|
7002
7342
|
|
|
7003
7343
|
// src/utils/tourStepTypes.ts
|
|
7004
7344
|
function isAskDrivenInputStepType(stepType) {
|
|
@@ -12298,6 +12638,9 @@ function useActionHighlight() {
|
|
|
12298
12638
|
};
|
|
12299
12639
|
}
|
|
12300
12640
|
|
|
12641
|
+
// src/index.ts
|
|
12642
|
+
init_auto_extract();
|
|
12643
|
+
|
|
12301
12644
|
// src/hooks/useExperiencePlayback.ts
|
|
12302
12645
|
function useExperiencePlayback(...args) {
|
|
12303
12646
|
return useTourPlayback(...args);
|