@midscene/web 0.11.1 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/es/appium.js +84 -39
  2. package/dist/es/bridge-mode-browser.js +58 -19
  3. package/dist/es/bridge-mode.js +61 -43
  4. package/dist/es/chrome-extension.js +104 -51
  5. package/dist/es/index.js +291 -218
  6. package/dist/es/midscene-playground.js +56 -38
  7. package/dist/es/playground.js +56 -38
  8. package/dist/es/playwright.js +251 -203
  9. package/dist/es/puppeteer.js +85 -60
  10. package/dist/es/ui-utils.js +43 -0
  11. package/dist/lib/appium.js +84 -39
  12. package/dist/lib/bridge-mode-browser.js +58 -19
  13. package/dist/lib/bridge-mode.js +61 -43
  14. package/dist/lib/chrome-extension.js +104 -51
  15. package/dist/lib/index.js +291 -218
  16. package/dist/lib/midscene-playground.js +56 -38
  17. package/dist/lib/playground.js +56 -38
  18. package/dist/lib/playwright.js +251 -203
  19. package/dist/lib/puppeteer.js +85 -60
  20. package/dist/lib/ui-utils.js +43 -0
  21. package/dist/types/{tasks-d5a01262.d.ts → agent-ac363fa3.d.ts} +41 -41
  22. package/dist/types/appium.d.ts +2 -2
  23. package/dist/types/bridge-mode-browser.d.ts +2 -2
  24. package/dist/types/bridge-mode.d.ts +3 -3
  25. package/dist/types/{browser-7d5614fb.d.ts → browser-eae1a5c1.d.ts} +4 -4
  26. package/dist/types/chrome-extension.d.ts +3 -3
  27. package/dist/types/index.d.ts +8 -8
  28. package/dist/types/{page-77af8d5f.d.ts → page-cf0f892e.d.ts} +32 -6
  29. package/dist/types/playground.d.ts +3 -3
  30. package/dist/types/playwright.d.ts +12 -6
  31. package/dist/types/puppeteer.d.ts +2 -2
  32. package/dist/types/ui-utils.d.ts +6 -1
  33. package/dist/types/{utils-1a3bc661.d.ts → utils-9a29bfa0.d.ts} +1 -1
  34. package/dist/types/utils.d.ts +1 -1
  35. package/dist/types/yaml.d.ts +3 -3
  36. package/package.json +6 -6
@@ -3364,7 +3364,9 @@ var TaskCache = class {
3364
3364
  if (!this.midscenePkgInfo) {
3365
3365
  return void 0;
3366
3366
  }
3367
- 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]) {
3368
3370
  return void 0;
3369
3371
  }
3370
3372
  return jsonData;
@@ -3398,6 +3400,56 @@ var TaskCache = class {
3398
3400
  }
3399
3401
  };
3400
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
+
3401
3453
  // src/common/tasks.ts
