@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.
@@ -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
- PlaygroundServer: () => PlaygroundServer,
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
- async function parseContextFromWebPage(page, _opt) {
746
- (0, import_node_assert.default)(page, "page is required");
747
- if (page._forceUsePageContext) {
748
- return await page._forceUsePageContext();
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
- return true;
760
- });
761
- const size = await (0, import_img.imageInfoOfBase64)(screenshotBase64);
762
- const screenshotBase64WithElementMarker = await (0, import_img2.compositeElementInfoImg)({
763
- inputImgBase64: screenshotBase64.split(";base64,").pop(),
764
- elementsPositionInfo: elementsPositionInfoWithoutText
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
- async function alignElements(elements, page) {
776
- const validElements = elements.filter((item) => {
777
- return item.rect.height >= sizeThreshold && item.rect.width >= sizeThreshold;
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, import_node_crypto.randomUUID)();
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.getMidscenePkgInfo)(__dirname);
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
- const cacheFile = (0, import_node_path2.join)((0, import_utils.getLogDirByType)("cache"), `${this.cacheId}.json`);
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.getMidscenePkgInfo)(__dirname);
944
- (0, import_utils.writeLogFile)({
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, import_utils.stringifyDumpData)(
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(async () => {
965
- return await parseContextFromWebPage(page);
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
- async recordScreenshot(timing) {
972
- const file = await this.page.screenshot();
973
- const item = {
974
- type: "screenshot",
975
- ts: Date.now(),
976
- screenshot: (0, import_img3.base64Encoded)(file),
977
- timing
978
- };
979
- return item;
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: async (param, context, ...args) => {
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 = await this.recordScreenshot(`before ${task.type}`);
680
+ const shot = yield this.recordScreenshot(`before ${task.type}`);
988
681
  recorder.push(shot);
989
- const result = await taskApply.executor(param, context, ...args);
682
+ const result = yield taskApply.executor(param, context, ...args);
990
683
  if (taskApply.type === "Action") {
991
- await (0, import_utils3.sleep)(1e3);
992
- const shot2 = await this.recordScreenshot("after Action");
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
- async convertPlanToExecutable(plans, cacheGroup) {
1001
- const tasks = plans.map((plan2) => {
1002
- if (plan2.type === "Locate") {
1003
- const taskFind = {
1004
- type: "Insight",
1005
- subType: "Locate",
1006
- param: plan2.param,
1007
- executor: async (param, taskContext) => {
1008
- const { task } = taskContext;
1009
- let insightDump;
1010
- const dumpCollector = (dump) => {
1011
- insightDump = dump;
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
- throw new Error(`Element not found: ${param.prompt}`);
1050
- }
1051
- return {
1052
- output: {
1053
- element
1054
- },
1055
- log: {
1056
- dump: insightDump
1057
- },
1058
- cache: {
1059
- hit: Boolean(locateCache)
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
- task.error = assertion.thought;
1093
- }
1094
- return {
1095
- output: assertion,
1096
- log: {
1097
- dump: insightDump
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
- return taskAssert;
1103
- }
1104
- if (plan2.type === "Input") {
1105
- const taskActionInput = {
1106
- type: "Action",
1107
- subType: "Input",
1108
- param: plan2.param,
1109
- executor: async (taskParam, { element }) => {
1110
- if (element) {
1111
- await this.page.clearInput(element);
1112
- if (taskParam.value === "") {
1113
- return;
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
- await this.page.keyboard.type(taskParam.value);
1116
- }
1117
- }
1118
- };
1119
- return taskActionInput;
1120
- }
1121
- if (plan2.type === "KeyboardPress") {
1122
- const taskActionKeyboardPress = {
1123
- type: "Action",
1124
- subType: "KeyboardPress",
1125
- param: plan2.param,
1126
- executor: async (taskParam) => {
1127
- (0, import_node_assert2.default)(taskParam.value, "No key to press");
1128
- await this.page.keyboard.press(taskParam.value);
1129
- }
1130
- };
1131
- return taskActionKeyboardPress;
1132
- }
1133
- if (plan2.type === "Tap") {
1134
- const taskActionTap = {
1135
- type: "Action",
1136
- subType: "Tap",
1137
- executor: async (param, { element }) => {
1138
- (0, import_node_assert2.default)(element, "Element not found, cannot tap");
1139
- await this.page.mouse.click(
1140
- element.center[0],
1141
- element.center[1]
1142
- );
1143
- }
1144
- };
1145
- return taskActionTap;
1146
- }
1147
- if (plan2.type === "Hover") {
1148
- const taskActionHover = {
1149
- type: "Action",
1150
- subType: "Hover",
1151
- executor: async (param, { element }) => {
1152
- (0, import_node_assert2.default)(element, "Element not found, cannot hover");
1153
- await this.page.mouse.move(
1154
- element.center[0],
1155
- element.center[1]
1156
- );
1157
- }
1158
- };
1159
- return taskActionHover;
1160
- }
1161
- if (plan2.type === "Scroll") {
1162
- const taskActionScroll = {
1163
- type: "Action",
1164
- subType: "Scroll",
1165
- param: plan2.param,
1166
- executor: async (taskParam) => {
1167
- const scrollToEventName = taskParam.scrollType;
1168
- switch (scrollToEventName) {
1169
- case "scrollUntilTop":
1170
- await this.page.scrollUntilTop();
1171
- break;
1172
- case "scrollUntilBottom":
1173
- await this.page.scrollUntilBottom();
1174
- break;
1175
- case "scrollUpOneScreen":
1176
- await this.page.scrollUpOneScreen();
1177
- break;
1178
- case "scrollDownOneScreen":
1179
- await this.page.scrollDownOneScreen();
1180
- break;
1181
- default:
1182
- console.error(
1183
- "Unknown scroll event type:",
1184
- scrollToEventName
1185
- );
1186
- }
1187
- }
1188
- };
1189
- return taskActionScroll;
1190
- }
1191
- if (plan2.type === "Sleep") {
1192
- const taskActionSleep = {
1193
- type: "Action",
1194
- subType: "Sleep",
1195
- param: plan2.param,
1196
- executor: async (taskParam) => {
1197
- await (0, import_utils3.sleep)(taskParam.timeMs || 3e3);
1198
- }
1199
- };
1200
- return taskActionSleep;
1201
- }
1202
- if (plan2.type === "Error") {
1203
- const taskActionError = {
1204
- type: "Action",
1205
- subType: "Error",
1206
- param: plan2.param,
1207
- executor: async (taskParam) => {
1208
- (0, import_node_assert2.default)(
1209
- taskParam.thought,
1210
- "An error occurred, but no thought provided"
1211
- );
1212
- throw new Error(taskParam.thought);
1213
- }
1214
- };
1215
- return taskActionError;
1216
- }
1217
- throw new Error(`Unknown or Unsupported task type: ${plan2.type}`);
1218
- }).map((task) => {
1219
- return this.wrapExecutorWithScreenshot(task);
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
- async action(userPrompt) {
1224
- const taskExecutor = new import_core.Executor(userPrompt);
1225
- const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
1226
- let plans = [];
1227
- const planningTask = {
1228
- type: "Planning",
1229
- param: {
1230
- userPrompt
1231
- },
1232
- executor: async (param) => {
1233
- const pageContext = await this.insight.contextRetrieverFn();
1234
- let planResult;
1235
- const planCache = cacheGroup.readCache(pageContext, "plan", userPrompt);
1236
- if (planCache) {
1237
- planResult = planCache;
1238
- } else {
1239
- planResult = await (0, import_core.plan)(param.userPrompt, {
1240
- context: pageContext
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
- (0, import_node_assert2.default)(planResult.plans.length > 0, "No plans found");
1244
- plans = planResult.plans;
1245
- cacheGroup.saveCache({
1246
- type: "plan",
1247
- pageContext: {
1248
- url: pageContext.url,
1249
- size: pageContext.size
1250
- },
1251
- prompt: userPrompt,
1252
- response: planResult
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: planResult,
1256
- cache: {
1257
- hit: Boolean(planCache)
1258
- }
962
+ output,
963
+ executor: taskExecutor
1259
964
  };
1260
965
  }
1261
- };
1262
- await taskExecutor.append(this.wrapExecutorWithScreenshot(planningTask));
1263
- let output = await taskExecutor.flush();
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
- async assert(assertion) {
1308
- const description = `assert: ${assertion}`;
1309
- const taskExecutor = new import_core.Executor(description);
1310
- const assertionPlan = {
1311
- type: "Assert",
1312
- param: {
1313
- assertion
1314
- }
1315
- };
1316
- const assertTask = await this.convertPlanToExecutable([assertionPlan]);
1317
- await taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
1318
- const output = await taskExecutor.flush();
1319
- return {
1320
- output,
1321
- executor: taskExecutor
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
- async waitFor(assertion, opt) {
1325
- const description = `waitFor: ${assertion}`;
1326
- const taskExecutor = new import_core.Executor(description);
1327
- const { timeoutMs, checkIntervalMs } = opt;
1328
- (0, import_node_assert2.default)(assertion, "No assertion for waitFor");
1329
- (0, import_node_assert2.default)(timeoutMs, "No timeoutMs for waitFor");
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 = await this.convertPlanToExecutable([assertPlan]);
1343
- await taskExecutor.append(this.wrapExecutorWithScreenshot(assertTask[0]));
1344
- const output = await taskExecutor.flush();
1345
- if (output == null ? void 0 : output.pass) {
1346
- return {
1347
- output: void 0,
1348
- executor: taskExecutor
1349
- };
1350
- }
1351
- errorThought = (output == null ? void 0 : output.thought) || "unknown error";
1352
- const now = Date.now();
1353
- if (now - startTime < checkIntervalMs) {
1354
- const timeRemaining = checkIntervalMs - (now - startTime);
1355
- const sleepPlan = {
1356
- type: "Sleep",
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
- timeMs: timeRemaining
1041
+ assertion
1359
1042
  }
1360
1043
  };
1361
- const sleepTask = await this.convertPlanToExecutable([sleepPlan]);
1362
- await taskExecutor.append(
1363
- this.wrapExecutorWithScreenshot(sleepTask[0])
1364
- );
1365
- await taskExecutor.flush();
1366
- }
1367
- }
1368
- const errorPlan = {
1369
- type: "Error",
1370
- param: {
1371
- thought: `waitFor timeout: ${errorThought}`
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
- const errorTask = await this.convertPlanToExecutable([errorPlan]);
1375
- await taskExecutor.append(errorTask[0]);
1376
- await taskExecutor.flush();
1377
- return {
1378
- output: void 0,
1379
- executor: taskExecutor
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, import_utils5.stringifyDumpData)(this.dump);
1117
+ return (0, import_utils7.stringifyDumpData)(this.dump);
1415
1118
  }
1416
1119
  writeOutActionDumps() {
1417
1120
  const { generateReport, autoPrintReportMsg } = this.opts;
1418
- this.reportFile = (0, import_utils5.writeLogFile)({
1121
+ this.reportFile = (0, import_utils7.writeLogFile)({
1419
1122
  fileName: this.reportFileName,
1420
- fileExt: import_utils5.groupedActionDumpFileExt,
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
- async aiAction(taskPrompt) {
1430
- const { executor } = await this.taskExecutor.action(taskPrompt);
1431
- this.appendExecutionDump(executor.dump());
1432
- this.writeOutActionDumps();
1433
- if (executor.isInErrorState()) {
1434
- const errorTask = executor.latestErrorTask();
1435
- throw new Error(`${errorTask == null ? void 0 : errorTask.error}
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
- async aiQuery(demand) {
1440
- const { output, executor } = await this.taskExecutor.query(demand);
1441
- this.appendExecutionDump(executor.dump());
1442
- this.writeOutActionDumps();
1443
- if (executor.isInErrorState()) {
1444
- const errorTask = executor.latestErrorTask();
1445
- throw new Error(`${errorTask == null ? void 0 : errorTask.error}
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
- async aiWaitFor(assertion, opt) {
1465
- const { executor } = await this.taskExecutor.waitFor(assertion, {
1466
- timeoutMs: (opt == null ? void 0 : opt.timeoutMs) || 15 * 1e3,
1467
- checkIntervalMs: (opt == null ? void 0 : opt.checkIntervalMs) || 3 * 1e3,
1468
- assertion
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
- this.appendExecutionDump(executor.dump());
1471
- this.writeOutActionDumps();
1472
- if (executor.isInErrorState()) {
1473
- const errorTask = executor.latestErrorTask();
1474
- throw new Error(`${errorTask == null ? void 0 : errorTask.error}
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
- async ai(taskPrompt, type = "action") {
1479
- if (type === "action") {
1480
- return this.aiAction(taskPrompt);
1481
- }
1482
- if (type === "query") {
1483
- return this.aiQuery(taskPrompt);
1484
- }
1485
- if (type === "assert") {
1486
- return this.aiAssert(taskPrompt);
1487
- }
1488
- throw new Error(
1489
- `Unknown type: ${type}, only support 'action', 'query', 'assert'`
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
- async getElementInfos() {
1534
- return ThrowNotImplemented("getElementInfos");
1235
+ getElementInfos() {
1236
+ return __async(this, null, function* () {
1237
+ return ThrowNotImplemented("getElementInfos");
1238
+ });
1535
1239
  }
1536
- async screenshot() {
1537
- const base64 = this.uiContext.screenshotBase64;
1538
- if (!base64) {
1539
- throw new Error("screenshot base64 is empty");
1540
- }
1541
- const tmpFilePath = (0, import_utils8.getTmpFile)("png");
1542
- await (0, import_img4.saveBase64Image)({ base64Data: base64, outputPath: tmpFilePath });
1543
- return tmpFilePath;
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
- async scrollUntilTop() {
1549
- return ThrowNotImplemented("scrollUntilTop");
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
- this.app.get("/", (req, res) => {
1610
- res.sendFile((0, import_node_path3.join)(staticPath, "index.html"));
1256
+ }
1257
+ scrollUntilBottom() {
1258
+ return __async(this, null, function* () {
1259
+ return ThrowNotImplemented("scrollUntilBottom");
1611
1260
  });
1612
- this.app.get("/playground/:uuid", async (req, res) => {
1613
- res.sendFile((0, import_node_path3.join)(staticPath, "index.html"));
1261
+ }
1262
+ scrollUpOneScreen() {
1263
+ return __async(this, null, function* () {
1264
+ return ThrowNotImplemented("scrollUpOneScreen");
1614
1265
  });
1615
- this.app.get("/context/:uuid", async (req, res) => {
1616
- const { uuid } = req.params;
1617
- const contextFile = this.filePathForUuid(uuid);
1618
- (0, import_node_assert3.default)((0, import_node_fs3.existsSync)(contextFile), "Context not found");
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
- this.app.post(
1625
- "/playground-with-context",
1626
- import_express.default.json({ limit: "50mb" }),
1627
- async (req, res) => {
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
- close() {
1699
- if (this.server) {
1700
- return this.server.close();
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
- PlaygroundServer,
1285
+ ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED,
1707
1286
  StaticPage,
1708
1287
  StaticPageAgent
1709
1288
  });