@midscene/web 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/es/appium.js +85 -39
  2. package/dist/es/bridge-mode-browser.js +58 -19
  3. package/dist/es/bridge-mode.js +62 -43
  4. package/dist/es/chrome-extension.js +105 -51
  5. package/dist/es/index.js +292 -218
  6. package/dist/es/midscene-playground.js +57 -38
  7. package/dist/es/playground.js +57 -38
  8. package/dist/es/playwright-report.js +4 -0
  9. package/dist/es/playwright.js +252 -203
  10. package/dist/es/puppeteer.js +86 -60
  11. package/dist/es/ui-utils.js +43 -0
  12. package/dist/lib/appium.js +85 -39
  13. package/dist/lib/bridge-mode-browser.js +58 -19
  14. package/dist/lib/bridge-mode.js +62 -43
  15. package/dist/lib/chrome-extension.js +105 -51
  16. package/dist/lib/index.js +292 -218
  17. package/dist/lib/midscene-playground.js +57 -38
  18. package/dist/lib/playground.js +57 -38
  19. package/dist/lib/playwright-report.js +4 -0
  20. package/dist/lib/playwright.js +252 -203
  21. package/dist/lib/puppeteer.js +86 -60
  22. package/dist/lib/ui-utils.js +43 -0
  23. package/dist/types/{tasks-d5a01262.d.ts → agent-ae110e80.d.ts} +43 -43
  24. package/dist/types/appium.d.ts +3 -3
  25. package/dist/types/bridge-mode-browser.d.ts +3 -3
  26. package/dist/types/bridge-mode.d.ts +4 -4
  27. package/dist/types/{browser-7d5614fb.d.ts → browser-9d620553.d.ts} +4 -4
  28. package/dist/types/chrome-extension.d.ts +4 -4
  29. package/dist/types/index.d.ts +8 -8
  30. package/dist/types/{page-77af8d5f.d.ts → page-97720803.d.ts} +34 -8
  31. package/dist/types/playground.d.ts +4 -4
  32. package/dist/types/playwright.d.ts +13 -7
  33. package/dist/types/puppeteer.d.ts +3 -3
  34. package/dist/types/ui-utils.d.ts +6 -1
  35. package/dist/types/{utils-1a3bc661.d.ts → utils-93b3f5f3.d.ts} +1 -1
  36. package/dist/types/utils.d.ts +2 -2
  37. package/dist/types/yaml.d.ts +4 -4
  38. package/package.json +6 -6