3402
3454
  var PageTaskExecutor = class {
3403
3455
  constructor(page, insight, opts) {
@@ -3611,8 +3663,8 @@ var PageTaskExecutor = class {
3611
3663
  thought: plan2.thought,
3612
3664
  locate: plan2.locate,
3613
3665
  executor: async (taskParam) => {
3614
- (0, import_node_assert3.default)(taskParam == null ? void 0 : taskParam.value, "No key to press");
3615
- await this.page.keyboard.press(taskParam.value);
3666
+ const keys = getKeyCommands(taskParam.value);
3667
+ await this.page.keyboard.press(keys);
3616
3668
  }
3617
3669
  };
3618
3670
  tasks.push(taskActionKeyboardPress);
@@ -4020,7 +4072,7 @@ var PageTaskExecutor = class {
4020
4072
  const cacheGroup = this.taskCache.getCacheGroupByPrompt(userPrompt);
4021
4073
  const isCompleted = false;
4022
4074
  let currentActionNumber = 0;
4023
- const maxActionNumber = 20;
4075
+ const maxActionNumber = 40;
4024
4076
  while (!isCompleted && currentActionNumber < maxActionNumber) {
4025
4077
  currentActionNumber++;
4026
4078
  const planningTask = this.planningTaskToGoal(
@@ -4240,40 +4292,6 @@ var WebElementInfo = class {
4240
4292
  }
4241
4293
  };
4242
4294
 
4243
- // src/common/ui-utils.ts
4244
- function typeStr(task) {
4245
- return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
4246
- }
4247
- function paramStr(task) {
4248
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4249
- let value;
4250
- if (task.type === "Planning") {
4251
- value = (_a = task == null ? void 0 : task.param) == null ? void 0 : _a.userPrompt;
4252
- }
4253
- if (task.type === "Insight") {
4254
- 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);
4255
- }
4256
- if (task.type === "Action") {
4257
- const sleepMs = (_f = task == null ? void 0 : task.param) == null ? void 0 : _f.timeMs;
4258
- const scrollType = (_g = task == null ? void 0 : task.param) == null ? void 0 : _g.scrollType;
4259
- if (sleepMs) {
4260
- value = `${sleepMs}ms`;
4261
- } else if (scrollType) {
4262
- const scrollDirection = (_h = task == null ? void 0 : task.param) == null ? void 0 : _h.direction;
4263
- const scrollDistance = (_i = task == null ? void 0 : task.param) == null ? void 0 : _i.distance;
4264
- value = `${scrollDirection || "down"}, ${scrollType || "once"}, ${scrollDistance || "distance-not-set"}`;
4265
- } else {
4266
- 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);
4267
- }
4268
- if (!value) {
4269
- value = task.thought;
4270
- }
4271
- }
4272
- if (typeof value === "undefined")
4273
- return "";
4274
- return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
4275
- }
4276
-
4277
4295
  // src/common/utils.ts
4278
4296
  var import_node_assert4 = __toESM(require("assert"));
4279
4297
  var import_node_fs3 = require("fs");
@@ -4581,12 +4599,19 @@ var Page = class {
4581
4599
  this.underlyingPage = underlyingPage;
4582
4600
  this.pageType = pageType;
4583
4601
  }
4602
+ async waitForNavigation() {
4603
+ if (this.pageType === "puppeteer" || this.pageType === "playwright") {
4604
+ await this.underlyingPage.waitForSelector("html");
4605
+ }
4606
+ }
4584
4607
  // @deprecated
4585
4608
  async getElementsInfo() {
4609
+ await this.waitForNavigation();
4586
4610
  const tree = await this.getElementsNodeTree();
4587
4611
  return (0, import_extractor2.treeToList)(tree);
4588
4612
  }
4589
4613
  async getElementsNodeTree() {
4614
+ await this.waitForNavigation();
4590
4615
  const scripts = await getExtraReturnLogic(true);
4591
4616
  const captureElementSnapshot = await this.evaluate(scripts);
4592
4617
  return captureElementSnapshot;
@@ -4607,6 +4632,7 @@ var Page = class {
4607
4632
  async screenshotBase64() {
4608
4633
  const imgType = "jpeg";
4609
4634
  const path2 = (0, import_utils9.getTmpFile)(imgType);
4635
+ await this.waitForNavigation();
4610
4636
  await this.underlyingPage.screenshot({
4611
4637
  path: path2,
4612
4638
  type: imgType,
@@ -4664,13 +4690,14 @@ var Page = class {
4664
4690
  get keyboard() {
4665
4691
  return {
4666
4692
  type: async (text) => this.underlyingPage.keyboard.type(text, { delay: 80 }),
4667
- press: async (key) => {
4668
- const keys = Array.isArray(key) ? key : [key];
4669
- for (const key2 of keys) {
4670
- await this.underlyingPage.keyboard.down(key2);
4693
+ press: async (action) => {
4694
+ const keys = Array.isArray(action) ? action : [action];
4695
+ for (const k of keys) {
4696
+ const commands = k.command ? [k.command] : [];
4697
+ await this.underlyingPage.keyboard.down(k.key, { commands });
4671
4698
  }
4672
- for (const key2 of [...keys].reverse()) {
4673
- await this.underlyingPage.keyboard.up(key2);
4699
+ for (const k of [...keys].reverse()) {
4700
+ await this.underlyingPage.keyboard.up(k.key);
4674
4701
  }
4675
4702
  },
4676
4703
  down: async (key) => {
@@ -4705,7 +4732,7 @@ var Page = class {
4705
4732
  await this.underlyingPage.keyboard.up("Control");
4706
4733
  }
4707
4734
  await (0, import_utils9.sleep)(100);
4708
- await this.keyboard.press("Backspace");
4735
+ await this.keyboard.press([{ key: "Backspace" }]);
4709
4736
  }
4710
4737
  async moveToPoint(point) {
4711
4738
  if (point) {
@@ -4893,7 +4920,7 @@ async function puppeteerAgentForTarget(target, preference) {
4893
4920
  const agent = new PuppeteerAgent(page, {
4894
4921
  autoPrintReportMsg: false,
4895
4922
  testId: preference == null ? void 0 : preference.testId,
4896
- trackingActiveTab: typeof target.trackingActiveTab !== "undefined" ? target.trackingActiveTab : true
4923
+ forceSameTabNavigation: typeof target.forceSameTabNavigation !== "undefined" ? target.forceSameTabNavigation : true
4897
4924
  // true for default in yaml script
4898
4925
  });
4899
4926
  freeFn.push({
@@ -4908,21 +4935,19 @@ var PuppeteerAgent = class extends PageAgent {
4908
4935
  constructor(page, opts) {
4909
4936
  const webPage = new WebPage(page);
4910
4937
  super(webPage, opts);
4911
- if (opts == null ? void 0 : opts.trackingActiveTab) {
4912
- const browser = this.page.underlyingPage.browser();
4913
- browser.on("targetcreated", async (target) => {
4914
- if (target.type() === "page") {
4915
- const targetPage = await target.page();
4916
- if (!targetPage) {
4917
- console.warn(
4918
- "got a targetPage event, but the page is not ready yet, skip"
4919
- );
4920
- return;
4921
- }
4922
- const midscenePage = new WebPage(targetPage);
4923
- this.page = midscenePage;
4924
- this.taskExecutor.page = midscenePage;
4938
+ const { forceSameTabNavigation = true } = opts != null ? opts : {};
4939
+ if (forceSameTabNavigation) {
4940
+ page.on("popup", async (popup) => {
4941
+ if (!popup) {
4942
+ console.warn(
4943
+ "got a popup event, but the popup is not ready yet, skip"
4944
+ );
4945
+ return;
4925
4946
  }
4947
+ const url = await popup.url();
4948
+ console.log(`Popup opened: ${url}`);
4949
+ await popup.close();
4950
+ await page.goto(url);
4926
4951
  });
4927
4952
  }
4928
4953
  }
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/common/ui-utils.ts
21
21
  var ui_utils_exports = {};
22
22
  __export(ui_utils_exports, {
23
+ getKeyCommands: () => getKeyCommands,
24
+ limitOpenNewTabScript: () => limitOpenNewTabScript,
23
25
  paramStr: () => paramStr,
24
26
  typeStr: () => typeStr
25
27
  });
@@ -27,6 +29,22 @@ module.exports = __toCommonJS(ui_utils_exports);
27
29
  function typeStr(task) {
28
30
  return task.subType ? `${task.type} / ${task.subType || ""}` : task.type;
29
31
  }
32
+ function getKeyCommands(value) {
33
+ const keys = Array.isArray(value) ? value : [value];
34
+ return keys.reduce((acc, k) => {
35
+ const includeMeta = keys.includes("Meta") || keys.includes("Control");
36
+ if (includeMeta && (k === "a" || k === "A")) {
37
+ return acc.concat([{ key: k, command: "SelectAll" }]);
38
+ }
39
+ if (includeMeta && (k === "c" || k === "C")) {
40
+ return acc.concat([{ key: k, command: "Copy" }]);
41
+ }
42
+ if (includeMeta && (k === "v" || k === "V")) {
43
+ return acc.concat([{ key: k, command: "Paste" }]);
44
+ }
45
+ return acc.concat([{ key: k }]);
46
+ }, []);
47
+ }
30
48
  function paramStr(task) {
31
49
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
32
50
  let value;
@@ -56,8 +74,33 @@ function paramStr(task) {
56
74
  return "";
57
75
  return typeof value === "string" ? value : JSON.stringify(value, void 0, 2);
58
76
  }
77
+ var limitOpenNewTabScript = `
78
+ if (!window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__) {
79
+ window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__ = true;
80
+
81
+ // Intercept the window.open method (only once)
82
+ window.open = function(url) {
83
+ console.log('Blocked window.open:', url);
84
+ window.location.href = url;
85
+ return null;
86
+ };
87
+
88
+ // Block all a tag clicks with target="_blank" (only once)
89
+ document.addEventListener('click', function(e) {
90
+ const target = e.target.closest('a');
91
+ if (target && target.target === '_blank') {
92
+ e.preventDefault();
93
+ console.log('Blocked new tab:', target.href);
94
+ window.location.href = target.href;
95
+ target.removeAttribute('target');
96
+ }
97
+ }, true);
98
+ }
99
+ `;
59
100
  // Annotate the CommonJS export names for ESM import in node:
60
101
  0 && (module.exports = {
102
+ getKeyCommands,
103
+ limitOpenNewTabScript,
61
104
  paramStr,
62
105
  typeStr
63
106
  });
@@ -1,6 +1,6 @@
1
1
  import * as _midscene_core_dist_lib_types_types_4eebf154 from '@midscene/core/dist/lib/types/types-4eebf154';
2
- import { c as WebUIContext, W as WebPage, d as WebElementInfo } from './page-77af8d5f.js';
3
- import { PlanningAIResponse, AIElementIdResponse, Insight, GroupedActionDump, InsightAction, ExecutionDump, AgentAssertOpt, AgentWaitForOpt, OnTaskStartTip, ExecutionTaskProgressOptions, Executor, InsightExtractParam, InsightAssertionResponse, PlanningActionParamWaitFor } from '@midscene/core';
2
+ import { c as WebUIContext, W as WebPage, d as WebElementInfo } from './page-cf0f892e.js';
3
+ import { PlanningAIResponse, AIElementIdResponse, Insight, ExecutionTaskProgressOptions, Executor, InsightExtractParam, InsightAssertionResponse, PlanningActionParamWaitFor, OnTaskStartTip, GroupedActionDump, InsightAction, ExecutionDump, AgentAssertOpt, AgentWaitForOpt } from '@midscene/core';
4
4
  import { vlmPlanning, ChatCompletionMessageParam } from '@midscene/core/ai-model';
5
5
  import { getRunningPkgInfo } from '@midscene/shared/fs';
6
6
 
@@ -92,8 +92,46 @@ declare class TaskCache {
92
92
  writeCacheToFile(): void;
93
93
  }
94
94
 
95
+ interface ExecutionResult<OutputType = any> {
96
+ output: OutputType;
97
+ executor: Executor;
98
+ }
99
+ declare class PageTaskExecutor {
100
+ page: WebPage;
101
+ insight: Insight<WebElementInfo, WebUIContext>;
102
+ taskCache: TaskCache;
103
+ conversationHistory: ChatCompletionMessageParam[];
104
+ constructor(page: WebPage, insight: Insight<WebElementInfo, WebUIContext>, opts: {
105
+ cacheId: string | undefined;
106
+ });
107
+ private recordScreenshot;
108
+ private prependExecutorWithScreenshot;
109
+ private convertPlanToExecutable;
110
+ private planningTaskFromPrompt;
111
+ private planningTaskToGoal;
112
+ action(userPrompt: string, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult>;
113
+ actionToGoal(userPrompt: string, options?: ExecutionTaskProgressOptions): Promise<{
114
+ output: any;
115
+ executor: Executor;
116
+ }>;
117
+ query(demand: InsightExtractParam, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult>;
118
+ assert(assertion: string, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult<InsightAssertionResponse>>;
119
+ /**
120
+ * Append a message to the conversation history
121
+ * For user messages with images:
122
+ * - Keep max 4 user image messages in history
123
+ * - Remove oldest user image message when limit reached
124
+ * For assistant messages:
125
+ * - Simply append to history
126
+ * @param conversationHistory Message to append
127
+ */
128
+ private appendConversationHistory;
129
+ private appendErrorPlan;
130
+ waitFor(assertion: string, opt: PlanningActionParamWaitFor): Promise<ExecutionResult<void>>;
131
+ }
132
+
95
133
  interface PageAgentOpt {
96
- trackingActiveTab?: boolean;
134
+ forceSameTabNavigation?: boolean;
97
135
  testId?: string;
98
136
  cacheId?: string;
99
137
  groupName?: string;
@@ -134,42 +172,4 @@ declare class PageAgent<PageType extends WebPage = WebPage> {
134
172
  destroy(): Promise<void>;
135
173
  }
136
174
 
137
- interface ExecutionResult<OutputType = any> {
138
- output: OutputType;
139
- executor: Executor;
140
- }
141
- declare class PageTaskExecutor {
142
- page: WebPage;
143
- insight: Insight<WebElementInfo, WebUIContext>;
144
- taskCache: TaskCache;
145
- conversationHistory: ChatCompletionMessageParam[];
146
- constructor(page: WebPage, insight: Insight<WebElementInfo, WebUIContext>, opts: {
147
- cacheId: string | undefined;
148
- });
149
- private recordScreenshot;
150
- private prependExecutorWithScreenshot;
151
- private convertPlanToExecutable;
152
- private planningTaskFromPrompt;
153
- private planningTaskToGoal;
154
- action(userPrompt: string, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult>;
155
- actionToGoal(userPrompt: string, options?: ExecutionTaskProgressOptions): Promise<{
156
- output: any;
157
- executor: Executor;
158
- }>;
159
- query(demand: InsightExtractParam, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult>;
160
- assert(assertion: string, options?: ExecutionTaskProgressOptions): Promise<ExecutionResult<InsightAssertionResponse>>;
161
- /**
162
- * Append a message to the conversation history
163
- * For user messages with images:
164
- * - Keep max 4 user image messages in history
165
- * - Remove oldest user image message when limit reached
166
- * For assistant messages:
167
- * - Simply append to history
168
- * @param conversationHistory Message to append
169
- */
170
- private appendConversationHistory;
171
- private appendErrorPlan;
172
- waitFor(assertion: string, opt: PlanningActionParamWaitFor): Promise<ExecutionResult<void>>;
173
- }
174
-
175
175
  export { PageAgent as P, type PageAgentOpt as a, PageTaskExecutor as b };
@@ -1,5 +1,5 @@
1
- export { P as AppiumAgent } from './tasks-d5a01262.js';
2
- export { P as AppiumPage } from './page-77af8d5f.js';
1
+ export { P as AppiumAgent } from './agent-ac363fa3.js';
2
+ export { P as AppiumPage } from './page-cf0f892e.js';
3
3
  import '@midscene/core/dist/lib/types/types-4eebf154';
4
4
  import '@midscene/core';
5
5
  import '@midscene/core/ai-model';
@@ -1,5 +1,5 @@
1
- export { C as ChromeExtensionPageBrowserSide } from './browser-7d5614fb.js';
2
- import './page-77af8d5f.js';
1
+ export { C as ChromeExtensionPageBrowserSide } from './browser-eae1a5c1.js';
2
+ import './page-cf0f892e.js';
3
3
  import 'playwright';
4
4
  import '@midscene/core';
5
5
  import '@midscene/shared/extractor';
@@ -1,8 +1,8 @@
1
- import { P as PageAgent, a as PageAgentOpt } from './tasks-d5a01262.js';
2
- import { B as BridgeConnectTabOptions, C as ChromeExtensionPageBrowserSide } from './browser-7d5614fb.js';
1
+ import { P as PageAgent, a as PageAgentOpt } from './agent-ac363fa3.js';
2
+ import { B as BridgeConnectTabOptions, C as ChromeExtensionPageBrowserSide } from './browser-eae1a5c1.js';
3
3
  export { overrideAIConfig } from '@midscene/core/env';
4
4
  import '@midscene/core/dist/lib/types/types-4eebf154';
5
- import './page-77af8d5f.js';
5
+ import './page-cf0f892e.js';
6
6
  import 'playwright';
7
7
  import '@midscene/core';
8
8
  import '@midscene/shared/extractor';
@@ -1,11 +1,11 @@
1
- import { C as ChromeExtensionProxyPage } from './page-77af8d5f.js';
1
+ import { C as ChromeExtensionProxyPage } from './page-cf0f892e.js';
2
2
 
3
3
  interface BridgeConnectTabOptions {
4
4
  /**
5
5
  * If true, the page will always track the active tab.
6
- * @default false
6
+ * @default true
7
7
  */
8
- trackingActiveTab?: boolean;
8
+ forceSameTabNavigation?: boolean;
9
9
  }
10
10
 
11
11
  declare class BridgeClient {
@@ -23,7 +23,7 @@ declare class ChromeExtensionPageBrowserSide extends ChromeExtensionProxyPage {
23
23
  onDisconnect: () => void;
24
24
  onLogMessage: (message: string, type: 'log' | 'status') => void;
25
25
  bridgeClient: BridgeClient | null;
26
- constructor(onDisconnect?: () => void, onLogMessage?: (message: string, type: 'log' | 'status') => void, trackingActiveTab?: boolean);
26
+ constructor(onDisconnect?: () => void, onLogMessage?: (message: string, type: 'log' | 'status') => void, forceSameTabNavigation?: boolean);
27
27
  private setupBridgeClient;
28
28
  connect(): Promise<void>;
29
29
  connectNewTabWithUrl(url: string, options?: BridgeConnectTabOptions): Promise<void>;
@@ -1,6 +1,6 @@
1
- import { C as ChromeExtensionProxyPage } from './page-77af8d5f.js';
2
- export { E as ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from './page-77af8d5f.js';
3
- import { P as PageAgent } from './tasks-d5a01262.js';
1
+ import { C as ChromeExtensionProxyPage } from './page-cf0f892e.js';
2
+ export { E as ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from './page-cf0f892e.js';
3
+ import { P as PageAgent } from './agent-ac363fa3.js';
4
4
  import 'playwright';
5
5
  import '@midscene/core';
6
6
  import '@midscene/shared/extractor';
@@ -1,17 +1,17 @@
1
- export { PlayWrightAiFixtureType, PlaywrightAiFixture } from './playwright.js';
2
- export { P as AppiumAgent, P as PlaywrightAgent } from './tasks-d5a01262.js';
3
- export { P as AppiumPage, W as WebPage } from './page-77af8d5f.js';
1
+ export { PlayWrightAiFixtureType, PlaywrightAgent, PlaywrightAiFixture } from './playwright.js';
2
+ export { P as AppiumPage, W as WebPage } from './page-cf0f892e.js';
4
3
  export { PuppeteerAgent } from './puppeteer.js';
4
+ export { P as AppiumAgent } from './agent-ac363fa3.js';
5
5
  export { StaticPageAgent } from './playground.js';
6
- export { S as ScriptPlayer, f as flowItemBrief, p as parseYamlScript } from './utils-1a3bc661.js';
6
+ export { S as ScriptPlayer, f as flowItemBrief, p as parseYamlScript } from './utils-9a29bfa0.js';
7
+ import 'playwright';
7
8
  import '@midscene/core';
8
9
  import '@playwright/test';
9
- import 'playwright';
10
10
  import '@midscene/core/env';
11
- import '@midscene/core/dist/lib/types/types-4eebf154';
12
- import '@midscene/core/ai-model';
13
- import '@midscene/shared/fs';
14
11
  import '@midscene/shared/extractor';
15
12
  import 'puppeteer';
16
13
  import '@midscene/shared/constants';
14
+ import '@midscene/core/dist/lib/types/types-4eebf154';
17
15
  import 'webdriverio';
16
+ import '@midscene/core/ai-model';
17
+ import '@midscene/shared/fs';
@@ -62,7 +62,13 @@ interface MouseAction {
62
62
  }
63
63
  interface KeyboardAction {
64
64
  type: (text: string) => Promise<void>;
65
- press: (key: WebKeyInput) => Promise<void>;
65
+ press: (action: {
66
+ key: WebKeyInput;
67
+ command?: string;
68
+ } | {
69
+ key: WebKeyInput;
70
+ command?: string;
71
+ }[]) => Promise<void>;
66
72
  }
67
73
  declare abstract class AbstractPage {
68
74
  abstract pageType: string;
@@ -115,7 +121,13 @@ declare class Page$1 implements AbstractPage {
115
121
  };
116
122
  get keyboard(): {
117
123
  type: (text: string) => Promise<void>;
118
- press: (key: WebKeyInput$1) => Promise<void>;
124
+ press: (action: {
125
+ key: WebKeyInput$1;
126
+ command?: string;
127
+ } | {
128
+ key: WebKeyInput$1;
129
+ command?: string;
130
+ }[]) => Promise<void>;
119
131
  };
120
132
  clearInput(element: ElementInfo): Promise<void>;
121
133
  url(): string;
@@ -129,6 +141,7 @@ declare class Page$1 implements AbstractPage {
129
141
  scrollRight(distance?: number, startingPoint?: Point): Promise<void>;
130
142
  private keyboardType;
131
143
  private keyboardPress;
144
+ private keyboardPressAction;
132
145
  private mouseClick;
133
146
  private mouseMove;
134
147
  private mouseDrag;
@@ -138,14 +151,14 @@ declare class Page$1 implements AbstractPage {
138
151
 
139
152
  declare class ChromeExtensionProxyPage implements AbstractPage {
140
153
  pageType: string;
141
- trackingActiveTab: boolean;
154
+ forceSameTabNavigation: boolean;
142
155
  private version;
143
156
  private viewportSize?;
144
157
  private activeTabId;
145
158
  private tabIdOfDebuggerAttached;
146
159
  private attachingDebugger;
147
160
  private destroyed;
148
- constructor(trackingActiveTab: boolean);
161
+ constructor(forceSameTabNavigation: boolean);
149
162
  getTabId(): Promise<number>;
150
163
  private attachDebugger;
151
164
  private showMousePointer;
@@ -184,7 +197,13 @@ declare class ChromeExtensionProxyPage implements AbstractPage {
184
197
  };
185
198
  keyboard: {
186
199
  type: (text: string) => Promise<void>;
187
- press: (key: WebKeyInput | WebKeyInput[]) => Promise<void>;
200
+ press: (action: {
201
+ key: WebKeyInput;
202
+ command?: string;
203
+ } | {
204
+ key: WebKeyInput;
205
+ command?: string;
206
+ }[]) => Promise<void>;
188
207
  };
189
208
  destroy(): Promise<void>;
190
209
  }
@@ -227,6 +246,7 @@ declare class Page<AgentType extends 'puppeteer' | 'playwright', PageType extend
227
246
  pageType: AgentType;
228
247
  private evaluate;
229
248
  constructor(underlyingPage: PageType, pageType: AgentType);
249
+ waitForNavigation(): Promise<void>;
230
250
  getElementsInfo(): Promise<ElementInfo[]>;
231
251
  getElementsNodeTree(): Promise<ElementTreeNode<ElementInfo>>;
232
252
  size(): Promise<Size>;
@@ -249,7 +269,13 @@ declare class Page<AgentType extends 'puppeteer' | 'playwright', PageType extend
249
269
  };
250
270
  get keyboard(): {
251
271
  type: (text: string) => Promise<void>;
252
- press: (key: WebKeyInput | WebKeyInput[]) => Promise<void>;
272
+ press: (action: {
273
+ key: WebKeyInput;
274
+ command?: string;
275
+ } | {
276
+ key: WebKeyInput;
277
+ command?: string;
278
+ }[]) => Promise<void>;
253
279
  down: (key: WebKeyInput) => Promise<void>;
254
280
  up: (key: WebKeyInput) => Promise<void>;
255
281
  };
@@ -1,6 +1,6 @@
1
- import { S as StaticPage } from './page-77af8d5f.js';
2
- export { E as ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from './page-77af8d5f.js';
3
- import { P as PageAgent } from './tasks-d5a01262.js';
1
+ import { S as StaticPage } from './page-cf0f892e.js';
2
+ export { E as ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED } from './page-cf0f892e.js';
3
+ import { P as PageAgent } from './agent-ac363fa3.js';
4
4
  import 'playwright';
5
5
  import '@midscene/core';
6
6
  import '@midscene/shared/extractor';
@@ -1,10 +1,9 @@
1
+ import { b as PageTaskExecutor, P as PageAgent, a as PageAgentOpt } from './agent-ac363fa3.js';
2
+ import { Page } from 'playwright';
1
3
  import { AgentWaitForOpt } from '@midscene/core';
2
4
  import { TestInfo } from '@playwright/test';
3
- import { Page } from 'playwright';
4
- import { b as PageTaskExecutor } from './tasks-d5a01262.js';
5
- export { P as PlaywrightAgent } from './tasks-d5a01262.js';
6
- export { b as PlaywrightWebPage } from './page-77af8d5f.js';
7
5
  export { overrideAIConfig } from '@midscene/core/env';
6
+ export { b as PlaywrightWebPage } from './page-cf0f892e.js';
8
7
  import '@midscene/core/dist/lib/types/types-4eebf154';
9
8
  import '@midscene/core/ai-model';
10
9
  import '@midscene/shared/fs';
@@ -13,7 +12,9 @@ import 'puppeteer';
13
12
  import '@midscene/shared/constants';
14
13
  import 'webdriverio';
15
14
 
16
- declare const PlaywrightAiFixture: () => {
15
+ declare const PlaywrightAiFixture: (options?: {
16
+ forceSameTabNavigation?: boolean;
17
+ }) => {
17
18
  ai: ({ page }: {
18
19
  page: Page;
19
20
  }, use: any, testInfo: TestInfo) => Promise<void>;
@@ -33,6 +34,7 @@ declare const PlaywrightAiFixture: () => {
33
34
  type PlayWrightAiFixtureType = {
34
35
  ai: <T = any>(prompt: string, opts?: {
35
36
  type?: 'action' | 'query';
37
+ trackNewTab?: boolean;
36
38
  }) => Promise<T>;
37
39
  aiAction: (taskPrompt: string) => ReturnType<PageTaskExecutor['action']>;
38
40
  aiQuery: <T = any>(demand: any) => Promise<T>;
@@ -40,4 +42,8 @@ type PlayWrightAiFixtureType = {
40
42
  aiWaitFor: (assertion: string, opt?: AgentWaitForOpt) => Promise<void>;
41
43
  };
42
44
 
43
- export { type PlayWrightAiFixtureType, PlaywrightAiFixture };
45
+ declare class PlaywrightAgent extends PageAgent {
46
+ constructor(page: Page, opts?: PageAgentOpt);
47
+ }
48
+
49
+ export { type PlayWrightAiFixtureType, PlaywrightAgent, PlaywrightAiFixture };
@@ -1,6 +1,6 @@
1
- import { P as PageAgent, a as PageAgentOpt } from './tasks-d5a01262.js';
1
+ import { P as PageAgent, a as PageAgentOpt } from './agent-ac363fa3.js';
2
2
  import { Page } from 'puppeteer';
3
- export { a as PuppeteerWebPage } from './page-77af8d5f.js';
3
+ export { a as PuppeteerWebPage } from './page-cf0f892e.js';
4
4
  export { overrideAIConfig } from '@midscene/core/env';
5
5
  import { MidsceneYamlScriptEnv } from '@midscene/core';
6
6
  import '@midscene/core/dist/lib/types/types-4eebf154';
@@ -1,6 +1,11 @@
1
1
  import { ExecutionTask } from '@midscene/core';
2
2
 
3
3
  declare function typeStr(task: ExecutionTask): any;
4
+ declare function getKeyCommands(value: string | string[]): Array<{
5
+ key: string;
6
+ command?: string;
7
+ }>;
4
8
  declare function paramStr(task: ExecutionTask): string;
9
+ declare const limitOpenNewTabScript = "\nif (!window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__) {\n window.__MIDSCENE_NEW_TAB_INTERCEPTOR_INITIALIZED__ = true;\n\n // Intercept the window.open method (only once)\n window.open = function(url) {\n console.log('Blocked window.open:', url);\n window.location.href = url;\n return null;\n };\n\n // Block all a tag clicks with target=\"_blank\" (only once)\n document.addEventListener('click', function(e) {\n const target = e.target.closest('a');\n if (target && target.target === '_blank') {\n e.preventDefault();\n console.log('Blocked new tab:', target.href);\n window.location.href = target.href;\n target.removeAttribute('target');\n }\n }, true);\n}\n";
5
10
 
6
- export { paramStr, typeStr };
11
+ export { getKeyCommands, limitOpenNewTabScript, paramStr, typeStr };
@@ -1,4 +1,4 @@
1
- import { P as PageAgent } from './tasks-d5a01262.js';
1
+ import { P as PageAgent } from './agent-ac363fa3.js';
2
2
  import { ScriptPlayerTaskStatus, ScriptPlayerStatusValue, MidsceneYamlScript, MidsceneYamlScriptEnv, FreeFn, MidsceneYamlFlowItem } from '@midscene/core';
3
3
 
4
4
  declare class ScriptPlayer {