@xpert-ai/chatkit-host-automation 0.3.1 → 0.3.2
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/README.md +9 -0
- package/dist/index.d.ts +73 -1
- package/dist/index.js +526 -163
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,3 +23,12 @@ The first version exposes a fixed tool allow-list:
|
|
|
23
23
|
- `host_page_select`
|
|
24
24
|
- `host_page_scroll`
|
|
25
25
|
- `host_page_navigate`
|
|
26
|
+
- `host_page_hover`
|
|
27
|
+
- `host_page_focus`
|
|
28
|
+
- `host_page_pointer`
|
|
29
|
+
- `host_page_screenshot`
|
|
30
|
+
- `host_page_wait_for`
|
|
31
|
+
|
|
32
|
+
Plain web hosts use the DOM fallback executor. The Chrome browser extension can
|
|
33
|
+
upgrade the same client tools through the Chrome DevTools Protocol for richer
|
|
34
|
+
snapshots and browser-level input.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ClientToolMessageInput } from '../../chatkit/src/index.ts';
|
|
|
2
2
|
|
|
3
3
|
export declare function createHostPageAutomationClientToolHandler(options?: HostPageAutomationOptions): HostPageAutomationClientToolHandler;
|
|
4
4
|
|
|
5
|
-
export declare const HOST_PAGE_AUTOMATION_TOOL_NAMES: readonly ["host_page_snapshot", "host_page_click", "host_page_fill", "host_page_press", "host_page_select", "host_page_scroll", "host_page_navigate"];
|
|
5
|
+
export declare const HOST_PAGE_AUTOMATION_TOOL_NAMES: readonly ["host_page_snapshot", "host_page_click", "host_page_fill", "host_page_press", "host_page_select", "host_page_scroll", "host_page_navigate", "host_page_hover", "host_page_focus", "host_page_pointer", "host_page_screenshot", "host_page_wait_for"];
|
|
6
6
|
|
|
7
7
|
export declare type HostPageAutomationClientToolCall = {
|
|
8
8
|
name: string;
|
|
@@ -19,17 +19,38 @@ export declare type HostPageAutomationElementSnapshot = {
|
|
|
19
19
|
role?: string;
|
|
20
20
|
name?: string;
|
|
21
21
|
text?: string;
|
|
22
|
+
nearbyText?: string[];
|
|
23
|
+
testId?: string;
|
|
22
24
|
value?: string;
|
|
23
25
|
placeholder?: string;
|
|
24
26
|
selector?: string;
|
|
25
27
|
disabled?: boolean;
|
|
28
|
+
enabled?: boolean;
|
|
26
29
|
checked?: boolean;
|
|
30
|
+
visible?: boolean;
|
|
31
|
+
actionable?: boolean;
|
|
27
32
|
rect: {
|
|
28
33
|
x: number;
|
|
29
34
|
y: number;
|
|
30
35
|
width: number;
|
|
31
36
|
height: number;
|
|
32
37
|
};
|
|
38
|
+
center?: {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
};
|
|
42
|
+
hitTarget?: {
|
|
43
|
+
tag: string;
|
|
44
|
+
role?: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
selector?: string;
|
|
47
|
+
};
|
|
48
|
+
hitStack?: Array<{
|
|
49
|
+
tag: string;
|
|
50
|
+
role?: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
selector?: string;
|
|
53
|
+
}>;
|
|
33
54
|
};
|
|
34
55
|
|
|
35
56
|
export declare class HostPageAutomationExecutor {
|
|
@@ -40,7 +61,11 @@ export declare class HostPageAutomationExecutor {
|
|
|
40
61
|
execute(name: HostPageAutomationToolName, params?: Record<string, unknown>): Promise<unknown>;
|
|
41
62
|
snapshot(): HostPageSnapshot;
|
|
42
63
|
private getRoot;
|
|
64
|
+
private getNavigationState;
|
|
65
|
+
private getFrameState;
|
|
43
66
|
private snapshotElement;
|
|
67
|
+
private snapshotElementWithoutRef;
|
|
68
|
+
private createElementSnapshot;
|
|
44
69
|
private resolveElement;
|
|
45
70
|
private click;
|
|
46
71
|
private fill;
|
|
@@ -48,6 +73,12 @@ export declare class HostPageAutomationExecutor {
|
|
|
48
73
|
private select;
|
|
49
74
|
private scroll;
|
|
50
75
|
private navigate;
|
|
76
|
+
private hover;
|
|
77
|
+
private focus;
|
|
78
|
+
private pointer;
|
|
79
|
+
private screenshot;
|
|
80
|
+
private waitFor;
|
|
81
|
+
private tryResolveElement;
|
|
51
82
|
private describeElement;
|
|
52
83
|
}
|
|
53
84
|
|
|
@@ -62,14 +93,55 @@ export declare type HostPageAutomationToolName = (typeof HOST_PAGE_AUTOMATION_TO
|
|
|
62
93
|
export declare type HostPageSnapshot = {
|
|
63
94
|
url: string;
|
|
64
95
|
title: string;
|
|
96
|
+
capabilities?: {
|
|
97
|
+
cdp?: boolean;
|
|
98
|
+
realInput?: boolean;
|
|
99
|
+
screenshot?: boolean;
|
|
100
|
+
accessibility?: boolean;
|
|
101
|
+
networkState?: boolean;
|
|
102
|
+
};
|
|
65
103
|
viewport: {
|
|
66
104
|
width: number;
|
|
67
105
|
height: number;
|
|
106
|
+
devicePixelRatio?: number;
|
|
68
107
|
};
|
|
69
108
|
scroll: {
|
|
70
109
|
x: number;
|
|
71
110
|
y: number;
|
|
72
111
|
};
|
|
112
|
+
page?: {
|
|
113
|
+
readyState?: string;
|
|
114
|
+
visibilityState?: string;
|
|
115
|
+
focusedElement?: HostPageAutomationElementSnapshot;
|
|
116
|
+
selection?: string;
|
|
117
|
+
};
|
|
118
|
+
navigation?: {
|
|
119
|
+
type?: string;
|
|
120
|
+
duration?: number;
|
|
121
|
+
domContentLoaded?: number;
|
|
122
|
+
loadEventEnd?: number;
|
|
123
|
+
};
|
|
124
|
+
frames?: Array<{
|
|
125
|
+
url?: string;
|
|
126
|
+
title?: string;
|
|
127
|
+
sameOrigin: boolean;
|
|
128
|
+
rect?: {
|
|
129
|
+
x: number;
|
|
130
|
+
y: number;
|
|
131
|
+
width: number;
|
|
132
|
+
height: number;
|
|
133
|
+
};
|
|
134
|
+
}>;
|
|
135
|
+
accessibility?: Array<{
|
|
136
|
+
ref?: string;
|
|
137
|
+
role?: string;
|
|
138
|
+
name?: string;
|
|
139
|
+
value?: string;
|
|
140
|
+
disabled?: boolean;
|
|
141
|
+
checked?: boolean;
|
|
142
|
+
expanded?: boolean;
|
|
143
|
+
focused?: boolean;
|
|
144
|
+
}>;
|
|
73
145
|
elements: HostPageAutomationElementSnapshot[];
|
|
74
146
|
};
|
|
75
147
|
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
const
|
|
1
|
+
const z = [
|
|
2
2
|
"host_page_snapshot",
|
|
3
3
|
"host_page_click",
|
|
4
4
|
"host_page_fill",
|
|
5
5
|
"host_page_press",
|
|
6
6
|
"host_page_select",
|
|
7
7
|
"host_page_scroll",
|
|
8
|
-
"host_page_navigate"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
"host_page_navigate",
|
|
9
|
+
"host_page_hover",
|
|
10
|
+
"host_page_focus",
|
|
11
|
+
"host_page_pointer",
|
|
12
|
+
"host_page_screenshot",
|
|
13
|
+
"host_page_wait_for"
|
|
14
|
+
], G = new Set(
|
|
15
|
+
z
|
|
16
|
+
), K = [
|
|
12
17
|
"a[href]",
|
|
13
18
|
"button",
|
|
14
19
|
"input",
|
|
@@ -20,52 +25,64 @@ const S = [
|
|
|
20
25
|
'[contenteditable=""]',
|
|
21
26
|
'[contenteditable="true"]',
|
|
22
27
|
"[aria-label]",
|
|
23
|
-
"[data-testid]"
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
"[data-testid]",
|
|
29
|
+
"[data-test-id]",
|
|
30
|
+
"[data-qa]"
|
|
31
|
+
].join(","), D = 100, J = 1e4, Q = 6e4;
|
|
32
|
+
function Z(t) {
|
|
33
|
+
return G.has(t);
|
|
27
34
|
}
|
|
28
|
-
function
|
|
35
|
+
function g(t) {
|
|
29
36
|
return t instanceof Document ? t : t.ownerDocument;
|
|
30
37
|
}
|
|
31
|
-
function
|
|
32
|
-
return
|
|
38
|
+
function N(t) {
|
|
39
|
+
return g(t).defaultView ?? window;
|
|
33
40
|
}
|
|
34
|
-
function
|
|
41
|
+
function h(t) {
|
|
35
42
|
return typeof t == "object" && t !== null && !Array.isArray(t) ? t : {};
|
|
36
43
|
}
|
|
37
|
-
function
|
|
44
|
+
function R(t, e) {
|
|
38
45
|
if (typeof t != "string" || t.trim() === "")
|
|
39
46
|
throw new Error(`${e} must be a non-empty string.`);
|
|
40
47
|
return t;
|
|
41
48
|
}
|
|
42
|
-
function
|
|
49
|
+
function p(t) {
|
|
43
50
|
return typeof t == "string" && t.trim() ? t : void 0;
|
|
44
51
|
}
|
|
45
|
-
function
|
|
52
|
+
function tt(t) {
|
|
53
|
+
return typeof t == "number" && Number.isInteger(t) ? t : void 0;
|
|
54
|
+
}
|
|
55
|
+
function M(t, e) {
|
|
46
56
|
if (typeof t != "number" || !Number.isFinite(t))
|
|
47
57
|
throw new Error(`${e} must be a finite number.`);
|
|
48
58
|
return t;
|
|
49
59
|
}
|
|
50
|
-
function
|
|
60
|
+
function T(t) {
|
|
51
61
|
return typeof t == "number" && Number.isFinite(t) ? t : void 0;
|
|
52
62
|
}
|
|
53
|
-
function
|
|
63
|
+
function F(t, e) {
|
|
64
|
+
return typeof t == "string" && e.includes(t) ? t : void 0;
|
|
65
|
+
}
|
|
66
|
+
function et(t) {
|
|
54
67
|
if (typeof t == "string")
|
|
55
68
|
return [t];
|
|
56
69
|
if (Array.isArray(t) && t.every((e) => typeof e == "string"))
|
|
57
70
|
return t;
|
|
58
71
|
throw new Error("value or values must be a string or an array of strings.");
|
|
59
72
|
}
|
|
60
|
-
function
|
|
73
|
+
function v(t) {
|
|
61
74
|
const e = (t.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
62
75
|
return e ? e.slice(0, 160) : void 0;
|
|
63
76
|
}
|
|
64
|
-
function
|
|
77
|
+
function V(t) {
|
|
78
|
+
const e = Array.from(t.childNodes).filter((n) => n.nodeType === Node.TEXT_NODE).map((n) => n.textContent ?? "").join(" ").replace(/\s+/g, " ").trim();
|
|
79
|
+
return e ? e.slice(0, 160) : void 0;
|
|
80
|
+
}
|
|
81
|
+
function nt(t) {
|
|
65
82
|
if (t instanceof HTMLInputElement || t instanceof HTMLTextAreaElement || t instanceof HTMLSelectElement)
|
|
66
83
|
return t.value;
|
|
67
84
|
}
|
|
68
|
-
function
|
|
85
|
+
function E(t) {
|
|
69
86
|
const e = t.getAttribute("aria-label");
|
|
70
87
|
if (e != null && e.trim())
|
|
71
88
|
return e.trim();
|
|
@@ -73,13 +90,54 @@ function L(t) {
|
|
|
73
90
|
if (n != null && n.trim())
|
|
74
91
|
return n.trim();
|
|
75
92
|
if (t instanceof HTMLInputElement) {
|
|
76
|
-
const r = Array.from(t.labels ?? []).map((
|
|
93
|
+
const r = Array.from(t.labels ?? []).map((c) => v(c)).filter(Boolean);
|
|
77
94
|
if (r.length > 0)
|
|
78
95
|
return r.join(" ").slice(0, 160);
|
|
79
96
|
}
|
|
80
|
-
|
|
97
|
+
const o = X(t)[0];
|
|
98
|
+
return o || v(t);
|
|
81
99
|
}
|
|
82
|
-
function
|
|
100
|
+
function ot(t) {
|
|
101
|
+
if (!(t instanceof HTMLElement || t instanceof SVGElement) || !m(t) || t.matches(
|
|
102
|
+
'input,textarea,select,button,a[href],[role="button"],[role="link"]'
|
|
103
|
+
))
|
|
104
|
+
return !1;
|
|
105
|
+
const e = V(t) ?? v(t);
|
|
106
|
+
return !!(e && e.length <= 120);
|
|
107
|
+
}
|
|
108
|
+
function X(t) {
|
|
109
|
+
const e = t.ownerDocument, n = e.body;
|
|
110
|
+
if (!n)
|
|
111
|
+
return [];
|
|
112
|
+
const o = t.getBoundingClientRect();
|
|
113
|
+
if (o.width <= 0 || o.height <= 0)
|
|
114
|
+
return [];
|
|
115
|
+
const r = o.top + o.height / 2, c = o.left + o.width / 2, s = [], i = e.createTreeWalker(n, NodeFilter.SHOW_ELEMENT);
|
|
116
|
+
let a = i.nextNode();
|
|
117
|
+
for (; a; ) {
|
|
118
|
+
const l = a;
|
|
119
|
+
if (l !== t && ot(l)) {
|
|
120
|
+
const u = l.getBoundingClientRect(), f = V(l) ?? v(l);
|
|
121
|
+
if (f) {
|
|
122
|
+
const b = u.top + u.height / 2, w = u.left + u.width / 2, y = u.right <= o.left + 12 && Math.abs(b - r) <= Math.max(28, o.height * 1.25), S = u.bottom <= o.top + 8 && o.top - u.bottom <= 80 && w >= o.left - 80 && w <= o.right + 80;
|
|
123
|
+
if (y || S) {
|
|
124
|
+
const j = y ? o.left - u.right + Math.abs(b - r) : o.top - u.bottom + Math.abs(w - c);
|
|
125
|
+
s.push({
|
|
126
|
+
text: f,
|
|
127
|
+
score: j + (y ? 0 : 100)
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
a = i.nextNode();
|
|
133
|
+
}
|
|
134
|
+
const d = /* @__PURE__ */ new Set();
|
|
135
|
+
return s.sort((l, u) => l.score - u.score).map((l) => l.text).filter((l) => d.has(l) ? !1 : (d.add(l), !0)).slice(0, 4);
|
|
136
|
+
}
|
|
137
|
+
function rt(t) {
|
|
138
|
+
return t.getAttribute("data-testid") ?? t.getAttribute("data-test-id") ?? t.getAttribute("data-qa") ?? void 0;
|
|
139
|
+
}
|
|
140
|
+
function x(t) {
|
|
83
141
|
const e = t.getAttribute("role");
|
|
84
142
|
if (e != null && e.trim())
|
|
85
143
|
return e.trim();
|
|
@@ -103,94 +161,221 @@ function A(t) {
|
|
|
103
161
|
return "textbox";
|
|
104
162
|
}
|
|
105
163
|
}
|
|
106
|
-
function
|
|
164
|
+
function q(t) {
|
|
107
165
|
return t instanceof HTMLButtonElement || t instanceof HTMLInputElement || t instanceof HTMLSelectElement || t instanceof HTMLTextAreaElement ? t.disabled || void 0 : t.getAttribute("aria-disabled") === "true" || void 0;
|
|
108
166
|
}
|
|
109
|
-
function
|
|
167
|
+
function it(t) {
|
|
110
168
|
return t instanceof HTMLInputElement && (t.type === "checkbox" || t.type === "radio") ? t.checked : void 0;
|
|
111
169
|
}
|
|
112
|
-
function
|
|
170
|
+
function st(t) {
|
|
171
|
+
const e = k(t);
|
|
172
|
+
if (!(e.width <= 0 || e.height <= 0))
|
|
173
|
+
return {
|
|
174
|
+
x: e.x + e.width / 2,
|
|
175
|
+
y: e.y + e.height / 2
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function $(t) {
|
|
179
|
+
return {
|
|
180
|
+
tag: t.tagName.toLowerCase(),
|
|
181
|
+
role: x(t),
|
|
182
|
+
name: E(t),
|
|
183
|
+
selector: P(t)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function m(t) {
|
|
113
187
|
if (!(t instanceof HTMLElement || t instanceof SVGElement) || t instanceof HTMLElement && t.hidden)
|
|
114
188
|
return !1;
|
|
115
189
|
const e = t.ownerDocument.defaultView, n = e == null ? void 0 : e.getComputedStyle(t);
|
|
116
190
|
return !(n && (n.display === "none" || n.visibility === "hidden" || n.opacity === "0"));
|
|
117
191
|
}
|
|
118
|
-
function
|
|
119
|
-
return t.matches(
|
|
192
|
+
function U(t) {
|
|
193
|
+
return t.matches(K) && m(t);
|
|
120
194
|
}
|
|
121
|
-
function
|
|
122
|
-
|
|
195
|
+
function ct(t) {
|
|
196
|
+
return q(t) !== !0;
|
|
197
|
+
}
|
|
198
|
+
function at(t) {
|
|
199
|
+
var n;
|
|
200
|
+
if (U(t))
|
|
201
|
+
return !0;
|
|
202
|
+
if (!(t instanceof HTMLElement))
|
|
203
|
+
return !1;
|
|
204
|
+
const e = (n = t.ownerDocument.defaultView) == null ? void 0 : n.getComputedStyle(t);
|
|
205
|
+
return ((e == null ? void 0 : e.cursor) === "pointer" || !!t.onclick) && m(t);
|
|
206
|
+
}
|
|
207
|
+
function k(t) {
|
|
208
|
+
var c, s;
|
|
123
209
|
const e = t.getBoundingClientRect();
|
|
124
|
-
let n = e.left,
|
|
210
|
+
let n = e.left, o = e.top, r = null;
|
|
125
211
|
try {
|
|
126
|
-
|
|
212
|
+
r = ((c = t.ownerDocument.defaultView) == null ? void 0 : c.frameElement) ?? null;
|
|
127
213
|
} catch {
|
|
128
|
-
|
|
214
|
+
r = null;
|
|
129
215
|
}
|
|
130
|
-
for (;
|
|
131
|
-
const
|
|
132
|
-
n +=
|
|
216
|
+
for (; r; ) {
|
|
217
|
+
const i = r.getBoundingClientRect();
|
|
218
|
+
n += i.left, o += i.top;
|
|
133
219
|
try {
|
|
134
|
-
|
|
220
|
+
r = ((s = r.ownerDocument.defaultView) == null ? void 0 : s.frameElement) ?? null;
|
|
135
221
|
} catch {
|
|
136
|
-
|
|
222
|
+
r = null;
|
|
137
223
|
}
|
|
138
224
|
}
|
|
139
225
|
return {
|
|
140
226
|
x: n,
|
|
141
|
-
y:
|
|
227
|
+
y: o,
|
|
142
228
|
width: e.width,
|
|
143
229
|
height: e.height
|
|
144
230
|
};
|
|
145
231
|
}
|
|
146
|
-
function
|
|
232
|
+
function P(t) {
|
|
147
233
|
const e = (o) => typeof CSS < "u" && typeof CSS.escape == "function" ? CSS.escape(o) : o.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
|
148
234
|
if (t.id)
|
|
149
235
|
return `#${e(t.id)}`;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
236
|
+
for (const o of ["data-testid", "data-test-id", "data-qa"]) {
|
|
237
|
+
const r = t.getAttribute(o);
|
|
238
|
+
if (r)
|
|
239
|
+
return `[${o}="${e(r)}"]`;
|
|
240
|
+
}
|
|
241
|
+
const n = t.getAttribute("name");
|
|
242
|
+
return n ? `${t.tagName.toLowerCase()}[name="${e(
|
|
243
|
+
n
|
|
156
244
|
)}"]` : t.tagName.toLowerCase();
|
|
157
245
|
}
|
|
158
|
-
function
|
|
159
|
-
const e =
|
|
246
|
+
function lt(t) {
|
|
247
|
+
const e = t.getBoundingClientRect();
|
|
248
|
+
if (!(e.width <= 0 || e.height <= 0))
|
|
249
|
+
return {
|
|
250
|
+
x: e.left + e.width / 2,
|
|
251
|
+
y: e.top + e.height / 2
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function W(t, e) {
|
|
255
|
+
if (typeof t.elementsFromPoint == "function")
|
|
256
|
+
return t.elementsFromPoint(e.x, e.y);
|
|
257
|
+
if (typeof t.elementFromPoint != "function")
|
|
258
|
+
return [];
|
|
259
|
+
const n = t.elementFromPoint(e.x, e.y);
|
|
260
|
+
return n ? [n] : [];
|
|
261
|
+
}
|
|
262
|
+
function ut(t) {
|
|
263
|
+
return typeof t.elementsFromPoint == "function" || typeof t.elementFromPoint == "function";
|
|
264
|
+
}
|
|
265
|
+
function C(t, e) {
|
|
266
|
+
return t === e || t.contains(e);
|
|
267
|
+
}
|
|
268
|
+
function ft(t) {
|
|
269
|
+
let e = t;
|
|
270
|
+
for (; e; ) {
|
|
271
|
+
if (at(e))
|
|
272
|
+
return e;
|
|
273
|
+
e = e.parentElement;
|
|
274
|
+
}
|
|
275
|
+
return t;
|
|
276
|
+
}
|
|
277
|
+
function B(t) {
|
|
278
|
+
return (t ?? "").replace(/\([^)]*\)/g, "").replace(/\s+/g, "").trim().toLowerCase();
|
|
279
|
+
}
|
|
280
|
+
function Y(t) {
|
|
281
|
+
const e = t.getBoundingClientRect();
|
|
282
|
+
if (e.width <= 0 || e.height <= 0)
|
|
283
|
+
return;
|
|
284
|
+
const n = t.ownerDocument;
|
|
285
|
+
return [
|
|
286
|
+
{ x: e.left + e.width / 2, y: e.top + e.height / 2 },
|
|
287
|
+
{ x: e.left + Math.min(8, e.width / 2), y: e.top + e.height / 2 },
|
|
288
|
+
{ x: e.right - Math.min(8, e.width / 2), y: e.top + e.height / 2 },
|
|
289
|
+
{ x: e.left + e.width / 2, y: e.top + Math.min(8, e.height / 2) },
|
|
290
|
+
{ x: e.left + e.width / 2, y: e.bottom - Math.min(8, e.height / 2) }
|
|
291
|
+
].find(
|
|
292
|
+
(r) => W(n, r).some(
|
|
293
|
+
(c) => C(t, c) || C(c, t)
|
|
294
|
+
)
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
function dt(t, e) {
|
|
298
|
+
var c;
|
|
299
|
+
const n = x(e), o = B(E(e));
|
|
300
|
+
return o ? ((c = I(t).filter((s) => s !== e).filter((s) => {
|
|
301
|
+
const i = x(s), a = B(E(s));
|
|
302
|
+
return n && i && n !== i ? !1 : a.includes(o) || o.includes(a);
|
|
303
|
+
}).map((s) => ({
|
|
304
|
+
candidate: s,
|
|
305
|
+
point: Y(s),
|
|
306
|
+
rect: k(s)
|
|
307
|
+
})).filter(
|
|
308
|
+
(s) => !!s.point
|
|
309
|
+
).sort((s, i) => i.rect.y - s.rect.y)[0]) == null ? void 0 : c.candidate) ?? null : null;
|
|
310
|
+
}
|
|
311
|
+
function L(t) {
|
|
312
|
+
const e = t.ownerDocument, n = lt(t), o = m(t) && !!n, r = ct(t), c = n ? W(e, n) : [], s = c[0], i = !!(s && (C(t, s) || C(s, t)));
|
|
313
|
+
return {
|
|
314
|
+
visible: o,
|
|
315
|
+
enabled: r,
|
|
316
|
+
receivesEvents: i,
|
|
317
|
+
actionable: o && r && i,
|
|
318
|
+
center: st(t),
|
|
319
|
+
hitTarget: s,
|
|
320
|
+
hitStack: c
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function ht(t, e) {
|
|
324
|
+
var i, a, d;
|
|
325
|
+
const n = p(e.testId);
|
|
326
|
+
if (n) {
|
|
327
|
+
const l = typeof CSS < "u" && typeof CSS.escape == "function" ? CSS.escape(n) : n.replaceAll("\\", "\\\\").replaceAll('"', '\\"'), u = t.querySelector(
|
|
328
|
+
`[data-testid="${l}"],[data-test-id="${l}"],[data-qa="${l}"]`
|
|
329
|
+
);
|
|
330
|
+
if (u)
|
|
331
|
+
return u;
|
|
332
|
+
}
|
|
333
|
+
const o = (i = p(e.role)) == null ? void 0 : i.toLowerCase(), r = (a = p(e.name)) == null ? void 0 : a.toLowerCase(), c = (d = p(e.text)) == null ? void 0 : d.toLowerCase();
|
|
334
|
+
return !o && !r && !c ? null : I(t).find((l) => {
|
|
335
|
+
var w, y, S;
|
|
336
|
+
const u = (w = x(l)) == null ? void 0 : w.toLowerCase(), f = (y = E(l)) == null ? void 0 : y.toLowerCase(), b = (S = v(l)) == null ? void 0 : S.toLowerCase();
|
|
337
|
+
return !(o && u !== o || r && !(f != null && f.includes(r)) || c && !(b != null && b.includes(c)));
|
|
338
|
+
}) ?? null;
|
|
339
|
+
}
|
|
340
|
+
function I(t) {
|
|
341
|
+
const e = g(t), n = t instanceof Document ? t.body ?? t.documentElement : t;
|
|
160
342
|
if (!n)
|
|
161
343
|
return [];
|
|
162
|
-
const
|
|
163
|
-
const
|
|
164
|
-
let
|
|
165
|
-
for (;
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
const d =
|
|
169
|
-
if (d &&
|
|
344
|
+
const o = [], r = (c) => {
|
|
345
|
+
const s = e.createTreeWalker(c, NodeFilter.SHOW_ELEMENT);
|
|
346
|
+
let i = s.nextNode();
|
|
347
|
+
for (; i; ) {
|
|
348
|
+
const a = i;
|
|
349
|
+
U(a) && o.push(a);
|
|
350
|
+
const d = a.shadowRoot;
|
|
351
|
+
if (d && r(d), a instanceof HTMLIFrameElement)
|
|
170
352
|
try {
|
|
171
|
-
|
|
353
|
+
a.contentDocument && r(a.contentDocument);
|
|
172
354
|
} catch {
|
|
173
355
|
}
|
|
174
|
-
if (
|
|
356
|
+
if (o.length >= D)
|
|
175
357
|
return;
|
|
176
|
-
|
|
358
|
+
i = s.nextNode();
|
|
177
359
|
}
|
|
178
360
|
};
|
|
179
|
-
return
|
|
361
|
+
return r(n), o.slice(0, D);
|
|
180
362
|
}
|
|
181
|
-
function
|
|
182
|
-
var
|
|
183
|
-
const n = Object.getPrototypeOf(t),
|
|
184
|
-
(
|
|
363
|
+
function gt(t, e) {
|
|
364
|
+
var r;
|
|
365
|
+
const n = Object.getPrototypeOf(t), o = Object.getOwnPropertyDescriptor(n, "value");
|
|
366
|
+
(r = o == null ? void 0 : o.set) == null || r.call(t, e);
|
|
185
367
|
}
|
|
186
|
-
function
|
|
368
|
+
function H(t) {
|
|
187
369
|
t.dispatchEvent(new Event("input", { bubbles: !0 })), t.dispatchEvent(new Event("change", { bubbles: !0 }));
|
|
188
370
|
}
|
|
189
|
-
function
|
|
371
|
+
function A(t) {
|
|
190
372
|
var e, n;
|
|
191
373
|
(t instanceof HTMLElement || t instanceof SVGElement) && ((e = t.scrollIntoView) == null || e.call(t, { block: "center", inline: "center" })), t instanceof HTMLElement && ((n = t.focus) == null || n.call(t));
|
|
192
374
|
}
|
|
193
|
-
|
|
375
|
+
function _(t, e) {
|
|
376
|
+
return typeof PointerEvent == "function" ? new PointerEvent(t, e) : new MouseEvent(t.replace("pointer", "mouse"), e);
|
|
377
|
+
}
|
|
378
|
+
class pt {
|
|
194
379
|
constructor(e = {}) {
|
|
195
380
|
this.options = e, this.refs = /* @__PURE__ */ new Map(), this.nextRef = 1;
|
|
196
381
|
}
|
|
@@ -212,187 +397,365 @@ class j {
|
|
|
212
397
|
return this.scroll(n);
|
|
213
398
|
case "host_page_navigate":
|
|
214
399
|
return this.navigate(n);
|
|
400
|
+
case "host_page_hover":
|
|
401
|
+
return this.hover(n);
|
|
402
|
+
case "host_page_focus":
|
|
403
|
+
return this.focus(n);
|
|
404
|
+
case "host_page_pointer":
|
|
405
|
+
return this.pointer(n);
|
|
406
|
+
case "host_page_screenshot":
|
|
407
|
+
return this.screenshot();
|
|
408
|
+
case "host_page_wait_for":
|
|
409
|
+
return this.waitFor(n);
|
|
215
410
|
}
|
|
216
411
|
}
|
|
217
412
|
snapshot() {
|
|
413
|
+
var c, s;
|
|
218
414
|
this.refs.clear(), this.nextRef = 1;
|
|
219
|
-
const e = this.getRoot(), n =
|
|
220
|
-
(
|
|
415
|
+
const e = this.getRoot(), n = g(e), o = N(e), r = I(e).map(
|
|
416
|
+
(i) => this.snapshotElement(i)
|
|
221
417
|
);
|
|
222
418
|
return {
|
|
223
|
-
url:
|
|
419
|
+
url: o.location.href,
|
|
224
420
|
title: n.title,
|
|
421
|
+
capabilities: {
|
|
422
|
+
cdp: !1,
|
|
423
|
+
realInput: !1,
|
|
424
|
+
screenshot: !1,
|
|
425
|
+
accessibility: !1,
|
|
426
|
+
networkState: !1
|
|
427
|
+
},
|
|
225
428
|
viewport: {
|
|
226
|
-
width:
|
|
227
|
-
height:
|
|
429
|
+
width: o.innerWidth,
|
|
430
|
+
height: o.innerHeight,
|
|
431
|
+
devicePixelRatio: o.devicePixelRatio
|
|
228
432
|
},
|
|
229
433
|
scroll: {
|
|
230
|
-
x:
|
|
231
|
-
y:
|
|
434
|
+
x: o.scrollX,
|
|
435
|
+
y: o.scrollY
|
|
436
|
+
},
|
|
437
|
+
page: {
|
|
438
|
+
readyState: n.readyState,
|
|
439
|
+
visibilityState: n.visibilityState,
|
|
440
|
+
focusedElement: n.activeElement && n.activeElement !== n.body ? this.snapshotElementWithoutRef(n.activeElement) : void 0,
|
|
441
|
+
selection: ((s = (c = n.getSelection) == null ? void 0 : c.call(n)) == null ? void 0 : s.toString()) || void 0
|
|
232
442
|
},
|
|
233
|
-
|
|
443
|
+
navigation: this.getNavigationState(o),
|
|
444
|
+
frames: this.getFrameState(n),
|
|
445
|
+
accessibility: r.map((i) => ({
|
|
446
|
+
ref: i.ref,
|
|
447
|
+
role: i.role,
|
|
448
|
+
name: i.name,
|
|
449
|
+
value: i.value,
|
|
450
|
+
disabled: i.disabled,
|
|
451
|
+
checked: i.checked,
|
|
452
|
+
focused: n.activeElement === this.refs.get(i.ref)
|
|
453
|
+
})),
|
|
454
|
+
elements: r
|
|
234
455
|
};
|
|
235
456
|
}
|
|
236
457
|
getRoot() {
|
|
237
458
|
return this.options.root ?? document;
|
|
238
459
|
}
|
|
460
|
+
getNavigationState(e) {
|
|
461
|
+
var o, r, c;
|
|
462
|
+
const n = (c = (r = (o = e.performance) == null ? void 0 : o.getEntriesByType) == null ? void 0 : r.call(o, "navigation")) == null ? void 0 : c[0];
|
|
463
|
+
if (!(typeof PerformanceNavigationTiming != "function" || !(n instanceof PerformanceNavigationTiming)))
|
|
464
|
+
return {
|
|
465
|
+
type: n.type,
|
|
466
|
+
duration: n.duration,
|
|
467
|
+
domContentLoaded: n.domContentLoadedEventEnd - n.startTime,
|
|
468
|
+
loadEventEnd: n.loadEventEnd - n.startTime
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
getFrameState(e) {
|
|
472
|
+
return Array.from(e.querySelectorAll("iframe")).map((n) => {
|
|
473
|
+
var r, c;
|
|
474
|
+
const o = k(n);
|
|
475
|
+
try {
|
|
476
|
+
return {
|
|
477
|
+
url: (r = n.contentWindow) == null ? void 0 : r.location.href,
|
|
478
|
+
title: (c = n.contentDocument) == null ? void 0 : c.title,
|
|
479
|
+
sameOrigin: !0,
|
|
480
|
+
rect: o
|
|
481
|
+
};
|
|
482
|
+
} catch {
|
|
483
|
+
return {
|
|
484
|
+
url: n.getAttribute("src") ?? void 0,
|
|
485
|
+
sameOrigin: !1,
|
|
486
|
+
rect: o
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
239
491
|
snapshotElement(e) {
|
|
240
492
|
const n = `e${this.nextRef}`;
|
|
241
|
-
this.nextRef += 1, this.refs.set(n, e);
|
|
242
|
-
|
|
493
|
+
return this.nextRef += 1, this.refs.set(n, e), this.createElementSnapshot(e, n);
|
|
494
|
+
}
|
|
495
|
+
snapshotElementWithoutRef(e) {
|
|
496
|
+
return this.createElementSnapshot(e, "");
|
|
497
|
+
}
|
|
498
|
+
createElementSnapshot(e, n) {
|
|
499
|
+
const o = (e instanceof HTMLInputElement || e instanceof HTMLTextAreaElement) && e.placeholder || void 0, r = L(e);
|
|
243
500
|
return {
|
|
244
501
|
ref: n,
|
|
245
502
|
tag: e.tagName.toLowerCase(),
|
|
246
|
-
role:
|
|
247
|
-
name:
|
|
248
|
-
text:
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
503
|
+
role: x(e),
|
|
504
|
+
name: E(e),
|
|
505
|
+
text: v(e),
|
|
506
|
+
nearbyText: X(e),
|
|
507
|
+
testId: rt(e),
|
|
508
|
+
value: nt(e),
|
|
509
|
+
placeholder: o,
|
|
510
|
+
selector: P(e),
|
|
511
|
+
disabled: q(e),
|
|
512
|
+
enabled: r.enabled,
|
|
513
|
+
checked: it(e),
|
|
514
|
+
visible: r.visible,
|
|
515
|
+
actionable: r.actionable,
|
|
516
|
+
rect: k(e),
|
|
517
|
+
center: r.center,
|
|
518
|
+
hitTarget: r.hitTarget ? $(r.hitTarget) : void 0,
|
|
519
|
+
hitStack: r.hitStack.slice(0, 5).map($)
|
|
255
520
|
};
|
|
256
521
|
}
|
|
257
522
|
resolveElement(e) {
|
|
258
|
-
const n =
|
|
523
|
+
const n = p(e.ref) ?? p(e.axRef);
|
|
259
524
|
if (n) {
|
|
260
|
-
const
|
|
261
|
-
if (!
|
|
525
|
+
const c = this.refs.get(n);
|
|
526
|
+
if (!c)
|
|
262
527
|
throw new Error(`Unknown element ref: ${n}. Take a new snapshot.`);
|
|
263
|
-
return
|
|
528
|
+
return c;
|
|
264
529
|
}
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
const
|
|
268
|
-
if (!
|
|
269
|
-
throw new Error(`No element matches selector: ${
|
|
270
|
-
return
|
|
530
|
+
const o = p(e.selector);
|
|
531
|
+
if (o) {
|
|
532
|
+
const c = this.getRoot().querySelector(o);
|
|
533
|
+
if (!c)
|
|
534
|
+
throw new Error(`No element matches selector: ${o}.`);
|
|
535
|
+
return c;
|
|
271
536
|
}
|
|
537
|
+
const r = ht(this.getRoot(), e);
|
|
538
|
+
if (r)
|
|
539
|
+
return r;
|
|
272
540
|
if (typeof e.x < "u" || typeof e.y < "u") {
|
|
273
|
-
const
|
|
274
|
-
x:
|
|
275
|
-
y:
|
|
276
|
-
}, s =
|
|
277
|
-
|
|
278
|
-
|
|
541
|
+
const c = {
|
|
542
|
+
x: M(e.x, "x"),
|
|
543
|
+
y: M(e.y, "y")
|
|
544
|
+
}, s = g(this.getRoot()).elementFromPoint(
|
|
545
|
+
c.x,
|
|
546
|
+
c.y
|
|
279
547
|
);
|
|
280
548
|
if (!s)
|
|
281
|
-
throw new Error(`No element found at (${
|
|
549
|
+
throw new Error(`No element found at (${c.x}, ${c.y}).`);
|
|
282
550
|
return s;
|
|
283
551
|
}
|
|
284
|
-
throw new Error(
|
|
552
|
+
throw new Error(
|
|
553
|
+
"Expected one of ref, selector, role/name/text/testId, or x/y."
|
|
554
|
+
);
|
|
285
555
|
}
|
|
286
556
|
click(e) {
|
|
287
|
-
const n = this.resolveElement(
|
|
288
|
-
|
|
557
|
+
const n = h(e), o = this.resolveElement(n), r = L(o), s = (r.actionable ? null : dt(this.getRoot(), o)) ?? ft(o), i = Y(s);
|
|
558
|
+
if (!i && !r.actionable && ut(o.ownerDocument))
|
|
559
|
+
throw new Error(
|
|
560
|
+
`Target "${E(o) ?? o.tagName.toLowerCase()}" is not receiving pointer events. Take a screenshot or use host_page_pointer coordinates.`
|
|
561
|
+
);
|
|
562
|
+
return A(s), s instanceof HTMLElement ? s.click() : s.dispatchEvent(new MouseEvent("click", { bubbles: !0 })), {
|
|
563
|
+
clicked: this.describeElement(s),
|
|
564
|
+
requested: this.describeElement(o),
|
|
565
|
+
strategy: s === o ? "dom" : "semantic_visible_fallback",
|
|
566
|
+
point: i ?? r.center,
|
|
567
|
+
actionability: {
|
|
568
|
+
visible: r.visible,
|
|
569
|
+
enabled: r.enabled,
|
|
570
|
+
receivesEvents: r.receivesEvents
|
|
571
|
+
}
|
|
572
|
+
};
|
|
289
573
|
}
|
|
290
574
|
fill(e) {
|
|
291
|
-
const n =
|
|
292
|
-
if (
|
|
293
|
-
return
|
|
294
|
-
if (
|
|
295
|
-
return
|
|
575
|
+
const n = h(e), o = R(n.value, "value"), r = this.resolveElement(n);
|
|
576
|
+
if (A(r), r instanceof HTMLInputElement || r instanceof HTMLTextAreaElement)
|
|
577
|
+
return gt(r, o), H(r), { filled: this.describeElement(r), value: o };
|
|
578
|
+
if (r instanceof HTMLElement && r.isContentEditable)
|
|
579
|
+
return r.textContent = o, H(r), { filled: this.describeElement(r), value: o };
|
|
296
580
|
throw new Error("Target element cannot be filled.");
|
|
297
581
|
}
|
|
298
582
|
press(e) {
|
|
299
|
-
const n =
|
|
300
|
-
if (!
|
|
583
|
+
const n = h(e), o = R(n.key, "key"), r = n.ref || n.selector || n.x !== void 0 && n.y !== void 0 ? this.resolveElement(n) : g(this.getRoot()).activeElement ?? g(this.getRoot()).body;
|
|
584
|
+
if (!r)
|
|
301
585
|
throw new Error("No target element is available for key press.");
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
return
|
|
586
|
+
A(r);
|
|
587
|
+
const c = { key: o, bubbles: !0, cancelable: !0 };
|
|
588
|
+
return r.dispatchEvent(new KeyboardEvent("keydown", c)), o.length === 1 && r.dispatchEvent(new KeyboardEvent("keypress", c)), r.dispatchEvent(new KeyboardEvent("keyup", c)), { pressed: o, target: this.describeElement(r) };
|
|
305
589
|
}
|
|
306
590
|
select(e) {
|
|
307
|
-
const n =
|
|
308
|
-
if (!(
|
|
591
|
+
const n = h(e), o = et(n.values ?? n.value), r = this.resolveElement(n);
|
|
592
|
+
if (!(r instanceof HTMLSelectElement))
|
|
309
593
|
throw new Error("Target element is not a select.");
|
|
310
|
-
const
|
|
311
|
-
for (const
|
|
312
|
-
|
|
313
|
-
return
|
|
314
|
-
selected: Array.from(
|
|
315
|
-
(
|
|
594
|
+
const c = new Set(o);
|
|
595
|
+
for (const s of Array.from(r.options))
|
|
596
|
+
s.selected = c.has(s.value);
|
|
597
|
+
return H(r), {
|
|
598
|
+
selected: Array.from(r.selectedOptions).map(
|
|
599
|
+
(s) => s.value
|
|
316
600
|
),
|
|
317
|
-
target: this.describeElement(
|
|
601
|
+
target: this.describeElement(r)
|
|
318
602
|
};
|
|
319
603
|
}
|
|
320
604
|
scroll(e) {
|
|
321
|
-
var
|
|
322
|
-
const n =
|
|
323
|
-
x:
|
|
324
|
-
y:
|
|
325
|
-
} : null,
|
|
326
|
-
if (n.ref || n.selector) {
|
|
327
|
-
const
|
|
328
|
-
if (!(
|
|
605
|
+
var a, d, l, u;
|
|
606
|
+
const n = h(e), o = n.x !== void 0 || n.y !== void 0 ? {
|
|
607
|
+
x: T(n.x) ?? 0,
|
|
608
|
+
y: T(n.y) ?? 0
|
|
609
|
+
} : null, r = T(n.deltaX) ?? 0, c = T(n.deltaY) ?? 0, s = this.getRoot(), i = N(s);
|
|
610
|
+
if (n.ref || n.selector || n.role || n.name || n.text || n.testId) {
|
|
611
|
+
const f = this.resolveElement(n);
|
|
612
|
+
if (!(f instanceof HTMLElement))
|
|
329
613
|
throw new Error("Target element cannot be scrolled.");
|
|
330
|
-
return
|
|
331
|
-
scrolled: this.describeElement(
|
|
332
|
-
scroll: { x:
|
|
614
|
+
return o ? (a = f.scrollTo) == null || a.call(f, o.x, o.y) : (d = f.scrollBy) == null || d.call(f, r, c), {
|
|
615
|
+
scrolled: this.describeElement(f),
|
|
616
|
+
scroll: { x: f.scrollLeft, y: f.scrollTop }
|
|
333
617
|
};
|
|
334
618
|
}
|
|
335
|
-
return
|
|
619
|
+
return o ? (l = i.scrollTo) == null || l.call(i, o.x, o.y) : (u = i.scrollBy) == null || u.call(i, r, c), { scroll: { x: i.scrollX, y: i.scrollY } };
|
|
336
620
|
}
|
|
337
621
|
navigate(e) {
|
|
338
622
|
if (this.options.allowNavigation === !1)
|
|
339
623
|
throw new Error("Navigation is disabled for host page automation.");
|
|
340
|
-
const n =
|
|
341
|
-
if (
|
|
624
|
+
const n = h(e), o = this.getRoot(), r = N(o), c = R(n.url, "url"), s = new URL(c, r.location.href);
|
|
625
|
+
if (s.protocol !== "http:" && s.protocol !== "https:")
|
|
342
626
|
throw new Error("Navigation only supports HTTP(S) URLs.");
|
|
343
|
-
return this.refs.clear(),
|
|
627
|
+
return this.refs.clear(), r.location.assign(s.toString()), { navigated: s.toString() };
|
|
628
|
+
}
|
|
629
|
+
hover(e) {
|
|
630
|
+
const n = h(e), o = this.resolveElement(n), r = L(o).center;
|
|
631
|
+
return o.dispatchEvent(
|
|
632
|
+
new MouseEvent("mouseover", {
|
|
633
|
+
bubbles: !0,
|
|
634
|
+
cancelable: !0,
|
|
635
|
+
clientX: r == null ? void 0 : r.x,
|
|
636
|
+
clientY: r == null ? void 0 : r.y
|
|
637
|
+
})
|
|
638
|
+
), o.dispatchEvent(
|
|
639
|
+
new MouseEvent("mousemove", {
|
|
640
|
+
bubbles: !0,
|
|
641
|
+
cancelable: !0,
|
|
642
|
+
clientX: r == null ? void 0 : r.x,
|
|
643
|
+
clientY: r == null ? void 0 : r.y
|
|
644
|
+
})
|
|
645
|
+
), { hovered: this.describeElement(o), point: r };
|
|
646
|
+
}
|
|
647
|
+
focus(e) {
|
|
648
|
+
const n = h(e), o = this.resolveElement(n);
|
|
649
|
+
return A(o), { focused: this.describeElement(o) };
|
|
650
|
+
}
|
|
651
|
+
pointer(e) {
|
|
652
|
+
const n = h(e), o = F(n.action, ["move", "down", "up", "click"]) ?? "click", r = tt(n.button) ?? 0, c = n.ref || n.selector || n.role || n.name || n.text || n.testId ? this.resolveElement(n) : null, s = c ? L(c).center : {
|
|
653
|
+
x: M(n.x, "x"),
|
|
654
|
+
y: M(n.y, "y")
|
|
655
|
+
};
|
|
656
|
+
if (!s)
|
|
657
|
+
throw new Error("Target element has no clickable point.");
|
|
658
|
+
const i = c ?? g(this.getRoot()).elementFromPoint(s.x, s.y);
|
|
659
|
+
if (!i)
|
|
660
|
+
throw new Error(`No element found at (${s.x}, ${s.y}).`);
|
|
661
|
+
const a = {
|
|
662
|
+
bubbles: !0,
|
|
663
|
+
cancelable: !0,
|
|
664
|
+
clientX: s.x,
|
|
665
|
+
clientY: s.y,
|
|
666
|
+
button: r
|
|
667
|
+
};
|
|
668
|
+
return o === "move" ? (i.dispatchEvent(_("pointermove", a)), i.dispatchEvent(new MouseEvent("mousemove", a))) : o === "down" ? (i.dispatchEvent(_("pointerdown", a)), i.dispatchEvent(new MouseEvent("mousedown", a))) : o === "up" ? (i.dispatchEvent(_("pointerup", a)), i.dispatchEvent(new MouseEvent("mouseup", a))) : (i.dispatchEvent(_("pointerdown", a)), i.dispatchEvent(new MouseEvent("mousedown", a)), i.dispatchEvent(_("pointerup", a)), i.dispatchEvent(new MouseEvent("mouseup", a)), i instanceof HTMLElement ? i.click() : i.dispatchEvent(new MouseEvent("click", a))), {
|
|
669
|
+
pointer: o,
|
|
670
|
+
point: s,
|
|
671
|
+
target: this.describeElement(i)
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
screenshot() {
|
|
675
|
+
throw new Error(
|
|
676
|
+
"host_page_screenshot requires the browser extension CDP adapter."
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
async waitFor(e) {
|
|
680
|
+
const n = h(e), o = F(n.state, [
|
|
681
|
+
"attached",
|
|
682
|
+
"visible",
|
|
683
|
+
"hidden",
|
|
684
|
+
"detached"
|
|
685
|
+
]) ?? "visible", r = T(n.timeoutSeconds), c = Math.min(
|
|
686
|
+
Q,
|
|
687
|
+
Math.max(0, (r ?? J / 1e3) * 1e3)
|
|
688
|
+
), s = Date.now();
|
|
689
|
+
for (; Date.now() - s <= c; ) {
|
|
690
|
+
const i = this.tryResolveElement(n);
|
|
691
|
+
if (o === "attached" ? !!i : o === "detached" ? !i : o === "hidden" ? !i || !m(i) : !!(i && m(i)))
|
|
692
|
+
return {
|
|
693
|
+
waitedFor: o,
|
|
694
|
+
elapsedMs: Date.now() - s,
|
|
695
|
+
target: i ? this.describeElement(i) : void 0
|
|
696
|
+
};
|
|
697
|
+
await new Promise((d) => setTimeout(d, 100));
|
|
698
|
+
}
|
|
699
|
+
throw new Error(`Timed out waiting for target to become ${o}.`);
|
|
700
|
+
}
|
|
701
|
+
tryResolveElement(e) {
|
|
702
|
+
try {
|
|
703
|
+
return this.resolveElement(e);
|
|
704
|
+
} catch {
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
344
707
|
}
|
|
345
708
|
describeElement(e) {
|
|
346
709
|
return {
|
|
347
710
|
tag: e.tagName.toLowerCase(),
|
|
348
|
-
role:
|
|
349
|
-
name:
|
|
350
|
-
selector:
|
|
711
|
+
role: x(e),
|
|
712
|
+
name: E(e),
|
|
713
|
+
selector: P(e)
|
|
351
714
|
};
|
|
352
715
|
}
|
|
353
716
|
}
|
|
354
|
-
function
|
|
717
|
+
function Et(t) {
|
|
355
718
|
return typeof t == "object" && t !== null && !Array.isArray(t) ? t : {};
|
|
356
719
|
}
|
|
357
|
-
function
|
|
720
|
+
function mt(t) {
|
|
358
721
|
return JSON.stringify(t);
|
|
359
722
|
}
|
|
360
|
-
function
|
|
723
|
+
function O(t, e, n) {
|
|
361
724
|
return {
|
|
362
725
|
tool_call_id: t.tool_call_id ?? t.id,
|
|
363
726
|
name: t.name,
|
|
364
727
|
status: e,
|
|
365
|
-
content:
|
|
728
|
+
content: mt(n)
|
|
366
729
|
};
|
|
367
730
|
}
|
|
368
|
-
function
|
|
731
|
+
function bt(t) {
|
|
369
732
|
return t instanceof Error ? t.message : String(t);
|
|
370
733
|
}
|
|
371
|
-
function
|
|
372
|
-
const e = new
|
|
734
|
+
function wt(t = {}) {
|
|
735
|
+
const e = new pt(t);
|
|
373
736
|
return async (n) => {
|
|
374
|
-
if (!
|
|
375
|
-
return
|
|
737
|
+
if (!Z(n.name))
|
|
738
|
+
return O(n, "error", {
|
|
376
739
|
ok: !1,
|
|
377
740
|
error: `Unknown host page automation tool: ${n.name}`
|
|
378
741
|
});
|
|
379
742
|
try {
|
|
380
|
-
const
|
|
743
|
+
const o = await e.execute(
|
|
381
744
|
n.name,
|
|
382
|
-
|
|
745
|
+
Et(n.params)
|
|
383
746
|
);
|
|
384
|
-
return
|
|
385
|
-
} catch (
|
|
386
|
-
return
|
|
747
|
+
return O(n, "success", { ok: !0, result: o });
|
|
748
|
+
} catch (o) {
|
|
749
|
+
return O(n, "error", {
|
|
387
750
|
ok: !1,
|
|
388
|
-
error:
|
|
751
|
+
error: bt(o)
|
|
389
752
|
});
|
|
390
753
|
}
|
|
391
754
|
};
|
|
392
755
|
}
|
|
393
756
|
export {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
757
|
+
z as HOST_PAGE_AUTOMATION_TOOL_NAMES,
|
|
758
|
+
pt as HostPageAutomationExecutor,
|
|
759
|
+
wt as createHostPageAutomationClientToolHandler,
|
|
760
|
+
Z as isHostPageAutomationToolName
|
|
398
761
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xpert-ai/chatkit-host-automation",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Host page automation tools for Xpert ChatKit client tools",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"!**/*.tsbuildinfo"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@xpert-ai/chatkit-types": "~0.3.
|
|
24
|
+
"@xpert-ai/chatkit-types": "~0.3.3"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"rimraf": "^6.0.0",
|