@modelnex/sdk 0.5.40 → 0.5.41
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-HDYNCIOY.mjs → aom-LJNCLNXL.mjs} +1 -1
- package/dist/chunk-H4LUY7LI.mjs +243 -0
- package/dist/index.js +241 -101
- package/dist/index.mjs +68 -94
- package/package.json +1 -1
- package/dist/chunk-N65UEB6X.mjs +0 -70
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// src/utils/editable-controls.ts
|
|
2
|
+
var EDITABLE_ROLES = /* @__PURE__ */ new Set(["textbox", "combobox"]);
|
|
3
|
+
var EDITABLE_CONTROL_SELECTOR = [
|
|
4
|
+
'input:not([type="hidden"])',
|
|
5
|
+
"textarea",
|
|
6
|
+
"select",
|
|
7
|
+
'[contenteditable="true"]',
|
|
8
|
+
'[role="textbox"]',
|
|
9
|
+
'[role="combobox"]'
|
|
10
|
+
].join(", ");
|
|
11
|
+
function getTagName(element) {
|
|
12
|
+
return String(element?.tagName || "").toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
function getRole(element) {
|
|
15
|
+
const role = element && typeof element.getAttribute === "function" ? element.getAttribute("role") : null;
|
|
16
|
+
return String(role || "").toLowerCase();
|
|
17
|
+
}
|
|
18
|
+
function getLabelControl(element) {
|
|
19
|
+
const labelCtor = typeof HTMLLabelElement !== "undefined" ? HTMLLabelElement : null;
|
|
20
|
+
if (labelCtor && element instanceof labelCtor && element.control instanceof HTMLElement) {
|
|
21
|
+
return element.control;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function isValueBearingElement(element) {
|
|
26
|
+
if (!element) return false;
|
|
27
|
+
const inputCtor = typeof HTMLInputElement !== "undefined" ? HTMLInputElement : null;
|
|
28
|
+
if (inputCtor && element instanceof inputCtor) return true;
|
|
29
|
+
const textareaCtor = typeof HTMLTextAreaElement !== "undefined" ? HTMLTextAreaElement : null;
|
|
30
|
+
if (textareaCtor && element instanceof textareaCtor) return true;
|
|
31
|
+
const selectCtor = typeof HTMLSelectElement !== "undefined" ? HTMLSelectElement : null;
|
|
32
|
+
if (selectCtor && element instanceof selectCtor) return true;
|
|
33
|
+
return ["input", "textarea", "select"].includes(getTagName(element));
|
|
34
|
+
}
|
|
35
|
+
function findEditableControlInShadowRoot(root) {
|
|
36
|
+
if (!root) return null;
|
|
37
|
+
if (root.shadowRoot) {
|
|
38
|
+
const found = root.shadowRoot.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
39
|
+
if (found) {
|
|
40
|
+
return resolveEditableControlElement(found);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
for (const child of Array.from(root.children)) {
|
|
44
|
+
if (child instanceof HTMLElement) {
|
|
45
|
+
const found = findEditableControlInShadowRoot(child);
|
|
46
|
+
if (found) return found;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function resolveEditableControlElement(element) {
|
|
52
|
+
const labelControl = getLabelControl(element);
|
|
53
|
+
if (labelControl) {
|
|
54
|
+
return resolveEditableControlElement(labelControl);
|
|
55
|
+
}
|
|
56
|
+
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
57
|
+
return element;
|
|
58
|
+
}
|
|
59
|
+
const role = getRole(element);
|
|
60
|
+
if (EDITABLE_ROLES.has(role)) {
|
|
61
|
+
const nested2 = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
62
|
+
if (nested2 && nested2 !== element) {
|
|
63
|
+
return resolveEditableControlElement(nested2);
|
|
64
|
+
}
|
|
65
|
+
const shadowNested2 = findEditableControlInShadowRoot(element);
|
|
66
|
+
return shadowNested2 ?? element;
|
|
67
|
+
}
|
|
68
|
+
const nested = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
69
|
+
if (nested) {
|
|
70
|
+
return resolveEditableControlElement(nested);
|
|
71
|
+
}
|
|
72
|
+
const shadowNested = findEditableControlInShadowRoot(element);
|
|
73
|
+
return shadowNested ?? element;
|
|
74
|
+
}
|
|
75
|
+
function readEditableControlValue(element, options = {}) {
|
|
76
|
+
const target = resolveEditableControlElement(element);
|
|
77
|
+
const maskPasswords = options.maskPasswords !== false;
|
|
78
|
+
if (isValueBearingElement(target)) {
|
|
79
|
+
const type = String(target.type || "").toLowerCase();
|
|
80
|
+
if (maskPasswords && type === "password") {
|
|
81
|
+
return "***";
|
|
82
|
+
}
|
|
83
|
+
return String(target.value || "").trim().slice(0, 100);
|
|
84
|
+
}
|
|
85
|
+
const genericValue = target.value;
|
|
86
|
+
if (typeof genericValue === "string") {
|
|
87
|
+
return genericValue.trim().slice(0, 100);
|
|
88
|
+
}
|
|
89
|
+
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
90
|
+
return String(genericValue).trim().slice(0, 100);
|
|
91
|
+
}
|
|
92
|
+
if (target.isContentEditable) {
|
|
93
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
94
|
+
}
|
|
95
|
+
const ariaValueText = target.getAttribute("aria-valuetext");
|
|
96
|
+
if (ariaValueText?.trim()) {
|
|
97
|
+
return ariaValueText.trim().slice(0, 100);
|
|
98
|
+
}
|
|
99
|
+
const ariaValueNow = target.getAttribute("aria-valuenow");
|
|
100
|
+
if (ariaValueNow?.trim()) {
|
|
101
|
+
return ariaValueNow.trim().slice(0, 100);
|
|
102
|
+
}
|
|
103
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
104
|
+
}
|
|
105
|
+
function readEditableControlPlaceholder(element) {
|
|
106
|
+
const target = resolveEditableControlElement(element);
|
|
107
|
+
if (typeof target.placeholder === "string") {
|
|
108
|
+
return String(target.placeholder || "").trim().slice(0, 100);
|
|
109
|
+
}
|
|
110
|
+
return String(target.getAttribute("placeholder") || "").trim().slice(0, 100);
|
|
111
|
+
}
|
|
112
|
+
function readEditableControlName(element) {
|
|
113
|
+
const target = resolveEditableControlElement(element);
|
|
114
|
+
const explicitName = target.name;
|
|
115
|
+
if (typeof explicitName === "string" && explicitName.trim()) {
|
|
116
|
+
return explicitName.trim().slice(0, 100);
|
|
117
|
+
}
|
|
118
|
+
return String(
|
|
119
|
+
target.getAttribute("name") || target.getAttribute("id") || target.getAttribute("aria-label") || ""
|
|
120
|
+
).trim().slice(0, 100);
|
|
121
|
+
}
|
|
122
|
+
function readEditableControlType(element) {
|
|
123
|
+
const target = resolveEditableControlElement(element);
|
|
124
|
+
const role = getRole(target);
|
|
125
|
+
if (role) return role;
|
|
126
|
+
const explicitType = target.type;
|
|
127
|
+
if (typeof explicitType === "string" && explicitType.trim()) {
|
|
128
|
+
return explicitType.trim().toLowerCase().slice(0, 50);
|
|
129
|
+
}
|
|
130
|
+
const attributeType = target.getAttribute("type");
|
|
131
|
+
if (attributeType?.trim()) {
|
|
132
|
+
return attributeType.trim().toLowerCase().slice(0, 50);
|
|
133
|
+
}
|
|
134
|
+
return getTagName(target);
|
|
135
|
+
}
|
|
136
|
+
function isEditableControlDisabled(element) {
|
|
137
|
+
const target = resolveEditableControlElement(element);
|
|
138
|
+
const ariaDisabled = String(target.getAttribute("aria-disabled") || "").toLowerCase();
|
|
139
|
+
if (ariaDisabled === "true") return true;
|
|
140
|
+
return Boolean(target.disabled);
|
|
141
|
+
}
|
|
142
|
+
function collectEditableControls(scope) {
|
|
143
|
+
const seen = /* @__PURE__ */ new Set();
|
|
144
|
+
const controls = [];
|
|
145
|
+
for (const rawElement of Array.from(scope.querySelectorAll(EDITABLE_CONTROL_SELECTOR))) {
|
|
146
|
+
const resolved = resolveEditableControlElement(rawElement);
|
|
147
|
+
if (seen.has(resolved)) continue;
|
|
148
|
+
if (isValueBearingElement(resolved) && String(resolved.type || "").toLowerCase() === "hidden") {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
seen.add(resolved);
|
|
152
|
+
controls.push(resolved);
|
|
153
|
+
}
|
|
154
|
+
return controls;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/utils/aom.ts
|
|
158
|
+
var uidMap = /* @__PURE__ */ new Map();
|
|
159
|
+
var nextUid = 1;
|
|
160
|
+
function generateMinifiedAOM() {
|
|
161
|
+
uidMap.clear();
|
|
162
|
+
nextUid = 1;
|
|
163
|
+
const interactiveSet = /* @__PURE__ */ new Set();
|
|
164
|
+
const interactiveCandidates = [
|
|
165
|
+
...Array.from(document.querySelectorAll(
|
|
166
|
+
'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], [role="textbox"], [role="combobox"], [contenteditable="true"]'
|
|
167
|
+
)),
|
|
168
|
+
...collectEditableControls(document)
|
|
169
|
+
];
|
|
170
|
+
const nodes = [];
|
|
171
|
+
interactiveCandidates.forEach((candidate) => {
|
|
172
|
+
const el = resolveEditableControlElement(candidate);
|
|
173
|
+
if (interactiveSet.has(el)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
interactiveSet.add(el);
|
|
177
|
+
if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const uid = `node:${nextUid++}`;
|
|
184
|
+
uidMap.set(uid, el);
|
|
185
|
+
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
186
|
+
const ariaLabel = el.getAttribute("aria-label");
|
|
187
|
+
const placeholder = el.getAttribute("placeholder");
|
|
188
|
+
const value = readEditableControlValue(el, { maskPasswords: false }) || void 0;
|
|
189
|
+
let role = el.tagName.toLowerCase();
|
|
190
|
+
if (el.hasAttribute("role")) {
|
|
191
|
+
role = el.getAttribute("role");
|
|
192
|
+
} else if (role === "a") {
|
|
193
|
+
role = "link";
|
|
194
|
+
} else if (el.tagName.toLowerCase() === "input") {
|
|
195
|
+
const inputType = el.type;
|
|
196
|
+
role = inputType ? `input[${inputType}]` : "input";
|
|
197
|
+
}
|
|
198
|
+
const node = { uid, role };
|
|
199
|
+
const displayLabel = ariaLabel || text || placeholder;
|
|
200
|
+
if (displayLabel) {
|
|
201
|
+
node.text = displayLabel.substring(0, 100);
|
|
202
|
+
}
|
|
203
|
+
const controlName = readEditableControlName(el);
|
|
204
|
+
if (controlName) {
|
|
205
|
+
node.name = controlName;
|
|
206
|
+
}
|
|
207
|
+
if (value) {
|
|
208
|
+
node.value = value.substring(0, 100);
|
|
209
|
+
}
|
|
210
|
+
if (el instanceof HTMLAnchorElement && el.href) {
|
|
211
|
+
try {
|
|
212
|
+
const url = new URL(el.href);
|
|
213
|
+
node.href = url.pathname + url.search + url.hash;
|
|
214
|
+
} catch {
|
|
215
|
+
node.href = el.getAttribute("href");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
nodes.push(node);
|
|
219
|
+
});
|
|
220
|
+
return { nodes };
|
|
221
|
+
}
|
|
222
|
+
function getElementByUid(uid) {
|
|
223
|
+
return uidMap.get(uid) || null;
|
|
224
|
+
}
|
|
225
|
+
function clearAOMMap() {
|
|
226
|
+
uidMap.clear();
|
|
227
|
+
nextUid = 1;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export {
|
|
231
|
+
isValueBearingElement,
|
|
232
|
+
findEditableControlInShadowRoot,
|
|
233
|
+
resolveEditableControlElement,
|
|
234
|
+
readEditableControlValue,
|
|
235
|
+
readEditableControlPlaceholder,
|
|
236
|
+
readEditableControlName,
|
|
237
|
+
readEditableControlType,
|
|
238
|
+
isEditableControlDisabled,
|
|
239
|
+
collectEditableControls,
|
|
240
|
+
generateMinifiedAOM,
|
|
241
|
+
getElementByUid,
|
|
242
|
+
clearAOMMap
|
|
243
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,168 @@ 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/editable-controls.ts
|
|
34
|
+
function getTagName(element) {
|
|
35
|
+
return String(element?.tagName || "").toLowerCase();
|
|
36
|
+
}
|
|
37
|
+
function getRole(element) {
|
|
38
|
+
const role = element && typeof element.getAttribute === "function" ? element.getAttribute("role") : null;
|
|
39
|
+
return String(role || "").toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
function getLabelControl(element) {
|
|
42
|
+
const labelCtor = typeof HTMLLabelElement !== "undefined" ? HTMLLabelElement : null;
|
|
43
|
+
if (labelCtor && element instanceof labelCtor && element.control instanceof HTMLElement) {
|
|
44
|
+
return element.control;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function isValueBearingElement(element) {
|
|
49
|
+
if (!element) return false;
|
|
50
|
+
const inputCtor = typeof HTMLInputElement !== "undefined" ? HTMLInputElement : null;
|
|
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));
|
|
57
|
+
}
|
|
58
|
+
function findEditableControlInShadowRoot(root) {
|
|
59
|
+
if (!root) return null;
|
|
60
|
+
if (root.shadowRoot) {
|
|
61
|
+
const found = root.shadowRoot.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
62
|
+
if (found) {
|
|
63
|
+
return resolveEditableControlElement(found);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const child of Array.from(root.children)) {
|
|
67
|
+
if (child instanceof HTMLElement) {
|
|
68
|
+
const found = findEditableControlInShadowRoot(child);
|
|
69
|
+
if (found) return found;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function resolveEditableControlElement(element) {
|
|
75
|
+
const labelControl = getLabelControl(element);
|
|
76
|
+
if (labelControl) {
|
|
77
|
+
return resolveEditableControlElement(labelControl);
|
|
78
|
+
}
|
|
79
|
+
if (isValueBearingElement(element) || element.isContentEditable) {
|
|
80
|
+
return element;
|
|
81
|
+
}
|
|
82
|
+
const role = getRole(element);
|
|
83
|
+
if (EDITABLE_ROLES.has(role)) {
|
|
84
|
+
const nested2 = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
85
|
+
if (nested2 && nested2 !== element) {
|
|
86
|
+
return resolveEditableControlElement(nested2);
|
|
87
|
+
}
|
|
88
|
+
const shadowNested2 = findEditableControlInShadowRoot(element);
|
|
89
|
+
return shadowNested2 ?? element;
|
|
90
|
+
}
|
|
91
|
+
const nested = element.querySelector(EDITABLE_CONTROL_SELECTOR);
|
|
92
|
+
if (nested) {
|
|
93
|
+
return resolveEditableControlElement(nested);
|
|
94
|
+
}
|
|
95
|
+
const shadowNested = findEditableControlInShadowRoot(element);
|
|
96
|
+
return shadowNested ?? element;
|
|
97
|
+
}
|
|
98
|
+
function readEditableControlValue(element, options = {}) {
|
|
99
|
+
const target = resolveEditableControlElement(element);
|
|
100
|
+
const maskPasswords = options.maskPasswords !== false;
|
|
101
|
+
if (isValueBearingElement(target)) {
|
|
102
|
+
const type = String(target.type || "").toLowerCase();
|
|
103
|
+
if (maskPasswords && type === "password") {
|
|
104
|
+
return "***";
|
|
105
|
+
}
|
|
106
|
+
return String(target.value || "").trim().slice(0, 100);
|
|
107
|
+
}
|
|
108
|
+
const genericValue = target.value;
|
|
109
|
+
if (typeof genericValue === "string") {
|
|
110
|
+
return genericValue.trim().slice(0, 100);
|
|
111
|
+
}
|
|
112
|
+
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
113
|
+
return String(genericValue).trim().slice(0, 100);
|
|
114
|
+
}
|
|
115
|
+
if (target.isContentEditable) {
|
|
116
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
117
|
+
}
|
|
118
|
+
const ariaValueText = target.getAttribute("aria-valuetext");
|
|
119
|
+
if (ariaValueText?.trim()) {
|
|
120
|
+
return ariaValueText.trim().slice(0, 100);
|
|
121
|
+
}
|
|
122
|
+
const ariaValueNow = target.getAttribute("aria-valuenow");
|
|
123
|
+
if (ariaValueNow?.trim()) {
|
|
124
|
+
return ariaValueNow.trim().slice(0, 100);
|
|
125
|
+
}
|
|
126
|
+
return String(target.textContent || "").trim().slice(0, 100);
|
|
127
|
+
}
|
|
128
|
+
function readEditableControlPlaceholder(element) {
|
|
129
|
+
const target = resolveEditableControlElement(element);
|
|
130
|
+
if (typeof target.placeholder === "string") {
|
|
131
|
+
return String(target.placeholder || "").trim().slice(0, 100);
|
|
132
|
+
}
|
|
133
|
+
return String(target.getAttribute("placeholder") || "").trim().slice(0, 100);
|
|
134
|
+
}
|
|
135
|
+
function readEditableControlName(element) {
|
|
136
|
+
const target = resolveEditableControlElement(element);
|
|
137
|
+
const explicitName = target.name;
|
|
138
|
+
if (typeof explicitName === "string" && explicitName.trim()) {
|
|
139
|
+
return explicitName.trim().slice(0, 100);
|
|
140
|
+
}
|
|
141
|
+
return String(
|
|
142
|
+
target.getAttribute("name") || target.getAttribute("id") || target.getAttribute("aria-label") || ""
|
|
143
|
+
).trim().slice(0, 100);
|
|
144
|
+
}
|
|
145
|
+
function readEditableControlType(element) {
|
|
146
|
+
const target = resolveEditableControlElement(element);
|
|
147
|
+
const role = getRole(target);
|
|
148
|
+
if (role) return role;
|
|
149
|
+
const explicitType = target.type;
|
|
150
|
+
if (typeof explicitType === "string" && explicitType.trim()) {
|
|
151
|
+
return explicitType.trim().toLowerCase().slice(0, 50);
|
|
152
|
+
}
|
|
153
|
+
const attributeType = target.getAttribute("type");
|
|
154
|
+
if (attributeType?.trim()) {
|
|
155
|
+
return attributeType.trim().toLowerCase().slice(0, 50);
|
|
156
|
+
}
|
|
157
|
+
return getTagName(target);
|
|
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);
|
|
164
|
+
}
|
|
165
|
+
function collectEditableControls(scope) {
|
|
166
|
+
const seen = /* @__PURE__ */ new Set();
|
|
167
|
+
const controls = [];
|
|
168
|
+
for (const rawElement of Array.from(scope.querySelectorAll(EDITABLE_CONTROL_SELECTOR))) {
|
|
169
|
+
const resolved = resolveEditableControlElement(rawElement);
|
|
170
|
+
if (seen.has(resolved)) continue;
|
|
171
|
+
if (isValueBearingElement(resolved) && String(resolved.type || "").toLowerCase() === "hidden") {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
seen.add(resolved);
|
|
175
|
+
controls.push(resolved);
|
|
176
|
+
}
|
|
177
|
+
return controls;
|
|
178
|
+
}
|
|
179
|
+
var EDITABLE_ROLES, EDITABLE_CONTROL_SELECTOR;
|
|
180
|
+
var init_editable_controls = __esm({
|
|
181
|
+
"src/utils/editable-controls.ts"() {
|
|
182
|
+
"use strict";
|
|
183
|
+
EDITABLE_ROLES = /* @__PURE__ */ new Set(["textbox", "combobox"]);
|
|
184
|
+
EDITABLE_CONTROL_SELECTOR = [
|
|
185
|
+
'input:not([type="hidden"])',
|
|
186
|
+
"textarea",
|
|
187
|
+
"select",
|
|
188
|
+
'[contenteditable="true"]',
|
|
189
|
+
'[role="textbox"]',
|
|
190
|
+
'[role="combobox"]'
|
|
191
|
+
].join(", ");
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
33
195
|
// src/utils/aom.ts
|
|
34
196
|
var aom_exports = {};
|
|
35
197
|
__export(aom_exports, {
|
|
@@ -40,11 +202,20 @@ __export(aom_exports, {
|
|
|
40
202
|
function generateMinifiedAOM() {
|
|
41
203
|
uidMap.clear();
|
|
42
204
|
nextUid = 1;
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
205
|
+
const interactiveSet = /* @__PURE__ */ new Set();
|
|
206
|
+
const interactiveCandidates = [
|
|
207
|
+
...Array.from(document.querySelectorAll(
|
|
208
|
+
'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], [role="textbox"], [role="combobox"], [contenteditable="true"]'
|
|
209
|
+
)),
|
|
210
|
+
...collectEditableControls(document)
|
|
211
|
+
];
|
|
46
212
|
const nodes = [];
|
|
47
|
-
|
|
213
|
+
interactiveCandidates.forEach((candidate) => {
|
|
214
|
+
const el = resolveEditableControlElement(candidate);
|
|
215
|
+
if (interactiveSet.has(el)) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
interactiveSet.add(el);
|
|
48
219
|
if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
|
|
49
220
|
return;
|
|
50
221
|
}
|
|
@@ -56,25 +227,24 @@ function generateMinifiedAOM() {
|
|
|
56
227
|
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
57
228
|
const ariaLabel = el.getAttribute("aria-label");
|
|
58
229
|
const placeholder = el.getAttribute("placeholder");
|
|
59
|
-
|
|
60
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
|
|
61
|
-
value = el.value;
|
|
62
|
-
}
|
|
230
|
+
const value = readEditableControlValue(el, { maskPasswords: false }) || void 0;
|
|
63
231
|
let role = el.tagName.toLowerCase();
|
|
64
232
|
if (el.hasAttribute("role")) {
|
|
65
233
|
role = el.getAttribute("role");
|
|
66
234
|
} else if (role === "a") {
|
|
67
235
|
role = "link";
|
|
68
|
-
} else if (el
|
|
69
|
-
|
|
236
|
+
} else if (el.tagName.toLowerCase() === "input") {
|
|
237
|
+
const inputType = el.type;
|
|
238
|
+
role = inputType ? `input[${inputType}]` : "input";
|
|
70
239
|
}
|
|
71
240
|
const node = { uid, role };
|
|
72
241
|
const displayLabel = ariaLabel || text || placeholder;
|
|
73
242
|
if (displayLabel) {
|
|
74
243
|
node.text = displayLabel.substring(0, 100);
|
|
75
244
|
}
|
|
76
|
-
|
|
77
|
-
|
|
245
|
+
const controlName = readEditableControlName(el);
|
|
246
|
+
if (controlName) {
|
|
247
|
+
node.name = controlName;
|
|
78
248
|
}
|
|
79
249
|
if (value) {
|
|
80
250
|
node.value = value.substring(0, 100);
|
|
@@ -102,6 +272,7 @@ var uidMap, nextUid;
|
|
|
102
272
|
var init_aom = __esm({
|
|
103
273
|
"src/utils/aom.ts"() {
|
|
104
274
|
"use strict";
|
|
275
|
+
init_editable_controls();
|
|
105
276
|
uidMap = /* @__PURE__ */ new Map();
|
|
106
277
|
nextUid = 1;
|
|
107
278
|
}
|
|
@@ -616,6 +787,7 @@ function useAutoExtract(devMode) {
|
|
|
616
787
|
}
|
|
617
788
|
|
|
618
789
|
// src/utils/dom-summary.ts
|
|
790
|
+
init_editable_controls();
|
|
619
791
|
function textOf(el) {
|
|
620
792
|
return el?.textContent?.trim().slice(0, 200) ?? "";
|
|
621
793
|
}
|
|
@@ -642,8 +814,9 @@ function safeQueryAll(selector) {
|
|
|
642
814
|
}
|
|
643
815
|
}
|
|
644
816
|
function findInputLabel(el) {
|
|
645
|
-
|
|
646
|
-
|
|
817
|
+
const labels = el.labels;
|
|
818
|
+
if (labels && labels.length > 0) {
|
|
819
|
+
const labelText = labels[0].textContent?.trim();
|
|
647
820
|
if (labelText) return labelText.slice(0, 80);
|
|
648
821
|
}
|
|
649
822
|
const ariaLabel = el.getAttribute("aria-label");
|
|
@@ -661,11 +834,12 @@ function findInputLabel(el) {
|
|
|
661
834
|
}
|
|
662
835
|
const closestCell = el.closest('td, th, div[role="cell"], div[role="columnheader"]');
|
|
663
836
|
if (closestCell) {
|
|
837
|
+
const inputType = String(el.type || "").toLowerCase();
|
|
664
838
|
if (closestCell.tagName === "TH" || closestCell.getAttribute("role") === "columnheader") {
|
|
665
|
-
if (
|
|
839
|
+
if (inputType === "checkbox") return "Select All";
|
|
666
840
|
}
|
|
667
841
|
const row = el.closest('tr, div[role="row"]');
|
|
668
|
-
if (row &&
|
|
842
|
+
if (row && inputType === "checkbox") {
|
|
669
843
|
const cells = row.querySelectorAll('td, div[role="cell"]');
|
|
670
844
|
for (const cell of cells) {
|
|
671
845
|
if (cell === closestCell) continue;
|
|
@@ -696,11 +870,11 @@ function captureDomSummary(tags) {
|
|
|
696
870
|
const mapInput = (input) => {
|
|
697
871
|
const el = input;
|
|
698
872
|
return {
|
|
699
|
-
name: el
|
|
700
|
-
type: el
|
|
701
|
-
value:
|
|
702
|
-
disabled: el
|
|
703
|
-
placeholder: el
|
|
873
|
+
name: readEditableControlName(el),
|
|
874
|
+
type: readEditableControlType(el),
|
|
875
|
+
value: readEditableControlValue(el),
|
|
876
|
+
disabled: isEditableControlDisabled(el),
|
|
877
|
+
placeholder: readEditableControlPlaceholder(el),
|
|
704
878
|
fingerprint: generateFingerprint(el),
|
|
705
879
|
label: findInputLabel(el)
|
|
706
880
|
};
|
|
@@ -708,17 +882,14 @@ function captureDomSummary(tags) {
|
|
|
708
882
|
const formElements = safeQueryAll("form").slice(0, 5);
|
|
709
883
|
const formInputSet = /* @__PURE__ */ new Set();
|
|
710
884
|
const forms = formElements.map((form) => {
|
|
711
|
-
const inputs =
|
|
885
|
+
const inputs = collectEditableControls(form).slice(0, 15);
|
|
712
886
|
inputs.forEach((el) => formInputSet.add(el));
|
|
713
887
|
return {
|
|
714
888
|
id: form.id || form.getAttribute("name") || null,
|
|
715
889
|
inputs: inputs.map(mapInput)
|
|
716
890
|
};
|
|
717
891
|
});
|
|
718
|
-
const standaloneInputs =
|
|
719
|
-
const type = el.type;
|
|
720
|
-
return type !== "hidden";
|
|
721
|
-
}).slice(0, 20).map(mapInput);
|
|
892
|
+
const standaloneInputs = collectEditableControls(document).filter((el) => !el.closest("form") && !formInputSet.has(el)).slice(0, 20).map(mapInput);
|
|
722
893
|
if (standaloneInputs.length > 0) {
|
|
723
894
|
forms.push({ id: "__standalone__", inputs: standaloneInputs });
|
|
724
895
|
}
|
|
@@ -3358,6 +3529,9 @@ function compactTourForTransport(tour) {
|
|
|
3358
3529
|
};
|
|
3359
3530
|
}
|
|
3360
3531
|
|
|
3532
|
+
// src/hooks/useTourPlayback.ts
|
|
3533
|
+
init_editable_controls();
|
|
3534
|
+
|
|
3361
3535
|
// src/utils/tour-playback-guards.ts
|
|
3362
3536
|
var playbackOwners = /* @__PURE__ */ new Map();
|
|
3363
3537
|
function shouldExecuteTourCommandBatch(isPlaybackActive) {
|
|
@@ -3699,8 +3873,8 @@ async function performInteractiveFill(target, value) {
|
|
|
3699
3873
|
inputTarget.dispatchEvent(new Event("change", { bubbles: true }));
|
|
3700
3874
|
inputTarget.blur();
|
|
3701
3875
|
} else {
|
|
3702
|
-
const shadowInput =
|
|
3703
|
-
if (shadowInput) {
|
|
3876
|
+
const shadowInput = findEditableControlInShadowRoot(target);
|
|
3877
|
+
if (shadowInput && isValueBearingElement(shadowInput)) {
|
|
3704
3878
|
const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
3705
3879
|
if (nativeSetter) nativeSetter.call(shadowInput, value);
|
|
3706
3880
|
else shadowInput.value = value;
|
|
@@ -3714,19 +3888,6 @@ async function performInteractiveFill(target, value) {
|
|
|
3714
3888
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
3715
3889
|
inputTarget.classList.remove("modelnex-agent-type");
|
|
3716
3890
|
}
|
|
3717
|
-
function findInputInShadowRoot(root) {
|
|
3718
|
-
if (root.shadowRoot) {
|
|
3719
|
-
const found = root.shadowRoot.querySelector('input:not([type="hidden"]):not([disabled]), textarea:not([disabled])');
|
|
3720
|
-
if (found) return found;
|
|
3721
|
-
}
|
|
3722
|
-
for (const child of Array.from(root.children)) {
|
|
3723
|
-
if (child instanceof HTMLElement) {
|
|
3724
|
-
const found = findInputInShadowRoot(child);
|
|
3725
|
-
if (found) return found;
|
|
3726
|
-
}
|
|
3727
|
-
}
|
|
3728
|
-
return null;
|
|
3729
|
-
}
|
|
3730
3891
|
function isTerminalAction(action) {
|
|
3731
3892
|
return [
|
|
3732
3893
|
"click_element",
|
|
@@ -3737,11 +3898,6 @@ function isTerminalAction(action) {
|
|
|
3737
3898
|
"end_tour"
|
|
3738
3899
|
].includes(action?.type);
|
|
3739
3900
|
}
|
|
3740
|
-
function isValueBearingElement(element) {
|
|
3741
|
-
return Boolean(
|
|
3742
|
-
element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
|
|
3743
|
-
);
|
|
3744
|
-
}
|
|
3745
3901
|
var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
|
|
3746
3902
|
var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
|
|
3747
3903
|
function getManualInputCommitPolicy(target) {
|
|
@@ -3757,59 +3913,10 @@ function getManualInputCommitPolicy(target) {
|
|
|
3757
3913
|
};
|
|
3758
3914
|
}
|
|
3759
3915
|
function resolveWaitTargetElement(element) {
|
|
3760
|
-
|
|
3761
|
-
return element;
|
|
3762
|
-
}
|
|
3763
|
-
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3764
|
-
return element;
|
|
3765
|
-
}
|
|
3766
|
-
if (element instanceof HTMLLabelElement && element.control instanceof HTMLElement) {
|
|
3767
|
-
return element.control;
|
|
3768
|
-
}
|
|
3769
|
-
const nestedControl = element.querySelector(
|
|
3770
|
-
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3771
|
-
);
|
|
3772
|
-
return nestedControl ?? element;
|
|
3916
|
+
return resolveEditableControlElement(element);
|
|
3773
3917
|
}
|
|
3774
3918
|
function readWaitTargetValue(element) {
|
|
3775
|
-
|
|
3776
|
-
return element.value.trim();
|
|
3777
|
-
}
|
|
3778
|
-
const genericValue = element.value;
|
|
3779
|
-
if (typeof genericValue === "string") {
|
|
3780
|
-
return genericValue.trim();
|
|
3781
|
-
}
|
|
3782
|
-
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
3783
|
-
return String(genericValue).trim();
|
|
3784
|
-
}
|
|
3785
|
-
if (element.isContentEditable) {
|
|
3786
|
-
return (element.textContent || "").trim();
|
|
3787
|
-
}
|
|
3788
|
-
const ariaValueText = element.getAttribute("aria-valuetext");
|
|
3789
|
-
if (typeof ariaValueText === "string" && ariaValueText.trim()) {
|
|
3790
|
-
return ariaValueText.trim();
|
|
3791
|
-
}
|
|
3792
|
-
const ariaValueNow = element.getAttribute("aria-valuenow");
|
|
3793
|
-
if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
|
|
3794
|
-
return ariaValueNow.trim();
|
|
3795
|
-
}
|
|
3796
|
-
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3797
|
-
const nestedControl = element.querySelector(
|
|
3798
|
-
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3799
|
-
);
|
|
3800
|
-
if (nestedControl && nestedControl !== element) {
|
|
3801
|
-
const nestedValue = readWaitTargetValue(nestedControl);
|
|
3802
|
-
if (nestedValue) {
|
|
3803
|
-
return nestedValue;
|
|
3804
|
-
}
|
|
3805
|
-
}
|
|
3806
|
-
return (element.textContent || "").trim();
|
|
3807
|
-
}
|
|
3808
|
-
const shadowInput = findInputInShadowRoot(element);
|
|
3809
|
-
if (shadowInput) {
|
|
3810
|
-
return shadowInput.value.trim();
|
|
3811
|
-
}
|
|
3812
|
-
return "";
|
|
3919
|
+
return readEditableControlValue(element, { maskPasswords: false });
|
|
3813
3920
|
}
|
|
3814
3921
|
function buildManualCompletionTranscript(step, eventName) {
|
|
3815
3922
|
const targetLabel = step?.element?.textContaining || step?.ask || step?.goal || step?.narration || "the highlighted step";
|
|
@@ -3826,7 +3933,7 @@ function isEditableWaitTarget(element) {
|
|
|
3826
3933
|
const target = resolveWaitTargetElement(element);
|
|
3827
3934
|
return isValueBearingElement(target) || target.isContentEditable || target.getAttribute("role") === "textbox" || target.getAttribute("role") === "combobox";
|
|
3828
3935
|
}
|
|
3829
|
-
function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
3936
|
+
function createManualWaitForTarget(rawTarget, eventName, step, options = {}) {
|
|
3830
3937
|
const target = resolveWaitTargetElement(rawTarget);
|
|
3831
3938
|
const completionTranscript = buildManualCompletionTranscript(step, eventName);
|
|
3832
3939
|
const isInputLikeEvent = isInputLikeWait(eventName, step);
|
|
@@ -3868,6 +3975,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3868
3975
|
}
|
|
3869
3976
|
};
|
|
3870
3977
|
const scheduleIdleCommit = () => {
|
|
3978
|
+
options.onObservedInput?.();
|
|
3871
3979
|
const currentValue = readWaitTargetValue(target);
|
|
3872
3980
|
if (!currentValue) {
|
|
3873
3981
|
clearIdleCommit();
|
|
@@ -3880,6 +3988,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3880
3988
|
}, commitPolicy.idleCommitMs);
|
|
3881
3989
|
};
|
|
3882
3990
|
const handleImmediateCommitEvent = () => {
|
|
3991
|
+
options.onObservedInput?.();
|
|
3883
3992
|
const currentValue = readWaitTargetValue(target);
|
|
3884
3993
|
if (currentValue) {
|
|
3885
3994
|
clearIdleCommit();
|
|
@@ -3895,6 +4004,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3895
4004
|
}
|
|
3896
4005
|
if (typeof MutationObserver !== "undefined") {
|
|
3897
4006
|
observer = new MutationObserver(() => {
|
|
4007
|
+
options.onObservedInput?.();
|
|
3898
4008
|
scheduleIdleCommit();
|
|
3899
4009
|
});
|
|
3900
4010
|
observer.observe(target, {
|
|
@@ -4018,6 +4128,7 @@ function useTourPlayback({
|
|
|
4018
4128
|
const voiceInputResolveRef = (0, import_react12.useRef)(null);
|
|
4019
4129
|
const askOrFillRef = (0, import_react12.useRef)(null);
|
|
4020
4130
|
const pendingManualWaitCleanupRef = (0, import_react12.useRef)(null);
|
|
4131
|
+
const pendingManualInputSyncRef = (0, import_react12.useRef)(null);
|
|
4021
4132
|
const llmRespondingRef = (0, import_react12.useRef)(false);
|
|
4022
4133
|
const interruptedForQuestionRef = (0, import_react12.useRef)(false);
|
|
4023
4134
|
const pendingInputBufRef = (0, import_react12.useRef)(null);
|
|
@@ -4117,6 +4228,7 @@ function useTourPlayback({
|
|
|
4117
4228
|
}, { devMode: devModeRef.current });
|
|
4118
4229
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4119
4230
|
pendingManualWaitCleanupRef.current = null;
|
|
4231
|
+
clearPendingManualInputSync();
|
|
4120
4232
|
if (voiceInputResolveRef.current) {
|
|
4121
4233
|
const resolvePendingVoiceInput = voiceInputResolveRef.current;
|
|
4122
4234
|
voiceInputResolveRef.current = null;
|
|
@@ -4503,6 +4615,7 @@ function useTourPlayback({
|
|
|
4503
4615
|
const preferredWaitTarget = inputLikeWait ? batchPreferredWaitTarget ?? highlightedWaitTarget : highlightedWaitTarget;
|
|
4504
4616
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4505
4617
|
pendingManualWaitCleanupRef.current = null;
|
|
4618
|
+
clearPendingManualInputSync();
|
|
4506
4619
|
if (waitTargetHints) {
|
|
4507
4620
|
let manualWaitTarget = await resolveTargetElement2(waitTargetHints, currentStep);
|
|
4508
4621
|
if (inputLikeWait && preferredWaitTarget && manualWaitTarget && manualWaitTarget !== preferredWaitTarget && !isEditableWaitTarget(manualWaitTarget) && isEditableWaitTarget(preferredWaitTarget)) {
|
|
@@ -4513,14 +4626,18 @@ function useTourPlayback({
|
|
|
4513
4626
|
}, { devMode: devModeRef.current });
|
|
4514
4627
|
}
|
|
4515
4628
|
if (manualWaitTarget) {
|
|
4516
|
-
const manualWait = createManualWaitForTarget(manualWaitTarget, waitEvent, currentStep
|
|
4629
|
+
const manualWait = createManualWaitForTarget(manualWaitTarget, waitEvent, currentStep, {
|
|
4630
|
+
onObservedInput: inputLikeWait ? scheduleManualInputSync : null
|
|
4631
|
+
});
|
|
4517
4632
|
manualWaitPromise = manualWait.promise;
|
|
4518
4633
|
manualWaitKind = manualWait.kind;
|
|
4519
4634
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
4520
4635
|
}
|
|
4521
4636
|
}
|
|
4522
4637
|
if (!manualWaitPromise && preferredWaitTarget) {
|
|
4523
|
-
const manualWait = createManualWaitForTarget(preferredWaitTarget, waitEvent, currentStep
|
|
4638
|
+
const manualWait = createManualWaitForTarget(preferredWaitTarget, waitEvent, currentStep, {
|
|
4639
|
+
onObservedInput: inputLikeWait ? scheduleManualInputSync : null
|
|
4640
|
+
});
|
|
4524
4641
|
manualWaitPromise = manualWait.promise;
|
|
4525
4642
|
manualWaitKind = manualWait.kind;
|
|
4526
4643
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
@@ -4534,7 +4651,9 @@ function useTourPlayback({
|
|
|
4534
4651
|
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), [contenteditable="true"], [role="textbox"]'
|
|
4535
4652
|
);
|
|
4536
4653
|
if (firstInput) {
|
|
4537
|
-
const manualWait = createManualWaitForTarget(firstInput, waitEvent, currentStep
|
|
4654
|
+
const manualWait = createManualWaitForTarget(firstInput, waitEvent, currentStep, {
|
|
4655
|
+
onObservedInput: scheduleManualInputSync
|
|
4656
|
+
});
|
|
4538
4657
|
manualWaitPromise = manualWait.promise;
|
|
4539
4658
|
manualWaitKind = manualWait.kind;
|
|
4540
4659
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
@@ -4580,6 +4699,7 @@ function useTourPlayback({
|
|
|
4580
4699
|
Promise.race([voiceOrTextWaitPromise, manualWaitPromise].filter(Boolean)).then(async (userText) => {
|
|
4581
4700
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4582
4701
|
pendingManualWaitCleanupRef.current = null;
|
|
4702
|
+
clearPendingManualInputSync();
|
|
4583
4703
|
voiceInputResolveRef.current = null;
|
|
4584
4704
|
setPlaybackState("executing");
|
|
4585
4705
|
const transcript = userText.trim();
|
|
@@ -4784,6 +4904,24 @@ function useTourPlayback({
|
|
|
4784
4904
|
domSummary: captureDomSummary()
|
|
4785
4905
|
});
|
|
4786
4906
|
}, []);
|
|
4907
|
+
const scheduleManualInputSync = (0, import_react12.useCallback)(() => {
|
|
4908
|
+
if (pendingManualInputSyncRef.current) {
|
|
4909
|
+
clearTimeout(pendingManualInputSyncRef.current);
|
|
4910
|
+
}
|
|
4911
|
+
pendingManualInputSyncRef.current = setTimeout(async () => {
|
|
4912
|
+
pendingManualInputSyncRef.current = null;
|
|
4913
|
+
if (!isActiveRef.current) return;
|
|
4914
|
+
const { waitForDomSettle: waitForDomSettle2 } = await Promise.resolve().then(() => (init_dom_sync(), dom_sync_exports));
|
|
4915
|
+
await waitForDomSettle2({ timeoutMs: 600, debounceMs: 100 });
|
|
4916
|
+
await syncAOM();
|
|
4917
|
+
}, 150);
|
|
4918
|
+
}, [syncAOM]);
|
|
4919
|
+
const clearPendingManualInputSync = (0, import_react12.useCallback)(() => {
|
|
4920
|
+
if (pendingManualInputSyncRef.current) {
|
|
4921
|
+
clearTimeout(pendingManualInputSyncRef.current);
|
|
4922
|
+
pendingManualInputSyncRef.current = null;
|
|
4923
|
+
}
|
|
4924
|
+
}, []);
|
|
4787
4925
|
const interruptExecution = (0, import_react12.useCallback)((transcript) => {
|
|
4788
4926
|
if (!isSocketWritable(socketRef.current) || !isActiveRef.current) return false;
|
|
4789
4927
|
if (!commandInFlightRef.current && !voice.isSpeaking) return false;
|
|
@@ -4822,6 +4960,7 @@ function useTourPlayback({
|
|
|
4822
4960
|
activeCommandBatchIdRef.current = null;
|
|
4823
4961
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4824
4962
|
pendingManualWaitCleanupRef.current = null;
|
|
4963
|
+
clearPendingManualInputSync();
|
|
4825
4964
|
removeHighlight();
|
|
4826
4965
|
removeCaption();
|
|
4827
4966
|
voice.stopSpeaking();
|
|
@@ -4873,6 +5012,7 @@ function useTourPlayback({
|
|
|
4873
5012
|
removeCaption();
|
|
4874
5013
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4875
5014
|
pendingManualWaitCleanupRef.current = null;
|
|
5015
|
+
clearPendingManualInputSync();
|
|
4876
5016
|
if (!skipRequestedRef.current && userProfile?.userId && tourRef.current) {
|
|
4877
5017
|
markTourComplete(serverUrl, toursApiBaseRef.current, tourRef.current.id, userProfile.userId, experienceType, websiteId);
|
|
4878
5018
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
collectEditableControls,
|
|
3
|
+
findEditableControlInShadowRoot,
|
|
4
|
+
generateMinifiedAOM,
|
|
5
|
+
isEditableControlDisabled,
|
|
6
|
+
isValueBearingElement,
|
|
7
|
+
readEditableControlName,
|
|
8
|
+
readEditableControlPlaceholder,
|
|
9
|
+
readEditableControlType,
|
|
10
|
+
readEditableControlValue,
|
|
11
|
+
resolveEditableControlElement
|
|
12
|
+
} from "./chunk-H4LUY7LI.mjs";
|
|
4
13
|
|
|
5
14
|
// src/index.ts
|
|
6
15
|
import React8, { useState as useState15, useCallback as useCallback14, useEffect as useEffect19, useMemo as useMemo5 } from "react";
|
|
@@ -431,8 +440,9 @@ function safeQueryAll(selector) {
|
|
|
431
440
|
}
|
|
432
441
|
}
|
|
433
442
|
function findInputLabel(el) {
|
|
434
|
-
|
|
435
|
-
|
|
443
|
+
const labels = el.labels;
|
|
444
|
+
if (labels && labels.length > 0) {
|
|
445
|
+
const labelText = labels[0].textContent?.trim();
|
|
436
446
|
if (labelText) return labelText.slice(0, 80);
|
|
437
447
|
}
|
|
438
448
|
const ariaLabel = el.getAttribute("aria-label");
|
|
@@ -450,11 +460,12 @@ function findInputLabel(el) {
|
|
|
450
460
|
}
|
|
451
461
|
const closestCell = el.closest('td, th, div[role="cell"], div[role="columnheader"]');
|
|
452
462
|
if (closestCell) {
|
|
463
|
+
const inputType = String(el.type || "").toLowerCase();
|
|
453
464
|
if (closestCell.tagName === "TH" || closestCell.getAttribute("role") === "columnheader") {
|
|
454
|
-
if (
|
|
465
|
+
if (inputType === "checkbox") return "Select All";
|
|
455
466
|
}
|
|
456
467
|
const row = el.closest('tr, div[role="row"]');
|
|
457
|
-
if (row &&
|
|
468
|
+
if (row && inputType === "checkbox") {
|
|
458
469
|
const cells = row.querySelectorAll('td, div[role="cell"]');
|
|
459
470
|
for (const cell of cells) {
|
|
460
471
|
if (cell === closestCell) continue;
|
|
@@ -485,11 +496,11 @@ function captureDomSummary(tags) {
|
|
|
485
496
|
const mapInput = (input) => {
|
|
486
497
|
const el = input;
|
|
487
498
|
return {
|
|
488
|
-
name: el
|
|
489
|
-
type: el
|
|
490
|
-
value:
|
|
491
|
-
disabled: el
|
|
492
|
-
placeholder: el
|
|
499
|
+
name: readEditableControlName(el),
|
|
500
|
+
type: readEditableControlType(el),
|
|
501
|
+
value: readEditableControlValue(el),
|
|
502
|
+
disabled: isEditableControlDisabled(el),
|
|
503
|
+
placeholder: readEditableControlPlaceholder(el),
|
|
493
504
|
fingerprint: generateFingerprint(el),
|
|
494
505
|
label: findInputLabel(el)
|
|
495
506
|
};
|
|
@@ -497,17 +508,14 @@ function captureDomSummary(tags) {
|
|
|
497
508
|
const formElements = safeQueryAll("form").slice(0, 5);
|
|
498
509
|
const formInputSet = /* @__PURE__ */ new Set();
|
|
499
510
|
const forms = formElements.map((form) => {
|
|
500
|
-
const inputs =
|
|
511
|
+
const inputs = collectEditableControls(form).slice(0, 15);
|
|
501
512
|
inputs.forEach((el) => formInputSet.add(el));
|
|
502
513
|
return {
|
|
503
514
|
id: form.id || form.getAttribute("name") || null,
|
|
504
515
|
inputs: inputs.map(mapInput)
|
|
505
516
|
};
|
|
506
517
|
});
|
|
507
|
-
const standaloneInputs =
|
|
508
|
-
const type = el.type;
|
|
509
|
-
return type !== "hidden";
|
|
510
|
-
}).slice(0, 20).map(mapInput);
|
|
518
|
+
const standaloneInputs = collectEditableControls(document).filter((el) => !el.closest("form") && !formInputSet.has(el)).slice(0, 20).map(mapInput);
|
|
511
519
|
if (standaloneInputs.length > 0) {
|
|
512
520
|
forms.push({ id: "__standalone__", inputs: standaloneInputs });
|
|
513
521
|
}
|
|
@@ -3488,8 +3496,8 @@ async function performInteractiveFill(target, value) {
|
|
|
3488
3496
|
inputTarget.dispatchEvent(new Event("change", { bubbles: true }));
|
|
3489
3497
|
inputTarget.blur();
|
|
3490
3498
|
} else {
|
|
3491
|
-
const shadowInput =
|
|
3492
|
-
if (shadowInput) {
|
|
3499
|
+
const shadowInput = findEditableControlInShadowRoot(target);
|
|
3500
|
+
if (shadowInput && isValueBearingElement(shadowInput)) {
|
|
3493
3501
|
const nativeSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
3494
3502
|
if (nativeSetter) nativeSetter.call(shadowInput, value);
|
|
3495
3503
|
else shadowInput.value = value;
|
|
@@ -3503,19 +3511,6 @@ async function performInteractiveFill(target, value) {
|
|
|
3503
3511
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
3504
3512
|
inputTarget.classList.remove("modelnex-agent-type");
|
|
3505
3513
|
}
|
|
3506
|
-
function findInputInShadowRoot(root) {
|
|
3507
|
-
if (root.shadowRoot) {
|
|
3508
|
-
const found = root.shadowRoot.querySelector('input:not([type="hidden"]):not([disabled]), textarea:not([disabled])');
|
|
3509
|
-
if (found) return found;
|
|
3510
|
-
}
|
|
3511
|
-
for (const child of Array.from(root.children)) {
|
|
3512
|
-
if (child instanceof HTMLElement) {
|
|
3513
|
-
const found = findInputInShadowRoot(child);
|
|
3514
|
-
if (found) return found;
|
|
3515
|
-
}
|
|
3516
|
-
}
|
|
3517
|
-
return null;
|
|
3518
|
-
}
|
|
3519
3514
|
function isTerminalAction(action) {
|
|
3520
3515
|
return [
|
|
3521
3516
|
"click_element",
|
|
@@ -3526,11 +3521,6 @@ function isTerminalAction(action) {
|
|
|
3526
3521
|
"end_tour"
|
|
3527
3522
|
].includes(action?.type);
|
|
3528
3523
|
}
|
|
3529
|
-
function isValueBearingElement(element) {
|
|
3530
|
-
return Boolean(
|
|
3531
|
-
element && (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement)
|
|
3532
|
-
);
|
|
3533
|
-
}
|
|
3534
3524
|
var DEFAULT_TEXT_INPUT_IDLE_COMMIT_MS = 700;
|
|
3535
3525
|
var DEFAULT_SELECTION_INPUT_IDLE_COMMIT_MS = 250;
|
|
3536
3526
|
function getManualInputCommitPolicy(target) {
|
|
@@ -3546,59 +3536,10 @@ function getManualInputCommitPolicy(target) {
|
|
|
3546
3536
|
};
|
|
3547
3537
|
}
|
|
3548
3538
|
function resolveWaitTargetElement(element) {
|
|
3549
|
-
|
|
3550
|
-
return element;
|
|
3551
|
-
}
|
|
3552
|
-
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3553
|
-
return element;
|
|
3554
|
-
}
|
|
3555
|
-
if (element instanceof HTMLLabelElement && element.control instanceof HTMLElement) {
|
|
3556
|
-
return element.control;
|
|
3557
|
-
}
|
|
3558
|
-
const nestedControl = element.querySelector(
|
|
3559
|
-
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3560
|
-
);
|
|
3561
|
-
return nestedControl ?? element;
|
|
3539
|
+
return resolveEditableControlElement(element);
|
|
3562
3540
|
}
|
|
3563
3541
|
function readWaitTargetValue(element) {
|
|
3564
|
-
|
|
3565
|
-
return element.value.trim();
|
|
3566
|
-
}
|
|
3567
|
-
const genericValue = element.value;
|
|
3568
|
-
if (typeof genericValue === "string") {
|
|
3569
|
-
return genericValue.trim();
|
|
3570
|
-
}
|
|
3571
|
-
if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
|
|
3572
|
-
return String(genericValue).trim();
|
|
3573
|
-
}
|
|
3574
|
-
if (element.isContentEditable) {
|
|
3575
|
-
return (element.textContent || "").trim();
|
|
3576
|
-
}
|
|
3577
|
-
const ariaValueText = element.getAttribute("aria-valuetext");
|
|
3578
|
-
if (typeof ariaValueText === "string" && ariaValueText.trim()) {
|
|
3579
|
-
return ariaValueText.trim();
|
|
3580
|
-
}
|
|
3581
|
-
const ariaValueNow = element.getAttribute("aria-valuenow");
|
|
3582
|
-
if (typeof ariaValueNow === "string" && ariaValueNow.trim()) {
|
|
3583
|
-
return ariaValueNow.trim();
|
|
3584
|
-
}
|
|
3585
|
-
if (element.getAttribute("role") === "textbox" || element.getAttribute("role") === "combobox") {
|
|
3586
|
-
const nestedControl = element.querySelector(
|
|
3587
|
-
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), select:not([disabled]), [contenteditable="true"], [role="textbox"], [role="combobox"]'
|
|
3588
|
-
);
|
|
3589
|
-
if (nestedControl && nestedControl !== element) {
|
|
3590
|
-
const nestedValue = readWaitTargetValue(nestedControl);
|
|
3591
|
-
if (nestedValue) {
|
|
3592
|
-
return nestedValue;
|
|
3593
|
-
}
|
|
3594
|
-
}
|
|
3595
|
-
return (element.textContent || "").trim();
|
|
3596
|
-
}
|
|
3597
|
-
const shadowInput = findInputInShadowRoot(element);
|
|
3598
|
-
if (shadowInput) {
|
|
3599
|
-
return shadowInput.value.trim();
|
|
3600
|
-
}
|
|
3601
|
-
return "";
|
|
3542
|
+
return readEditableControlValue(element, { maskPasswords: false });
|
|
3602
3543
|
}
|
|
3603
3544
|
function buildManualCompletionTranscript(step, eventName) {
|
|
3604
3545
|
const targetLabel = step?.element?.textContaining || step?.ask || step?.goal || step?.narration || "the highlighted step";
|
|
@@ -3615,7 +3556,7 @@ function isEditableWaitTarget(element) {
|
|
|
3615
3556
|
const target = resolveWaitTargetElement(element);
|
|
3616
3557
|
return isValueBearingElement(target) || target.isContentEditable || target.getAttribute("role") === "textbox" || target.getAttribute("role") === "combobox";
|
|
3617
3558
|
}
|
|
3618
|
-
function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
3559
|
+
function createManualWaitForTarget(rawTarget, eventName, step, options = {}) {
|
|
3619
3560
|
const target = resolveWaitTargetElement(rawTarget);
|
|
3620
3561
|
const completionTranscript = buildManualCompletionTranscript(step, eventName);
|
|
3621
3562
|
const isInputLikeEvent = isInputLikeWait(eventName, step);
|
|
@@ -3657,6 +3598,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3657
3598
|
}
|
|
3658
3599
|
};
|
|
3659
3600
|
const scheduleIdleCommit = () => {
|
|
3601
|
+
options.onObservedInput?.();
|
|
3660
3602
|
const currentValue = readWaitTargetValue(target);
|
|
3661
3603
|
if (!currentValue) {
|
|
3662
3604
|
clearIdleCommit();
|
|
@@ -3669,6 +3611,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3669
3611
|
}, commitPolicy.idleCommitMs);
|
|
3670
3612
|
};
|
|
3671
3613
|
const handleImmediateCommitEvent = () => {
|
|
3614
|
+
options.onObservedInput?.();
|
|
3672
3615
|
const currentValue = readWaitTargetValue(target);
|
|
3673
3616
|
if (currentValue) {
|
|
3674
3617
|
clearIdleCommit();
|
|
@@ -3684,6 +3627,7 @@ function createManualWaitForTarget(rawTarget, eventName, step) {
|
|
|
3684
3627
|
}
|
|
3685
3628
|
if (typeof MutationObserver !== "undefined") {
|
|
3686
3629
|
observer = new MutationObserver(() => {
|
|
3630
|
+
options.onObservedInput?.();
|
|
3687
3631
|
scheduleIdleCommit();
|
|
3688
3632
|
});
|
|
3689
3633
|
observer.observe(target, {
|
|
@@ -3807,6 +3751,7 @@ function useTourPlayback({
|
|
|
3807
3751
|
const voiceInputResolveRef = useRef8(null);
|
|
3808
3752
|
const askOrFillRef = useRef8(null);
|
|
3809
3753
|
const pendingManualWaitCleanupRef = useRef8(null);
|
|
3754
|
+
const pendingManualInputSyncRef = useRef8(null);
|
|
3810
3755
|
const llmRespondingRef = useRef8(false);
|
|
3811
3756
|
const interruptedForQuestionRef = useRef8(false);
|
|
3812
3757
|
const pendingInputBufRef = useRef8(null);
|
|
@@ -3906,6 +3851,7 @@ function useTourPlayback({
|
|
|
3906
3851
|
}, { devMode: devModeRef.current });
|
|
3907
3852
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
3908
3853
|
pendingManualWaitCleanupRef.current = null;
|
|
3854
|
+
clearPendingManualInputSync();
|
|
3909
3855
|
if (voiceInputResolveRef.current) {
|
|
3910
3856
|
const resolvePendingVoiceInput = voiceInputResolveRef.current;
|
|
3911
3857
|
voiceInputResolveRef.current = null;
|
|
@@ -3991,7 +3937,7 @@ function useTourPlayback({
|
|
|
3991
3937
|
resolve: async () => {
|
|
3992
3938
|
let targetEl = null;
|
|
3993
3939
|
if (params.uid) {
|
|
3994
|
-
const { getElementByUid } = await import("./aom-
|
|
3940
|
+
const { getElementByUid } = await import("./aom-LJNCLNXL.mjs");
|
|
3995
3941
|
targetEl = getElementByUid(params.uid);
|
|
3996
3942
|
}
|
|
3997
3943
|
if (!targetEl) {
|
|
@@ -4292,6 +4238,7 @@ function useTourPlayback({
|
|
|
4292
4238
|
const preferredWaitTarget = inputLikeWait ? batchPreferredWaitTarget ?? highlightedWaitTarget : highlightedWaitTarget;
|
|
4293
4239
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4294
4240
|
pendingManualWaitCleanupRef.current = null;
|
|
4241
|
+
clearPendingManualInputSync();
|
|
4295
4242
|
if (waitTargetHints) {
|
|
4296
4243
|
let manualWaitTarget = await resolveTargetElement2(waitTargetHints, currentStep);
|
|
4297
4244
|
if (inputLikeWait && preferredWaitTarget && manualWaitTarget && manualWaitTarget !== preferredWaitTarget && !isEditableWaitTarget(manualWaitTarget) && isEditableWaitTarget(preferredWaitTarget)) {
|
|
@@ -4302,14 +4249,18 @@ function useTourPlayback({
|
|
|
4302
4249
|
}, { devMode: devModeRef.current });
|
|
4303
4250
|
}
|
|
4304
4251
|
if (manualWaitTarget) {
|
|
4305
|
-
const manualWait = createManualWaitForTarget(manualWaitTarget, waitEvent, currentStep
|
|
4252
|
+
const manualWait = createManualWaitForTarget(manualWaitTarget, waitEvent, currentStep, {
|
|
4253
|
+
onObservedInput: inputLikeWait ? scheduleManualInputSync : null
|
|
4254
|
+
});
|
|
4306
4255
|
manualWaitPromise = manualWait.promise;
|
|
4307
4256
|
manualWaitKind = manualWait.kind;
|
|
4308
4257
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
4309
4258
|
}
|
|
4310
4259
|
}
|
|
4311
4260
|
if (!manualWaitPromise && preferredWaitTarget) {
|
|
4312
|
-
const manualWait = createManualWaitForTarget(preferredWaitTarget, waitEvent, currentStep
|
|
4261
|
+
const manualWait = createManualWaitForTarget(preferredWaitTarget, waitEvent, currentStep, {
|
|
4262
|
+
onObservedInput: inputLikeWait ? scheduleManualInputSync : null
|
|
4263
|
+
});
|
|
4313
4264
|
manualWaitPromise = manualWait.promise;
|
|
4314
4265
|
manualWaitKind = manualWait.kind;
|
|
4315
4266
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
@@ -4323,7 +4274,9 @@ function useTourPlayback({
|
|
|
4323
4274
|
'input:not([type="hidden"]):not([disabled]), textarea:not([disabled]), [contenteditable="true"], [role="textbox"]'
|
|
4324
4275
|
);
|
|
4325
4276
|
if (firstInput) {
|
|
4326
|
-
const manualWait = createManualWaitForTarget(firstInput, waitEvent, currentStep
|
|
4277
|
+
const manualWait = createManualWaitForTarget(firstInput, waitEvent, currentStep, {
|
|
4278
|
+
onObservedInput: scheduleManualInputSync
|
|
4279
|
+
});
|
|
4327
4280
|
manualWaitPromise = manualWait.promise;
|
|
4328
4281
|
manualWaitKind = manualWait.kind;
|
|
4329
4282
|
pendingManualWaitCleanupRef.current = manualWait.cleanup;
|
|
@@ -4369,6 +4322,7 @@ function useTourPlayback({
|
|
|
4369
4322
|
Promise.race([voiceOrTextWaitPromise, manualWaitPromise].filter(Boolean)).then(async (userText) => {
|
|
4370
4323
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4371
4324
|
pendingManualWaitCleanupRef.current = null;
|
|
4325
|
+
clearPendingManualInputSync();
|
|
4372
4326
|
voiceInputResolveRef.current = null;
|
|
4373
4327
|
setPlaybackState("executing");
|
|
4374
4328
|
const transcript = userText.trim();
|
|
@@ -4451,7 +4405,7 @@ function useTourPlayback({
|
|
|
4451
4405
|
void recordTourEvent(serverUrl, toursApiBaseRef.current, tour.id, userProfile.userId, "started", websiteId);
|
|
4452
4406
|
}
|
|
4453
4407
|
try {
|
|
4454
|
-
const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-
|
|
4408
|
+
const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
|
|
4455
4409
|
const aom = generateMinifiedAOM2();
|
|
4456
4410
|
if (socketRef.current === socket) {
|
|
4457
4411
|
emitSocketEvent(socket, "tour:sync_dom", {
|
|
@@ -4565,7 +4519,7 @@ function useTourPlayback({
|
|
|
4565
4519
|
}, [isActive, playbackState, voice.isListening, voice.isSpeaking]);
|
|
4566
4520
|
const syncAOM = useCallback7(async () => {
|
|
4567
4521
|
if (!isActiveRef.current) return;
|
|
4568
|
-
const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-
|
|
4522
|
+
const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-LJNCLNXL.mjs");
|
|
4569
4523
|
const aom = generateMinifiedAOM2();
|
|
4570
4524
|
emitSocketEvent(socketRef.current, "tour:sync_dom", {
|
|
4571
4525
|
url: window.location.pathname + window.location.search + window.location.hash,
|
|
@@ -4573,6 +4527,24 @@ function useTourPlayback({
|
|
|
4573
4527
|
domSummary: captureDomSummary()
|
|
4574
4528
|
});
|
|
4575
4529
|
}, []);
|
|
4530
|
+
const scheduleManualInputSync = useCallback7(() => {
|
|
4531
|
+
if (pendingManualInputSyncRef.current) {
|
|
4532
|
+
clearTimeout(pendingManualInputSyncRef.current);
|
|
4533
|
+
}
|
|
4534
|
+
pendingManualInputSyncRef.current = setTimeout(async () => {
|
|
4535
|
+
pendingManualInputSyncRef.current = null;
|
|
4536
|
+
if (!isActiveRef.current) return;
|
|
4537
|
+
const { waitForDomSettle } = await import("./dom-sync-GABDEODR.mjs");
|
|
4538
|
+
await waitForDomSettle({ timeoutMs: 600, debounceMs: 100 });
|
|
4539
|
+
await syncAOM();
|
|
4540
|
+
}, 150);
|
|
4541
|
+
}, [syncAOM]);
|
|
4542
|
+
const clearPendingManualInputSync = useCallback7(() => {
|
|
4543
|
+
if (pendingManualInputSyncRef.current) {
|
|
4544
|
+
clearTimeout(pendingManualInputSyncRef.current);
|
|
4545
|
+
pendingManualInputSyncRef.current = null;
|
|
4546
|
+
}
|
|
4547
|
+
}, []);
|
|
4576
4548
|
const interruptExecution = useCallback7((transcript) => {
|
|
4577
4549
|
if (!isSocketWritable(socketRef.current) || !isActiveRef.current) return false;
|
|
4578
4550
|
if (!commandInFlightRef.current && !voice.isSpeaking) return false;
|
|
@@ -4611,6 +4583,7 @@ function useTourPlayback({
|
|
|
4611
4583
|
activeCommandBatchIdRef.current = null;
|
|
4612
4584
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4613
4585
|
pendingManualWaitCleanupRef.current = null;
|
|
4586
|
+
clearPendingManualInputSync();
|
|
4614
4587
|
removeHighlight();
|
|
4615
4588
|
removeCaption();
|
|
4616
4589
|
voice.stopSpeaking();
|
|
@@ -4662,6 +4635,7 @@ function useTourPlayback({
|
|
|
4662
4635
|
removeCaption();
|
|
4663
4636
|
runCleanup(pendingManualWaitCleanupRef.current);
|
|
4664
4637
|
pendingManualWaitCleanupRef.current = null;
|
|
4638
|
+
clearPendingManualInputSync();
|
|
4665
4639
|
if (!skipRequestedRef.current && userProfile?.userId && tourRef.current) {
|
|
4666
4640
|
markTourComplete(serverUrl, toursApiBaseRef.current, tourRef.current.id, userProfile.userId, experienceType, websiteId);
|
|
4667
4641
|
}
|
package/package.json
CHANGED
package/dist/chunk-N65UEB6X.mjs
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// src/utils/aom.ts
|
|
2
|
-
var uidMap = /* @__PURE__ */ new Map();
|
|
3
|
-
var nextUid = 1;
|
|
4
|
-
function generateMinifiedAOM() {
|
|
5
|
-
uidMap.clear();
|
|
6
|
-
nextUid = 1;
|
|
7
|
-
const interactives = document.querySelectorAll(
|
|
8
|
-
'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"]'
|
|
9
|
-
);
|
|
10
|
-
const nodes = [];
|
|
11
|
-
interactives.forEach((el) => {
|
|
12
|
-
if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const uid = `node:${nextUid++}`;
|
|
19
|
-
uidMap.set(uid, el);
|
|
20
|
-
let text = (el.textContent || "").replace(/\s+/g, " ").trim();
|
|
21
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
22
|
-
const placeholder = el.getAttribute("placeholder");
|
|
23
|
-
let value = void 0;
|
|
24
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
|
|
25
|
-
value = el.value;
|
|
26
|
-
}
|
|
27
|
-
let role = el.tagName.toLowerCase();
|
|
28
|
-
if (el.hasAttribute("role")) {
|
|
29
|
-
role = el.getAttribute("role");
|
|
30
|
-
} else if (role === "a") {
|
|
31
|
-
role = "link";
|
|
32
|
-
} else if (el instanceof HTMLInputElement) {
|
|
33
|
-
role = el.type ? `input[${el.type}]` : "input";
|
|
34
|
-
}
|
|
35
|
-
const node = { uid, role };
|
|
36
|
-
const displayLabel = ariaLabel || text || placeholder;
|
|
37
|
-
if (displayLabel) {
|
|
38
|
-
node.text = displayLabel.substring(0, 100);
|
|
39
|
-
}
|
|
40
|
-
if (el.getAttribute("name")) {
|
|
41
|
-
node.name = el.getAttribute("name");
|
|
42
|
-
}
|
|
43
|
-
if (value) {
|
|
44
|
-
node.value = value.substring(0, 100);
|
|
45
|
-
}
|
|
46
|
-
if (el instanceof HTMLAnchorElement && el.href) {
|
|
47
|
-
try {
|
|
48
|
-
const url = new URL(el.href);
|
|
49
|
-
node.href = url.pathname + url.search + url.hash;
|
|
50
|
-
} catch {
|
|
51
|
-
node.href = el.getAttribute("href");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
nodes.push(node);
|
|
55
|
-
});
|
|
56
|
-
return { nodes };
|
|
57
|
-
}
|
|
58
|
-
function getElementByUid(uid) {
|
|
59
|
-
return uidMap.get(uid) || null;
|
|
60
|
-
}
|
|
61
|
-
function clearAOMMap() {
|
|
62
|
-
uidMap.clear();
|
|
63
|
-
nextUid = 1;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export {
|
|
67
|
-
generateMinifiedAOM,
|
|
68
|
-
getElementByUid,
|
|
69
|
-
clearAOMMap
|
|
70
|
-
};
|