@@ -328,16 +328,13 @@ var require_dayjs_min = __commonJS({
328
328
  // src/playwright/index.ts
329
329
  var playwright_exports = {};
330
330
  __export(playwright_exports, {
331
- PlaywrightAgent: () => PageAgent,
331
+ PlaywrightAgent: () => PlaywrightAgent,
332
332
  PlaywrightAiFixture: () => PlaywrightAiFixture,
333
333
  PlaywrightWebPage: () => WebPage,
334
334
  overrideAIConfig: () => import_env4.overrideAIConfig
335
335
  });
336
336
  module.exports = __toCommonJS(playwright_exports);
337
337
 
338
- // src/playwright/ai-fixture.ts
339
- var import_node_crypto = require("crypto");
340
-
341
338
  // src/common/agent.ts
342
339
  var import_core2 = require("@midscene/core");
343
340
  var import_constants2 = require("@midscene/shared/constants");
@@ -3367,7 +3364,9 @@ var TaskCache = class {
3367
3364
  if (!this.midscenePkgInfo) {
3368
3365
  return void 0;
3369
3366
  }
3370
- if (jsonData.pkgName !== this.midscenePkgInfo.name || jsonData.pkgVersion !== this.midscenePkgInfo.version) {
3367
+ const jsonDataPkgVersion = jsonData.pkgVersion.split(".");
3368
+ const midscenePkgInfoPkgVersion = this.midscenePkgInfo.version.split(".");
3369
+ if (jsonDataPkgVersion[0] !== midscenePkgInfoPkgVersion[0] || jsonDataPkgVersion[1] !== midscenePkgInfoPkgVersion[1]) {
3371
3370
  return void 0;
3372
3371
  }
3373
3372
  return jsonData;
@@ -3401,6 +3400,56 @@ var TaskCache = class {
3401
3400
  }
3402
3401
  };
3403
3402
 
3403
+ // src/common/ui-utils.ts
3404
+ function typeStr(task) {
3405
+ return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
3406
+ }
3407
+ function getKeyCommands(value) {
3408
+ const keys = Array.isArray(value) ? value : [value];
3409
+ return keys.reduce((acc, k) => {
3410
+ const includeMeta = keys.includes("Meta") || keys.includes("Control");
3411
+ if (includeMeta && (k === "a" || k === "A")) {
3412
+ return acc.concat([{ key: k, command: "SelectAll" }]);
3413
+ }
3414
+ if (includeMeta && (k === "c" || k === "C")) {
3415
+ return acc.concat([{ key: k, command: "Copy" }]);
3416
+ }
3417
+ if (includeMeta && (k === "v" || k === "V")) {
3418
+ return acc.concat([{ key: k, command: "Paste" }]);
3419
+ }
3420
+ return acc.concat([{ key: k }]);
3421
+ }, []);
3422
+ }
3423
+ function paramStr(task) {
3424
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3425
+ let value;
3426
+ if (task.type === "Planning") {
3427
+ value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
3428
+ }
3429
+ if (task.type === "Insight") {
3430
+ value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
3431
+ }
3432
+ if (task.type === "Action") {
3433
+ const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
3434
+ const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
3435
+ if (sleepMs) {
3436
+ value = `${sleepMs}ms`;
3437
+ } else if (scrollType) {
3438
+ const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
3439
+ const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
3440
+ value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
3441
+ } else {
3442
+ value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
3443
+ }
3444
+ if (!value) {
3445
+ value = task.thought;
3446
+ }
3447
+ }
3448
+ if (typeof value === "undefined")
3449
+ return "";
3450
+ return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
3451
+ }
3452
+
3404
3453
  // src/common/tasks.ts
3405
3454
  var PageTaskExecutor = class {
3406
3455
  constructor(page, insight, opts) {
@@ -3535,6 +3584,7 @@ var PageTaskExecutor = class {
3535
3584
  output: {
3536
3585
  element
3537
3586
  },
3587
+ pageContext,
3538
3588
  log: {
3539
3589
  dump: insightDump
3540
3590
  },
@@ -3614,8 +3664,8 @@ var PageTaskExecutor = class {
3614
3664
  thought: plan2.thought,
3615
3665
  locate: plan2.locate,
3616
3666
  executor: async (taskParam) => {
3617
- (0, import_node_assert3.default)(taskParam == null ? void 0 : taskParam.value, "No key to press");
3618
- await this.page.keyboard.press(taskParam.value);
3667
+ const keys = getKeyCommands(taskParam.value);
3668
+ await this.page.keyboard.press(keys);
3619
3669
  }
3620
3670
  };
3621
3671
  tasks.push(taskActionKeyboardPress);
@@ -4023,7 +4073,7 @@ var PageTaskExecutor = class {
4023
4073
  const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
4024
4074
  const isCompleted = false;
4025
4075
  let currentActionNumber = 0;
4026
- const maxActionNumber = 20;
4076
+ const maxActionNumber = 40;
4027
4077
  while (!isCompleted && currentActionNumber < maxActionNumber) {
4028
4078
  currentActionNumber++;
4029
4079
  const planningTask = this.planningTaskToGoal(
@@ -4243,40 +4293,6 @@ var WebElementInfo = class {
4243
4293
  }
4244
4294
  };
4245
4295
 
4246
- // src/common/ui-utils.ts
4247
- function typeStr(task) {
4248
- return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
4249
- }
4250
- function paramStr(task) {
4251
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4252
- let value;
4253
- if (task.type === "Planning") {
4254
- value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
4255
- }
4256
- if (task.type === "Insight") {
4257
- value = ((_b = task == null ? void 0 : task.param) == null ? void 0 : _b.prompt) || ((_c = task == null ? void 0 : task.param) == null ? void 0 : _c.id) || ((_d = task == null ? void 0 : task.param) == null ? void 0 : _d.dataDemand) || ((_e = task == null ? void 0 : task.param) == null ? void 0 : _e.assertion);
4258
- }
4259
- if (task.type === "Action") {
4260
- const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
4261
- const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
4262
- if (sleepMs) {
4263
- value = `${sleepMs}ms`;
4264
- } else if (scrollType) {
4265
- const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
4266
- const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
4267
- value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
4268
- } else {
4269
- value = ((_j = task == null ? void 0 : task.param) == null ? void 0 : _j.value) || ((_k = task == null ? void 0 : task.param) == null ? void 0 : _k.scrollType);
4270
- }
4271
- if (!value) {
4272
- value = task.thought;
4273
- }
4274
- }
4275
- if (typeof value === "undefined")
4276
- return "";
4277
- return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
4278
- }
4279
-
4280
4296
  // src/common/utils.ts
4281
4297
  var import_node_assert4 = __toESM(require("assert"));
4282
4298
  var import_node_fs3 = require("fs");
@@ -4569,160 +4585,6 @@ ${errors}`);
4569
4585
  }
4570
4586
  };
4571
4587
 
4572
- // src/playwright/ai-fixture.ts
4573
- var import_test = require("@playwright/test");
4574
- var groupAndCaseForTest = (testInfo) => {
4575
- let taskFile;
4576
- let taskTitle;
4577
- const titlePath = [...testInfo.titlePath];
4578
- if (titlePath.length > 1) {
4579
- taskTitle = titlePath.pop() || "unnamed";
4580
- taskFile = `${titlePath.join(" > ")}`;
4581
- } else if (titlePath.length === 1) {
4582
- taskTitle = titlePath[0];
4583
- taskFile = `${taskTitle}`;
4584
- } else {
4585
- taskTitle = "unnamed";
4586
- taskFile = "unnamed";
4587
- }
4588
- return { taskFile, taskTitle };
4589
- };
4590
- var midsceneAgentKeyId = "_midsceneAgentId";
4591
- var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
4592
- var PlaywrightAiFixture = () => {
4593
- const pageAgentMap = {};
4594
- const agentForPage = (page, testInfo) => {
4595
- let idForPage = page[midsceneAgentKeyId];
4596
- if (!idForPage) {
4597
- idForPage = (0, import_node_crypto.randomUUID)();
4598
- page[midsceneAgentKeyId] = idForPage;
4599
- const { testId } = testInfo;
4600
- const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
4601
- pageAgentMap[idForPage] = new PageAgent(new WebPage(page), {
4602
- testId: `playwright-${testId}-${idForPage}`,
4603
- cacheId: `${taskFile}(${taskTitle})`,
4604
- groupName: taskTitle,
4605
- groupDescription: taskFile,
4606
- generateReport: false
4607
- // we will generate it in the reporter
4608
- });
4609
- }
4610
- return pageAgentMap[idForPage];
4611
- };
4612
- const updateDumpAnnotation = (test2, dump2) => {
4613
- const currentAnnotation = test2.annotations.find((item) => {
4614
- return item.type === midsceneDumpAnnotationId;
4615
- });
4616
- if (currentAnnotation) {
4617
- currentAnnotation.description = dump2;
4618
- } else {
4619
- test2.annotations.push({
4620
- type: midsceneDumpAnnotationId,
4621
- description: dump2
4622
- });
4623
- }
4624
- };
4625
- return {
4626
- ai: async ({ page }, use, testInfo) => {
4627
- const agent = agentForPage(page, testInfo);
4628
- await use(
4629
- async (taskPrompt, opts) => {
4630
- return new Promise((resolve, reject) => {
4631
- import_test.test.step(`ai - ${taskPrompt}`, async () => {
4632
- await waitForNetworkIdle(page);
4633
- const actionType = (opts == null ? void 0 : opts.type) || "action";
4634
- try {
4635
- const result = await agent.ai(taskPrompt, actionType);
4636
- resolve(result);
4637
- } catch (error) {
4638
- reject(error);
4639
- }
4640
- });
4641
- });
4642
- }
4643
- );
4644
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4645
- },
4646
- aiAction: async ({ page }, use, testInfo) => {
4647
- const agent = agentForPage(page, testInfo);
4648
- await use(async (taskPrompt) => {
4649
- return new Promise((resolve, reject) => {
4650
- import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
4651
- await waitForNetworkIdle(page);
4652
- try {
4653
- const result = await agent.aiAction(taskPrompt);
4654
- resolve(result);
4655
- } catch (error) {
4656
- reject(error);
4657
- }
4658
- });
4659
- });
4660
- });
4661
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4662
- },
4663
- aiQuery: async ({ page }, use, testInfo) => {
4664
- const agent = agentForPage(page, testInfo);
4665
- await use(async (demand) => {
4666
- return new Promise((resolve, reject) => {
4667
- import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
4668
- await waitForNetworkIdle(page);
4669
- try {
4670
- const result = await agent.aiQuery(demand);
4671
- resolve(result);
4672
- } catch (error) {
4673
- reject(error);
4674
- }
4675
- });
4676
- });
4677
- });
4678
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4679
- },
4680
- aiAssert: async ({ page }, use, testInfo) => {
4681
- const agent = agentForPage(page, testInfo);
4682
- await use(async (assertion, errorMsg) => {
4683
- return new Promise((resolve, reject) => {
4684
- import_test.test.step(`aiAssert - ${assertion}`, async () => {
4685
- await waitForNetworkIdle(page);
4686
- try {
4687
- await agent.aiAssert(assertion, errorMsg);
4688
- resolve(null);
4689
- } catch (error) {
4690
- reject(error);
4691
- }
4692
- });
4693
- });
4694
- });
4695
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4696
- },
4697
- aiWaitFor: async ({ page }, use, testInfo) => {
4698
- const agent = agentForPage(page, testInfo);
4699
- await use(async (assertion, opt) => {
4700
- return new Promise((resolve, reject) => {
4701
- import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
4702
- await waitForNetworkIdle(page);
4703
- try {
4704
- await agent.aiWaitFor(assertion, opt);
4705
- resolve(null);
4706
- } catch (error) {
4707
- reject(error);
4708
- }
4709
- });
4710
- });
4711
- });
4712
- updateDumpAnnotation(testInfo, agent.dumpDataString());
4713
- }
4714
- };
4715
- };
4716
- async function waitForNetworkIdle(page, timeout = 2e4) {
4717
- try {
4718
- await page.waitForLoadState("networkidle", { timeout });
4719
- } catch (error) {
4720
- console.warn(
4721
- `Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
4722
- );
4723
- }
4724
- }
4725
-
4726
4588
  // src/puppeteer/base-page.ts
4727
4589
  var import_utils9 = require("@midscene/core/utils");
4728
4590
  var import_extractor2 = require("@midscene/shared/extractor");
@@ -4738,12 +4600,19 @@ var Page = class {
4738
4600
  this.underlyingPage = underlyingPage;
4739
4601
  this.pageType = pageType;
4740
4602
  }
4603
+ async waitForNavigation() {
4604
+ if (this.pageType === "puppeteer" || this.pageType === "playwright") {
4605
+ await this.underlyingPage.waitForSelector("html");
4606
+ }
4607
+ }
4741
4608
  // @deprecated
4742
4609
  async getElementsInfo() {
4610
+ await this.waitForNavigation();
4743
4611
  const tree = await this.getElementsNodeTree();
4744
4612
  return (0, import_extractor2.treeToList)(tree);
4745
4613
  }
4746
4614
  async getElementsNodeTree() {
4615
+ await this.waitForNavigation();
4747
4616
  const scripts = await getExtraReturnLogic(true);
4748
4617
  const captureElementSnapshot = await this.evaluate(scripts);
4749
4618
  return captureElementSnapshot;
@@ -4764,6 +4633,7 @@ var Page = class {
4764
4633
  async screenshotBase64() {
4765
4634
  const imgType = "jpeg";
4766
4635
  const path2 = (0, import_utils9.getTmpFile)(imgType);
4636
+ await this.waitForNavigation();
4767
4637
  await this.underlyingPage.screenshot({
4768
4638
  path: path2,
4769
4639
  type: imgType,
@@ -4821,13 +4691,14 @@ var Page = class {
4821
4691
  get keyboard() {
4822
4692
  return {
4823
4693
  type: async (text) => this.underlyingPage.keyboard.type(text, { delay: 80 }),
4824
- press: async (key) => {
4825
- const keys = Array.isArray(key) ? key : [key];
4826
- for (const key2 of keys) {
4827
- await this.underlyingPage.keyboard.down(key2);
4694
+ press: async (action) => {
4695
+ const keys = Array.isArray(action) ? action : [action];
4696
+ for (const k of keys) {
4697
+ const commands = k.command ? [k.command] : [];
4698
+ await this.underlyingPage.keyboard.down(k.key, { commands });
4828
4699
  }
4829
- for (const key2 of [...keys].reverse()) {
4830
- await this.underlyingPage.keyboard.up(key2);
4700
+ for (const k of [...keys].reverse()) {
4701
+ await this.underlyingPage.keyboard.up(k.key);
4831
4702
  }
4832
4703
  },
4833
4704
  down: async (key) => {
@@ -4862,7 +4733,7 @@ var Page = class {
4862
4733
  await this.underlyingPage.keyboard.up("Control");
4863
4734
  }
4864
4735
  await (0, import_utils9.sleep)(100);
4865
- await this.keyboard.press("Backspace");
4736
+ await this.keyboard.press([{ key: "Backspace" }]);
4866
4737
  }
4867
4738
  async moveToPoint(point) {
4868
4739
  if (point) {
@@ -4923,8 +4794,186 @@ var WebPage = class extends Page {
4923
4794
  }
4924
4795
  };
4925
4796
 
4797
+ // src/playwright/ai-fixture.ts
4798
+ var import_node_crypto = require("crypto");
4799
+ var import_test = require("@playwright/test");
4800
+ var groupAndCaseForTest = (testInfo) => {
4801
+ let taskFile;
4802
+ let taskTitle;
4803
+ const titlePath = [...testInfo.titlePath];
4804
+ if (titlePath.length > 1) {
4805
+ taskTitle = titlePath.pop() || "unnamed";
4806
+ taskFile = `${titlePath.join(" > ")}`;
4807
+ } else if (titlePath.length === 1) {
4808
+ taskTitle = titlePath[0];
4809
+ taskFile = `${taskTitle}`;
4810
+ } else {
4811
+ taskTitle = "unnamed";
4812
+ taskFile = "unnamed";
4813
+ }
4814
+ return { taskFile, taskTitle };
4815
+ };
4816
+ var midsceneAgentKeyId = "_midsceneAgentId";
4817
+ var midsceneDumpAnnotationId = "MIDSCENE_DUMP_ANNOTATION";
4818
+ var PlaywrightAiFixture = (options) => {
4819
+ const { forceSameTabNavigation = true } = options != null ? options : {};
4820
+ const pageAgentMap = {};
4821
+ const agentForPage = (page, testInfo) => {
4822
+ let idForPage = page[midsceneAgentKeyId];
4823
+ if (!idForPage) {
4824
+ idForPage = (0, import_node_crypto.randomUUID)();
4825
+ page[midsceneAgentKeyId] = idForPage;
4826
+ const { testId } = testInfo;
4827
+ const { taskFile, taskTitle } = groupAndCaseForTest(testInfo);
4828
+ pageAgentMap[idForPage] = new PlaywrightAgent(page, {
4829
+ testId: `playwright-${testId}-${idForPage}`,
4830
+ forceSameTabNavigation,
4831
+ cacheId: `${taskFile}(${taskTitle})`,
4832
+ groupName: taskTitle,
4833
+ groupDescription: taskFile,
4834
+ generateReport: false
4835
+ // we will generate it in the reporter
4836
+ });
4837
+ }
4838
+ return pageAgentMap[idForPage];
4839
+ };
4840
+ const updateDumpAnnotation = (test2, dump2) => {
4841
+ const currentAnnotation = test2.annotations.find((item) => {
4842
+ return item.type === midsceneDumpAnnotationId;
4843
+ });
4844
+ if (currentAnnotation) {
4845
+ currentAnnotation.description = dump2;
4846
+ } else {
4847
+ test2.annotations.push({
4848
+ type: midsceneDumpAnnotationId,
4849
+ description: dump2
4850
+ });
4851
+ }
4852
+ };
4853
+ return {
4854
+ ai: async ({ page }, use, testInfo) => {
4855
+ const agent = agentForPage(page, testInfo);
4856
+ await use(
4857
+ async (taskPrompt, opts) => {
4858
+ return new Promise((resolve, reject) => {
4859
+ const { type: type2 = "action" } = opts || {};
4860
+ import_test.test.step(`ai - ${taskPrompt}`, async () => {
4861
+ await waitForNetworkIdle(page);
4862
+ try {
4863
+ const result = await agent.ai(taskPrompt, type2);
4864
+ resolve(result);
4865
+ } catch (error) {
4866
+ reject(error);
4867
+ }
4868
+ });
4869
+ });
4870
+ }
4871
+ );
4872
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4873
+ },
4874
+ aiAction: async ({ page }, use, testInfo) => {
4875
+ const agent = agentForPage(page, testInfo);
4876
+ await use(async (taskPrompt) => {
4877
+ return new Promise((resolve, reject) => {
4878
+ import_test.test.step(`aiAction - ${taskPrompt}`, async () => {
4879
+ await waitForNetworkIdle(page);
4880
+ try {
4881
+ const result = await agent.aiAction(taskPrompt);
4882
+ resolve(result);
4883
+ } catch (error) {
4884
+ reject(error);
4885
+ }
4886
+ });
4887
+ });
4888
+ });
4889
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4890
+ },
4891
+ aiQuery: async ({ page }, use, testInfo) => {
4892
+ const agent = agentForPage(page, testInfo);
4893
+ await use(async (demand) => {
4894
+ return new Promise((resolve, reject) => {
4895
+ import_test.test.step(`aiQuery - ${JSON.stringify(demand)}`, async () => {
4896
+ await waitForNetworkIdle(page);
4897
+ try {
4898
+ const result = await agent.aiQuery(demand);
4899
+ resolve(result);
4900
+ } catch (error) {
4901
+ reject(error);
4902
+ }
4903
+ });
4904
+ });
4905
+ });
4906
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4907
+ },
4908
+ aiAssert: async ({ page }, use, testInfo) => {
4909
+ const agent = agentForPage(page, testInfo);
4910
+ await use(async (assertion, errorMsg) => {
4911
+ return new Promise((resolve, reject) => {
4912
+ import_test.test.step(`aiAssert - ${assertion}`, async () => {
4913
+ await waitForNetworkIdle(page);
4914
+ try {
4915
+ await agent.aiAssert(assertion, errorMsg);
4916
+ resolve(null);
4917
+ } catch (error) {
4918
+ reject(error);
4919
+ }
4920
+ });
4921
+ });
4922
+ });
4923
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4924
+ },
4925
+ aiWaitFor: async ({ page }, use, testInfo) => {
4926
+ const agent = agentForPage(page, testInfo);
4927
+ await use(async (assertion, opt) => {
4928
+ return new Promise((resolve, reject) => {
4929
+ import_test.test.step(`aiWaitFor - ${assertion}`, async () => {
4930
+ await waitForNetworkIdle(page);
4931
+ try {
4932
+ await agent.aiWaitFor(assertion, opt);
4933
+ resolve(null);
4934
+ } catch (error) {
4935
+ reject(error);
4936
+ }
4937
+ });
4938
+ });
4939
+ });
4940
+ updateDumpAnnotation(testInfo, agent.dumpDataString());
4941
+ }
4942
+ };
4943
+ };
4944
+ async function waitForNetworkIdle(page, timeout = 2e4) {
4945
+ try {
4946
+ await page.waitForLoadState("networkidle", { timeout });
4947
+ } catch (error) {
4948
+ console.warn(
4949
+ `Network idle timeout exceeded: ${error instanceof Error ? error.message : String(error)}`
4950
+ );
4951
+ }
4952
+ }
4953
+
4926
4954
  // src/playwright/index.ts
4927
4955
  var import_env4 = require("@midscene/core/env");
4956
+ var PlaywrightAgent = class extends PageAgent {
4957
+ constructor(page, opts) {
4958
+ const webPage = new WebPage(page);
4959
+ super(webPage, opts);
4960
+ const { forceSameTabNavigation = true } = opts != null ? opts : {};
4961
+ if (forceSameTabNavigation) {
4962
+ page.on("popup", async (popup) => {
4963
+ if (!popup) {
4964
+ console.warn(
4965
+ "got a popup event, but the popup is not ready yet, skip"
4966
+ );
4967
+ return;
4968
+ }
4969
+ const url = await popup.url();
4970
+ console.log(`Popup opened: ${url}`);
4971
+ await popup.close();
4972
+ await page.goto(url);
4973
+ });
4974
+ }
4975
+ }
4976
+ };
4928
4977
  // Annotate the CommonJS export names for ESM import in node:
4929
4978
  0 && (module.exports = {
4930
4979
  PlaywrightAgent,