@midscene/web 0.3.2 → 0.3.3

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.
@@ -0,0 +1,1245 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __commonJS = (cb, mod) => function __require() {
26
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
27
+ };
28
+ var __export = (target, all) => {
29
+ for (var name in all)
30
+ __defProp(target, name, { get: all[name], enumerable: true });
31
+ };
32
+ var __copyProps = (to, from, except, desc) => {
33
+ if (from && typeof from === "object" || typeof from === "function") {
34
+ for (let key of __getOwnPropNames(from))
35
+ if (!__hasOwnProp.call(to, key) && key !== except)
36
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
37
+ }
38
+ return to;
39
+ };
40
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
41
+ // If the importer is in node compatibility mode or this is not an ESM
42
+ // file that has been converted to a CommonJS file using a Babel-
43
+ // compatible transform (i.e. "__esModule" has not been set), then set
44
+ // "default" to the CommonJS "module.exports" for node compatibility.
45
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
46
+ mod
47
+ ));
48
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
49
+
50
+ // ../../node_modules/.pnpm/dayjs@1.11.11/node_modules/dayjs/dayjs.min.js
51
+ var require_dayjs_min = __commonJS({
52
+ "../../node_modules/.pnpm/dayjs@1.11.11/node_modules/dayjs/dayjs.min.js"(exports, module2) {
53
+ "use strict";
54
+ !function(t, e) {
55
+ "object" == typeof exports && "undefined" != typeof module2 ? module2.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).dayjs = e();
56
+ }(exports, function() {
57
+ "use strict";
58
+ var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
59
+ var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
60
+ return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
61
+ } }, m = function(t2, e2, n2) {
62
+ var r2 = String(t2);
63
+ return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
64
+ }, v = { s: m, z: function(t2) {
65
+ var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
66
+ return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
67
+ }, m: function t2(e2, n2) {
68
+ if (e2.date() < n2.date())
69
+ return -t2(n2, e2);
70
+ var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, c), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), c);
71
+ return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
72
+ }, a: function(t2) {
73
+ return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
74
+ }, p: function(t2) {
75
+ return { M: c, y: h, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: f }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
76
+ }, u: function(t2) {
77
+ return void 0 === t2;
78
+ } }, g = "en", D = {};
79
+ D[g] = M;
80
+ var p = "$isDayjsObject", S = function(t2) {
81
+ return t2 instanceof _ || !(!t2 || !t2[p]);
82
+ }, w = function t2(e2, n2, r2) {
83
+ var i2;
84
+ if (!e2)
85
+ return g;
86
+ if ("string" == typeof e2) {
87
+ var s2 = e2.toLowerCase();
88
+ D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
89
+ var u2 = e2.split("-");
90
+ if (!i2 && u2.length > 1)
91
+ return t2(u2[0]);
92
+ } else {
93
+ var a2 = e2.name;
94
+ D[a2] = e2, i2 = a2;
95
+ }
96
+ return !r2 && i2 && (g = i2), i2 || !r2 && g;
97
+ }, O = function(t2, e2) {
98
+ if (S(t2))
99
+ return t2.clone();
100
+ var n2 = "object" == typeof e2 ? e2 : {};
101
+ return n2.date = t2, n2.args = arguments, new _(n2);
102
+ }, b = v;
103
+ b.l = w, b.i = S, b.w = function(t2, e2) {
104
+ return O(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
105
+ };
106
+ var _ = function() {
107
+ function M2(t2) {
108
+ this.$L = w(t2.locale, null, true), this.parse(t2), this.$x = this.$x || t2.x || {}, this[p] = true;
109
+ }
110
+ var m2 = M2.prototype;
111
+ return m2.parse = function(t2) {
112
+ this.$d = function(t3) {
113
+ var e2 = t3.date, n2 = t3.utc;
114
+ if (null === e2)
115
+ return /* @__PURE__ */ new Date(NaN);
116
+ if (b.u(e2))
117
+ return /* @__PURE__ */ new Date();
118
+ if (e2 instanceof Date)
119
+ return new Date(e2);
120
+ if ("string" == typeof e2 && !/Z$/i.test(e2)) {
121
+ var r2 = e2.match($);
122
+ if (r2) {
123
+ var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
124
+ return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
125
+ }
126
+ }
127
+ return new Date(e2);
128
+ }(t2), this.init();
129
+ }, m2.init = function() {
130
+ var t2 = this.$d;
131
+ this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
132
+ }, m2.$utils = function() {
133
+ return b;
134
+ }, m2.isValid = function() {
135
+ return !(this.$d.toString() === l);
136
+ }, m2.isSame = function(t2, e2) {
137
+ var n2 = O(t2);
138
+ return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
139
+ }, m2.isAfter = function(t2, e2) {
140
+ return O(t2) < this.startOf(e2);
141
+ }, m2.isBefore = function(t2, e2) {
142
+ return this.endOf(e2) < O(t2);
143
+ }, m2.$g = function(t2, e2, n2) {
144
+ return b.u(t2) ? this[e2] : this.set(n2, t2);
145
+ }, m2.unix = function() {
146
+ return Math.floor(this.valueOf() / 1e3);
147
+ }, m2.valueOf = function() {
148
+ return this.$d.getTime();
149
+ }, m2.startOf = function(t2, e2) {
150
+ var n2 = this, r2 = !!b.u(e2) || e2, f2 = b.p(t2), l2 = function(t3, e3) {
151
+ var i2 = b.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
152
+ return r2 ? i2 : i2.endOf(a);
153
+ }, $2 = function(t3, e3) {
154
+ return b.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
155
+ }, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
156
+ switch (f2) {
157
+ case h:
158
+ return r2 ? l2(1, 0) : l2(31, 11);
159
+ case c:
160
+ return r2 ? l2(1, M3) : l2(0, M3 + 1);
161
+ case o:
162
+ var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
163
+ return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
164
+ case a:
165
+ case d:
166
+ return $2(v2 + "Hours", 0);
167
+ case u:
168
+ return $2(v2 + "Minutes", 1);
169
+ case s:
170
+ return $2(v2 + "Seconds", 2);
171
+ case i:
172
+ return $2(v2 + "Milliseconds", 3);
173
+ default:
174
+ return this.clone();
175
+ }
176
+ }, m2.endOf = function(t2) {
177
+ return this.startOf(t2, false);
178
+ }, m2.$set = function(t2, e2) {
179
+ var n2, o2 = b.p(t2), f2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = f2 + "Date", n2[d] = f2 + "Date", n2[c] = f2 + "Month", n2[h] = f2 + "FullYear", n2[u] = f2 + "Hours", n2[s] = f2 + "Minutes", n2[i] = f2 + "Seconds", n2[r] = f2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
180
+ if (o2 === c || o2 === h) {
181
+ var y2 = this.clone().set(d, 1);
182
+ y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
183
+ } else
184
+ l2 && this.$d[l2]($2);
185
+ return this.init(), this;
186
+ }, m2.set = function(t2, e2) {
187
+ return this.clone().$set(t2, e2);
188
+ }, m2.get = function(t2) {
189
+ return this[b.p(t2)]();
190
+ }, m2.add = function(r2, f2) {
191
+ var d2, l2 = this;
192
+ r2 = Number(r2);
193
+ var $2 = b.p(f2), y2 = function(t2) {
194
+ var e2 = O(l2);
195
+ return b.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
196
+ };
197
+ if ($2 === c)
198
+ return this.set(c, this.$M + r2);
199
+ if ($2 === h)
200
+ return this.set(h, this.$y + r2);
201
+ if ($2 === a)
202
+ return y2(1);
203
+ if ($2 === o)
204
+ return y2(7);
205
+ var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
206
+ return b.w(m3, this);
207
+ }, m2.subtract = function(t2, e2) {
208
+ return this.add(-1 * t2, e2);
209
+ }, m2.format = function(t2) {
210
+ var e2 = this, n2 = this.$locale();
211
+ if (!this.isValid())
212
+ return n2.invalidDate || l;
213
+ var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = b.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, c2 = n2.months, f2 = n2.meridiem, h2 = function(t3, n3, i3, s3) {
214
+ return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
215
+ }, d2 = function(t3) {
216
+ return b.s(s2 % 12 || 12, t3, "0");
217
+ }, $2 = f2 || function(t3, e3, n3) {
218
+ var r3 = t3 < 12 ? "AM" : "PM";
219
+ return n3 ? r3.toLowerCase() : r3;
220
+ };
221
+ return r2.replace(y, function(t3, r3) {
222
+ return r3 || function(t4) {
223
+ switch (t4) {
224
+ case "YY":
225
+ return String(e2.$y).slice(-2);
226
+ case "YYYY":
227
+ return b.s(e2.$y, 4, "0");
228
+ case "M":
229
+ return a2 + 1;
230
+ case "MM":
231
+ return b.s(a2 + 1, 2, "0");
232
+ case "MMM":
233
+ return h2(n2.monthsShort, a2, c2, 3);
234
+ case "MMMM":
235
+ return h2(c2, a2);
236
+ case "D":
237
+ return e2.$D;
238
+ case "DD":
239
+ return b.s(e2.$D, 2, "0");
240
+ case "d":
241
+ return String(e2.$W);
242
+ case "dd":
243
+ return h2(n2.weekdaysMin, e2.$W, o2, 2);
244
+ case "ddd":
245
+ return h2(n2.weekdaysShort, e2.$W, o2, 3);
246
+ case "dddd":
247
+ return o2[e2.$W];
248
+ case "H":
249
+ return String(s2);
250
+ case "HH":
251
+ return b.s(s2, 2, "0");
252
+ case "h":
253
+ return d2(1);
254
+ case "hh":
255
+ return d2(2);
256
+ case "a":
257
+ return $2(s2, u2, true);
258
+ case "A":
259
+ return $2(s2, u2, false);
260
+ case "m":
261
+ return String(u2);
262
+ case "mm":
263
+ return b.s(u2, 2, "0");
264
+ case "s":
265
+ return String(e2.$s);
266
+ case "ss":
267
+ return b.s(e2.$s, 2, "0");
268
+ case "SSS":
269
+ return b.s(e2.$ms, 3, "0");
270
+ case "Z":
271
+ return i2;
272
+ }
273
+ return null;
274
+ }(t3) || i2.replace(":", "");
275
+ });
276
+ }, m2.utcOffset = function() {
277
+ return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
278
+ }, m2.diff = function(r2, d2, l2) {
279
+ var $2, y2 = this, M3 = b.p(d2), m3 = O(r2), v2 = (m3.utcOffset() - this.utcOffset()) * e, g2 = this - m3, D2 = function() {
280
+ return b.m(y2, m3);
281
+ };
282
+ switch (M3) {
283
+ case h:
284
+ $2 = D2() / 12;
285
+ break;
286
+ case c:
287
+ $2 = D2();
288
+ break;
289
+ case f:
290
+ $2 = D2() / 3;
291
+ break;
292
+ case o:
293
+ $2 = (g2 - v2) / 6048e5;
294
+ break;
295
+ case a:
296
+ $2 = (g2 - v2) / 864e5;
297
+ break;
298
+ case u:
299
+ $2 = g2 / n;
300
+ break;
301
+ case s:
302
+ $2 = g2 / e;
303
+ break;
304
+ case i:
305
+ $2 = g2 / t;
306
+ break;
307
+ default:
308
+ $2 = g2;
309
+ }
310
+ return l2 ? $2 : b.a($2);
311
+ }, m2.daysInMonth = function() {
312
+ return this.endOf(c).$D;
313
+ }, m2.$locale = function() {
314
+ return D[this.$L];
315
+ }, m2.locale = function(t2, e2) {
316
+ if (!t2)
317
+ return this.$L;
318
+ var n2 = this.clone(), r2 = w(t2, e2, true);
319
+ return r2 && (n2.$L = r2), n2;
320
+ }, m2.clone = function() {
321
+ return b.w(this.$d, this);
322
+ }, m2.toDate = function() {
323
+ return new Date(this.valueOf());
324
+ }, m2.toJSON = function() {
325
+ return this.isValid() ? this.toISOString() : null;
326
+ }, m2.toISOString = function() {
327
+ return this.$d.toISOString();
328
+ }, m2.toString = function() {
329
+ return this.$d.toUTCString();
330
+ }, M2;
331
+ }(), k = _.prototype;
332
+ return O.prototype = k, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", c], ["$y", h], ["$D", d]].forEach(function(t2) {
333
+ k[t2[1]] = function(e2) {
334
+ return this.$g(e2, t2[0], t2[1]);
335
+ };
336
+ }), O.extend = function(t2, e2) {
337
+ return t2.$i || (t2(e2, _, O), t2.$i = true), O;
338
+ }, O.locale = w, O.isDayjs = S, O.unix = function(t2) {
339
+ return O(1e3 * t2);
340
+ }, O.en = D[g], O.Ls = D, O.p = {}, O;
341
+ });
342
+ }
343
+ });
344
+
345
+ // src/playwright/index.ts
346
+ var playwright_exports = {};
347
+ __export(playwright_exports, {
348
+ PlaywrightAiFixture: () => PlaywrightAiFixture
349
+ });
350
+ module.exports = __toCommonJS(playwright_exports);
351
+
352
+ // src/playwright/ai-fixture.ts
353
+ var import_node_crypto = require("crypto");
354
+
355
+ // src/common/agent.ts
356
+ var import_utils4 = require("@midscene/core/utils");
357
+
358
+ // src/common/tasks.ts
359
+ var import_node_assert2 = __toESM(require("assert"));
360
+ var import_core = __toESM(require("@midscene/core"));
361
+ var import_image2 = require("@midscene/core/image");
362
+ var import_utils2 = require("@midscene/core/utils");
363
+
364
+ // src/common/task-cache.ts
365
+ var TaskCache = class {
366
+ constructor(opts) {
367
+ this.cache = opts == null ? void 0 : opts.cache;
368
+ this.newCache = {
369
+ aiTasks: []
370
+ };
371
+ }
372
+ readCache(pageContext, type, userPrompt) {
373
+ var _a;
374
+ if (this.cache) {
375
+ const { aiTasks } = this.cache;
376
+ const index = aiTasks.findIndex((item) => item.prompt === userPrompt);
377
+ if (index === -1) {
378
+ return false;
379
+ }
380
+ const taskRes = aiTasks.splice(index, 1)[0];
381
+ if ((taskRes == null ? void 0 : taskRes.type) === "locate" && !((_a = taskRes.response) == null ? void 0 : _a.elements.every((element) => {
382
+ const findIndex = pageContext.content.findIndex(
383
+ (contentElement) => contentElement.id === element.id
384
+ );
385
+ if (findIndex === -1) {
386
+ return false;
387
+ }
388
+ return true;
389
+ }))) {
390
+ return false;
391
+ }
392
+ if (taskRes && taskRes.type === type && taskRes.prompt === userPrompt && this.pageContextEqual(taskRes.pageContext, pageContext)) {
393
+ return taskRes.response;
394
+ }
395
+ }
396
+ return false;
397
+ }
398
+ saveCache(cache) {
399
+ var _a;
400
+ if (cache) {
401
+ (_a = this.newCache) == null ? void 0 : _a.aiTasks.push(cache);
402
+ }
403
+ }
404
+ pageContextEqual(taskPageContext, pageContext) {
405
+ return taskPageContext.size.width === pageContext.size.width && taskPageContext.size.height === pageContext.size.height;
406
+ }
407
+ /**
408
+ * Generate task cache data.
409
+ * This method is mainly used to create or obtain some cached data for tasks, and it returns a new cache object.
410
+ * In the cache object, it may contain task-related information, states, or other necessary data.
411
+ * It is assumed that the `newCache` property already exists in the current class or object and is a data structure used to store task cache.
412
+ * @returns {Object} Returns a new cache object, which may include task cache data.
413
+ */
414
+ generateTaskCache() {
415
+ return this.newCache;
416
+ }
417
+ };
418
+
419
+ // src/common/utils.ts
420
+ var import_node_assert = __toESM(require("assert"));
421
+ var import_node_fs = __toESM(require("fs"));
422
+ var import_node_path = __toESM(require("path"));
423
+ var import_image = require("@midscene/core/image");
424
+ var import_utils = require("@midscene/core/utils");
425
+ var import_dayjs = __toESM(require_dayjs_min());
426
+
427
+ // src/web-element.ts
428
+ var WebElementInfo = class {
429
+ constructor({
430
+ content,
431
+ rect,
432
+ page,
433
+ locator,
434
+ id,
435
+ attributes
436
+ }) {
437
+ this.content = content;
438
+ this.rect = rect;
439
+ this.center = [
440
+ Math.floor(rect.left + rect.width / 2),
441
+ Math.floor(rect.top + rect.height / 2)
442
+ ];
443
+ this.page = page;
444
+ this.locator = locator;
445
+ this.id = id;
446
+ this.attributes = attributes;
447
+ }
448
+ };
449
+
450
+ // src/common/utils.ts
451
+ async function parseContextFromWebPage(page, _opt) {
452
+ (0, import_node_assert.default)(page, "page is required");
453
+ const url = page.url();
454
+ const file = (0, import_utils.getTmpFile)("jpeg");
455
+ await page.screenshot({ path: file, type: "jpeg", quality: 75 });
456
+ const screenshotBuffer = (0, import_node_fs.readFileSync)(file);
457
+ const screenshotBase64 = (0, import_image.base64Encoded)(file);
458
+ const captureElementSnapshot = await getElementInfosFromPage(page);
459
+ const elementsInfo = await alignElements(
460
+ screenshotBuffer,
461
+ captureElementSnapshot,
462
+ page
463
+ );
464
+ const size = await (0, import_image.imageInfoOfBase64)(screenshotBase64);
465
+ return {
466
+ content: elementsInfo,
467
+ size,
468
+ screenshotBase64,
469
+ url
470
+ };
471
+ }
472
+ async function getElementInfosFromPage(page) {
473
+ const pathDir = findNearestPackageJson(__dirname);
474
+ (0, import_node_assert.default)(pathDir, `can't find pathDir, with ${__dirname}`);
475
+ const scriptPath = import_node_path.default.join(pathDir, "./dist/script/htmlElement.js");
476
+ const elementInfosScriptContent = (0, import_node_fs.readFileSync)(scriptPath, "utf-8");
477
+ const extraReturnLogic = `${elementInfosScriptContent}midscene_element_inspector.extractTextWithPosition()`;
478
+ const captureElementSnapshot = await page.evaluate(extraReturnLogic);
479
+ return captureElementSnapshot;
480
+ }
481
+ var sizeThreshold = 3;
482
+ async function alignElements(screenshotBuffer, elements, page) {
483
+ const textsAligned = [];
484
+ const validElements = elements.filter((item) => {
485
+ return item.rect.height >= sizeThreshold && item.rect.width >= sizeThreshold;
486
+ });
487
+ for (const item of validElements) {
488
+ const { rect, id, content, attributes, locator } = item;
489
+ textsAligned.push(
490
+ new WebElementInfo({
491
+ rect,
492
+ locator,
493
+ id,
494
+ content,
495
+ attributes,
496
+ page
497
+ })
498
+ );
499
+ }
500
+ return textsAligned;
501
+ }
502
+ function findNearestPackageJson(dir) {
503
+ const packageJsonPath = import_node_path.default.join(dir, "package.json");
504
+ if (import_node_fs.default.existsSync(packageJsonPath)) {
505
+ return dir;
506
+ }
507
+ const parentDir = import_node_path.default.dirname(dir);
508
+ if (parentDir === dir) {
509
+ return null;
510
+ }
511
+ return findNearestPackageJson(parentDir);
512
+ }
513
+ function reportFileName(tag = "web") {
514
+ const dateTimeInFileName = (0, import_dayjs.default)().format("YYYY-MM-DD_HH-mm-ss-SSS");
515
+ return `${tag}-${dateTimeInFileName}`;
516
+ }
517
+ function printReportMsg(filepath) {
518
+ console.log("Midscene - report file updated:", filepath);
519
+ }
520
+
521
+ // src/common/tasks.ts
522
+ var PageTaskExecutor = class {
523
+ constructor(page, opts) {
524
+ this.page = page;
525
+ this.insight = new import_core.default(async () => {
526
+ return await parseContextFromWebPage(page);
527
+ });
528
+ this.taskCache = new TaskCache(opts);
529
+ }
530
+ async recordScreenshot(timing) {
531
+ const file = (0, import_utils2.getTmpFile)("jpeg");
532
+ await this.page.screenshot(__spreadProps(__spreadValues({}, import_utils2.commonScreenshotParam), {
533
+ path: file
534
+ }));
535
+ const item = {
536
+ type: "screenshot",
537
+ ts: Date.now(),
538
+ screenshot: (0, import_image2.base64Encoded)(file),
539
+ timing
540
+ };
541
+ return item;
542
+ }
543
+ wrapExecutorWithScreenshot(taskApply) {
544
+ const taskWithScreenshot = __spreadProps(__spreadValues({}, taskApply), {
545
+ executor: async (param, context, ...args) => {
546
+ const recorder = [];
547
+ const { task } = context;
548
+ task.recorder = recorder;
549
+ const shot = await this.recordScreenshot(`before ${task.type}`);
550
+ recorder.push(shot);
551
+ const result = await taskApply.executor(param, context, ...args);
552
+ if (taskApply.type === "Action") {
553
+ await (0, import_utils2.sleep)(1e3);
554
+ const shot2 = await this.recordScreenshot("after Action");
555
+ recorder.push(shot2);
556
+ }
557
+ return result;
558
+ }
559
+ });
560
+ return taskWithScreenshot;
561
+ }
562
+ async convertPlanToExecutable(plans) {
563
+ const tasks = plans.map((plan2) => {
564
+ if (plan2.type === "Locate") {
565
+ const taskFind = {
566
+ type: "Insight",
567
+ subType: "Locate",
568
+ param: plan2.param,
569
+ executor: async (param) => {
570
+ let insightDump;
571
+ const dumpCollector = (dump) => {
572
+ insightDump = dump;
573
+ };
574
+ this.insight.onceDumpUpdatedFn = dumpCollector;
575
+ const pageContext = await this.insight.contextRetrieverFn();
576
+ const locateCache = this.taskCache.readCache(
577
+ pageContext,
578
+ "locate",
579
+ param.prompt
580
+ );
581
+ let locateResult;
582
+ const callAI = this.insight.aiVendorFn;
583
+ const element = await this.insight.locate(param.prompt, {
584
+ callAI: async (...message) => {
585
+ if (locateCache) {
586
+ locateResult = locateCache;
587
+ return Promise.resolve(locateCache);
588
+ }
589
+ locateResult = await callAI(...message);
590
+ (0, import_node_assert2.default)(locateResult);
591
+ return locateResult;
592
+ }
593
+ });
594
+ (0, import_node_assert2.default)(element, `Element not found: ${param.prompt}`);
595
+ if (locateResult) {
596
+ this.taskCache.saveCache({
597
+ type: "locate",
598
+ pageContext: {
599
+ url: pageContext.url,
600
+ size: pageContext.size
601
+ },
602
+ prompt: param.prompt,
603
+ response: locateResult
604
+ });
605
+ }
606
+ return {
607
+ output: {
608
+ element
609
+ },
610
+ log: {
611
+ dump: insightDump
612
+ },
613
+ cache: {
614
+ hit: Boolean(locateResult)
615
+ }
616
+ };
617
+ }
618
+ };
619
+ return taskFind;
620
+ }
621
+ if (plan2.type === "Assert" || plan2.type === "AssertWithoutThrow") {
622
+ const assertPlan = plan2;
623
+ const taskAssert = {
624
+ type: "Insight",
625
+ subType: "Assert",
626
+ param: assertPlan.param,
627
+ executor: async (param, taskContext) => {
628
+ const { task } = taskContext;
629
+ let insightDump;
630
+ const dumpCollector = (dump) => {
631
+ insightDump = dump;
632
+ };
633
+ this.insight.onceDumpUpdatedFn = dumpCollector;
634
+ const assertion = await this.insight.assert(
635
+ assertPlan.param.assertion
636
+ );
637
+ if (!assertion.pass) {
638
+ if (plan2.type === "Assert") {
639
+ task.output = assertion;
640
+ task.log = {
641
+ dump: insightDump
642
+ };
643
+ throw new Error(
644
+ assertion.thought || "Assertion failed without reason"
645
+ );
646
+ }
647
+ task.error = assertion.thought;
648
+ }
649
+ return {
650
+ output: assertion,
651
+ log: {
652
+ dump: insightDump
653
+ }
654
+ };
655
+ }
656
+ };
657
+ return taskAssert;
658
+ }
659
+ if (plan2.type === "Input") {
660
+ const taskActionInput = {
661
+ type: "Action",
662
+ subType: "Input",
663
+ param: plan2.param,
664
+ executor: async (taskParam, { element }) => {
665
+ if (element) {
666
+ await this.page.mouse.click(
667
+ element.center[0],
668
+ element.center[1]
669
+ );
670
+ }
671
+ (0, import_node_assert2.default)(taskParam.value, "No value to input");
672
+ await this.page.keyboard.type(taskParam.value);
673
+ }
674
+ };
675
+ return taskActionInput;
676
+ }
677
+ if (plan2.type === "KeyboardPress") {
678
+ const taskActionKeyboardPress = {
679
+ type: "Action",
680
+ subType: "KeyboardPress",
681
+ param: plan2.param,
682
+ executor: async (taskParam) => {
683
+ (0, import_node_assert2.default)(taskParam.value, "No key to press");
684
+ await this.page.keyboard.press(taskParam.value);
685
+ }
686
+ };
687
+ return taskActionKeyboardPress;
688
+ }
689
+ if (plan2.type === "Tap") {
690
+ const taskActionTap = {
691
+ type: "Action",
692
+ subType: "Tap",
693
+ executor: async (param, { element }) => {
694
+ (0, import_node_assert2.default)(element, "Element not found, cannot tap");
695
+ await this.page.mouse.click(
696
+ element.center[0],
697
+ element.center[1]
698
+ );
699
+ }
700
+ };
701
+ return taskActionTap;
702
+ }
703
+ if (plan2.type === "Hover") {
704
+ const taskActionHover = {
705
+ type: "Action",
706
+ subType: "Hover",
707
+ executor: async (param, { element }) => {
708
+ (0, import_node_assert2.default)(element, "Element not found, cannot hover");
709
+ await this.page.mouse.move(
710
+ element.center[0],
711
+ element.center[1]
712
+ );
713
+ }
714
+ };
715
+ return taskActionHover;
716
+ }
717
+ if (plan2.type === "Scroll") {
718
+ const taskActionScroll = {
719
+ type: "Action",
720
+ subType: "Scroll",
721
+ param: plan2.param,
722
+ executor: async (taskParam) => {
723
+ const scrollToEventName = taskParam.scrollType;
724
+ const innerHeight = await this.page.evaluate(
725
+ () => window.innerHeight
726
+ );
727
+ switch (scrollToEventName) {
728
+ case "ScrollUntilTop":
729
+ await this.page.mouse.wheel(0, -9999999);
730
+ break;
731
+ case "ScrollUntilBottom":
732
+ await this.page.mouse.wheel(0, 9999999);
733
+ break;
734
+ case "ScrollUp":
735
+ await this.page.mouse.wheel(0, -innerHeight);
736
+ break;
737
+ case "ScrollDown":
738
+ await this.page.mouse.wheel(0, innerHeight);
739
+ break;
740
+ default:
741
+ console.error(
742
+ "Unknown scroll event type:",
743
+ scrollToEventName
744
+ );
745
+ }
746
+ }
747
+ };
748
+ return taskActionScroll;
749
+ }
750
+ if (plan2.type === "Sleep") {
751
+ const taskActionSleep = {
752
+ type: "Action",
753
+ subType: "Sleep",
754
+ param: plan2.param,
755
+ executor: async (taskParam) => {
756
+ (0, import_node_assert2.default)(taskParam.timeMs, "No time to sleep");
757
+ await (0, import_utils2.sleep)(taskParam.timeMs);
758
+ }
759
+ };
760
+ return taskActionSleep;
761
+ }
762
+ if (plan2.type === "Error") {
763
+ const taskActionError = {
764
+ type: "Action",
765
+ subType: "Error",
766
+ param: plan2.param,
767
+ executor: async (taskParam) => {
768
+ (0, import_node_assert2.default)(
769
+ taskParam.thought,
770
+ "An error occurred, but no thought provided"
771
+ );
772
+ throw new Error(taskParam.thought);
773
+ }
774
+ };
775
+ return taskActionError;
776
+ }
777
+ throw new Error(`Unknown or Unsupported task type: ${plan2.type}`);
778
+ }).map((task) => {
779
+ return this.wrapExecutorWithScreenshot(task);
780
+ });
781
+ return tasks;
782
+ }
783
+ async action(userPrompt) {
784
+ const taskExecutor = new import_core.Executor(userPrompt);
785
+ let plans = [];
786
+ const planningTask = {
787
+ type: "Planning",
788
+ param: {
789
+ userPrompt
790
+ },
791
+ executor: async (param) => {
792
+ const pageContext = await this.insight.contextRetrieverFn();
793
+ let planResult;
794
+ const planCache = this.taskCache.readCache(
795
+ pageContext,
796
+ "plan",
797
+ userPrompt
798
+ );
799
+ if (planCache) {
800
+ planResult = planCache;
801
+ } else {
802
+ planResult = await (0, import_core.plan)(param.userPrompt, {
803
+ context: pageContext
804
+ });
805
+ }
806
+ (0, import_node_assert2.default)(planResult.plans.length > 0, "No plans found");
807
+ plans = planResult.plans;
808
+ this.taskCache.saveCache({
809
+ type: "plan",
810
+ pageContext: {
811
+ url: pageContext.url,
812
+ size: pageContext.size
813
+ },
814
+ prompt: userPrompt,
815
+ response: planResult
816
+ });
817
+ return {
818
+ output: planResult,
819
+ cache: {
820
+ hit: Boolean(planCache)
821
+ }
822
+ };
823
+ }
824
+ };
825
+ await taskExecutor.append(this.wrapExecutorWithScreenshot(planningTask));
826
+ let output = await taskExecutor.flush();
827
+ if (taskExecutor.isInErrorState()) {
828
+ return {
829
+ output,
830
+ executor: taskExecutor
831
+ };
832
+ }
833
+ const executables = await this.convertPlanToExecutable(plans);
834
+ await taskExecutor.append(executables);
835
+ output = await taskExecutor.flush();
836
+ return {
837
+ output,
838
+ executor: taskExecutor
839
+ };
840
+ }
841
+ async query(demand) {
842
+ const description = typeof demand === "string" ? demand : JSON.stringify(demand);
843
+ const taskExecutor = new import_core.Executor(description);
844
+ const queryTask = {
845
+ type: "Insight",
846
+ subType: "Query",
847
+ param: {
848
+ dataDemand: demand
849
+ },
850
+ executor: async (param) => {
851
+ let insightDump;
852
+ const dumpCollector = (dump) => {
853
+ insightDump = dump;
854
+ };
855
+ this.insight.onceDumpUpdatedFn = dumpCollector;
856
+ const data = await this.insight.extract(param.dataDemand);
857
+ return {
858
+ output: data,
859
+ log: { dump: insightDump }
860
+ };
861
+ }
862
+ };
863
+ await taskExecutor.append(this.wrapExecutorWithScreenshot(queryTask));
864
+ const output = await taskExecutor.flush();
865
+ return {
866
+ output,
867
+ executor: taskExecutor
868
+ };
869
+ }
870
+ async assert(assertion) {
871
+ const description = `assert: ${assertion}`;
872
+ const taskExecutor = new import_core.Executor(description);
873
+ const assertionPlan = {
874
+ type: "Assert",
875
+ param: {
876
+ assertion
877
+ }
878
+ };
879
+ const assertTask = await this.convertPlanToExecutable([assertionPlan]);
880
+ await taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
881
+ const output = await taskExecutor.flush();
882
+ return {
883
+ output,
884
+ executor: taskExecutor
885
+ };
886
+ }
887
+ async waitFor(assertion, opt) {
888
+ const description = `waitFor: ${assertion}`;
889
+ const taskExecutor = new import_core.Executor(description);
890
+ const { timeoutMs, checkIntervalMs } = opt;
891
+ (0, import_node_assert2.default)(assertion, "No assertion for waitFor");
892
+ (0, import_node_assert2.default)(timeoutMs, "No timeoutMs for waitFor");
893
+ (0, import_node_assert2.default)(checkIntervalMs, "No checkIntervalMs for waitFor");
894
+ const overallStartTime = Date.now();
895
+ let startTime = Date.now();
896
+ let errorThought = "";
897
+ while (Date.now() - overallStartTime < timeoutMs) {
898
+ startTime = Date.now();
899
+ const assertPlan = {
900
+ type: "AssertWithoutThrow",
901
+ param: {
902
+ assertion
903
+ }
904
+ };
905
+ const assertTask = await this.convertPlanToExecutable([assertPlan]);
906
+ await taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
907
+ const output = await taskExecutor.flush();
908
+ if (output.pass) {
909
+ return {
910
+ output: void 0,
911
+ executor: taskExecutor
912
+ };
913
+ }
914
+ errorThought = output.thought;
915
+ const now = Date.now();
916
+ if (now - startTime < checkIntervalMs) {
917
+ const timeRemaining = checkIntervalMs - (now - startTime);
918
+ const sleepPlan = {
919
+ type: "Sleep",
920
+ param: {
921
+ timeMs: timeRemaining
922
+ }
923
+ };
924
+ const sleepTask = await this.convertPlanToExecutable([sleepPlan]);
925
+ await taskExecutor.append(
926
+ this.wrapExecutorWithScreenshot(sleepTask[0])
927
+ );
928
+ await taskExecutor.flush();
929
+ }
930
+ }
931
+ const errorPlan = {
932
+ type: "Error",
933
+ param: {
934
+ thought: `waitFor timeout: ${errorThought}`
935
+ }
936
+ };
937
+ const errorTask = await this.convertPlanToExecutable([errorPlan]);
938
+ await taskExecutor.append(errorTask[0]);
939
+ await taskExecutor.flush();
940
+ return {
941
+ output: void 0,
942
+ executor: taskExecutor
943
+ };
944
+ }
945
+ };
946
+
947
+ // src/common/agent.ts
948
+ var PageAgent = class {
949
+ constructor(page, opts) {
950
+ this.page = page;
951
+ this.opts = Object.assign(
952
+ {
953
+ generateReport: true,
954
+ autoPrintReportMsg: true,
955
+ groupName: "Midscene Report",
956
+ groupDescription: ""
957
+ },
958
+ opts || {}
959
+ );
960
+ this.dump = {
961
+ groupName: this.opts.groupName,
962
+ groupDescription: this.opts.groupDescription,
963
+ executions: []
964
+ };
965
+ this.taskExecutor = new PageTaskExecutor(this.page, {
966
+ cache: (opts == null ? void 0 : opts.cache) || { aiTasks: [] }
967
+ });
968
+ this.reportFileName = reportFileName((opts == null ? void 0 : opts.testId) || "web");
969
+ }
970
+ appendExecutionDump(execution) {
971
+ const currentDump = this.dump;
972
+ currentDump.executions.push(execution);
973
+ }
974
+ dumpDataString() {
975
+ this.dump.groupName = this.opts.groupName;
976
+ this.dump.groupDescription = this.opts.groupDescription;
977
+ return (0, import_utils4.stringifyDumpData)(this.dump);
978
+ }
979
+ writeOutActionDumps() {
980
+ const { generateReport, autoPrintReportMsg } = this.opts;
981
+ this.reportFile = (0, import_utils4.writeLogFile)({
982
+ fileName: this.reportFileName,
983
+ fileExt: import_utils4.groupedActionDumpFileExt,
984
+ fileContent: this.dumpDataString(),
985
+ type: "dump",
986
+ generateReport
987
+ });
988
+ if (generateReport && autoPrintReportMsg) {
989
+ printReportMsg(this.reportFile);
990
+ }
991
+ }
992
+ async aiAction(taskPrompt) {
993
+ const { executor } = await this.taskExecutor.action(taskPrompt);
994
+ this.appendExecutionDump(executor.dump());
995
+ this.writeOutActionDumps();
996
+ if (executor.isInErrorState()) {
997
+ const errorTask = executor.latestErrorTask();
998
+ throw new Error(`${errorTask == null ? void 0 : errorTask.error}
999
+ ${errorTask == null ? void 0 : errorTask.errorStack}`);
1000
+ }
1001
+ }
1002
+ async aiQuery(demand) {
1003
+ const { output, executor } = await this.taskExecutor.query(demand);
1004
+ this.appendExecutionDump(executor.dump());
1005
+ this.writeOutActionDumps();
1006
+ if (executor.isInErrorState()) {
1007
+ const errorTask = executor.latestErrorTask();
1008
+ throw new Error(`${errorTask == null ? void 0 : errorTask.error}
1009
+ ${errorTask == null ? void 0 : errorTask.errorStack}`);
1010
+ }
1011
+ return output;
1012
+ }
1013
+ async aiAssert(assertion, msg) {
1014
+ const { output, executor } = await this.taskExecutor.assert(assertion);
1015
+ this.appendExecutionDump(executor.dump());
1016
+ this.writeOutActionDumps();
1017
+ if (!(output == null ? void 0 : output.pass)) {
1018
+ const errMsg = msg || `Assertion failed: ${assertion}`;
1019
+ const reasonMsg = `Reason: ${output == null ? void 0 : output.thought} || (no_reason)`;
1020
+ throw new Error(`${errMsg}
1021
+ ${reasonMsg}`);
1022
+ }
1023
+ }
1024
+ async aiWaitFor(assertion, opt) {
1025
+ const { executor } = await this.taskExecutor.waitFor(assertion, {
1026
+ timeoutMs: (opt == null ? void 0 : opt.timeoutMs) || 15 * 1e3,
1027
+ checkIntervalMs: (opt == null ? void 0 : opt.checkIntervalMs) || 3 * 1e3,
1028
+ assertion
1029
+ });
1030
+ this.appendExecutionDump(executor.dump());
1031
+ this.writeOutActionDumps();
1032
+ if (executor.isInErrorState()) {
1033
+ const errorTask = executor.latestErrorTask();
1034
+ throw new Error(`${errorTask == null ? void 0 : errorTask.error}
1035
+ ${errorTask == null ? void 0 : errorTask.errorStack}`);
1036
+ }
1037
+ }
1038
+ async ai(taskPrompt, type = "action") {
1039
+ if (type === "action") {
1040
+ return this.aiAction(taskPrompt);
1041
+ }
1042
+ if (type === "query") {
1043
+ return this.aiQuery(taskPrompt);
1044
+ }
1045
+ if (type === "assert") {
1046
+ return this.aiAssert(taskPrompt);
1047
+ }
1048
+ throw new Error(
1049
+ `Unknown type: ${type}, only support 'action', 'query', 'assert'`
1050
+ );
1051
+ }
1052
+ };
1053
+
1054
+ // src/playwright/ai-fixture.ts
1055
+ var import_test = require("@playwright/test");
1056
+
1057
+ // src/playwright/cache.ts
1058
+ var import_node_fs2 = __toESM(require("fs"));
1059
+ var import_node_path2 = __toESM(require("path"));
1060
+ var import_utils7 = require("@midscene/core/utils");
1061
+ function writeTestCache(taskFile, taskTitle, taskCacheJson) {
1062
+ const packageJson = getPkgInfo();
1063
+ (0, import_utils7.writeLogFile)({
1064
+ fileName: `${taskFile}(${taskTitle})`,
1065
+ fileExt: "json",
1066
+ fileContent: (0, import_utils7.stringifyDumpData)(
1067
+ __spreadValues({
1068
+ pkgName: packageJson.name,
1069
+ pkgVersion: packageJson.version,
1070
+ taskFile,
1071
+ taskTitle
1072
+ }, taskCacheJson),
1073
+ 2
1074
+ ),
1075
+ type: "cache"
1076
+ });
1077
+ }
1078
+ function readTestCache(taskFile, taskTitle) {
1079
+ const cacheFile = (0, import_node_path2.join)(
1080
+ (0, import_utils7.getLogDirByType)("cache"),
1081
+ `${taskFile}(${taskTitle}).json`
1082
+ );
1083
+ const pkgInfo = getPkgInfo();
1084
+ if (process.env.MIDSCENE_CACHE === "true" && import_node_fs2.default.existsSync(cacheFile)) {
1085
+ try {
1086
+ const data = import_node_fs2.default.readFileSync(cacheFile, "utf8");
1087
+ const jsonData = JSON.parse(data);
1088
+ if (jsonData.pkgName !== pkgInfo.name || jsonData.pkgVersion !== pkgInfo.version) {
1089
+ return void 0;
1090
+ }
1091
+ return jsonData;
1092
+ } catch (err) {
1093
+ return void 0;
1094
+ }
1095
+ }
1096
+ return void 0;
1097
+ }
1098
+ function getPkgInfo() {
1099
+ const packageJsonDir = findNearestPackageJson(__dirname);
1100
+ if (!packageJsonDir) {
1101
+ console.error("Cannot find package.json directory: ", __dirname);
1102
+ return {
1103
+ name: "@midscene/web",
1104
+ version: "0.0.0"
1105
+ };
1106
+ }
1107
+ const packageJsonPath = import_node_path2.default.join(packageJsonDir, "package.json");
1108
+ const data = import_node_fs2.default.readFileSync(packageJsonPath, "utf8");
1109
+ const packageJson = JSON.parse(data);
1110
+ return {
1111
+ name: packageJson.name,
1112
+ version: packageJson.version
1113
+ };
1114
+ }
1115
+
1116
+ // src/playwright/ai-fixture.ts
1117
+ var groupAndCaseForTest = (testInfo) => {
1118
+ let taskFile;
1119
+ let taskTitle;
1120
+ const titlePath = [...testInfo.titlePath];
1121
+ if (titlePath.length > 1) {
1122
+ taskTitle = titlePath.pop() || "unnamed";
1123
+ taskFile = `${titlePath.join(" > ")}`;
1124
+ } else if (titlePath.length === 1) {
1125
+ taskTitle = titlePath[0];
1126
+ taskFile = `${taskTitle}`;
1127
+ } else {
1128
+ taskTitle = "unnamed";
1129
+ taskFile = "unnamed";
1130
+ }
1131
+ return { taskFile, taskTitle };
1132
+ };
1133
+ var midsceneAgentKeyId = "_midsceneAgentId";
1134
+ var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
1135
+ var PlaywrightAiFixture = () => {
1136
+ const pageAgentMap = {};
1137
+ const agentForPage = (page, testInfo) => {
1138
+ let idForPage = page[midsceneAgentKeyId];
1139
+ if (!idForPage) {
1140
+ idForPage = (0, import_node_crypto.randomUUID)();
1141
+ page[midsceneAgentKeyId] = idForPage;
1142
+ const { testId } = testInfo;
1143
+ const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
1144
+ const testCase = readTestCache(taskFile, taskTitle) || {
1145
+ aiTasks: []
1146
+ };
1147
+ pageAgentMap[idForPage] = new PageAgent(page, {
1148
+ testId: `playwright-${testId}-${idForPage}`,
1149
+ groupName: taskTitle,
1150
+ groupDescription: taskFile,
1151
+ cache: testCase,
1152
+ generateReport: false
1153
+ // we will generate it in the reporter
1154
+ });
1155
+ }
1156
+ return pageAgentMap[idForPage];
1157
+ };
1158
+ const updateDumpAnnotation = (test2, dump) => {
1159
+ const currentAnnotation = test2.annotations.find((item) => {
1160
+ return item.type === midsceneDumpAnnotationId;
1161
+ });
1162
+ if (currentAnnotation) {
1163
+ currentAnnotation.description = dump;
1164
+ } else {
1165
+ test2.annotations.push({
1166
+ type: midsceneDumpAnnotationId,
1167
+ description: dump
1168
+ });
1169
+ }
1170
+ };
1171
+ return {
1172
+ ai: async ({ page }, use, testInfo) => {
1173
+ const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
1174
+ const agent = agentForPage(page, testInfo);
1175
+ await use(
1176
+ async (taskPrompt, opts) => {
1177
+ return new Promise((resolve, reject) => {
1178
+ import_test.test.step(`ai - ${taskPrompt}`, async () => {
1179
+ await page.waitForLoadState("networkidle");
1180
+ const actionType = (opts == null ? void 0 : opts.type) || "action";
1181
+ const result = await agent.ai(taskPrompt, actionType);
1182
+ resolve(result);
1183
+ });
1184
+ });
1185
+ }
1186
+ );
1187
+ const taskCacheJson = agent.taskExecutor.taskCache.generateTaskCache();
1188
+ writeTestCache(taskFile, taskTitle, taskCacheJson);
1189
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
1190
+ },
1191
+ aiAction: async ({ page }, use, testInfo) => {
1192
+ const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
1193
+ const agent = agentForPage(page, testInfo);
1194
+ await use(async (taskPrompt) => {
1195
+ import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
1196
+ await page.waitForLoadState("networkidle");
1197
+ await agent.aiAction(taskPrompt);
1198
+ });
1199
+ });
1200
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
1201
+ },
1202
+ aiQuery: async ({ page }, use, testInfo) => {
1203
+ const agent = agentForPage(page, testInfo);
1204
+ await use(async (demand) => {
1205
+ return new Promise((resolve, reject) => {
1206
+ import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
1207
+ await page.waitForLoadState("networkidle");
1208
+ const result = await agent.aiQuery(demand);
1209
+ resolve(result);
1210
+ });
1211
+ });
1212
+ });
1213
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
1214
+ },
1215
+ aiAssert: async ({ page }, use, testInfo) => {
1216
+ const agent = agentForPage(page, testInfo);
1217
+ await use(async (assertion, errorMsg) => {
1218
+ return new Promise((resolve, reject) => {
1219
+ import_test.test.step(`aiAssert - ${assertion}`, async () => {
1220
+ await page.waitForLoadState("networkidle");
1221
+ await agent.aiAssert(assertion, errorMsg);
1222
+ resolve(null);
1223
+ });
1224
+ });
1225
+ });
1226
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
1227
+ },
1228
+ aiWaitFor: async ({ page }, use, testInfo) => {
1229
+ const agent = agentForPage(page, testInfo);
1230
+ await use(async (assertion, opt) => {
1231
+ return new Promise((resolve, reject) => {
1232
+ import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
1233
+ await agent.aiWaitFor(assertion, opt);
1234
+ resolve(null);
1235
+ });
1236
+ });
1237
+ });
1238
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
1239
+ }
1240
+ };
1241
+ };
1242
+ // Annotate the CommonJS export names for ESM import in node:
1243
+ 0 && (module.exports = {
1244
+ PlaywrightAiFixture
1245
+ });