@midscene/web 0.7.1 → 0.7.2-beta-20241024094141.0
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/browser/playground.js +8438 -0
- package/dist/browser/types/playground.d.ts +313 -0
- package/dist/es/appium.js +680 -604
- package/dist/es/debug.js +95 -73
- package/dist/es/index.js +939 -797
- package/dist/es/midscene-playground.js +678 -609
- package/dist/es/playground.js +593 -1024
- package/dist/es/playwright-report.js +29 -11
- package/dist/es/playwright.js +705 -597
- package/dist/es/puppeteer.js +636 -552
- package/dist/lib/appium.js +688 -609
- package/dist/lib/debug.js +95 -73
- package/dist/lib/index.js +950 -804
- package/dist/lib/midscene-playground.js +687 -615
- package/dist/lib/playground.js +586 -1007
- package/dist/lib/playwright-report.js +30 -9
- package/dist/lib/playwright.js +713 -602
- package/dist/lib/puppeteer.js +644 -557
- package/dist/script/htmlElement.js +11 -10
- package/dist/script/htmlElementDebug.js +11 -10
- package/dist/types/appium.d.ts +2 -3
- package/dist/types/debug.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/{page-ad820b3c.d.ts → page-8117b0ad.d.ts} +8 -7
- package/dist/types/playground.d.ts +6 -21
- package/dist/types/playwright.d.ts +3 -4
- package/dist/types/puppeteer.d.ts +2 -3
- package/dist/types/{tasks-82c1054b.d.ts → tasks-cb6bf758.d.ts} +6 -6
- package/package.json +11 -5
- package/static/index.html +1 -1
package/dist/lib/playground.js
CHANGED
|
@@ -46,6 +46,26 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
46
46
|
mod
|
|
47
47
|
));
|
|
48
48
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
49
|
+
var __async = (__this, __arguments, generator) => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
var fulfilled = (value) => {
|
|
52
|
+
try {
|
|
53
|
+
step(generator.next(value));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
reject(e);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var rejected = (value) => {
|
|
59
|
+
try {
|
|
60
|
+
step(generator.throw(value));
|
|
61
|
+
} catch (e) {
|
|
62
|
+
reject(e);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
66
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
67
|
+
});
|
|
68
|
+
};
|
|
49
69
|
|
|
50
70
|
// ../../node_modules/.pnpm/dayjs@1.11.11/node_modules/dayjs/dayjs.min.js
|
|
51
71
|
var require_dayjs_min = __commonJS({
|
|
@@ -342,378 +362,24 @@ var require_dayjs_min = __commonJS({
|
|
|
342
362
|
}
|
|
343
363
|
});
|
|
344
364
|
|
|
345
|
-
// ../../node_modules/.pnpm/dotenv@16.4.5/node_modules/dotenv/package.json
|
|
346
|
-
var require_package = __commonJS({
|
|
347
|
-
"../../node_modules/.pnpm/dotenv@16.4.5/node_modules/dotenv/package.json"(exports, module2) {
|
|
348
|
-
module2.exports = {
|
|
349
|
-
name: "dotenv",
|
|
350
|
-
version: "16.4.5",
|
|
351
|
-
description: "Loads environment variables from .env file",
|
|
352
|
-
main: "lib/main.js",
|
|
353
|
-
types: "lib/main.d.ts",
|
|
354
|
-
exports: {
|
|
355
|
-
".": {
|
|
356
|
-
types: "./lib/main.d.ts",
|
|
357
|
-
require: "./lib/main.js",
|
|
358
|
-
default: "./lib/main.js"
|
|
359
|
-
},
|
|
360
|
-
"./config": "./config.js",
|
|
361
|
-
"./config.js": "./config.js",
|
|
362
|
-
"./lib/env-options": "./lib/env-options.js",
|
|
363
|
-
"./lib/env-options.js": "./lib/env-options.js",
|
|
364
|
-
"./lib/cli-options": "./lib/cli-options.js",
|
|
365
|
-
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
366
|
-
"./package.json": "./package.json"
|
|
367
|
-
},
|
|
368
|
-
scripts: {
|
|
369
|
-
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
370
|
-
lint: "standard",
|
|
371
|
-
"lint-readme": "standard-markdown",
|
|
372
|
-
pretest: "npm run lint && npm run dts-check",
|
|
373
|
-
test: "tap tests/*.js --100 -Rspec",
|
|
374
|
-
"test:coverage": "tap --coverage-report=lcov",
|
|
375
|
-
prerelease: "npm test",
|
|
376
|
-
release: "standard-version"
|
|
377
|
-
},
|
|
378
|
-
repository: {
|
|
379
|
-
type: "git",
|
|
380
|
-
url: "git://github.com/motdotla/dotenv.git"
|
|
381
|
-
},
|
|
382
|
-
funding: "https://dotenvx.com",
|
|
383
|
-
keywords: [
|
|
384
|
-
"dotenv",
|
|
385
|
-
"env",
|
|
386
|
-
".env",
|
|
387
|
-
"environment",
|
|
388
|
-
"variables",
|
|
389
|
-
"config",
|
|
390
|
-
"settings"
|
|
391
|
-
],
|
|
392
|
-
readmeFilename: "README.md",
|
|
393
|
-
license: "BSD-2-Clause",
|
|
394
|
-
devDependencies: {
|
|
395
|
-
"@definitelytyped/dtslint": "^0.0.133",
|
|
396
|
-
"@types/node": "^18.11.3",
|
|
397
|
-
decache: "^4.6.1",
|
|
398
|
-
sinon: "^14.0.1",
|
|
399
|
-
standard: "^17.0.0",
|
|
400
|
-
"standard-markdown": "^7.1.0",
|
|
401
|
-
"standard-version": "^9.5.0",
|
|
402
|
-
tap: "^16.3.0",
|
|
403
|
-
tar: "^6.1.11",
|
|
404
|
-
typescript: "^4.8.4"
|
|
405
|
-
},
|
|
406
|
-
engines: {
|
|
407
|
-
node: ">=12"
|
|
408
|
-
},
|
|
409
|
-
browser: {
|
|
410
|
-
fs: false
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
// ../../node_modules/.pnpm/dotenv@16.4.5/node_modules/dotenv/lib/main.js
|
|
417
|
-
var require_main = __commonJS({
|
|
418
|
-
"../../node_modules/.pnpm/dotenv@16.4.5/node_modules/dotenv/lib/main.js"(exports, module2) {
|
|
419
|
-
"use strict";
|
|
420
|
-
var fs = require("fs");
|
|
421
|
-
var path2 = require("path");
|
|
422
|
-
var os = require("os");
|
|
423
|
-
var crypto = require("crypto");
|
|
424
|
-
var packageJson = require_package();
|
|
425
|
-
var version = packageJson.version;
|
|
426
|
-
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
427
|
-
function parse(src) {
|
|
428
|
-
const obj = {};
|
|
429
|
-
let lines = src.toString();
|
|
430
|
-
lines = lines.replace(/\r\n?/mg, "\n");
|
|
431
|
-
let match;
|
|
432
|
-
while ((match = LINE.exec(lines)) != null) {
|
|
433
|
-
const key = match[1];
|
|
434
|
-
let value = match[2] || "";
|
|
435
|
-
value = value.trim();
|
|
436
|
-
const maybeQuote = value[0];
|
|
437
|
-
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
438
|
-
if (maybeQuote === '"') {
|
|
439
|
-
value = value.replace(/\\n/g, "\n");
|
|
440
|
-
value = value.replace(/\\r/g, "\r");
|
|
441
|
-
}
|
|
442
|
-
obj[key] = value;
|
|
443
|
-
}
|
|
444
|
-
return obj;
|
|
445
|
-
}
|
|
446
|
-
function _parseVault(options) {
|
|
447
|
-
const vaultPath = _vaultPath(options);
|
|
448
|
-
const result = DotenvModule.configDotenv({ path: vaultPath });
|
|
449
|
-
if (!result.parsed) {
|
|
450
|
-
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
451
|
-
err.code = "MISSING_DATA";
|
|
452
|
-
throw err;
|
|
453
|
-
}
|
|
454
|
-
const keys = _dotenvKey(options).split(",");
|
|
455
|
-
const length = keys.length;
|
|
456
|
-
let decrypted;
|
|
457
|
-
for (let i = 0; i < length; i++) {
|
|
458
|
-
try {
|
|
459
|
-
const key = keys[i].trim();
|
|
460
|
-
const attrs = _instructions(result, key);
|
|
461
|
-
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
462
|
-
break;
|
|
463
|
-
} catch (error) {
|
|
464
|
-
if (i + 1 >= length) {
|
|
465
|
-
throw error;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
return DotenvModule.parse(decrypted);
|
|
470
|
-
}
|
|
471
|
-
function _log(message) {
|
|
472
|
-
console.log(`[dotenv@${version}][INFO] ${message}`);
|
|
473
|
-
}
|
|
474
|
-
function _warn(message) {
|
|
475
|
-
console.log(`[dotenv@${version}][WARN] ${message}`);
|
|
476
|
-
}
|
|
477
|
-
function _debug(message) {
|
|
478
|
-
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
479
|
-
}
|
|
480
|
-
function _dotenvKey(options) {
|
|
481
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
482
|
-
return options.DOTENV_KEY;
|
|
483
|
-
}
|
|
484
|
-
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
485
|
-
return process.env.DOTENV_KEY;
|
|
486
|
-
}
|
|
487
|
-
return "";
|
|
488
|
-
}
|
|
489
|
-
function _instructions(result, dotenvKey) {
|
|
490
|
-
let uri;
|
|
491
|
-
try {
|
|
492
|
-
uri = new URL(dotenvKey);
|
|
493
|
-
} catch (error) {
|
|
494
|
-
if (error.code === "ERR_INVALID_URL") {
|
|
495
|
-
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
496
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
497
|
-
throw err;
|
|
498
|
-
}
|
|
499
|
-
throw error;
|
|
500
|
-
}
|
|
501
|
-
const key = uri.password;
|
|
502
|
-
if (!key) {
|
|
503
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
504
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
505
|
-
throw err;
|
|
506
|
-
}
|
|
507
|
-
const environment = uri.searchParams.get("environment");
|
|
508
|
-
if (!environment) {
|
|
509
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
510
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
511
|
-
throw err;
|
|
512
|
-
}
|
|
513
|
-
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
514
|
-
const ciphertext = result.parsed[environmentKey];
|
|
515
|
-
if (!ciphertext) {
|
|
516
|
-
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
517
|
-
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
518
|
-
throw err;
|
|
519
|
-
}
|
|
520
|
-
return { ciphertext, key };
|
|
521
|
-
}
|
|
522
|
-
function _vaultPath(options) {
|
|
523
|
-
let possibleVaultPath = null;
|
|
524
|
-
if (options && options.path && options.path.length > 0) {
|
|
525
|
-
if (Array.isArray(options.path)) {
|
|
526
|
-
for (const filepath of options.path) {
|
|
527
|
-
if (fs.existsSync(filepath)) {
|
|
528
|
-
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
} else {
|
|
532
|
-
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
533
|
-
}
|
|
534
|
-
} else {
|
|
535
|
-
possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
|
|
536
|
-
}
|
|
537
|
-
if (fs.existsSync(possibleVaultPath)) {
|
|
538
|
-
return possibleVaultPath;
|
|
539
|
-
}
|
|
540
|
-
return null;
|
|
541
|
-
}
|
|
542
|
-
function _resolveHome(envPath) {
|
|
543
|
-
return envPath[0] === "~" ? path2.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
544
|
-
}
|
|
545
|
-
function _configVault(options) {
|
|
546
|
-
_log("Loading env from encrypted .env.vault");
|
|
547
|
-
const parsed = DotenvModule._parseVault(options);
|
|
548
|
-
let processEnv = process.env;
|
|
549
|
-
if (options && options.processEnv != null) {
|
|
550
|
-
processEnv = options.processEnv;
|
|
551
|
-
}
|
|
552
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
553
|
-
return { parsed };
|
|
554
|
-
}
|
|
555
|
-
function configDotenv(options) {
|
|
556
|
-
const dotenvPath = path2.resolve(process.cwd(), ".env");
|
|
557
|
-
let encoding = "utf8";
|
|
558
|
-
const debug = Boolean(options && options.debug);
|
|
559
|
-
if (options && options.encoding) {
|
|
560
|
-
encoding = options.encoding;
|
|
561
|
-
} else {
|
|
562
|
-
if (debug) {
|
|
563
|
-
_debug("No encoding is specified. UTF-8 is used by default");
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
let optionPaths = [dotenvPath];
|
|
567
|
-
if (options && options.path) {
|
|
568
|
-
if (!Array.isArray(options.path)) {
|
|
569
|
-
optionPaths = [_resolveHome(options.path)];
|
|
570
|
-
} else {
|
|
571
|
-
optionPaths = [];
|
|
572
|
-
for (const filepath of options.path) {
|
|
573
|
-
optionPaths.push(_resolveHome(filepath));
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
let lastError;
|
|
578
|
-
const parsedAll = {};
|
|
579
|
-
for (const path3 of optionPaths) {
|
|
580
|
-
try {
|
|
581
|
-
const parsed = DotenvModule.parse(fs.readFileSync(path3, { encoding }));
|
|
582
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
583
|
-
} catch (e) {
|
|
584
|
-
if (debug) {
|
|
585
|
-
_debug(`Failed to load ${path3} ${e.message}`);
|
|
586
|
-
}
|
|
587
|
-
lastError = e;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
let processEnv = process.env;
|
|
591
|
-
if (options && options.processEnv != null) {
|
|
592
|
-
processEnv = options.processEnv;
|
|
593
|
-
}
|
|
594
|
-
DotenvModule.populate(processEnv, parsedAll, options);
|
|
595
|
-
if (lastError) {
|
|
596
|
-
return { parsed: parsedAll, error: lastError };
|
|
597
|
-
} else {
|
|
598
|
-
return { parsed: parsedAll };
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
function config(options) {
|
|
602
|
-
if (_dotenvKey(options).length === 0) {
|
|
603
|
-
return DotenvModule.configDotenv(options);
|
|
604
|
-
}
|
|
605
|
-
const vaultPath = _vaultPath(options);
|
|
606
|
-
if (!vaultPath) {
|
|
607
|
-
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
608
|
-
return DotenvModule.configDotenv(options);
|
|
609
|
-
}
|
|
610
|
-
return DotenvModule._configVault(options);
|
|
611
|
-
}
|
|
612
|
-
function decrypt(encrypted, keyStr) {
|
|
613
|
-
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
614
|
-
let ciphertext = Buffer.from(encrypted, "base64");
|
|
615
|
-
const nonce = ciphertext.subarray(0, 12);
|
|
616
|
-
const authTag = ciphertext.subarray(-16);
|
|
617
|
-
ciphertext = ciphertext.subarray(12, -16);
|
|
618
|
-
try {
|
|
619
|
-
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
620
|
-
aesgcm.setAuthTag(authTag);
|
|
621
|
-
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
622
|
-
} catch (error) {
|
|
623
|
-
const isRange = error instanceof RangeError;
|
|
624
|
-
const invalidKeyLength = error.message === "Invalid key length";
|
|
625
|
-
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
626
|
-
if (isRange || invalidKeyLength) {
|
|
627
|
-
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
628
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
629
|
-
throw err;
|
|
630
|
-
} else if (decryptionFailed) {
|
|
631
|
-
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
632
|
-
err.code = "DECRYPTION_FAILED";
|
|
633
|
-
throw err;
|
|
634
|
-
} else {
|
|
635
|
-
throw error;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
function populate(processEnv, parsed, options = {}) {
|
|
640
|
-
const debug = Boolean(options && options.debug);
|
|
641
|
-
const override = Boolean(options && options.override);
|
|
642
|
-
if (typeof parsed !== "object") {
|
|
643
|
-
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
644
|
-
err.code = "OBJECT_REQUIRED";
|
|
645
|
-
throw err;
|
|
646
|
-
}
|
|
647
|
-
for (const key of Object.keys(parsed)) {
|
|
648
|
-
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
649
|
-
if (override === true) {
|
|
650
|
-
processEnv[key] = parsed[key];
|
|
651
|
-
}
|
|
652
|
-
if (debug) {
|
|
653
|
-
if (override === true) {
|
|
654
|
-
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
655
|
-
} else {
|
|
656
|
-
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
} else {
|
|
660
|
-
processEnv[key] = parsed[key];
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
var DotenvModule = {
|
|
665
|
-
configDotenv,
|
|
666
|
-
_configVault,
|
|
667
|
-
_parseVault,
|
|
668
|
-
config,
|
|
669
|
-
decrypt,
|
|
670
|
-
parse,
|
|
671
|
-
populate
|
|
672
|
-
};
|
|
673
|
-
module2.exports.configDotenv = DotenvModule.configDotenv;
|
|
674
|
-
module2.exports._configVault = DotenvModule._configVault;
|
|
675
|
-
module2.exports._parseVault = DotenvModule._parseVault;
|
|
676
|
-
module2.exports.config = DotenvModule.config;
|
|
677
|
-
module2.exports.decrypt = DotenvModule.decrypt;
|
|
678
|
-
module2.exports.parse = DotenvModule.parse;
|
|
679
|
-
module2.exports.populate = DotenvModule.populate;
|
|
680
|
-
module2.exports = DotenvModule;
|
|
681
|
-
}
|
|
682
|
-
});
|
|
683
|
-
|
|
684
365
|
// src/playground/index.ts
|
|
685
366
|
var playground_exports = {};
|
|
686
367
|
__export(playground_exports, {
|
|
687
|
-
|
|
368
|
+
ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED: () => ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED,
|
|
688
369
|
StaticPage: () => StaticPage,
|
|
689
370
|
StaticPageAgent: () => StaticPageAgent
|
|
690
371
|
});
|
|
691
372
|
module.exports = __toCommonJS(playground_exports);
|
|
692
373
|
|
|
693
|
-
// src/common/agent.ts
|
|
694
|
-
var import_utils5 = require("@midscene/core/utils");
|
|
695
|
-
|
|
696
|
-
// src/common/tasks.ts
|
|
697
|
-
var import_node_assert2 = __toESM(require("assert"));
|
|
698
|
-
var import_core = require("@midscene/core");
|
|
699
|
-
var import_utils3 = require("@midscene/core/utils");
|
|
700
|
-
var import_img3 = require("@midscene/shared/img");
|
|
701
|
-
|
|
702
|
-
// src/common/task-cache.ts
|
|
703
|
-
var import_node_fs2 = require("fs");
|
|
704
|
-
var import_node_path2 = require("path");
|
|
705
|
-
var import_utils = require("@midscene/core/utils");
|
|
706
|
-
var import_fs2 = require("@midscene/shared/fs");
|
|
707
|
-
|
|
708
374
|
// src/common/utils.ts
|
|
709
375
|
var import_node_assert = __toESM(require("assert"));
|
|
710
|
-
var import_node_crypto = require("crypto");
|
|
711
376
|
var import_node_fs = require("fs");
|
|
712
377
|
var import_node_path = __toESM(require("path"));
|
|
713
378
|
var import_constants = require("@midscene/shared/constants");
|
|
714
379
|
var import_fs = require("@midscene/shared/fs");
|
|
715
380
|
var import_img = require("@midscene/shared/img");
|
|
716
381
|
var import_img2 = require("@midscene/shared/img");
|
|
382
|
+
var import_utils = require("@midscene/shared/utils");
|
|
717
383
|
var import_dayjs = __toESM(require_dayjs_min());
|
|
718
384
|
|
|
719
385
|
// src/web-element.ts
|
|
@@ -742,56 +408,59 @@ var WebElementInfo = class {
|
|
|
742
408
|
};
|
|
743
409
|
|
|
744
410
|
// src/common/utils.ts
|
|
745
|
-
|
|
746
|
-
(
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const url = page.url();
|
|
751
|
-
const file = await page.screenshot();
|
|
752
|
-
const screenshotBase64 = (0, import_img.base64Encoded)(file);
|
|
753
|
-
const captureElementSnapshot = await page.getElementInfos();
|
|
754
|
-
const elementsInfo = await alignElements(captureElementSnapshot, page);
|
|
755
|
-
const elementsPositionInfoWithoutText = elementsInfo.filter((elementInfo) => {
|
|
756
|
-
if (elementInfo.attributes.nodeType === import_constants.NodeType.TEXT) {
|
|
757
|
-
return false;
|
|
411
|
+
function parseContextFromWebPage(page, _opt) {
|
|
412
|
+
return __async(this, null, function* () {
|
|
413
|
+
(0, import_node_assert.default)(page, "page is required");
|
|
414
|
+
if (page._forceUsePageContext) {
|
|
415
|
+
return yield page._forceUsePageContext();
|
|
758
416
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
417
|
+
const url = page.url();
|
|
418
|
+
const screenshotBase64 = yield page.screenshotBase64();
|
|
419
|
+
const captureElementSnapshot = yield page.getElementInfos();
|
|
420
|
+
const elementsInfo = yield alignElements(captureElementSnapshot, page);
|
|
421
|
+
const elementsPositionInfoWithoutText = elementsInfo.filter((elementInfo) => {
|
|
422
|
+
if (elementInfo.attributes.nodeType === import_constants.NodeType.TEXT) {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
return true;
|
|
426
|
+
});
|
|
427
|
+
const size = yield (0, import_img.imageInfoOfBase64)(screenshotBase64);
|
|
428
|
+
const screenshotBase64WithElementMarker = yield (0, import_img2.compositeElementInfoImg)({
|
|
429
|
+
inputImgBase64: screenshotBase64,
|
|
430
|
+
elementsPositionInfo: elementsPositionInfoWithoutText
|
|
431
|
+
});
|
|
432
|
+
return {
|
|
433
|
+
content: elementsInfo,
|
|
434
|
+
size,
|
|
435
|
+
screenshotBase64,
|
|
436
|
+
screenshotBase64WithElementMarker: `data:image/png;base64,${screenshotBase64WithElementMarker}`,
|
|
437
|
+
url
|
|
438
|
+
};
|
|
765
439
|
});
|
|
766
|
-
return {
|
|
767
|
-
content: elementsInfo,
|
|
768
|
-
size,
|
|
769
|
-
screenshotBase64,
|
|
770
|
-
screenshotBase64WithElementMarker: `data:image/png;base64,${screenshotBase64WithElementMarker}`,
|
|
771
|
-
url
|
|
772
|
-
};
|
|
773
440
|
}
|
|
774
441
|
var sizeThreshold = 3;
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
442
|
+
function alignElements(elements, page) {
|
|
443
|
+
return __async(this, null, function* () {
|
|
444
|
+
const validElements = elements.filter((item) => {
|
|
445
|
+
return item.rect.height >= sizeThreshold && item.rect.width >= sizeThreshold;
|
|
446
|
+
});
|
|
447
|
+
const textsAligned = [];
|
|
448
|
+
for (const item of validElements) {
|
|
449
|
+
const { rect, id, content, attributes, locator, indexId } = item;
|
|
450
|
+
textsAligned.push(
|
|
451
|
+
new WebElementInfo({
|
|
452
|
+
rect,
|
|
453
|
+
locator,
|
|
454
|
+
id,
|
|
455
|
+
content,
|
|
456
|
+
attributes,
|
|
457
|
+
page,
|
|
458
|
+
indexId
|
|
459
|
+
})
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
return textsAligned;
|
|
778
463
|
});
|
|
779
|
-
const textsAligned = [];
|
|
780
|
-
for (const item of validElements) {
|
|
781
|
-
const { rect, id, content, attributes, locator, indexId } = item;
|
|
782
|
-
textsAligned.push(
|
|
783
|
-
new WebElementInfo({
|
|
784
|
-
rect,
|
|
785
|
-
locator,
|
|
786
|
-
id,
|
|
787
|
-
content,
|
|
788
|
-
attributes,
|
|
789
|
-
page,
|
|
790
|
-
indexId
|
|
791
|
-
})
|
|
792
|
-
);
|
|
793
|
-
}
|
|
794
|
-
return textsAligned;
|
|
795
464
|
}
|
|
796
465
|
function reportFileName(tag = "web") {
|
|
797
466
|
const dateTimeInFileName = (0, import_dayjs.default)().format("YYYY-MM-DD_HH-mm-ss-SSS");
|
|
@@ -822,7 +491,7 @@ var testFileIndex = /* @__PURE__ */ new Map();
|
|
|
822
491
|
function generateCacheId(fileName) {
|
|
823
492
|
let taskFile = fileName || getCurrentExecutionFile();
|
|
824
493
|
if (!taskFile) {
|
|
825
|
-
taskFile = (0,
|
|
494
|
+
taskFile = (0, import_utils.uuid)();
|
|
826
495
|
console.warn(
|
|
827
496
|
"Midscene - using random UUID for cache id. Cache may be invalid."
|
|
828
497
|
);
|
|
@@ -839,10 +508,23 @@ function generateCacheId(fileName) {
|
|
|
839
508
|
}
|
|
840
509
|
var ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED = "NOT_IMPLEMENTED_AS_DESIGNED";
|
|
841
510
|
|
|
511
|
+
// src/common/agent.ts
|
|
512
|
+
var import_utils7 = require("@midscene/core/utils");
|
|
513
|
+
|
|
514
|
+
// src/common/tasks.ts
|
|
515
|
+
var import_node_assert2 = __toESM(require("assert"));
|
|
516
|
+
var import_core = require("@midscene/core");
|
|
517
|
+
var import_utils5 = require("@midscene/core/utils");
|
|
518
|
+
|
|
842
519
|
// src/common/task-cache.ts
|
|
520
|
+
var import_node_fs2 = require("fs");
|
|
521
|
+
var import_node_path2 = require("path");
|
|
522
|
+
var import_utils2 = require("@midscene/core/utils");
|
|
523
|
+
var import_fs2 = require("@midscene/shared/fs");
|
|
524
|
+
var import_utils3 = require("@midscene/shared/utils");
|
|
843
525
|
var TaskCache = class {
|
|
844
526
|
constructor(opts) {
|
|
845
|
-
this.midscenePkgInfo = (0, import_fs2.
|
|
527
|
+
this.midscenePkgInfo = (0, import_fs2.getRunningPkgInfo)();
|
|
846
528
|
this.cacheId = generateCacheId(opts == null ? void 0 : opts.fileName);
|
|
847
529
|
this.cache = this.readCacheFromFile() || {
|
|
848
530
|
aiTasks: []
|
|
@@ -924,11 +606,17 @@ var TaskCache = class {
|
|
|
924
606
|
return this.newCache;
|
|
925
607
|
}
|
|
926
608
|
readCacheFromFile() {
|
|
927
|
-
|
|
609
|
+
if (import_utils3.ifInBrowser) {
|
|
610
|
+
return void 0;
|
|
611
|
+
}
|
|
612
|
+
const cacheFile = (0, import_node_path2.join)((0, import_utils2.getLogDirByType)("cache"), `${this.cacheId}.json`);
|
|
928
613
|
if (process.env.MIDSCENE_CACHE === "true" && (0, import_node_fs2.existsSync)(cacheFile)) {
|
|
929
614
|
try {
|
|
930
615
|
const data = (0, import_node_fs2.readFileSync)(cacheFile, "utf8");
|
|
931
616
|
const jsonData = JSON.parse(data);
|
|
617
|
+
if (!this.midscenePkgInfo) {
|
|
618
|
+
return void 0;
|
|
619
|
+
}
|
|
932
620
|
if (jsonData.pkgName !== this.midscenePkgInfo.name || jsonData.pkgVersion !== this.midscenePkgInfo.version) {
|
|
933
621
|
return void 0;
|
|
934
622
|
}
|
|
@@ -940,11 +628,14 @@ var TaskCache = class {
|
|
|
940
628
|
return void 0;
|
|
941
629
|
}
|
|
942
630
|
writeCacheToFile() {
|
|
943
|
-
const midscenePkgInfo = (0, import_fs2.
|
|
944
|
-
(
|
|
631
|
+
const midscenePkgInfo = (0, import_fs2.getRunningPkgInfo)();
|
|
632
|
+
if (!midscenePkgInfo) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
(0, import_utils2.writeLogFile)({
|
|
945
636
|
fileName: `${this.cacheId}`,
|
|
946
637
|
fileExt: "json",
|
|
947
|
-
fileContent: (0,
|
|
638
|
+
fileContent: (0, import_utils2.stringifyDumpData)(
|
|
948
639
|
__spreadValues({
|
|
949
640
|
pkgName: midscenePkgInfo.name,
|
|
950
641
|
pkgVersion: midscenePkgInfo.version,
|
|
@@ -961,423 +652,435 @@ var TaskCache = class {
|
|
|
961
652
|
var PageTaskExecutor = class {
|
|
962
653
|
constructor(page, opts) {
|
|
963
654
|
this.page = page;
|
|
964
|
-
this.insight = new import_core.Insight(
|
|
965
|
-
return
|
|
966
|
-
});
|
|
655
|
+
this.insight = new import_core.Insight(() => __async(this, null, function* () {
|
|
656
|
+
return yield parseContextFromWebPage(page);
|
|
657
|
+
}));
|
|
967
658
|
this.taskCache = new TaskCache({
|
|
968
659
|
fileName: opts == null ? void 0 : opts.cacheId
|
|
969
660
|
});
|
|
970
661
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
662
|
+
recordScreenshot(timing) {
|
|
663
|
+
return __async(this, null, function* () {
|
|
664
|
+
const base64 = yield this.page.screenshotBase64();
|
|
665
|
+
const item = {
|
|
666
|
+
type: "screenshot",
|
|
667
|
+
ts: Date.now(),
|
|
668
|
+
screenshot: base64,
|
|
669
|
+
timing
|
|
670
|
+
};
|
|
671
|
+
return item;
|
|
672
|
+
});
|
|
980
673
|
}
|
|
981
674
|
wrapExecutorWithScreenshot(taskApply) {
|
|
982
675
|
const taskWithScreenshot = __spreadProps(__spreadValues({}, taskApply), {
|
|
983
|
-
executor:
|
|
676
|
+
executor: (param, context, ...args) => __async(this, null, function* () {
|
|
984
677
|
const recorder = [];
|
|
985
678
|
const { task } = context;
|
|
986
679
|
task.recorder = recorder;
|
|
987
|
-
const shot =
|
|
680
|
+
const shot = yield this.recordScreenshot(`before ${task.type}`);
|
|
988
681
|
recorder.push(shot);
|
|
989
|
-
const result =
|
|
682
|
+
const result = yield taskApply.executor(param, context, ...args);
|
|
990
683
|
if (taskApply.type === "Action") {
|
|
991
|
-
|
|
992
|
-
const shot2 =
|
|
684
|
+
yield (0, import_utils5.sleep)(1e3);
|
|
685
|
+
const shot2 = yield this.recordScreenshot("after Action");
|
|
993
686
|
recorder.push(shot2);
|
|
994
687
|
}
|
|
995
688
|
return result;
|
|
996
|
-
}
|
|
689
|
+
})
|
|
997
690
|
});
|
|
998
691
|
return taskWithScreenshot;
|
|
999
692
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1014
|
-
const pageContext = await this.insight.contextRetrieverFn();
|
|
1015
|
-
const locateCache = cacheGroup == null ? void 0 : cacheGroup.readCache(
|
|
1016
|
-
pageContext,
|
|
1017
|
-
"locate",
|
|
1018
|
-
param.prompt
|
|
1019
|
-
);
|
|
1020
|
-
let locateResult;
|
|
1021
|
-
const callAI = this.insight.aiVendorFn;
|
|
1022
|
-
const element = await this.insight.locate(param.prompt, {
|
|
1023
|
-
quickAnswer: plan2.quickAnswer,
|
|
1024
|
-
callAI: async (...message) => {
|
|
1025
|
-
if (locateCache) {
|
|
1026
|
-
locateResult = locateCache;
|
|
1027
|
-
return Promise.resolve(locateCache);
|
|
1028
|
-
}
|
|
1029
|
-
locateResult = await callAI(...message);
|
|
1030
|
-
(0, import_node_assert2.default)(locateResult);
|
|
1031
|
-
return locateResult;
|
|
1032
|
-
}
|
|
1033
|
-
});
|
|
1034
|
-
if (locateResult) {
|
|
1035
|
-
cacheGroup == null ? void 0 : cacheGroup.saveCache({
|
|
1036
|
-
type: "locate",
|
|
1037
|
-
pageContext: {
|
|
1038
|
-
url: pageContext.url,
|
|
1039
|
-
size: pageContext.size
|
|
1040
|
-
},
|
|
1041
|
-
prompt: param.prompt,
|
|
1042
|
-
response: locateResult
|
|
1043
|
-
});
|
|
1044
|
-
}
|
|
1045
|
-
if (!element) {
|
|
1046
|
-
task.log = {
|
|
1047
|
-
dump: insightDump
|
|
693
|
+
convertPlanToExecutable(plans, cacheGroup) {
|
|
694
|
+
return __async(this, null, function* () {
|
|
695
|
+
const tasks = plans.map((plan2) => {
|
|
696
|
+
if (plan2.type === "Locate") {
|
|
697
|
+
const taskFind = {
|
|
698
|
+
type: "Insight",
|
|
699
|
+
subType: "Locate",
|
|
700
|
+
param: plan2.param,
|
|
701
|
+
executor: (param, taskContext) => __async(this, null, function* () {
|
|
702
|
+
const { task } = taskContext;
|
|
703
|
+
let insightDump;
|
|
704
|
+
const dumpCollector = (dump) => {
|
|
705
|
+
insightDump = dump;
|
|
1048
706
|
};
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
707
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
708
|
+
const pageContext = yield this.insight.contextRetrieverFn();
|
|
709
|
+
const locateCache = cacheGroup == null ? void 0 : cacheGroup.readCache(
|
|
710
|
+
pageContext,
|
|
711
|
+
"locate",
|
|
712
|
+
param.prompt
|
|
713
|
+
);
|
|
714
|
+
let locateResult;
|
|
715
|
+
const callAI = this.insight.aiVendorFn;
|
|
716
|
+
const element = yield this.insight.locate(param.prompt, {
|
|
717
|
+
quickAnswer: plan2.quickAnswer,
|
|
718
|
+
callAI: (...message) => __async(this, null, function* () {
|
|
719
|
+
if (locateCache) {
|
|
720
|
+
locateResult = locateCache;
|
|
721
|
+
return Promise.resolve(locateCache);
|
|
722
|
+
}
|
|
723
|
+
locateResult = yield callAI(...message);
|
|
724
|
+
(0, import_node_assert2.default)(locateResult);
|
|
725
|
+
return locateResult;
|
|
726
|
+
})
|
|
727
|
+
});
|
|
728
|
+
if (locateResult) {
|
|
729
|
+
cacheGroup == null ? void 0 : cacheGroup.saveCache({
|
|
730
|
+
type: "locate",
|
|
731
|
+
pageContext: {
|
|
732
|
+
url: pageContext.url,
|
|
733
|
+
size: pageContext.size
|
|
734
|
+
},
|
|
735
|
+
prompt: param.prompt,
|
|
736
|
+
response: locateResult
|
|
737
|
+
});
|
|
1060
738
|
}
|
|
1061
|
-
|
|
1062
|
-
}
|
|
1063
|
-
};
|
|
1064
|
-
return taskFind;
|
|
1065
|
-
}
|
|
1066
|
-
if (plan2.type === "Assert" || plan2.type === "AssertWithoutThrow") {
|
|
1067
|
-
const assertPlan = plan2;
|
|
1068
|
-
const taskAssert = {
|
|
1069
|
-
type: "Insight",
|
|
1070
|
-
subType: "Assert",
|
|
1071
|
-
param: assertPlan.param,
|
|
1072
|
-
executor: async (param, taskContext) => {
|
|
1073
|
-
const { task } = taskContext;
|
|
1074
|
-
let insightDump;
|
|
1075
|
-
const dumpCollector = (dump) => {
|
|
1076
|
-
insightDump = dump;
|
|
1077
|
-
};
|
|
1078
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1079
|
-
const assertion = await this.insight.assert(
|
|
1080
|
-
assertPlan.param.assertion
|
|
1081
|
-
);
|
|
1082
|
-
if (!assertion.pass) {
|
|
1083
|
-
if (plan2.type === "Assert") {
|
|
1084
|
-
task.output = assertion;
|
|
739
|
+
if (!element) {
|
|
1085
740
|
task.log = {
|
|
1086
741
|
dump: insightDump
|
|
1087
742
|
};
|
|
1088
|
-
throw new Error(
|
|
1089
|
-
assertion.thought || "Assertion failed without reason"
|
|
1090
|
-
);
|
|
743
|
+
throw new Error(`Element not found: ${param.prompt}`);
|
|
1091
744
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
745
|
+
return {
|
|
746
|
+
output: {
|
|
747
|
+
element
|
|
748
|
+
},
|
|
749
|
+
log: {
|
|
750
|
+
dump: insightDump
|
|
751
|
+
},
|
|
752
|
+
cache: {
|
|
753
|
+
hit: Boolean(locateCache)
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
})
|
|
757
|
+
};
|
|
758
|
+
return taskFind;
|
|
759
|
+
}
|
|
760
|
+
if (plan2.type === "Assert" || plan2.type === "AssertWithoutThrow") {
|
|
761
|
+
const assertPlan = plan2;
|
|
762
|
+
const taskAssert = {
|
|
763
|
+
type: "Insight",
|
|
764
|
+
subType: "Assert",
|
|
765
|
+
param: assertPlan.param,
|
|
766
|
+
executor: (param, taskContext) => __async(this, null, function* () {
|
|
767
|
+
const { task } = taskContext;
|
|
768
|
+
let insightDump;
|
|
769
|
+
const dumpCollector = (dump) => {
|
|
770
|
+
insightDump = dump;
|
|
771
|
+
};
|
|
772
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
773
|
+
const assertion = yield this.insight.assert(
|
|
774
|
+
assertPlan.param.assertion
|
|
775
|
+
);
|
|
776
|
+
if (!assertion.pass) {
|
|
777
|
+
if (plan2.type === "Assert") {
|
|
778
|
+
task.output = assertion;
|
|
779
|
+
task.log = {
|
|
780
|
+
dump: insightDump
|
|
781
|
+
};
|
|
782
|
+
throw new Error(
|
|
783
|
+
assertion.thought || "Assertion failed without reason"
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
task.error = assertion.thought;
|
|
1098
787
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
788
|
+
return {
|
|
789
|
+
output: assertion,
|
|
790
|
+
log: {
|
|
791
|
+
dump: insightDump
|
|
792
|
+
}
|
|
793
|
+
};
|
|
794
|
+
})
|
|
795
|
+
};
|
|
796
|
+
return taskAssert;
|
|
797
|
+
}
|
|
798
|
+
if (plan2.type === "Input") {
|
|
799
|
+
const taskActionInput = {
|
|
800
|
+
type: "Action",
|
|
801
|
+
subType: "Input",
|
|
802
|
+
param: plan2.param,
|
|
803
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (taskParam, { element }) {
|
|
804
|
+
if (element) {
|
|
805
|
+
yield this.page.clearInput(element);
|
|
806
|
+
if (taskParam.value === "") {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
yield this.page.keyboard.type(taskParam.value);
|
|
1114
810
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
)
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
return
|
|
811
|
+
})
|
|
812
|
+
};
|
|
813
|
+
return taskActionInput;
|
|
814
|
+
}
|
|
815
|
+
if (plan2.type === "KeyboardPress") {
|
|
816
|
+
const taskActionKeyboardPress = {
|
|
817
|
+
type: "Action",
|
|
818
|
+
subType: "KeyboardPress",
|
|
819
|
+
param: plan2.param,
|
|
820
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
821
|
+
(0, import_node_assert2.default)(taskParam.value, "No key to press");
|
|
822
|
+
yield this.page.keyboard.press(taskParam.value);
|
|
823
|
+
})
|
|
824
|
+
};
|
|
825
|
+
return taskActionKeyboardPress;
|
|
826
|
+
}
|
|
827
|
+
if (plan2.type === "Tap") {
|
|
828
|
+
const taskActionTap = {
|
|
829
|
+
type: "Action",
|
|
830
|
+
subType: "Tap",
|
|
831
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (param, { element }) {
|
|
832
|
+
(0, import_node_assert2.default)(element, "Element not found, cannot tap");
|
|
833
|
+
yield this.page.mouse.click(
|
|
834
|
+
element.center[0],
|
|
835
|
+
element.center[1]
|
|
836
|
+
);
|
|
837
|
+
})
|
|
838
|
+
};
|
|
839
|
+
return taskActionTap;
|
|
840
|
+
}
|
|
841
|
+
if (plan2.type === "Hover") {
|
|
842
|
+
const taskActionHover = {
|
|
843
|
+
type: "Action",
|
|
844
|
+
subType: "Hover",
|
|
845
|
+
executor: (_0, _1) => __async(this, [_0, _1], function* (param, { element }) {
|
|
846
|
+
(0, import_node_assert2.default)(element, "Element not found, cannot hover");
|
|
847
|
+
yield this.page.mouse.move(
|
|
848
|
+
element.center[0],
|
|
849
|
+
element.center[1]
|
|
850
|
+
);
|
|
851
|
+
})
|
|
852
|
+
};
|
|
853
|
+
return taskActionHover;
|
|
854
|
+
}
|
|
855
|
+
if (plan2.type === "Scroll") {
|
|
856
|
+
const taskActionScroll = {
|
|
857
|
+
type: "Action",
|
|
858
|
+
subType: "Scroll",
|
|
859
|
+
param: plan2.param,
|
|
860
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
861
|
+
const scrollToEventName = taskParam.scrollType;
|
|
862
|
+
switch (scrollToEventName) {
|
|
863
|
+
case "scrollUntilTop":
|
|
864
|
+
yield this.page.scrollUntilTop();
|
|
865
|
+
break;
|
|
866
|
+
case "scrollUntilBottom":
|
|
867
|
+
yield this.page.scrollUntilBottom();
|
|
868
|
+
break;
|
|
869
|
+
case "scrollUpOneScreen":
|
|
870
|
+
yield this.page.scrollUpOneScreen();
|
|
871
|
+
break;
|
|
872
|
+
case "scrollDownOneScreen":
|
|
873
|
+
yield this.page.scrollDownOneScreen();
|
|
874
|
+
break;
|
|
875
|
+
default:
|
|
876
|
+
console.error(
|
|
877
|
+
"Unknown scroll event type:",
|
|
878
|
+
scrollToEventName
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
})
|
|
882
|
+
};
|
|
883
|
+
return taskActionScroll;
|
|
884
|
+
}
|
|
885
|
+
if (plan2.type === "Sleep") {
|
|
886
|
+
const taskActionSleep = {
|
|
887
|
+
type: "Action",
|
|
888
|
+
subType: "Sleep",
|
|
889
|
+
param: plan2.param,
|
|
890
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
891
|
+
yield (0, import_utils5.sleep)(taskParam.timeMs || 3e3);
|
|
892
|
+
})
|
|
893
|
+
};
|
|
894
|
+
return taskActionSleep;
|
|
895
|
+
}
|
|
896
|
+
if (plan2.type === "Error") {
|
|
897
|
+
const taskActionError = {
|
|
898
|
+
type: "Action",
|
|
899
|
+
subType: "Error",
|
|
900
|
+
param: plan2.param,
|
|
901
|
+
executor: (taskParam) => __async(this, null, function* () {
|
|
902
|
+
(0, import_node_assert2.default)(
|
|
903
|
+
taskParam.thought,
|
|
904
|
+
"An error occurred, but no thought provided"
|
|
905
|
+
);
|
|
906
|
+
throw new Error(taskParam.thought);
|
|
907
|
+
})
|
|
908
|
+
};
|
|
909
|
+
return taskActionError;
|
|
910
|
+
}
|
|
911
|
+
throw new Error(`Unknown or Unsupported task type: ${plan2.type}`);
|
|
912
|
+
}).map((task) => {
|
|
913
|
+
return this.wrapExecutorWithScreenshot(task);
|
|
914
|
+
});
|
|
915
|
+
return tasks;
|
|
1220
916
|
});
|
|
1221
|
-
return tasks;
|
|
1222
917
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
918
|
+
action(userPrompt) {
|
|
919
|
+
return __async(this, null, function* () {
|
|
920
|
+
const taskExecutor = new import_core.Executor(userPrompt);
|
|
921
|
+
const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
|
|
922
|
+
let plans = [];
|
|
923
|
+
const planningTask = {
|
|
924
|
+
type: "Planning",
|
|
925
|
+
param: {
|
|
926
|
+
userPrompt
|
|
927
|
+
},
|
|
928
|
+
executor: (param) => __async(this, null, function* () {
|
|
929
|
+
const pageContext = yield this.insight.contextRetrieverFn();
|
|
930
|
+
let planResult;
|
|
931
|
+
const planCache = cacheGroup.readCache(pageContext, "plan", userPrompt);
|
|
932
|
+
if (planCache) {
|
|
933
|
+
planResult = planCache;
|
|
934
|
+
} else {
|
|
935
|
+
planResult = yield (0, import_core.plan)(param.userPrompt, {
|
|
936
|
+
context: pageContext
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
(0, import_node_assert2.default)(planResult.plans.length > 0, "No plans found");
|
|
940
|
+
plans = planResult.plans;
|
|
941
|
+
cacheGroup.saveCache({
|
|
942
|
+
type: "plan",
|
|
943
|
+
pageContext: {
|
|
944
|
+
url: pageContext.url,
|
|
945
|
+
size: pageContext.size
|
|
946
|
+
},
|
|
947
|
+
prompt: userPrompt,
|
|
948
|
+
response: planResult
|
|
1241
949
|
});
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
});
|
|
950
|
+
return {
|
|
951
|
+
output: planResult,
|
|
952
|
+
cache: {
|
|
953
|
+
hit: Boolean(planCache)
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
})
|
|
957
|
+
};
|
|
958
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(planningTask));
|
|
959
|
+
let output = yield taskExecutor.flush();
|
|
960
|
+
if (taskExecutor.isInErrorState()) {
|
|
1254
961
|
return {
|
|
1255
|
-
output
|
|
1256
|
-
|
|
1257
|
-
hit: Boolean(planCache)
|
|
1258
|
-
}
|
|
962
|
+
output,
|
|
963
|
+
executor: taskExecutor
|
|
1259
964
|
};
|
|
1260
965
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
if (taskExecutor.isInErrorState()) {
|
|
966
|
+
const executables = yield this.convertPlanToExecutable(plans, cacheGroup);
|
|
967
|
+
yield taskExecutor.append(executables);
|
|
968
|
+
output = yield taskExecutor.flush();
|
|
1265
969
|
return {
|
|
1266
970
|
output,
|
|
1267
971
|
executor: taskExecutor
|
|
1268
972
|
};
|
|
1269
|
-
}
|
|
1270
|
-
const executables = await this.convertPlanToExecutable(plans, cacheGroup);
|
|
1271
|
-
await taskExecutor.append(executables);
|
|
1272
|
-
output = await taskExecutor.flush();
|
|
1273
|
-
return {
|
|
1274
|
-
output,
|
|
1275
|
-
executor: taskExecutor
|
|
1276
|
-
};
|
|
1277
|
-
}
|
|
1278
|
-
async query(demand) {
|
|
1279
|
-
const description = typeof demand === "string" ? demand : JSON.stringify(demand);
|
|
1280
|
-
const taskExecutor = new import_core.Executor(description);
|
|
1281
|
-
const queryTask = {
|
|
1282
|
-
type: "Insight",
|
|
1283
|
-
subType: "Query",
|
|
1284
|
-
param: {
|
|
1285
|
-
dataDemand: demand
|
|
1286
|
-
},
|
|
1287
|
-
executor: async (param) => {
|
|
1288
|
-
let insightDump;
|
|
1289
|
-
const dumpCollector = (dump) => {
|
|
1290
|
-
insightDump = dump;
|
|
1291
|
-
};
|
|
1292
|
-
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
1293
|
-
const data = await this.insight.extract(param.dataDemand);
|
|
1294
|
-
return {
|
|
1295
|
-
output: data,
|
|
1296
|
-
log: { dump: insightDump }
|
|
1297
|
-
};
|
|
1298
|
-
}
|
|
1299
|
-
};
|
|
1300
|
-
await taskExecutor.append(this.wrapExecutorWithScreenshot(queryTask));
|
|
1301
|
-
const output = await taskExecutor.flush();
|
|
1302
|
-
return {
|
|
1303
|
-
output,
|
|
1304
|
-
executor: taskExecutor
|
|
1305
|
-
};
|
|
973
|
+
});
|
|
1306
974
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
975
|
+
query(demand) {
|
|
976
|
+
return __async(this, null, function* () {
|
|
977
|
+
const description = typeof demand === "string" ? demand : JSON.stringify(demand);
|
|
978
|
+
const taskExecutor = new import_core.Executor(description);
|
|
979
|
+
const queryTask = {
|
|
980
|
+
type: "Insight",
|
|
981
|
+
subType: "Query",
|
|
982
|
+
param: {
|
|
983
|
+
dataDemand: demand
|
|
984
|
+
},
|
|
985
|
+
executor: (param) => __async(this, null, function* () {
|
|
986
|
+
let insightDump;
|
|
987
|
+
const dumpCollector = (dump) => {
|
|
988
|
+
insightDump = dump;
|
|
989
|
+
};
|
|
990
|
+
this.insight.onceDumpUpdatedFn = dumpCollector;
|
|
991
|
+
const data = yield this.insight.extract(param.dataDemand);
|
|
992
|
+
return {
|
|
993
|
+
output: data,
|
|
994
|
+
log: { dump: insightDump }
|
|
995
|
+
};
|
|
996
|
+
})
|
|
997
|
+
};
|
|
998
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(queryTask));
|
|
999
|
+
const output = yield taskExecutor.flush();
|
|
1000
|
+
return {
|
|
1001
|
+
output,
|
|
1002
|
+
executor: taskExecutor
|
|
1003
|
+
};
|
|
1004
|
+
});
|
|
1323
1005
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
(0, import_node_assert2.default)(checkIntervalMs, "No checkIntervalMs for waitFor");
|
|
1331
|
-
const overallStartTime = Date.now();
|
|
1332
|
-
let startTime = Date.now();
|
|
1333
|
-
let errorThought = "";
|
|
1334
|
-
while (Date.now() - overallStartTime < timeoutMs) {
|
|
1335
|
-
startTime = Date.now();
|
|
1336
|
-
const assertPlan = {
|
|
1337
|
-
type: "AssertWithoutThrow",
|
|
1006
|
+
assert(assertion) {
|
|
1007
|
+
return __async(this, null, function* () {
|
|
1008
|
+
const description = `assert: ${assertion}`;
|
|
1009
|
+
const taskExecutor = new import_core.Executor(description);
|
|
1010
|
+
const assertionPlan = {
|
|
1011
|
+
type: "Assert",
|
|
1338
1012
|
param: {
|
|
1339
1013
|
assertion
|
|
1340
1014
|
}
|
|
1341
1015
|
};
|
|
1342
|
-
const assertTask =
|
|
1343
|
-
|
|
1344
|
-
const output =
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1016
|
+
const assertTask = yield this.convertPlanToExecutable([assertionPlan]);
|
|
1017
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
|
|
1018
|
+
const output = yield taskExecutor.flush();
|
|
1019
|
+
return {
|
|
1020
|
+
output,
|
|
1021
|
+
executor: taskExecutor
|
|
1022
|
+
};
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
waitFor(assertion, opt) {
|
|
1026
|
+
return __async(this, null, function* () {
|
|
1027
|
+
const description = `waitFor: ${assertion}`;
|
|
1028
|
+
const taskExecutor = new import_core.Executor(description);
|
|
1029
|
+
const { timeoutMs, checkIntervalMs } = opt;
|
|
1030
|
+
(0, import_node_assert2.default)(assertion, "No assertion for waitFor");
|
|
1031
|
+
(0, import_node_assert2.default)(timeoutMs, "No timeoutMs for waitFor");
|
|
1032
|
+
(0, import_node_assert2.default)(checkIntervalMs, "No checkIntervalMs for waitFor");
|
|
1033
|
+
const overallStartTime = Date.now();
|
|
1034
|
+
let startTime = Date.now();
|
|
1035
|
+
let errorThought = "";
|
|
1036
|
+
while (Date.now() - overallStartTime < timeoutMs) {
|
|
1037
|
+
startTime = Date.now();
|
|
1038
|
+
const assertPlan = {
|
|
1039
|
+
type: "AssertWithoutThrow",
|
|
1357
1040
|
param: {
|
|
1358
|
-
|
|
1041
|
+
assertion
|
|
1359
1042
|
}
|
|
1360
1043
|
};
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
)
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1044
|
+
const assertTask = yield this.convertPlanToExecutable([assertPlan]);
|
|
1045
|
+
yield taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
|
|
1046
|
+
const output = yield taskExecutor.flush();
|
|
1047
|
+
if (output == null ? void 0 : output.pass) {
|
|
1048
|
+
return {
|
|
1049
|
+
output: void 0,
|
|
1050
|
+
executor: taskExecutor
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
errorThought = (output == null ? void 0 : output.thought) || "unknown error";
|
|
1054
|
+
const now = Date.now();
|
|
1055
|
+
if (now - startTime < checkIntervalMs) {
|
|
1056
|
+
const timeRemaining = checkIntervalMs - (now - startTime);
|
|
1057
|
+
const sleepPlan = {
|
|
1058
|
+
type: "Sleep",
|
|
1059
|
+
param: {
|
|
1060
|
+
timeMs: timeRemaining
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
const sleepTask = yield this.convertPlanToExecutable([sleepPlan]);
|
|
1064
|
+
yield taskExecutor.append(
|
|
1065
|
+
this.wrapExecutorWithScreenshot(sleepTask[0])
|
|
1066
|
+
);
|
|
1067
|
+
yield taskExecutor.flush();
|
|
1068
|
+
}
|
|
1372
1069
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1070
|
+
const errorPlan = {
|
|
1071
|
+
type: "Error",
|
|
1072
|
+
param: {
|
|
1073
|
+
thought: `waitFor timeout: ${errorThought}`
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
const errorTask = yield this.convertPlanToExecutable([errorPlan]);
|
|
1077
|
+
yield taskExecutor.append(errorTask[0]);
|
|
1078
|
+
yield taskExecutor.flush();
|
|
1079
|
+
return {
|
|
1080
|
+
output: void 0,
|
|
1081
|
+
executor: taskExecutor
|
|
1082
|
+
};
|
|
1083
|
+
});
|
|
1381
1084
|
}
|
|
1382
1085
|
};
|
|
1383
1086
|
|
|
@@ -1411,83 +1114,94 @@ var PageAgent = class {
|
|
|
1411
1114
|
dumpDataString() {
|
|
1412
1115
|
this.dump.groupName = this.opts.groupName;
|
|
1413
1116
|
this.dump.groupDescription = this.opts.groupDescription;
|
|
1414
|
-
return (0,
|
|
1117
|
+
return (0, import_utils7.stringifyDumpData)(this.dump);
|
|
1415
1118
|
}
|
|
1416
1119
|
writeOutActionDumps() {
|
|
1417
1120
|
const { generateReport, autoPrintReportMsg } = this.opts;
|
|
1418
|
-
this.reportFile = (0,
|
|
1121
|
+
this.reportFile = (0, import_utils7.writeLogFile)({
|
|
1419
1122
|
fileName: this.reportFileName,
|
|
1420
|
-
fileExt:
|
|
1123
|
+
fileExt: import_utils7.groupedActionDumpFileExt,
|
|
1421
1124
|
fileContent: this.dumpDataString(),
|
|
1422
1125
|
type: "dump",
|
|
1423
1126
|
generateReport
|
|
1424
1127
|
});
|
|
1425
|
-
if (generateReport && autoPrintReportMsg) {
|
|
1128
|
+
if (generateReport && autoPrintReportMsg && this.reportFile) {
|
|
1426
1129
|
printReportMsg(this.reportFile);
|
|
1427
1130
|
}
|
|
1428
1131
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1132
|
+
aiAction(taskPrompt) {
|
|
1133
|
+
return __async(this, null, function* () {
|
|
1134
|
+
const { executor } = yield this.taskExecutor.action(taskPrompt);
|
|
1135
|
+
this.appendExecutionDump(executor.dump());
|
|
1136
|
+
this.writeOutActionDumps();
|
|
1137
|
+
if (executor.isInErrorState()) {
|
|
1138
|
+
const errorTask = executor.latestErrorTask();
|
|
1139
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1436
1140
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1437
|
-
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
1438
1143
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1144
|
+
aiQuery(demand) {
|
|
1145
|
+
return __async(this, null, function* () {
|
|
1146
|
+
const { output, executor } = yield this.taskExecutor.query(demand);
|
|
1147
|
+
this.appendExecutionDump(executor.dump());
|
|
1148
|
+
this.writeOutActionDumps();
|
|
1149
|
+
if (executor.isInErrorState()) {
|
|
1150
|
+
const errorTask = executor.latestErrorTask();
|
|
1151
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1446
1152
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1447
|
-
|
|
1448
|
-
return output;
|
|
1449
|
-
}
|
|
1450
|
-
async aiAssert(assertion, msg, opt) {
|
|
1451
|
-
const { output, executor } = await this.taskExecutor.assert(assertion);
|
|
1452
|
-
this.appendExecutionDump(executor.dump());
|
|
1453
|
-
this.writeOutActionDumps();
|
|
1454
|
-
if (opt == null ? void 0 : opt.keepRawResponse) {
|
|
1153
|
+
}
|
|
1455
1154
|
return output;
|
|
1456
|
-
}
|
|
1457
|
-
if (!(output == null ? void 0 : output.pass)) {
|
|
1458
|
-
const errMsg = msg || `Assertion failed: ${assertion}`;
|
|
1459
|
-
const reasonMsg = `Reason: ${(output == null ? void 0 : output.thought) || "(no_reason)"}`;
|
|
1460
|
-
throw new Error(`${errMsg}
|
|
1461
|
-
${reasonMsg}`);
|
|
1462
|
-
}
|
|
1155
|
+
});
|
|
1463
1156
|
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1157
|
+
aiAssert(assertion, msg, opt) {
|
|
1158
|
+
return __async(this, null, function* () {
|
|
1159
|
+
var _a;
|
|
1160
|
+
const { output, executor } = yield this.taskExecutor.assert(assertion);
|
|
1161
|
+
this.appendExecutionDump(executor.dump());
|
|
1162
|
+
this.writeOutActionDumps();
|
|
1163
|
+
if (opt == null ? void 0 : opt.keepRawResponse) {
|
|
1164
|
+
return output;
|
|
1165
|
+
}
|
|
1166
|
+
if (!(output == null ? void 0 : output.pass)) {
|
|
1167
|
+
const errMsg = msg || `Assertion failed: ${assertion}`;
|
|
1168
|
+
const reasonMsg = `Reason: ${(output == null ? void 0 : output.thought) || ((_a = executor.latestErrorTask()) == null ? void 0 : _a.error) || "(no_reason)"}`;
|
|
1169
|
+
throw new Error(`${errMsg}
|
|
1170
|
+
${reasonMsg}`);
|
|
1171
|
+
}
|
|
1469
1172
|
});
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1173
|
+
}
|
|
1174
|
+
aiWaitFor(assertion, opt) {
|
|
1175
|
+
return __async(this, null, function* () {
|
|
1176
|
+
const { executor } = yield this.taskExecutor.waitFor(assertion, {
|
|
1177
|
+
timeoutMs: (opt == null ? void 0 : opt.timeoutMs) || 15 * 1e3,
|
|
1178
|
+
checkIntervalMs: (opt == null ? void 0 : opt.checkIntervalMs) || 3 * 1e3,
|
|
1179
|
+
assertion
|
|
1180
|
+
});
|
|
1181
|
+
this.appendExecutionDump(executor.dump());
|
|
1182
|
+
this.writeOutActionDumps();
|
|
1183
|
+
if (executor.isInErrorState()) {
|
|
1184
|
+
const errorTask = executor.latestErrorTask();
|
|
1185
|
+
throw new Error(`${errorTask == null ? void 0 : errorTask.error}
|
|
1475
1186
|
${errorTask == null ? void 0 : errorTask.errorStack}`);
|
|
1476
|
-
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1477
1189
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1190
|
+
ai(taskPrompt, type = "action") {
|
|
1191
|
+
return __async(this, null, function* () {
|
|
1192
|
+
if (type === "action") {
|
|
1193
|
+
return this.aiAction(taskPrompt);
|
|
1194
|
+
}
|
|
1195
|
+
if (type === "query") {
|
|
1196
|
+
return this.aiQuery(taskPrompt);
|
|
1197
|
+
}
|
|
1198
|
+
if (type === "assert") {
|
|
1199
|
+
return this.aiAssert(taskPrompt);
|
|
1200
|
+
}
|
|
1201
|
+
throw new Error(
|
|
1202
|
+
`Unknown type: ${type}, only support 'action', 'query', 'assert'`
|
|
1203
|
+
);
|
|
1204
|
+
});
|
|
1491
1205
|
}
|
|
1492
1206
|
};
|
|
1493
1207
|
|
|
@@ -1498,19 +1212,7 @@ var StaticPageAgent = class extends PageAgent {
|
|
|
1498
1212
|
}
|
|
1499
1213
|
};
|
|
1500
1214
|
|
|
1501
|
-
// src/playground/server.ts
|
|
1502
|
-
var import_node_assert3 = __toESM(require("assert"));
|
|
1503
|
-
var import_node_crypto2 = require("crypto");
|
|
1504
|
-
var import_node_fs3 = require("fs");
|
|
1505
|
-
var import_node_path3 = require("path");
|
|
1506
|
-
var import_utils10 = require("@midscene/core/utils");
|
|
1507
|
-
var import_cors = __toESM(require("cors"));
|
|
1508
|
-
var import_dotenv = __toESM(require_main());
|
|
1509
|
-
var import_express = __toESM(require("express"));
|
|
1510
|
-
|
|
1511
1215
|
// src/playground/static-page.ts
|
|
1512
|
-
var import_utils8 = require("@midscene/core/utils");
|
|
1513
|
-
var import_img4 = require("@midscene/shared/img");
|
|
1514
1216
|
var ThrowNotImplemented = (methodName) => {
|
|
1515
1217
|
throw new Error(
|
|
1516
1218
|
`The method "${methodName}" is not implemented as designed since this is a static UI context. (${ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED})`
|
|
@@ -1530,180 +1232,57 @@ var StaticPage = class {
|
|
|
1530
1232
|
};
|
|
1531
1233
|
this.uiContext = uiContext;
|
|
1532
1234
|
}
|
|
1533
|
-
|
|
1534
|
-
return
|
|
1235
|
+
getElementInfos() {
|
|
1236
|
+
return __async(this, null, function* () {
|
|
1237
|
+
return ThrowNotImplemented("getElementInfos");
|
|
1238
|
+
});
|
|
1535
1239
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1240
|
+
screenshotBase64() {
|
|
1241
|
+
return __async(this, null, function* () {
|
|
1242
|
+
const base64 = this.uiContext.screenshotBase64;
|
|
1243
|
+
if (!base64) {
|
|
1244
|
+
throw new Error("screenshot base64 is empty");
|
|
1245
|
+
}
|
|
1246
|
+
return base64;
|
|
1247
|
+
});
|
|
1544
1248
|
}
|
|
1545
1249
|
url() {
|
|
1546
1250
|
return this.uiContext.url;
|
|
1547
1251
|
}
|
|
1548
|
-
|
|
1549
|
-
return
|
|
1550
|
-
|
|
1551
|
-
async scrollUntilBottom() {
|
|
1552
|
-
return ThrowNotImplemented("scrollUntilBottom");
|
|
1553
|
-
}
|
|
1554
|
-
async scrollUpOneScreen() {
|
|
1555
|
-
return ThrowNotImplemented("scrollUpOneScreen");
|
|
1556
|
-
}
|
|
1557
|
-
async scrollDownOneScreen() {
|
|
1558
|
-
return ThrowNotImplemented("scrollDownOneScreen");
|
|
1559
|
-
}
|
|
1560
|
-
async clearInput() {
|
|
1561
|
-
return ThrowNotImplemented("clearInput");
|
|
1562
|
-
}
|
|
1563
|
-
async _forceUsePageContext() {
|
|
1564
|
-
return this.uiContext;
|
|
1565
|
-
}
|
|
1566
|
-
};
|
|
1567
|
-
|
|
1568
|
-
// src/playground/server.ts
|
|
1569
|
-
var defaultPort = 5800;
|
|
1570
|
-
var staticPath = (0, import_node_path3.join)(__dirname, "../../static");
|
|
1571
|
-
var agentRequestCount = 1;
|
|
1572
|
-
var errorHandler = (err, req, res, next) => {
|
|
1573
|
-
console.error(err);
|
|
1574
|
-
res.status(500).json({
|
|
1575
|
-
error: err.message
|
|
1576
|
-
});
|
|
1577
|
-
};
|
|
1578
|
-
var setup = () => {
|
|
1579
|
-
import_dotenv.default.config();
|
|
1580
|
-
};
|
|
1581
|
-
var PlaygroundServer = class {
|
|
1582
|
-
constructor() {
|
|
1583
|
-
this.app = (0, import_express.default)();
|
|
1584
|
-
this.tmpDir = (0, import_utils10.getTmpDir)();
|
|
1585
|
-
setup();
|
|
1586
|
-
}
|
|
1587
|
-
filePathForUuid(uuid) {
|
|
1588
|
-
return (0, import_node_path3.join)(this.tmpDir, `${uuid}.json`);
|
|
1589
|
-
}
|
|
1590
|
-
saveContextFile(uuid, context) {
|
|
1591
|
-
const tmpFile = this.filePathForUuid(uuid);
|
|
1592
|
-
console.log(`save context file: ${tmpFile}`);
|
|
1593
|
-
(0, import_node_fs3.writeFileSync)(tmpFile, context);
|
|
1594
|
-
return tmpFile;
|
|
1595
|
-
}
|
|
1596
|
-
async launch() {
|
|
1597
|
-
this.app.use(errorHandler);
|
|
1598
|
-
this.app.use(
|
|
1599
|
-
(0, import_cors.default)({
|
|
1600
|
-
origin: "*",
|
|
1601
|
-
credentials: true
|
|
1602
|
-
})
|
|
1603
|
-
);
|
|
1604
|
-
this.app.get("/status", (0, import_cors.default)(), async (req, res) => {
|
|
1605
|
-
res.send({
|
|
1606
|
-
status: "ok"
|
|
1607
|
-
});
|
|
1252
|
+
scrollUntilTop() {
|
|
1253
|
+
return __async(this, null, function* () {
|
|
1254
|
+
return ThrowNotImplemented("scrollUntilTop");
|
|
1608
1255
|
});
|
|
1609
|
-
|
|
1610
|
-
|
|
1256
|
+
}
|
|
1257
|
+
scrollUntilBottom() {
|
|
1258
|
+
return __async(this, null, function* () {
|
|
1259
|
+
return ThrowNotImplemented("scrollUntilBottom");
|
|
1611
1260
|
});
|
|
1612
|
-
|
|
1613
|
-
|
|
1261
|
+
}
|
|
1262
|
+
scrollUpOneScreen() {
|
|
1263
|
+
return __async(this, null, function* () {
|
|
1264
|
+
return ThrowNotImplemented("scrollUpOneScreen");
|
|
1614
1265
|
});
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
const context = (0, import_node_fs3.readFileSync)(contextFile, "utf8");
|
|
1620
|
-
res.json({
|
|
1621
|
-
context
|
|
1622
|
-
});
|
|
1266
|
+
}
|
|
1267
|
+
scrollDownOneScreen() {
|
|
1268
|
+
return __async(this, null, function* () {
|
|
1269
|
+
return ThrowNotImplemented("scrollDownOneScreen");
|
|
1623
1270
|
});
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
const context = req.body.context;
|
|
1629
|
-
(0, import_node_assert3.default)(context, "context is required");
|
|
1630
|
-
const uuid = (0, import_node_crypto2.randomUUID)();
|
|
1631
|
-
this.saveContextFile(uuid, context);
|
|
1632
|
-
return res.json({
|
|
1633
|
-
location: `/playground/${uuid}`,
|
|
1634
|
-
uuid
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
);
|
|
1638
|
-
this.app.post(
|
|
1639
|
-
"/execute",
|
|
1640
|
-
import_express.default.json({ limit: "30mb" }),
|
|
1641
|
-
async (req, res) => {
|
|
1642
|
-
const { context, type, prompt } = req.body;
|
|
1643
|
-
(0, import_node_assert3.default)(context, "context is required");
|
|
1644
|
-
(0, import_node_assert3.default)(type, "type is required");
|
|
1645
|
-
(0, import_node_assert3.default)(prompt, "prompt is required");
|
|
1646
|
-
const requestId = agentRequestCount++;
|
|
1647
|
-
console.log(`handle request: #${requestId}, ${type}, ${prompt}`);
|
|
1648
|
-
const page = new StaticPage(context);
|
|
1649
|
-
const agent = new StaticPageAgent(page);
|
|
1650
|
-
const response = {
|
|
1651
|
-
result: null,
|
|
1652
|
-
dump: null,
|
|
1653
|
-
error: null
|
|
1654
|
-
};
|
|
1655
|
-
try {
|
|
1656
|
-
if (type === "aiQuery") {
|
|
1657
|
-
response.result = await agent.aiQuery(prompt);
|
|
1658
|
-
} else if (type === "aiAction") {
|
|
1659
|
-
response.result = await agent.aiAction(prompt);
|
|
1660
|
-
} else if (type === "aiAssert") {
|
|
1661
|
-
response.result = await agent.aiAssert(prompt, void 0, {
|
|
1662
|
-
keepRawResponse: true
|
|
1663
|
-
});
|
|
1664
|
-
} else {
|
|
1665
|
-
response.error = `Unknown type: ${type}`;
|
|
1666
|
-
}
|
|
1667
|
-
} catch (error) {
|
|
1668
|
-
if (!error.message.includes(ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED)) {
|
|
1669
|
-
response.error = error.message;
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
try {
|
|
1673
|
-
response.dump = JSON.parse(agent.dumpDataString());
|
|
1674
|
-
agent.writeOutActionDumps();
|
|
1675
|
-
} catch (error) {
|
|
1676
|
-
console.error(
|
|
1677
|
-
`write out dump failed: #${requestId}, ${error.message}`
|
|
1678
|
-
);
|
|
1679
|
-
}
|
|
1680
|
-
res.send(response);
|
|
1681
|
-
if (response.error) {
|
|
1682
|
-
console.error(
|
|
1683
|
-
`handle request failed: #${requestId}, ${response.error}`
|
|
1684
|
-
);
|
|
1685
|
-
} else {
|
|
1686
|
-
console.log(`handle request done: #${requestId}`);
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
);
|
|
1690
|
-
return new Promise((resolve, reject) => {
|
|
1691
|
-
const port = this.port || defaultPort;
|
|
1692
|
-
this.server = this.app.listen(port, () => {
|
|
1693
|
-
this.port = port;
|
|
1694
|
-
resolve(this);
|
|
1695
|
-
});
|
|
1271
|
+
}
|
|
1272
|
+
clearInput() {
|
|
1273
|
+
return __async(this, null, function* () {
|
|
1274
|
+
return ThrowNotImplemented("clearInput");
|
|
1696
1275
|
});
|
|
1697
1276
|
}
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
return this.
|
|
1701
|
-
}
|
|
1277
|
+
_forceUsePageContext() {
|
|
1278
|
+
return __async(this, null, function* () {
|
|
1279
|
+
return this.uiContext;
|
|
1280
|
+
});
|
|
1702
1281
|
}
|
|
1703
1282
|
};
|
|
1704
1283
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1705
1284
|
0 && (module.exports = {
|
|
1706
|
-
|
|
1285
|
+
ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED,
|
|
1707
1286
|
StaticPage,
|
|
1708
1287
|
StaticPageAgent
|
|
1709
1288
|
});
|