@midscene/web 1.10.4-beta-20260710032704.0 → 1.10.4-beta-20260710115744.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.
Files changed (79) hide show
  1. package/dist/es/bridge-mode/io-client.mjs +1 -1
  2. package/dist/es/bridge-mode/io-server.mjs +2 -2
  3. package/dist/es/bridge-mode/page-browser-side.mjs +1 -1
  4. package/dist/es/cli.mjs +1 -1
  5. package/dist/es/common/browser-agent-utils.mjs +41 -0
  6. package/dist/es/common/browser-agent-utils.mjs.map +1 -0
  7. package/dist/es/common/browser-agent.mjs +140 -0
  8. package/dist/es/common/browser-agent.mjs.map +1 -0
  9. package/dist/es/index.mjs +3 -3
  10. package/dist/es/playwright/agent.mjs +2 -0
  11. package/dist/es/playwright/ai-fixture.mjs +18 -4
  12. package/dist/es/playwright/ai-fixture.mjs.map +1 -1
  13. package/dist/es/playwright/browser-agent.mjs +84 -0
  14. package/dist/es/playwright/browser-agent.mjs.map +1 -0
  15. package/dist/es/playwright/index.mjs +4 -38
  16. package/dist/es/playwright/page-agent.mjs +24 -0
  17. package/dist/es/playwright/page-agent.mjs.map +1 -0
  18. package/dist/es/puppeteer/agent-launcher.mjs +20 -4
  19. package/dist/es/puppeteer/agent-launcher.mjs.map +1 -1
  20. package/dist/es/puppeteer/agent.mjs +2 -0
  21. package/dist/es/puppeteer/base-page.mjs +2 -22
  22. package/dist/es/puppeteer/base-page.mjs.map +1 -1
  23. package/dist/es/puppeteer/browser-agent.mjs +85 -0
  24. package/dist/es/puppeteer/browser-agent.mjs.map +1 -0
  25. package/dist/es/puppeteer/index.mjs +3 -37
  26. package/dist/es/puppeteer/page-agent.mjs +24 -0
  27. package/dist/es/puppeteer/page-agent.mjs.map +1 -0
  28. package/dist/es/web-page.mjs +5 -17
  29. package/dist/es/web-page.mjs.map +1 -1
  30. package/dist/lib/bridge-mode/io-client.js +1 -1
  31. package/dist/lib/bridge-mode/io-server.js +2 -2
  32. package/dist/lib/bridge-mode/page-browser-side.js +1 -1
  33. package/dist/lib/cli.js +1 -1
  34. package/dist/lib/common/browser-agent-utils.js +88 -0
  35. package/dist/lib/common/browser-agent-utils.js.map +1 -0
  36. package/dist/lib/common/browser-agent.js +180 -0
  37. package/dist/lib/common/browser-agent.js.map +1 -0
  38. package/dist/lib/index.js +12 -0
  39. package/dist/lib/playwright/agent.js +41 -0
  40. package/dist/lib/playwright/agent.js.map +1 -0
  41. package/dist/lib/playwright/ai-fixture.js +17 -3
  42. package/dist/lib/playwright/ai-fixture.js.map +1 -1
  43. package/dist/lib/playwright/browser-agent.js +118 -0
  44. package/dist/lib/playwright/browser-agent.js.map +1 -0
  45. package/dist/lib/playwright/index.js +10 -46
  46. package/dist/lib/playwright/index.js.map +1 -1
  47. package/dist/lib/playwright/page-agent.js +61 -0
  48. package/dist/lib/playwright/page-agent.js.map +1 -0
  49. package/dist/lib/puppeteer/agent-launcher.js +19 -3
  50. package/dist/lib/puppeteer/agent-launcher.js.map +1 -1
  51. package/dist/lib/puppeteer/agent.js +41 -0
  52. package/dist/lib/puppeteer/agent.js.map +1 -0
  53. package/dist/lib/puppeteer/base-page.js +2 -22
  54. package/dist/lib/puppeteer/base-page.js.map +1 -1
  55. package/dist/lib/puppeteer/browser-agent.js +119 -0
  56. package/dist/lib/puppeteer/browser-agent.js.map +1 -0
  57. package/dist/lib/puppeteer/index.js +10 -46
  58. package/dist/lib/puppeteer/index.js.map +1 -1
  59. package/dist/lib/puppeteer/page-agent.js +61 -0
  60. package/dist/lib/puppeteer/page-agent.js.map +1 -0
  61. package/dist/lib/web-page.js +5 -17
  62. package/dist/lib/web-page.js.map +1 -1
  63. package/dist/types/common/browser-agent-utils.d.ts +6 -0
  64. package/dist/types/common/browser-agent.d.ts +61 -0
  65. package/dist/types/index.d.ts +2 -2
  66. package/dist/types/playwright/agent.d.ts +1 -0
  67. package/dist/types/playwright/ai-fixture.d.ts +1 -0
  68. package/dist/types/playwright/browser-agent.d.ts +24 -0
  69. package/dist/types/playwright/index.d.ts +2 -8
  70. package/dist/types/playwright/page-agent.d.ts +8 -0
  71. package/dist/types/puppeteer/agent-launcher.d.ts +2 -2
  72. package/dist/types/puppeteer/agent.d.ts +1 -0
  73. package/dist/types/puppeteer/base-page.d.ts +0 -2
  74. package/dist/types/puppeteer/browser-agent.d.ts +24 -0
  75. package/dist/types/puppeteer/index.d.ts +2 -8
  76. package/dist/types/puppeteer/page-agent.d.ts +8 -0
  77. package/package.json +4 -4
  78. package/dist/es/playwright/index.mjs.map +0 -1
  79. package/dist/es/puppeteer/index.mjs.map +0 -1
@@ -23,7 +23,7 @@ class BridgeClient {
23
23
  ]
24
24
  } : {},
25
25
  query: {
26
- version: "1.10.4-beta-20260710032704.0"
26
+ version: "1.10.4-beta-20260710115744.0"
27
27
  }
28
28
  });
29
29
  const timeout = setTimeout(()=>{
@@ -102,7 +102,7 @@ class BridgeServer {
102
102
  logMsg('one client connected');
103
103
  this.socket = socket;
104
104
  const clientVersion = socket.handshake.query.version;
105
- logMsg(`Bridge connected, cli-side version v1.10.4-beta-20260710032704.0, browser-side version v${clientVersion}`);
105
+ logMsg(`Bridge connected, cli-side version v1.10.4-beta-20260710115744.0, browser-side version v${clientVersion}`);
106
106
  socket.on(BridgeEvent.CallResponse, (params)=>{
107
107
  const id = params.id;
108
108
  const response = params.response;
@@ -126,7 +126,7 @@ class BridgeServer {
126
126
  setTimeout(()=>{
127
127
  this.onConnect?.();
128
128
  const payload = {
129
- version: "1.10.4-beta-20260710032704.0"
129
+ version: "1.10.4-beta-20260710115744.0"
130
130
  };
131
131
  socket.emit(BridgeEvent.Connected, payload);
132
132
  Promise.resolve().then(()=>{
@@ -100,7 +100,7 @@ class ExtensionBridgePageBrowserSide extends page {
100
100
  throw new Error('Connection denied by user');
101
101
  }
102
102
  }
103
- this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.10.4-beta-20260710032704.0`, 'log');
103
+ this.onLogMessage(`Bridge connected, cli-side version v${this.bridgeClient.serverVersion}, browser-side version v1.10.4-beta-20260710115744.0`, 'log');
104
104
  }
105
105
  async connect() {
106
106
  return await this.setupBridgeClient();
package/dist/es/cli.mjs CHANGED
@@ -18,7 +18,7 @@ Promise.resolve().then(()=>{
18
18
  return runToolsCLI(tools, 'midscene-web', {
19
19
  stripPrefix: 'web_',
20
20
  argv: parsedOptions.argv,
21
- version: "1.10.4-beta-20260710032704.0",
21
+ version: "1.10.4-beta-20260710115744.0",
22
22
  extraCommands: createReportCliCommands()
23
23
  });
24
24
  }).catch((e)=>{
@@ -0,0 +1,41 @@
1
+ import { getWebpackRequire } from "../utils.mjs";
2
+ import semver from "semver";
3
+ import { BROWSER_NAVIGATION_ERROR_PATTERN, forceChromeSelectRendering } from "../puppeteer/base-page.mjs";
4
+ const browserRuntimeConfig = {
5
+ puppeteer: {
6
+ displayName: 'Puppeteer',
7
+ packageName: 'puppeteer',
8
+ minimumVersion: '24.6.0',
9
+ requirementLabel: '> 24.6.0'
10
+ },
11
+ playwright: {
12
+ displayName: 'Playwright',
13
+ packageName: 'playwright',
14
+ minimumVersion: '1.52.0',
15
+ requirementLabel: '>= 1.52.0'
16
+ }
17
+ };
18
+ function getPackageVersion(packageName) {
19
+ try {
20
+ const pkg = getWebpackRequire()(`${packageName}/package.json`);
21
+ return pkg.version || null;
22
+ } catch (error) {
23
+ console.error(`[midscene:error] Failed to get ${packageName} version`, error);
24
+ return null;
25
+ }
26
+ }
27
+ function isRetryableBrowserNavigationError(error) {
28
+ return error instanceof Error && BROWSER_NAVIGATION_ERROR_PATTERN.test(error.message);
29
+ }
30
+ function applyForceChromeSelectRendering(page, runtime, enabled) {
31
+ if (false === enabled) return;
32
+ const config = browserRuntimeConfig[runtime];
33
+ if (true === enabled) {
34
+ const version = getPackageVersion(config.packageName);
35
+ if (version && !semver.gte(version, config.minimumVersion)) console.warn(`[midscene:error] forceChromeSelectRendering requires ${config.displayName} ${config.requirementLabel}, but current version is ${version}. This feature may not work correctly.`);
36
+ }
37
+ forceChromeSelectRendering(page);
38
+ }
39
+ export { applyForceChromeSelectRendering, isRetryableBrowserNavigationError };
40
+
41
+ //# sourceMappingURL=browser-agent-utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common/browser-agent-utils.mjs","sources":["../../../src/common/browser-agent-utils.ts"],"sourcesContent":["import { getWebpackRequire } from '@/utils';\nimport type { Page as PlaywrightPage } from 'playwright';\nimport type { Page as PuppeteerPage } from 'puppeteer';\nimport semver from 'semver';\nimport {\n BROWSER_NAVIGATION_ERROR_PATTERN,\n forceChromeSelectRendering,\n} from '../puppeteer/base-page';\n\ntype BrowserRuntime = 'puppeteer' | 'playwright';\n\nconst browserRuntimeConfig: Record<\n BrowserRuntime,\n {\n displayName: string;\n packageName: string;\n minimumVersion: string;\n requirementLabel: string;\n }\n> = {\n puppeteer: {\n displayName: 'Puppeteer',\n packageName: 'puppeteer',\n minimumVersion: '24.6.0',\n requirementLabel: '> 24.6.0',\n },\n playwright: {\n displayName: 'Playwright',\n packageName: 'playwright',\n minimumVersion: '1.52.0',\n requirementLabel: '>= 1.52.0',\n },\n};\n\nfunction getPackageVersion(packageName: string): string | null {\n try {\n const pkg = getWebpackRequire()(`${packageName}/package.json`);\n return pkg.version || null;\n } catch (error) {\n console.error(\n `[midscene:error] Failed to get ${packageName} version`,\n error,\n );\n return null;\n }\n}\n\nexport function isRetryableBrowserNavigationError(error: unknown): boolean {\n return (\n error instanceof Error &&\n BROWSER_NAVIGATION_ERROR_PATTERN.test(error.message)\n );\n}\n\nexport function applyForceChromeSelectRendering(\n page: PuppeteerPage | PlaywrightPage,\n runtime: BrowserRuntime,\n enabled?: boolean,\n): void {\n if (enabled === false) {\n return;\n }\n\n const config = browserRuntimeConfig[runtime];\n if (enabled === true) {\n const version = getPackageVersion(config.packageName);\n if (version && !semver.gte(version, config.minimumVersion)) {\n console.warn(\n `[midscene:error] forceChromeSelectRendering requires ${config.displayName} ${config.requirementLabel}, but current version is ${version}. This feature may not work correctly.`,\n );\n }\n }\n forceChromeSelectRendering(page);\n}\n"],"names":["browserRuntimeConfig","getPackageVersion","packageName","pkg","getWebpackRequire","error","console","isRetryableBrowserNavigationError","Error","BROWSER_NAVIGATION_ERROR_PATTERN","applyForceChromeSelectRendering","page","runtime","enabled","config","version","semver","forceChromeSelectRendering"],"mappings":";;;AAWA,MAAMA,uBAQF;IACF,WAAW;QACT,aAAa;QACb,aAAa;QACb,gBAAgB;QAChB,kBAAkB;IACpB;IACA,YAAY;QACV,aAAa;QACb,aAAa;QACb,gBAAgB;QAChB,kBAAkB;IACpB;AACF;AAEA,SAASC,kBAAkBC,WAAmB;IAC5C,IAAI;QACF,MAAMC,MAAMC,oBAAoB,GAAGF,YAAY,aAAa,CAAC;QAC7D,OAAOC,IAAI,OAAO,IAAI;IACxB,EAAE,OAAOE,OAAO;QACdC,QAAQ,KAAK,CACX,CAAC,+BAA+B,EAAEJ,YAAY,QAAQ,CAAC,EACvDG;QAEF,OAAO;IACT;AACF;AAEO,SAASE,kCAAkCF,KAAc;IAC9D,OACEA,iBAAiBG,SACjBC,iCAAiC,IAAI,CAACJ,MAAM,OAAO;AAEvD;AAEO,SAASK,gCACdC,IAAoC,EACpCC,OAAuB,EACvBC,OAAiB;IAEjB,IAAIA,AAAY,UAAZA,SACF;IAGF,MAAMC,SAASd,oBAAoB,CAACY,QAAQ;IAC5C,IAAIC,AAAY,SAAZA,SAAkB;QACpB,MAAME,UAAUd,kBAAkBa,OAAO,WAAW;QACpD,IAAIC,WAAW,CAACC,OAAO,GAAG,CAACD,SAASD,OAAO,cAAc,GACvDR,QAAQ,IAAI,CACV,CAAC,qDAAqD,EAAEQ,OAAO,WAAW,CAAC,CAAC,EAAEA,OAAO,gBAAgB,CAAC,yBAAyB,EAAEC,QAAQ,sCAAsC,CAAC;IAGtL;IACAE,2BAA2BN;AAC7B"}
@@ -0,0 +1,140 @@
1
+ import { Agent } from "@midscene/core/agent";
2
+ import { isRetryableBrowserNavigationError } from "./browser-agent-utils.mjs";
3
+ function _define_property(obj, key, value) {
4
+ if (key in obj) Object.defineProperty(obj, key, {
5
+ value: value,
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true
9
+ });
10
+ else obj[key] = value;
11
+ return obj;
12
+ }
13
+ class WebAgentCore extends Agent {
14
+ isRetryableContextError(error) {
15
+ return isRetryableBrowserNavigationError(error);
16
+ }
17
+ }
18
+ const DEFAULT_NEW_PAGE_TIMEOUT = 5000;
19
+ function resolveBrowserAgentRuntimeOptions({ agentName, pageScope, forceSameTabNavigation, autoFollowNewPage, newPageTimeout = DEFAULT_NEW_PAGE_TIMEOUT }) {
20
+ if ('page' === pageScope) {
21
+ if (autoFollowNewPage) throw new Error(`[midscene] autoFollowNewPage requires browser mode for ${agentName}. Use BrowserAgent when one agent should follow newly opened pages.`);
22
+ return {
23
+ pageScope,
24
+ forceSameTabNavigation: forceSameTabNavigation ?? true,
25
+ autoFollowNewPage: false,
26
+ newPageTimeout
27
+ };
28
+ }
29
+ if (void 0 !== forceSameTabNavigation) throw new Error(`[midscene] forceSameTabNavigation cannot be used in browser mode for ${agentName}. Use PageAgent when same-tab navigation is required.`);
30
+ return {
31
+ pageScope,
32
+ forceSameTabNavigation: false,
33
+ autoFollowNewPage: autoFollowNewPage ?? false,
34
+ newPageTimeout
35
+ };
36
+ }
37
+ class BrowserPageManager {
38
+ get activePage() {
39
+ return this.getActivePageValue();
40
+ }
41
+ pages() {
42
+ return this.adapter.pages();
43
+ }
44
+ async newPage() {
45
+ const page = await this.adapter.newPage();
46
+ await this.setActivePage(page);
47
+ return page;
48
+ }
49
+ async setActivePage(page) {
50
+ if (!page || this.adapter.isPageClosed(page)) throw new Error(`[midscene] Cannot set ${this.agentName} active page to a closed or invalid page.`);
51
+ this.setActivePageValue(page);
52
+ try {
53
+ await this.adapter.bringToFront(page);
54
+ } catch (error) {
55
+ this.debug(`failed to bring page to front: ${error}`);
56
+ }
57
+ }
58
+ async waitForNewPage(action, opts) {
59
+ const waiter = this.createNewPageWaiter(opts?.timeout);
60
+ try {
61
+ await action?.();
62
+ return await waiter.promise;
63
+ } catch (error) {
64
+ waiter.dispose();
65
+ throw error;
66
+ }
67
+ }
68
+ destroy() {
69
+ this.adapter.offNewPage(this.newPageHandler);
70
+ }
71
+ async followNewPage(event) {
72
+ if (!this.isNewPageEvent(event)) return;
73
+ try {
74
+ const page = await this.adapter.resolveNewPage(event);
75
+ if (page) await this.setActivePage(page);
76
+ } catch (error) {
77
+ this.debug(`failed to follow new page: ${error}`);
78
+ }
79
+ }
80
+ isNewPageEvent(event) {
81
+ return this.adapter.isNewPageEvent?.(event) ?? true;
82
+ }
83
+ createNewPageWaiter(timeout = this.newPageTimeout) {
84
+ let settled = false;
85
+ const dispose = ()=>{
86
+ this.adapter.offNewPage(handler);
87
+ clearTimeout(timer);
88
+ };
89
+ const handler = async (event)=>{
90
+ if (settled || !this.isNewPageEvent(event)) return;
91
+ settled = true;
92
+ dispose();
93
+ try {
94
+ const page = await this.adapter.resolveNewPage(event);
95
+ if (!page) throw new Error('new target did not resolve to a page');
96
+ resolvePage(page);
97
+ } catch (error) {
98
+ rejectPage(error);
99
+ }
100
+ };
101
+ let resolvePage;
102
+ let rejectPage;
103
+ const promise = new Promise((resolve, reject)=>{
104
+ resolvePage = resolve;
105
+ rejectPage = reject;
106
+ });
107
+ const timer = setTimeout(()=>{
108
+ if (settled) return;
109
+ settled = true;
110
+ dispose();
111
+ rejectPage(new Error(`[midscene] Timed out waiting for a new ${this.agentName} page after ${timeout}ms.`));
112
+ }, timeout);
113
+ this.adapter.onNewPage(handler);
114
+ return {
115
+ promise,
116
+ dispose
117
+ };
118
+ }
119
+ constructor(options){
120
+ _define_property(this, "agentName", void 0);
121
+ _define_property(this, "adapter", void 0);
122
+ _define_property(this, "getActivePageValue", void 0);
123
+ _define_property(this, "setActivePageValue", void 0);
124
+ _define_property(this, "newPageTimeout", void 0);
125
+ _define_property(this, "debug", void 0);
126
+ _define_property(this, "newPageHandler", (event)=>{
127
+ this.followNewPage(event);
128
+ });
129
+ this.agentName = options.agentName;
130
+ this.adapter = options.adapter;
131
+ this.getActivePageValue = options.getActivePage;
132
+ this.setActivePageValue = options.setActivePageValue;
133
+ this.newPageTimeout = options.newPageTimeout;
134
+ this.debug = options.debug;
135
+ if (options.autoFollowNewPage) this.adapter.onNewPage(this.newPageHandler);
136
+ }
137
+ }
138
+ export { BrowserPageManager, WebAgentCore, resolveBrowserAgentRuntimeOptions };
139
+
140
+ //# sourceMappingURL=browser-agent.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common/browser-agent.mjs","sources":["../../../src/common/browser-agent.ts"],"sourcesContent":["import { Agent as CoreAgent } from '@midscene/core/agent';\nimport type { AbstractInterface } from '@midscene/core/device';\nimport type { DebugFunction } from '@midscene/shared/logger';\nimport { isRetryableBrowserNavigationError } from './browser-agent-utils';\n\nexport type BrowserAgentPageScope = 'page' | 'browser';\n\nexport type BrowserAgentAdapter<Page, NewPageEvent> = {\n pages(): Page[] | Promise<Page[]>;\n newPage(): Promise<Page>;\n isPageClosed(page: Page): boolean;\n bringToFront(page: Page): Promise<void> | void;\n onNewPage(handler: (event: NewPageEvent) => void): void;\n offNewPage(handler: (event: NewPageEvent) => void): void;\n resolveNewPage(event: NewPageEvent): Page | Promise<Page | null> | null;\n isNewPageEvent?: (event: NewPageEvent) => boolean;\n};\n\nexport type BrowserPageManagerOptions<Page, NewPageEvent> = {\n agentName: string;\n adapter: BrowserAgentAdapter<Page, NewPageEvent>;\n getActivePage(): Page;\n setActivePageValue(page: Page): void;\n autoFollowNewPage: boolean;\n newPageTimeout: number;\n debug: DebugFunction;\n};\n\nexport type BrowserAgentRuntimeOptions = {\n agentName: string;\n pageScope: BrowserAgentPageScope;\n forceSameTabNavigation?: boolean;\n autoFollowNewPage?: boolean;\n newPageTimeout?: number;\n};\n\nexport type ResolvedBrowserAgentRuntimeOptions = {\n pageScope: BrowserAgentPageScope;\n forceSameTabNavigation: boolean;\n autoFollowNewPage: boolean;\n newPageTimeout: number;\n};\n\nexport abstract class WebAgentCore<\n InterfaceType extends AbstractInterface,\n> extends CoreAgent<InterfaceType> {\n protected isRetryableContextError(error: unknown): boolean {\n return isRetryableBrowserNavigationError(error);\n }\n}\n\nconst DEFAULT_NEW_PAGE_TIMEOUT = 5000;\n\nexport function resolveBrowserAgentRuntimeOptions({\n agentName,\n pageScope,\n forceSameTabNavigation,\n autoFollowNewPage,\n newPageTimeout = DEFAULT_NEW_PAGE_TIMEOUT,\n}: BrowserAgentRuntimeOptions): ResolvedBrowserAgentRuntimeOptions {\n if (pageScope === 'page') {\n if (autoFollowNewPage) {\n throw new Error(\n `[midscene] autoFollowNewPage requires browser mode for ${agentName}. Use BrowserAgent when one agent should follow newly opened pages.`,\n );\n }\n\n return {\n pageScope,\n forceSameTabNavigation: forceSameTabNavigation ?? true,\n autoFollowNewPage: false,\n newPageTimeout,\n };\n }\n\n if (typeof forceSameTabNavigation !== 'undefined') {\n throw new Error(\n `[midscene] forceSameTabNavigation cannot be used in browser mode for ${agentName}. Use PageAgent when same-tab navigation is required.`,\n );\n }\n\n return {\n pageScope,\n forceSameTabNavigation: false,\n autoFollowNewPage: autoFollowNewPage ?? false,\n newPageTimeout,\n };\n}\n\nexport class BrowserPageManager<Page, NewPageEvent> {\n private readonly agentName: string;\n private readonly adapter: BrowserAgentAdapter<Page, NewPageEvent>;\n private readonly getActivePageValue: () => Page;\n private readonly setActivePageValue: (page: Page) => void;\n private readonly newPageTimeout: number;\n private readonly debug: DebugFunction;\n\n private readonly newPageHandler = (event: NewPageEvent) => {\n void this.followNewPage(event);\n };\n\n constructor(options: BrowserPageManagerOptions<Page, NewPageEvent>) {\n this.agentName = options.agentName;\n this.adapter = options.adapter;\n this.getActivePageValue = options.getActivePage;\n this.setActivePageValue = options.setActivePageValue;\n this.newPageTimeout = options.newPageTimeout;\n this.debug = options.debug;\n\n if (options.autoFollowNewPage) {\n this.adapter.onNewPage(this.newPageHandler);\n }\n }\n\n get activePage() {\n return this.getActivePageValue();\n }\n\n pages() {\n return this.adapter.pages();\n }\n\n async newPage() {\n const page = await this.adapter.newPage();\n await this.setActivePage(page);\n return page;\n }\n\n async setActivePage(page: Page) {\n if (!page || this.adapter.isPageClosed(page)) {\n throw new Error(\n `[midscene] Cannot set ${this.agentName} active page to a closed or invalid page.`,\n );\n }\n\n this.setActivePageValue(page);\n try {\n await this.adapter.bringToFront(page);\n } catch (error) {\n this.debug(`failed to bring page to front: ${error}`);\n }\n }\n\n async waitForNewPage(\n action?: () => Promise<unknown> | unknown,\n opts?: { timeout?: number },\n ) {\n const waiter = this.createNewPageWaiter(opts?.timeout);\n\n try {\n await action?.();\n return await waiter.promise;\n } catch (error) {\n waiter.dispose();\n throw error;\n }\n }\n\n destroy() {\n this.adapter.offNewPage(this.newPageHandler);\n }\n\n private async followNewPage(event: NewPageEvent) {\n if (!this.isNewPageEvent(event)) {\n return;\n }\n\n try {\n const page = await this.adapter.resolveNewPage(event);\n if (page) {\n await this.setActivePage(page);\n }\n } catch (error) {\n this.debug(`failed to follow new page: ${error}`);\n }\n }\n\n private isNewPageEvent(event: NewPageEvent) {\n return this.adapter.isNewPageEvent?.(event) ?? true;\n }\n\n private createNewPageWaiter(timeout = this.newPageTimeout) {\n let settled = false;\n\n const dispose = () => {\n this.adapter.offNewPage(handler);\n clearTimeout(timer);\n };\n\n const handler = async (event: NewPageEvent) => {\n if (settled || !this.isNewPageEvent(event)) {\n return;\n }\n\n settled = true;\n dispose();\n\n try {\n const page = await this.adapter.resolveNewPage(event);\n if (!page) {\n throw new Error('new target did not resolve to a page');\n }\n resolvePage(page);\n } catch (error) {\n rejectPage(error);\n }\n };\n\n let resolvePage!: (page: Page) => void;\n let rejectPage!: (error: unknown) => void;\n const promise = new Promise<Page>((resolve, reject) => {\n resolvePage = resolve;\n rejectPage = reject;\n });\n\n const timer = setTimeout(() => {\n if (settled) {\n return;\n }\n settled = true;\n dispose();\n rejectPage(\n new Error(\n `[midscene] Timed out waiting for a new ${this.agentName} page after ${timeout}ms.`,\n ),\n );\n }, timeout);\n\n this.adapter.onNewPage(handler);\n\n return { promise, dispose };\n }\n}\n"],"names":["WebAgentCore","CoreAgent","error","isRetryableBrowserNavigationError","DEFAULT_NEW_PAGE_TIMEOUT","resolveBrowserAgentRuntimeOptions","agentName","pageScope","forceSameTabNavigation","autoFollowNewPage","newPageTimeout","Error","BrowserPageManager","page","action","opts","waiter","event","timeout","settled","dispose","handler","clearTimeout","timer","resolvePage","rejectPage","promise","Promise","resolve","reject","setTimeout","options"],"mappings":"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"}
package/dist/es/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { PlaywrightAgent, PlaywrightAiFixture } from "./playwright/index.mjs";
1
+ import { PlaywrightAgent, PlaywrightAiFixture, PlaywrightBrowserAgent, PlaywrightPageAgent } from "./playwright/index.mjs";
2
2
  import { Agent } from "@midscene/core/agent";
3
- import { PuppeteerAgent } from "./puppeteer/index.mjs";
3
+ import { PuppeteerAgent, PuppeteerBrowserAgent, PuppeteerPageAgent } from "./puppeteer/index.mjs";
4
4
  import { StaticPage, StaticPageAgent } from "./static/index.mjs";
5
5
  import { WebMidsceneTools } from "./agent-tools.mjs";
6
6
  import { webPlaygroundPlatform } from "./platform.mjs";
7
7
  import { WebCdpMidsceneTools } from "./agent-tools-cdp.mjs";
8
- export { Agent as PageAgent, PlaywrightAgent, PlaywrightAiFixture, PuppeteerAgent, StaticPage, StaticPageAgent, WebCdpMidsceneTools, WebMidsceneTools, webPlaygroundPlatform };
8
+ export { Agent as PageAgent, PlaywrightAgent, PlaywrightAiFixture, PlaywrightBrowserAgent, PlaywrightPageAgent, PuppeteerAgent, PuppeteerBrowserAgent, PuppeteerPageAgent, StaticPage, StaticPageAgent, WebCdpMidsceneTools, WebMidsceneTools, webPlaygroundPlatform };
@@ -0,0 +1,2 @@
1
+ import { PlaywrightPageAgent } from "./page-agent.mjs";
2
+ export { PlaywrightPageAgent as PlaywrightAgent, PlaywrightPageAgent };
@@ -1,4 +1,5 @@
1
- import { PlaywrightAgent } from "./index.mjs";
1
+ import { resolveBrowserAgentRuntimeOptions } from "../common/browser-agent.mjs";
2
+ import { PlaywrightAgent, PlaywrightBrowserAgent } from "./index.mjs";
2
3
  import { processCacheConfig } from "@midscene/core/utils";
3
4
  import { DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT } from "@midscene/shared/constants";
4
5
  import { getDebug } from "@midscene/shared/logger";
@@ -31,7 +32,7 @@ const groupAndCaseForTest = (testInfo)=>{
31
32
  const midsceneAgentKeyId = '_midsceneAgentId';
32
33
  const midsceneDumpAnnotationId = 'MIDSCENE_DUMP_ANNOTATION';
33
34
  const PlaywrightAiFixture = (options)=>{
34
- const { forceSameTabNavigation = true, waitForNetworkIdleTimeout = DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, waitForNavigationTimeout = DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, cache, ...sharedAgentOptions } = options ?? {};
35
+ const { forceSameTabNavigation = true, autoFollowNewPage = false, waitForNetworkIdleTimeout = DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT, waitForNavigationTimeout = DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT, cache, ...sharedAgentOptions } = options ?? {};
35
36
  const processTestCacheConfig = (testInfo)=>{
36
37
  const { id } = groupAndCaseForTest(testInfo);
37
38
  return processCacheConfig(cache, id);
@@ -70,16 +71,29 @@ const PlaywrightAiFixture = (options)=>{
70
71
  const { file, title } = groupAndCaseForTest(testInfo);
71
72
  const cacheConfig = processTestCacheConfig(testInfo);
72
73
  const reportTag = `playwright-${title.replace(/[\\/]/g, '-')}-${idForPage}`;
73
- const agent = new PlaywrightAgent(page, {
74
+ if (autoFollowNewPage && true === forceSameTabNavigation) throw new Error('[midscene] autoFollowNewPage cannot be used with forceSameTabNavigation: true.');
75
+ const runtimeOptions = resolveBrowserAgentRuntimeOptions({
76
+ agentName: 'PlaywrightAiFixture',
77
+ pageScope: autoFollowNewPage ? 'browser' : 'page',
78
+ forceSameTabNavigation: autoFollowNewPage ? void 0 : forceSameTabNavigation,
79
+ autoFollowNewPage
80
+ });
81
+ const commonAgentOpts = {
74
82
  testId: reportTag,
75
83
  reportFileName: reportTag,
76
- forceSameTabNavigation,
77
84
  cache: cacheConfig,
78
85
  groupName: title,
79
86
  groupDescription: file,
80
87
  generateReport: true,
81
88
  ...sharedAgentOptions,
82
89
  ...opts
90
+ };
91
+ const agent = autoFollowNewPage ? new PlaywrightBrowserAgent(page.context(), page, {
92
+ ...commonAgentOpts,
93
+ autoFollowNewPage: runtimeOptions.autoFollowNewPage
94
+ }) : new PlaywrightAgent(page, {
95
+ ...commonAgentOpts,
96
+ forceSameTabNavigation: runtimeOptions.forceSameTabNavigation
83
97
  });
84
98
  pageAgentMap[idForPage] = agent;
85
99
  const records = getAgentRecordsForTest(testInfo);
@@ -1 +1 @@
1
- {"version":3,"file":"playwright/ai-fixture.mjs","sources":["../../../src/playwright/ai-fixture.ts"],"sourcesContent":["import { PlaywrightAgent, type PlaywrightWebPage } from '@/playwright/index';\nimport type { WebPageAgentOpt } from '@/web-element';\nimport type { Cache } from '@midscene/core';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport { processCacheConfig } from '@midscene/core/utils';\nimport {\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n} from '@midscene/shared/constants';\nimport { getDebug } from '@midscene/shared/logger';\nimport { uuid } from '@midscene/shared/utils';\nimport { replaceIllegalPathCharsAndSpace } from '@midscene/shared/utils';\nimport { type TestInfo, type TestType, test } from '@playwright/test';\nimport type { Page as OriginPlaywrightPage } from 'playwright';\nexport type APITestType = Pick<TestType<any, any>, 'step'>;\n\nconst debugPage = getDebug('web:playwright:ai-fixture');\n\nconst groupAndCaseForTest = (testInfo: TestInfo) => {\n let taskFile: string;\n let taskTitle: string;\n const titlePath = [...testInfo.titlePath];\n\n if (titlePath.length > 1) {\n taskFile = titlePath.shift() || 'unnamed';\n taskTitle = titlePath.join('__');\n } else if (titlePath.length === 1) {\n taskTitle = titlePath[0];\n taskFile = `${taskTitle}`;\n } else {\n taskTitle = 'unnamed';\n taskFile = 'unnamed';\n }\n\n const taskTitleWithRetry = `${taskTitle}${testInfo.retry ? `(retry #${testInfo.retry})` : ''}`;\n\n return {\n file: taskFile,\n id: replaceIllegalPathCharsAndSpace(`${taskFile}(${taskTitle})`),\n title: replaceIllegalPathCharsAndSpace(taskTitleWithRetry),\n };\n};\n\nconst midsceneAgentKeyId = '_midsceneAgentId';\nexport const midsceneDumpAnnotationId = 'MIDSCENE_DUMP_ANNOTATION';\n\ntype AgentRecord = {\n agent: PageAgent<PlaywrightWebPage>;\n finalizePromise?: Promise<string | undefined>;\n finalReportPath?: string;\n};\n\ntype PlaywrightCacheConfig = {\n strategy?: 'read-only' | 'read-write' | 'write-only';\n id?: string;\n};\ntype PlaywrightCache = false | true | PlaywrightCacheConfig;\n\nexport type PlaywrightAiFixtureOptions = Omit<\n WebPageAgentOpt,\n | 'testId'\n | 'cacheId'\n | 'groupName'\n | 'groupDescription'\n | 'reportFileName'\n | 'cache'\n> & {\n cache?: PlaywrightCache;\n};\n\nexport const PlaywrightAiFixture = (options?: PlaywrightAiFixtureOptions) => {\n const {\n forceSameTabNavigation = true,\n waitForNetworkIdleTimeout = DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n waitForNavigationTimeout = DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n cache,\n ...sharedAgentOptions\n } = options ?? {};\n\n // Helper function to process cache configuration and auto-generate ID from test info\n const processTestCacheConfig = (testInfo: TestInfo): Cache | undefined => {\n // Generate ID from test info\n const { id } = groupAndCaseForTest(testInfo);\n\n // Use shared processCacheConfig with generated ID as fallback\n return processCacheConfig(cache as Cache, id);\n };\n\n const pageAgentMap: Record<string, PageAgent<PlaywrightWebPage>> = {};\n const testAgentRecords = new Map<string, Map<string, AgentRecord>>();\n\n const getAgentRecordsForTest = (testInfo: TestInfo) => {\n let records = testAgentRecords.get(testInfo.testId);\n if (!records) {\n records = new Map<string, AgentRecord>();\n testAgentRecords.set(testInfo.testId, records);\n }\n return records;\n };\n\n const setReportAnnotation = (testInfo: TestInfo, reportPaths: string[]) => {\n testInfo.annotations = testInfo.annotations.filter((item) => {\n return item.type !== midsceneDumpAnnotationId;\n });\n\n for (const reportPath of reportPaths) {\n testInfo.annotations.push({\n type: midsceneDumpAnnotationId,\n description: reportPath,\n });\n }\n };\n\n const finalizeAgentRecord = async (\n record: AgentRecord,\n ): Promise<string | undefined> => {\n if (!record.finalizePromise) {\n record.finalizePromise = (async () => {\n await record.agent.destroy();\n const reportPath = record.agent.reportFile || undefined;\n record.finalReportPath = reportPath;\n return reportPath;\n })();\n }\n\n return await record.finalizePromise;\n };\n\n const createOrReuseAgentForPage = (\n page: OriginPlaywrightPage,\n testInfo: TestInfo, // { testId: string; taskFile: string; taskTitle: string },\n opts?: WebPageAgentOpt,\n ) => {\n let idForPage = (page as any)[midsceneAgentKeyId];\n if (!idForPage) {\n idForPage = uuid();\n (page as any)[midsceneAgentKeyId] = idForPage;\n const { file, title } = groupAndCaseForTest(testInfo);\n const cacheConfig = processTestCacheConfig(testInfo);\n // `replaceIllegalPathCharsAndSpace` intentionally preserves `/` and `\\`\n // so groupName/groupDescription can still carry hierarchy. But\n // ReportGenerator rejects path separators in the file name, so strip\n // them here for the report tag only.\n const reportTag = `playwright-${title.replace(/[\\\\/]/g, '-')}-${idForPage}`;\n\n const agent = new PlaywrightAgent(page, {\n testId: reportTag,\n reportFileName: reportTag,\n forceSameTabNavigation,\n cache: cacheConfig,\n groupName: title,\n groupDescription: file,\n generateReport: true,\n ...sharedAgentOptions,\n ...opts,\n });\n pageAgentMap[idForPage] = agent;\n const records = getAgentRecordsForTest(testInfo);\n const record: AgentRecord = { agent };\n records.set(idForPage, record);\n\n page.on('close', async () => {\n debugPage('page closed');\n try {\n await finalizeAgentRecord(record);\n } finally {\n delete pageAgentMap[idForPage];\n }\n });\n }\n\n return pageAgentMap[idForPage];\n };\n\n async function generateAiFunction(options: {\n page: OriginPlaywrightPage;\n testInfo: TestInfo;\n use: any;\n aiActionType:\n | 'ai'\n | 'aiAct'\n | 'aiAction'\n | 'aiHover'\n | 'aiInput'\n | 'aiKeyboardPress'\n | 'aiScroll'\n | 'aiTap'\n | 'aiRightClick'\n | 'aiDoubleClick'\n | 'aiQuery'\n | 'aiAssert'\n | 'aiWaitFor'\n | 'aiLocate'\n | 'aiNumber'\n | 'aiString'\n | 'aiBoolean'\n | 'aiAsk'\n | 'runYaml'\n | 'setAIActionContext'\n | 'evaluateJavaScript'\n | 'recordToReport'\n | 'logScreenshot'\n | 'freezePageContext'\n | 'unfreezePageContext';\n }) {\n const { page, testInfo, use, aiActionType } = options;\n const agent = createOrReuseAgentForPage(page, testInfo, {\n waitForNavigationTimeout,\n waitForNetworkIdleTimeout,\n }) as PlaywrightAgent;\n\n await use(async (taskPrompt: unknown, ...args: any[]) => {\n return new Promise((resolve, reject) => {\n test.step(`ai-${aiActionType} - ${JSON.stringify(taskPrompt)}`, async () => {\n try {\n type AgentMethod = (...methodArgs: any[]) => Promise<any>;\n const result = await (agent[aiActionType] as AgentMethod).bind(\n agent,\n )(taskPrompt, ...args);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n });\n });\n });\n }\n\n return {\n _midsceneFinalizeReports: [\n // biome-ignore lint/correctness/noEmptyPattern: Playwright fixture callbacks must use object destructuring for the first parameter even when no fixtures are consumed.\n async ({}: Record<string, unknown>, use: any, testInfo: TestInfo) => {\n await use();\n\n const records = testAgentRecords.get(testInfo.testId);\n if (!records || records.size === 0) {\n return;\n }\n\n const reportPaths = (\n await Promise.all(\n Array.from(records.values()).map((record) =>\n finalizeAgentRecord(record),\n ),\n )\n ).filter((reportPath): reportPath is string => Boolean(reportPath));\n\n if (reportPaths.length > 0) {\n setReportAnnotation(testInfo, reportPaths);\n }\n\n testAgentRecords.delete(testInfo.testId);\n },\n { auto: true },\n ],\n agentForPage: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await use(\n async (\n propsPage?: OriginPlaywrightPage | undefined,\n opts?: WebPageAgentOpt,\n ) => {\n const cacheConfig = processTestCacheConfig(testInfo);\n\n // Handle cache configuration priority:\n // 1. If user provides cache in opts, use it (but auto-generate ID if missing)\n // 2. Otherwise use fixture's cache config\n let finalCacheConfig = cacheConfig;\n if (opts?.cache !== undefined) {\n const userCache = opts.cache;\n if (userCache === false) {\n finalCacheConfig = false;\n } else if (userCache === true) {\n // Auto-generate ID for user's cache: true\n const { id } = groupAndCaseForTest(testInfo);\n finalCacheConfig = { id };\n } else if (typeof userCache === 'object') {\n if (!userCache.id) {\n // Auto-generate ID for user's cache object without ID\n const { id } = groupAndCaseForTest(testInfo);\n finalCacheConfig = { ...userCache, id };\n } else {\n finalCacheConfig = userCache;\n }\n }\n }\n\n const agent = createOrReuseAgentForPage(propsPage || page, testInfo, {\n waitForNavigationTimeout,\n waitForNetworkIdleTimeout,\n cache: finalCacheConfig,\n ...opts,\n });\n return agent;\n },\n );\n },\n ai: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'ai',\n });\n },\n aiAct: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAct',\n });\n },\n /**\n * @deprecated Use {@link PlaywrightAiFixture.aiAct} instead.\n */\n aiAction: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAction',\n });\n },\n aiTap: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiTap',\n });\n },\n aiRightClick: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiRightClick',\n });\n },\n aiDoubleClick: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiDoubleClick',\n });\n },\n aiHover: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiHover',\n });\n },\n aiInput: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiInput',\n });\n },\n aiKeyboardPress: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiKeyboardPress',\n });\n },\n aiScroll: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiScroll',\n });\n },\n aiQuery: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiQuery',\n });\n },\n aiAssert: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAssert',\n });\n },\n aiWaitFor: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiWaitFor',\n });\n },\n aiLocate: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiLocate',\n });\n },\n aiNumber: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiNumber',\n });\n },\n aiString: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiString',\n });\n },\n aiBoolean: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiBoolean',\n });\n },\n aiAsk: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAsk',\n });\n },\n runYaml: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'runYaml',\n });\n },\n setAIActionContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'setAIActionContext',\n });\n },\n evaluateJavaScript: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'evaluateJavaScript',\n });\n },\n recordToReport: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'recordToReport',\n });\n },\n logScreenshot: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'logScreenshot',\n });\n },\n freezePageContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'freezePageContext',\n });\n },\n unfreezePageContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'unfreezePageContext',\n });\n },\n };\n};\n\nexport type PlayWrightAiFixtureType = {\n agentForPage: (\n page?: OriginPlaywrightPage,\n opts?: WebPageAgentOpt,\n ) => Promise<PageAgent<PlaywrightWebPage>>;\n ai: <T = any>(...args: Parameters<PageAgent['ai']>) => Promise<T>;\n aiAct: (\n ...args: Parameters<PageAgent['aiAct']>\n ) => ReturnType<PageAgent['aiAct']>;\n /**\n * @deprecated Use {@link PlayWrightAiFixtureType.aiAct} instead.\n */\n aiAction: (\n ...args: Parameters<PageAgent['aiAction']>\n ) => ReturnType<PageAgent['aiAction']>;\n aiTap: (\n ...args: Parameters<PageAgent['aiTap']>\n ) => ReturnType<PageAgent['aiTap']>;\n aiRightClick: (\n ...args: Parameters<PageAgent['aiRightClick']>\n ) => ReturnType<PageAgent['aiRightClick']>;\n aiDoubleClick: (\n ...args: Parameters<PageAgent['aiDoubleClick']>\n ) => ReturnType<PageAgent['aiDoubleClick']>;\n aiHover: (\n ...args: Parameters<PageAgent['aiHover']>\n ) => ReturnType<PageAgent['aiHover']>;\n aiInput: (\n ...args: Parameters<PageAgent['aiInput']>\n ) => ReturnType<PageAgent['aiInput']>;\n aiKeyboardPress: (\n ...args: Parameters<PageAgent['aiKeyboardPress']>\n ) => ReturnType<PageAgent['aiKeyboardPress']>;\n aiScroll: (\n ...args: Parameters<PageAgent['aiScroll']>\n ) => ReturnType<PageAgent['aiScroll']>;\n aiQuery: <T = any>(...args: Parameters<PageAgent['aiQuery']>) => Promise<T>;\n aiAssert: (\n ...args: Parameters<PageAgent['aiAssert']>\n ) => ReturnType<PageAgent['aiAssert']>;\n aiWaitFor: (...args: Parameters<PageAgent['aiWaitFor']>) => Promise<void>;\n aiLocate: (\n ...args: Parameters<PageAgent['aiLocate']>\n ) => ReturnType<PageAgent['aiLocate']>;\n aiNumber: (\n ...args: Parameters<PageAgent['aiNumber']>\n ) => ReturnType<PageAgent['aiNumber']>;\n aiString: (\n ...args: Parameters<PageAgent['aiString']>\n ) => ReturnType<PageAgent['aiString']>;\n aiBoolean: (\n ...args: Parameters<PageAgent['aiBoolean']>\n ) => ReturnType<PageAgent['aiBoolean']>;\n aiAsk: (\n ...args: Parameters<PageAgent['aiAsk']>\n ) => ReturnType<PageAgent['aiAsk']>;\n runYaml: (\n ...args: Parameters<PageAgent['runYaml']>\n ) => ReturnType<PageAgent['runYaml']>;\n setAIActionContext: (\n ...args: Parameters<PageAgent['setAIActionContext']>\n ) => ReturnType<PageAgent['setAIActionContext']>;\n evaluateJavaScript: (\n ...args: Parameters<PageAgent['evaluateJavaScript']>\n ) => ReturnType<PageAgent['evaluateJavaScript']>;\n recordToReport: (\n ...args: Parameters<PageAgent['recordToReport']>\n ) => ReturnType<PageAgent['recordToReport']>;\n logScreenshot: (\n ...args: Parameters<PageAgent['logScreenshot']>\n ) => ReturnType<PageAgent['logScreenshot']>;\n freezePageContext: (\n ...args: Parameters<PageAgent['freezePageContext']>\n ) => ReturnType<PageAgent['freezePageContext']>;\n unfreezePageContext: (\n ...args: Parameters<PageAgent['unfreezePageContext']>\n ) => ReturnType<PageAgent['unfreezePageContext']>;\n};\n"],"names":["debugPage","getDebug","groupAndCaseForTest","testInfo","taskFile","taskTitle","titlePath","taskTitleWithRetry","replaceIllegalPathCharsAndSpace","midsceneAgentKeyId","midsceneDumpAnnotationId","PlaywrightAiFixture","options","forceSameTabNavigation","waitForNetworkIdleTimeout","DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT","waitForNavigationTimeout","DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT","cache","sharedAgentOptions","processTestCacheConfig","id","processCacheConfig","pageAgentMap","testAgentRecords","Map","getAgentRecordsForTest","records","setReportAnnotation","reportPaths","item","reportPath","finalizeAgentRecord","record","undefined","createOrReuseAgentForPage","page","opts","idForPage","uuid","file","title","cacheConfig","reportTag","agent","PlaywrightAgent","generateAiFunction","use","aiActionType","taskPrompt","args","Promise","resolve","reject","test","JSON","result","error","Array","Boolean","propsPage","finalCacheConfig","userCache"],"mappings":"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"}
1
+ {"version":3,"file":"playwright/ai-fixture.mjs","sources":["../../../src/playwright/ai-fixture.ts"],"sourcesContent":["import { resolveBrowserAgentRuntimeOptions } from '@/common/browser-agent';\nimport {\n PlaywrightAgent,\n PlaywrightBrowserAgent,\n type PlaywrightWebPage,\n} from '@/playwright/index';\nimport type { WebPageAgentOpt } from '@/web-element';\nimport type { Cache } from '@midscene/core';\nimport type { Agent as PageAgent } from '@midscene/core/agent';\nimport { processCacheConfig } from '@midscene/core/utils';\nimport {\n DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n} from '@midscene/shared/constants';\nimport { getDebug } from '@midscene/shared/logger';\nimport { uuid } from '@midscene/shared/utils';\nimport { replaceIllegalPathCharsAndSpace } from '@midscene/shared/utils';\nimport { type TestInfo, type TestType, test } from '@playwright/test';\nimport type { Page as OriginPlaywrightPage } from 'playwright';\nexport type APITestType = Pick<TestType<any, any>, 'step'>;\n\nconst debugPage = getDebug('web:playwright:ai-fixture');\n\nconst groupAndCaseForTest = (testInfo: TestInfo) => {\n let taskFile: string;\n let taskTitle: string;\n const titlePath = [...testInfo.titlePath];\n\n if (titlePath.length > 1) {\n taskFile = titlePath.shift() || 'unnamed';\n taskTitle = titlePath.join('__');\n } else if (titlePath.length === 1) {\n taskTitle = titlePath[0];\n taskFile = `${taskTitle}`;\n } else {\n taskTitle = 'unnamed';\n taskFile = 'unnamed';\n }\n\n const taskTitleWithRetry = `${taskTitle}${testInfo.retry ? `(retry #${testInfo.retry})` : ''}`;\n\n return {\n file: taskFile,\n id: replaceIllegalPathCharsAndSpace(`${taskFile}(${taskTitle})`),\n title: replaceIllegalPathCharsAndSpace(taskTitleWithRetry),\n };\n};\n\nconst midsceneAgentKeyId = '_midsceneAgentId';\nexport const midsceneDumpAnnotationId = 'MIDSCENE_DUMP_ANNOTATION';\n\ntype AgentRecord = {\n agent: PageAgent<PlaywrightWebPage>;\n finalizePromise?: Promise<string | undefined>;\n finalReportPath?: string;\n};\n\ntype PlaywrightCacheConfig = {\n strategy?: 'read-only' | 'read-write' | 'write-only';\n id?: string;\n};\ntype PlaywrightCache = false | true | PlaywrightCacheConfig;\n\nexport type PlaywrightAiFixtureOptions = Omit<\n WebPageAgentOpt,\n | 'testId'\n | 'cacheId'\n | 'groupName'\n | 'groupDescription'\n | 'reportFileName'\n | 'cache'\n> & {\n autoFollowNewPage?: boolean;\n cache?: PlaywrightCache;\n};\n\nexport const PlaywrightAiFixture = (options?: PlaywrightAiFixtureOptions) => {\n const {\n forceSameTabNavigation = true,\n autoFollowNewPage = false,\n waitForNetworkIdleTimeout = DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT,\n waitForNavigationTimeout = DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT,\n cache,\n ...sharedAgentOptions\n } = options ?? {};\n\n // Helper function to process cache configuration and auto-generate ID from test info\n const processTestCacheConfig = (testInfo: TestInfo): Cache | undefined => {\n // Generate ID from test info\n const { id } = groupAndCaseForTest(testInfo);\n\n // Use shared processCacheConfig with generated ID as fallback\n return processCacheConfig(cache as Cache, id);\n };\n\n const pageAgentMap: Record<string, PageAgent<PlaywrightWebPage>> = {};\n const testAgentRecords = new Map<string, Map<string, AgentRecord>>();\n\n const getAgentRecordsForTest = (testInfo: TestInfo) => {\n let records = testAgentRecords.get(testInfo.testId);\n if (!records) {\n records = new Map<string, AgentRecord>();\n testAgentRecords.set(testInfo.testId, records);\n }\n return records;\n };\n\n const setReportAnnotation = (testInfo: TestInfo, reportPaths: string[]) => {\n testInfo.annotations = testInfo.annotations.filter((item) => {\n return item.type !== midsceneDumpAnnotationId;\n });\n\n for (const reportPath of reportPaths) {\n testInfo.annotations.push({\n type: midsceneDumpAnnotationId,\n description: reportPath,\n });\n }\n };\n\n const finalizeAgentRecord = async (\n record: AgentRecord,\n ): Promise<string | undefined> => {\n if (!record.finalizePromise) {\n record.finalizePromise = (async () => {\n await record.agent.destroy();\n const reportPath = record.agent.reportFile || undefined;\n record.finalReportPath = reportPath;\n return reportPath;\n })();\n }\n\n return await record.finalizePromise;\n };\n\n const createOrReuseAgentForPage = (\n page: OriginPlaywrightPage,\n testInfo: TestInfo, // { testId: string; taskFile: string; taskTitle: string },\n opts?: WebPageAgentOpt,\n ) => {\n let idForPage = (page as any)[midsceneAgentKeyId];\n if (!idForPage) {\n idForPage = uuid();\n (page as any)[midsceneAgentKeyId] = idForPage;\n const { file, title } = groupAndCaseForTest(testInfo);\n const cacheConfig = processTestCacheConfig(testInfo);\n // `replaceIllegalPathCharsAndSpace` intentionally preserves `/` and `\\`\n // so groupName/groupDescription can still carry hierarchy. But\n // ReportGenerator rejects path separators in the file name, so strip\n // them here for the report tag only.\n const reportTag = `playwright-${title.replace(/[\\\\/]/g, '-')}-${idForPage}`;\n\n if (autoFollowNewPage && forceSameTabNavigation === true) {\n throw new Error(\n '[midscene] autoFollowNewPage cannot be used with forceSameTabNavigation: true.',\n );\n }\n\n const runtimeOptions = resolveBrowserAgentRuntimeOptions({\n agentName: 'PlaywrightAiFixture',\n pageScope: autoFollowNewPage ? 'browser' : 'page',\n forceSameTabNavigation: autoFollowNewPage\n ? undefined\n : forceSameTabNavigation,\n autoFollowNewPage,\n });\n\n const commonAgentOpts = {\n testId: reportTag,\n reportFileName: reportTag,\n cache: cacheConfig,\n groupName: title,\n groupDescription: file,\n generateReport: true,\n ...sharedAgentOptions,\n ...opts,\n };\n\n const agent = autoFollowNewPage\n ? new PlaywrightBrowserAgent(page.context(), page, {\n ...commonAgentOpts,\n autoFollowNewPage: runtimeOptions.autoFollowNewPage,\n })\n : new PlaywrightAgent(page, {\n ...commonAgentOpts,\n forceSameTabNavigation: runtimeOptions.forceSameTabNavigation,\n });\n pageAgentMap[idForPage] = agent;\n const records = getAgentRecordsForTest(testInfo);\n const record: AgentRecord = { agent };\n records.set(idForPage, record);\n\n page.on('close', async () => {\n debugPage('page closed');\n try {\n await finalizeAgentRecord(record);\n } finally {\n delete pageAgentMap[idForPage];\n }\n });\n }\n\n return pageAgentMap[idForPage];\n };\n\n async function generateAiFunction(options: {\n page: OriginPlaywrightPage;\n testInfo: TestInfo;\n use: any;\n aiActionType:\n | 'ai'\n | 'aiAct'\n | 'aiAction'\n | 'aiHover'\n | 'aiInput'\n | 'aiKeyboardPress'\n | 'aiScroll'\n | 'aiTap'\n | 'aiRightClick'\n | 'aiDoubleClick'\n | 'aiQuery'\n | 'aiAssert'\n | 'aiWaitFor'\n | 'aiLocate'\n | 'aiNumber'\n | 'aiString'\n | 'aiBoolean'\n | 'aiAsk'\n | 'runYaml'\n | 'setAIActionContext'\n | 'evaluateJavaScript'\n | 'recordToReport'\n | 'logScreenshot'\n | 'freezePageContext'\n | 'unfreezePageContext';\n }) {\n const { page, testInfo, use, aiActionType } = options;\n const agent = createOrReuseAgentForPage(page, testInfo, {\n waitForNavigationTimeout,\n waitForNetworkIdleTimeout,\n }) as PlaywrightAgent;\n\n await use(async (taskPrompt: unknown, ...args: any[]) => {\n return new Promise((resolve, reject) => {\n test.step(`ai-${aiActionType} - ${JSON.stringify(taskPrompt)}`, async () => {\n try {\n type AgentMethod = (...methodArgs: any[]) => Promise<any>;\n const result = await (agent[aiActionType] as AgentMethod).bind(\n agent,\n )(taskPrompt, ...args);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n });\n });\n });\n }\n\n return {\n _midsceneFinalizeReports: [\n // biome-ignore lint/correctness/noEmptyPattern: Playwright fixture callbacks must use object destructuring for the first parameter even when no fixtures are consumed.\n async ({}: Record<string, unknown>, use: any, testInfo: TestInfo) => {\n await use();\n\n const records = testAgentRecords.get(testInfo.testId);\n if (!records || records.size === 0) {\n return;\n }\n\n const reportPaths = (\n await Promise.all(\n Array.from(records.values()).map((record) =>\n finalizeAgentRecord(record),\n ),\n )\n ).filter((reportPath): reportPath is string => Boolean(reportPath));\n\n if (reportPaths.length > 0) {\n setReportAnnotation(testInfo, reportPaths);\n }\n\n testAgentRecords.delete(testInfo.testId);\n },\n { auto: true },\n ],\n agentForPage: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await use(\n async (\n propsPage?: OriginPlaywrightPage | undefined,\n opts?: WebPageAgentOpt,\n ) => {\n const cacheConfig = processTestCacheConfig(testInfo);\n\n // Handle cache configuration priority:\n // 1. If user provides cache in opts, use it (but auto-generate ID if missing)\n // 2. Otherwise use fixture's cache config\n let finalCacheConfig = cacheConfig;\n if (opts?.cache !== undefined) {\n const userCache = opts.cache;\n if (userCache === false) {\n finalCacheConfig = false;\n } else if (userCache === true) {\n // Auto-generate ID for user's cache: true\n const { id } = groupAndCaseForTest(testInfo);\n finalCacheConfig = { id };\n } else if (typeof userCache === 'object') {\n if (!userCache.id) {\n // Auto-generate ID for user's cache object without ID\n const { id } = groupAndCaseForTest(testInfo);\n finalCacheConfig = { ...userCache, id };\n } else {\n finalCacheConfig = userCache;\n }\n }\n }\n\n const agent = createOrReuseAgentForPage(propsPage || page, testInfo, {\n waitForNavigationTimeout,\n waitForNetworkIdleTimeout,\n cache: finalCacheConfig,\n ...opts,\n });\n return agent;\n },\n );\n },\n ai: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'ai',\n });\n },\n aiAct: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAct',\n });\n },\n /**\n * @deprecated Use {@link PlaywrightAiFixture.aiAct} instead.\n */\n aiAction: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAction',\n });\n },\n aiTap: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiTap',\n });\n },\n aiRightClick: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiRightClick',\n });\n },\n aiDoubleClick: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiDoubleClick',\n });\n },\n aiHover: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiHover',\n });\n },\n aiInput: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiInput',\n });\n },\n aiKeyboardPress: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiKeyboardPress',\n });\n },\n aiScroll: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiScroll',\n });\n },\n aiQuery: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiQuery',\n });\n },\n aiAssert: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAssert',\n });\n },\n aiWaitFor: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiWaitFor',\n });\n },\n aiLocate: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiLocate',\n });\n },\n aiNumber: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiNumber',\n });\n },\n aiString: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiString',\n });\n },\n aiBoolean: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiBoolean',\n });\n },\n aiAsk: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'aiAsk',\n });\n },\n runYaml: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'runYaml',\n });\n },\n setAIActionContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'setAIActionContext',\n });\n },\n evaluateJavaScript: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'evaluateJavaScript',\n });\n },\n recordToReport: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'recordToReport',\n });\n },\n logScreenshot: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'logScreenshot',\n });\n },\n freezePageContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'freezePageContext',\n });\n },\n unfreezePageContext: async (\n { page }: { page: OriginPlaywrightPage },\n use: any,\n testInfo: TestInfo,\n ) => {\n await generateAiFunction({\n page,\n testInfo,\n use,\n aiActionType: 'unfreezePageContext',\n });\n },\n };\n};\n\nexport type PlayWrightAiFixtureType = {\n agentForPage: (\n page?: OriginPlaywrightPage,\n opts?: WebPageAgentOpt,\n ) => Promise<PageAgent<PlaywrightWebPage>>;\n ai: <T = any>(...args: Parameters<PageAgent['ai']>) => Promise<T>;\n aiAct: (\n ...args: Parameters<PageAgent['aiAct']>\n ) => ReturnType<PageAgent['aiAct']>;\n /**\n * @deprecated Use {@link PlayWrightAiFixtureType.aiAct} instead.\n */\n aiAction: (\n ...args: Parameters<PageAgent['aiAction']>\n ) => ReturnType<PageAgent['aiAction']>;\n aiTap: (\n ...args: Parameters<PageAgent['aiTap']>\n ) => ReturnType<PageAgent['aiTap']>;\n aiRightClick: (\n ...args: Parameters<PageAgent['aiRightClick']>\n ) => ReturnType<PageAgent['aiRightClick']>;\n aiDoubleClick: (\n ...args: Parameters<PageAgent['aiDoubleClick']>\n ) => ReturnType<PageAgent['aiDoubleClick']>;\n aiHover: (\n ...args: Parameters<PageAgent['aiHover']>\n ) => ReturnType<PageAgent['aiHover']>;\n aiInput: (\n ...args: Parameters<PageAgent['aiInput']>\n ) => ReturnType<PageAgent['aiInput']>;\n aiKeyboardPress: (\n ...args: Parameters<PageAgent['aiKeyboardPress']>\n ) => ReturnType<PageAgent['aiKeyboardPress']>;\n aiScroll: (\n ...args: Parameters<PageAgent['aiScroll']>\n ) => ReturnType<PageAgent['aiScroll']>;\n aiQuery: <T = any>(...args: Parameters<PageAgent['aiQuery']>) => Promise<T>;\n aiAssert: (\n ...args: Parameters<PageAgent['aiAssert']>\n ) => ReturnType<PageAgent['aiAssert']>;\n aiWaitFor: (...args: Parameters<PageAgent['aiWaitFor']>) => Promise<void>;\n aiLocate: (\n ...args: Parameters<PageAgent['aiLocate']>\n ) => ReturnType<PageAgent['aiLocate']>;\n aiNumber: (\n ...args: Parameters<PageAgent['aiNumber']>\n ) => ReturnType<PageAgent['aiNumber']>;\n aiString: (\n ...args: Parameters<PageAgent['aiString']>\n ) => ReturnType<PageAgent['aiString']>;\n aiBoolean: (\n ...args: Parameters<PageAgent['aiBoolean']>\n ) => ReturnType<PageAgent['aiBoolean']>;\n aiAsk: (\n ...args: Parameters<PageAgent['aiAsk']>\n ) => ReturnType<PageAgent['aiAsk']>;\n runYaml: (\n ...args: Parameters<PageAgent['runYaml']>\n ) => ReturnType<PageAgent['runYaml']>;\n setAIActionContext: (\n ...args: Parameters<PageAgent['setAIActionContext']>\n ) => ReturnType<PageAgent['setAIActionContext']>;\n evaluateJavaScript: (\n ...args: Parameters<PageAgent['evaluateJavaScript']>\n ) => ReturnType<PageAgent['evaluateJavaScript']>;\n recordToReport: (\n ...args: Parameters<PageAgent['recordToReport']>\n ) => ReturnType<PageAgent['recordToReport']>;\n logScreenshot: (\n ...args: Parameters<PageAgent['logScreenshot']>\n ) => ReturnType<PageAgent['logScreenshot']>;\n freezePageContext: (\n ...args: Parameters<PageAgent['freezePageContext']>\n ) => ReturnType<PageAgent['freezePageContext']>;\n unfreezePageContext: (\n ...args: Parameters<PageAgent['unfreezePageContext']>\n ) => ReturnType<PageAgent['unfreezePageContext']>;\n};\n"],"names":["debugPage","getDebug","groupAndCaseForTest","testInfo","taskFile","taskTitle","titlePath","taskTitleWithRetry","replaceIllegalPathCharsAndSpace","midsceneAgentKeyId","midsceneDumpAnnotationId","PlaywrightAiFixture","options","forceSameTabNavigation","autoFollowNewPage","waitForNetworkIdleTimeout","DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT","waitForNavigationTimeout","DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT","cache","sharedAgentOptions","processTestCacheConfig","id","processCacheConfig","pageAgentMap","testAgentRecords","Map","getAgentRecordsForTest","records","setReportAnnotation","reportPaths","item","reportPath","finalizeAgentRecord","record","undefined","createOrReuseAgentForPage","page","opts","idForPage","uuid","file","title","cacheConfig","reportTag","Error","runtimeOptions","resolveBrowserAgentRuntimeOptions","commonAgentOpts","agent","PlaywrightBrowserAgent","PlaywrightAgent","generateAiFunction","use","aiActionType","taskPrompt","args","Promise","resolve","reject","test","JSON","result","error","Array","Boolean","propsPage","finalCacheConfig","userCache"],"mappings":";;;;;;;AAqBA,MAAMA,YAAYC,SAAS;AAE3B,MAAMC,sBAAsB,CAACC;IAC3B,IAAIC;IACJ,IAAIC;IACJ,MAAMC,YAAY;WAAIH,SAAS,SAAS;KAAC;IAEzC,IAAIG,UAAU,MAAM,GAAG,GAAG;QACxBF,WAAWE,UAAU,KAAK,MAAM;QAChCD,YAAYC,UAAU,IAAI,CAAC;IAC7B,OAAO,IAAIA,AAAqB,MAArBA,UAAU,MAAM,EAAQ;QACjCD,YAAYC,SAAS,CAAC,EAAE;QACxBF,WAAW,GAAGC,WAAW;IAC3B,OAAO;QACLA,YAAY;QACZD,WAAW;IACb;IAEA,MAAMG,qBAAqB,GAAGF,YAAYF,SAAS,KAAK,GAAG,CAAC,QAAQ,EAAEA,SAAS,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI;IAE9F,OAAO;QACL,MAAMC;QACN,IAAII,gCAAgC,GAAGJ,SAAS,CAAC,EAAEC,UAAU,CAAC,CAAC;QAC/D,OAAOG,gCAAgCD;IACzC;AACF;AAEA,MAAME,qBAAqB;AACpB,MAAMC,2BAA2B;AA2BjC,MAAMC,sBAAsB,CAACC;IAClC,MAAM,EACJC,yBAAyB,IAAI,EAC7BC,oBAAoB,KAAK,EACzBC,4BAA4BC,qCAAqC,EACjEC,2BAA2BC,mCAAmC,EAC9DC,KAAK,EACL,GAAGC,oBACJ,GAAGR,WAAW,CAAC;IAGhB,MAAMS,yBAAyB,CAAClB;QAE9B,MAAM,EAAEmB,EAAE,EAAE,GAAGpB,oBAAoBC;QAGnC,OAAOoB,mBAAmBJ,OAAgBG;IAC5C;IAEA,MAAME,eAA6D,CAAC;IACpE,MAAMC,mBAAmB,IAAIC;IAE7B,MAAMC,yBAAyB,CAACxB;QAC9B,IAAIyB,UAAUH,iBAAiB,GAAG,CAACtB,SAAS,MAAM;QAClD,IAAI,CAACyB,SAAS;YACZA,UAAU,IAAIF;YACdD,iBAAiB,GAAG,CAACtB,SAAS,MAAM,EAAEyB;QACxC;QACA,OAAOA;IACT;IAEA,MAAMC,sBAAsB,CAAC1B,UAAoB2B;QAC/C3B,SAAS,WAAW,GAAGA,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC4B,OAC3CA,KAAK,IAAI,KAAKrB;QAGvB,KAAK,MAAMsB,cAAcF,YACvB3B,SAAS,WAAW,CAAC,IAAI,CAAC;YACxB,MAAMO;YACN,aAAasB;QACf;IAEJ;IAEA,MAAMC,sBAAsB,OAC1BC;QAEA,IAAI,CAACA,OAAO,eAAe,EACzBA,OAAO,eAAe,GAAI;YACxB,MAAMA,OAAO,KAAK,CAAC,OAAO;YAC1B,MAAMF,aAAaE,OAAO,KAAK,CAAC,UAAU,IAAIC;YAC9CD,OAAO,eAAe,GAAGF;YACzB,OAAOA;QACT;QAGF,OAAO,MAAME,OAAO,eAAe;IACrC;IAEA,MAAME,4BAA4B,CAChCC,MACAlC,UACAmC;QAEA,IAAIC,YAAaF,IAAY,CAAC5B,mBAAmB;QACjD,IAAI,CAAC8B,WAAW;YACdA,YAAYC;YACXH,IAAY,CAAC5B,mBAAmB,GAAG8B;YACpC,MAAM,EAAEE,IAAI,EAAEC,KAAK,EAAE,GAAGxC,oBAAoBC;YAC5C,MAAMwC,cAActB,uBAAuBlB;YAK3C,MAAMyC,YAAY,CAAC,WAAW,EAAEF,MAAM,OAAO,CAAC,UAAU,KAAK,CAAC,EAAEH,WAAW;YAE3E,IAAIzB,qBAAqBD,AAA2B,SAA3BA,wBACvB,MAAM,IAAIgC,MACR;YAIJ,MAAMC,iBAAiBC,kCAAkC;gBACvD,WAAW;gBACX,WAAWjC,oBAAoB,YAAY;gBAC3C,wBAAwBA,oBACpBqB,SACAtB;gBACJC;YACF;YAEA,MAAMkC,kBAAkB;gBACtB,QAAQJ;gBACR,gBAAgBA;gBAChB,OAAOD;gBACP,WAAWD;gBACX,kBAAkBD;gBAClB,gBAAgB;gBAChB,GAAGrB,kBAAkB;gBACrB,GAAGkB,IAAI;YACT;YAEA,MAAMW,QAAQnC,oBACV,IAAIoC,uBAAuBb,KAAK,OAAO,IAAIA,MAAM;gBAC/C,GAAGW,eAAe;gBAClB,mBAAmBF,eAAe,iBAAiB;YACrD,KACA,IAAIK,gBAAgBd,MAAM;gBACxB,GAAGW,eAAe;gBAClB,wBAAwBF,eAAe,sBAAsB;YAC/D;YACJtB,YAAY,CAACe,UAAU,GAAGU;YAC1B,MAAMrB,UAAUD,uBAAuBxB;YACvC,MAAM+B,SAAsB;gBAAEe;YAAM;YACpCrB,QAAQ,GAAG,CAACW,WAAWL;YAEvBG,KAAK,EAAE,CAAC,SAAS;gBACfrC,UAAU;gBACV,IAAI;oBACF,MAAMiC,oBAAoBC;gBAC5B,SAAU;oBACR,OAAOV,YAAY,CAACe,UAAU;gBAChC;YACF;QACF;QAEA,OAAOf,YAAY,CAACe,UAAU;IAChC;IAEA,eAAea,mBAAmBxC,OA8BjC;QACC,MAAM,EAAEyB,IAAI,EAAElC,QAAQ,EAAEkD,GAAG,EAAEC,YAAY,EAAE,GAAG1C;QAC9C,MAAMqC,QAAQb,0BAA0BC,MAAMlC,UAAU;YACtDc;YACAF;QACF;QAEA,MAAMsC,IAAI,OAAOE,YAAqB,GAAGC,OAChC,IAAIC,QAAQ,CAACC,SAASC;gBAC3BC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAEN,aAAa,GAAG,EAAEO,KAAK,SAAS,CAACN,aAAa,EAAE;oBAC9D,IAAI;wBAEF,MAAMO,SAAS,MAAOb,KAAK,CAACK,aAAa,CAAiB,IAAI,CAC5DL,OACAM,eAAeC;wBACjBE,QAAQI;oBACV,EAAE,OAAOC,OAAO;wBACdJ,OAAOI;oBACT;gBACF;YACF;IAEJ;IAEA,OAAO;QACL,0BAA0B;YAExB,OAAO,EAA2B,EAAEV,KAAUlD;gBAC5C,MAAMkD;gBAEN,MAAMzB,UAAUH,iBAAiB,GAAG,CAACtB,SAAS,MAAM;gBACpD,IAAI,CAACyB,WAAWA,AAAiB,MAAjBA,QAAQ,IAAI,EAC1B;gBAGF,MAAME,cACJ,OAAM2B,QAAQ,GAAG,CACfO,MAAM,IAAI,CAACpC,QAAQ,MAAM,IAAI,GAAG,CAAC,CAACM,SAChCD,oBAAoBC,SAAAA,EAGxB,MAAM,CAAC,CAACF,aAAqCiC,QAAQjC;gBAEvD,IAAIF,YAAY,MAAM,GAAG,GACvBD,oBAAoB1B,UAAU2B;gBAGhCL,iBAAiB,MAAM,CAACtB,SAAS,MAAM;YACzC;YACA;gBAAE,MAAM;YAAK;SACd;QACD,cAAc,OACZ,EAAEkC,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMkD,IACJ,OACEa,WACA5B;gBAEA,MAAMK,cAActB,uBAAuBlB;gBAK3C,IAAIgE,mBAAmBxB;gBACvB,IAAIL,MAAM,UAAUH,QAAW;oBAC7B,MAAMiC,YAAY9B,KAAK,KAAK;oBAC5B,IAAI8B,AAAc,UAAdA,WACFD,mBAAmB;yBACd,IAAIC,AAAc,SAAdA,WAAoB;wBAE7B,MAAM,EAAE9C,EAAE,EAAE,GAAGpB,oBAAoBC;wBACnCgE,mBAAmB;4BAAE7C;wBAAG;oBAC1B,OAAO,IAAI,AAAqB,YAArB,OAAO8C,WAChB,IAAKA,UAAU,EAAE,EAKfD,mBAAmBC;yBALF;wBAEjB,MAAM,EAAE9C,EAAE,EAAE,GAAGpB,oBAAoBC;wBACnCgE,mBAAmB;4BAAE,GAAGC,SAAS;4BAAE9C;wBAAG;oBACxC;gBAIJ;gBAEA,MAAM2B,QAAQb,0BAA0B8B,aAAa7B,MAAMlC,UAAU;oBACnEc;oBACAF;oBACA,OAAOoD;oBACP,GAAG7B,IAAI;gBACT;gBACA,OAAOW;YACT;QAEJ;QACA,IAAI,OACF,EAAEZ,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,OAAO,OACL,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QAIA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,OAAO,OACL,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,cAAc,OACZ,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,eAAe,OACb,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,SAAS,OACP,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,SAAS,OACP,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,iBAAiB,OACf,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,SAAS,OACP,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,WAAW,OACT,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,UAAU,OACR,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,WAAW,OACT,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,OAAO,OACL,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,SAAS,OACP,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,oBAAoB,OAClB,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,oBAAoB,OAClB,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,gBAAgB,OACd,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,eAAe,OACb,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,mBAAmB,OACjB,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;QACA,qBAAqB,OACnB,EAAEhB,IAAI,EAAkC,EACxCgB,KACAlD;YAEA,MAAMiD,mBAAmB;gBACvBf;gBACAlC;gBACAkD;gBACA,cAAc;YAChB;QACF;IACF;AACF"}
@@ -0,0 +1,84 @@
1
+ import { BrowserPageManager, WebAgentCore, resolveBrowserAgentRuntimeOptions } from "../common/browser-agent.mjs";
2
+ import { applyForceChromeSelectRendering } from "../common/browser-agent-utils.mjs";
3
+ import { getDebug } from "@midscene/shared/logger";
4
+ import { WebPage } from "./page.mjs";
5
+ function _define_property(obj, key, value) {
6
+ if (key in obj) Object.defineProperty(obj, key, {
7
+ value: value,
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true
11
+ });
12
+ else obj[key] = value;
13
+ return obj;
14
+ }
15
+ const debug = getDebug('playwright:browser-agent');
16
+ const createPlaywrightBrowserAdapter = (context)=>({
17
+ pages: ()=>context.pages(),
18
+ newPage: ()=>context.newPage(),
19
+ isPageClosed: (page)=>page.isClosed(),
20
+ bringToFront: (page)=>page.bringToFront(),
21
+ onNewPage: (handler)=>context.on('page', handler),
22
+ offNewPage: (handler)=>context.off('page', handler),
23
+ resolveNewPage: (page)=>page
24
+ });
25
+ class PlaywrightBrowserAgent extends WebAgentCore {
26
+ static async create(context, opts) {
27
+ const { initialPage, ...agentOpts } = opts ?? {};
28
+ const page = initialPage ?? context.pages()[0] ?? await context.newPage();
29
+ return new PlaywrightBrowserAgent(context, page, agentOpts);
30
+ }
31
+ get activePage() {
32
+ return this.pageManager.activePage;
33
+ }
34
+ pages() {
35
+ return this.pageManager.pages();
36
+ }
37
+ async newPage() {
38
+ return this.pageManager.newPage();
39
+ }
40
+ async setActivePage(page) {
41
+ await this.pageManager.setActivePage(page);
42
+ }
43
+ async waitForNewPage(action, opts) {
44
+ return this.pageManager.waitForNewPage(action, opts);
45
+ }
46
+ async destroy() {
47
+ this.pageManager.destroy();
48
+ await super.destroy();
49
+ }
50
+ constructor(context, initialPage, opts){
51
+ if (!context) throw new Error('[midscene] PlaywrightBrowserAgent requires a valid Playwright browser context.');
52
+ if (!initialPage) throw new Error('[midscene] PlaywrightBrowserAgent requires a valid initial page instance.');
53
+ const { autoFollowNewPage, newPageTimeout, ...agentOpts } = opts ?? {};
54
+ const runtimeOptions = resolveBrowserAgentRuntimeOptions({
55
+ agentName: 'PlaywrightBrowserAgent',
56
+ pageScope: 'browser',
57
+ forceSameTabNavigation: opts?.forceSameTabNavigation,
58
+ autoFollowNewPage,
59
+ newPageTimeout
60
+ });
61
+ const { forceChromeSelectRendering } = agentOpts;
62
+ const webPage = new WebPage(initialPage, {
63
+ ...agentOpts,
64
+ forceSameTabNavigation: runtimeOptions.forceSameTabNavigation
65
+ });
66
+ const pageManager = new BrowserPageManager({
67
+ agentName: 'PlaywrightBrowserAgent',
68
+ adapter: createPlaywrightBrowserAdapter(context),
69
+ getActivePage: ()=>webPage.underlyingPage,
70
+ setActivePageValue: (page)=>{
71
+ webPage.underlyingPage = page;
72
+ },
73
+ autoFollowNewPage: runtimeOptions.autoFollowNewPage,
74
+ newPageTimeout: runtimeOptions.newPageTimeout,
75
+ debug
76
+ });
77
+ super(webPage, agentOpts), _define_property(this, "pageManager", void 0);
78
+ this.pageManager = pageManager;
79
+ applyForceChromeSelectRendering(initialPage, 'playwright', forceChromeSelectRendering);
80
+ }
81
+ }
82
+ export { PlaywrightBrowserAgent };
83
+
84
+ //# sourceMappingURL=browser-agent.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright/browser-agent.mjs","sources":["../../../src/playwright/browser-agent.ts"],"sourcesContent":["import {\n type BrowserAgentAdapter,\n BrowserPageManager,\n WebAgentCore,\n resolveBrowserAgentRuntimeOptions,\n} from '@/common/browser-agent';\nimport { applyForceChromeSelectRendering } from '@/common/browser-agent-utils';\nimport type { WebPageAgentOpt } from '@/web-element';\nimport { getDebug } from '@midscene/shared/logger';\nimport type {\n BrowserContext as PlaywrightBrowserContext,\n Page as PlaywrightPage,\n} from 'playwright';\nimport { WebPage as PlaywrightWebPage } from './page';\n\nconst debug = getDebug('playwright:browser-agent');\n\nconst createPlaywrightBrowserAdapter = (\n context: PlaywrightBrowserContext,\n): BrowserAgentAdapter<PlaywrightPage, PlaywrightPage> => ({\n pages: () => context.pages(),\n newPage: () => context.newPage(),\n isPageClosed: (page) => page.isClosed(),\n bringToFront: (page) => page.bringToFront(),\n onNewPage: (handler) => context.on('page', handler),\n offNewPage: (handler) => context.off('page', handler),\n resolveNewPage: (page) => page,\n});\n\nexport type PlaywrightBrowserAgentOpt = Omit<\n WebPageAgentOpt,\n 'forceSameTabNavigation'\n> & {\n autoFollowNewPage?: boolean;\n newPageTimeout?: number;\n};\n\nexport type PlaywrightBrowserAgentCreateOpt = PlaywrightBrowserAgentOpt & {\n initialPage?: PlaywrightPage;\n};\n\nexport class PlaywrightBrowserAgent extends WebAgentCore<PlaywrightWebPage> {\n private readonly pageManager: BrowserPageManager<\n PlaywrightPage,\n PlaywrightPage\n >;\n\n constructor(\n context: PlaywrightBrowserContext,\n initialPage: PlaywrightPage,\n opts?: PlaywrightBrowserAgentOpt,\n ) {\n if (!context) {\n throw new Error(\n '[midscene] PlaywrightBrowserAgent requires a valid Playwright browser context.',\n );\n }\n if (!initialPage) {\n throw new Error(\n '[midscene] PlaywrightBrowserAgent requires a valid initial page instance.',\n );\n }\n\n const { autoFollowNewPage, newPageTimeout, ...agentOpts } = opts ?? {};\n const runtimeOptions = resolveBrowserAgentRuntimeOptions({\n agentName: 'PlaywrightBrowserAgent',\n pageScope: 'browser',\n forceSameTabNavigation: (opts as WebPageAgentOpt | undefined)\n ?.forceSameTabNavigation,\n autoFollowNewPage,\n newPageTimeout,\n });\n const { forceChromeSelectRendering } = agentOpts;\n const webPage = new PlaywrightWebPage(initialPage, {\n ...agentOpts,\n forceSameTabNavigation: runtimeOptions.forceSameTabNavigation,\n });\n const pageManager = new BrowserPageManager({\n agentName: 'PlaywrightBrowserAgent',\n adapter: createPlaywrightBrowserAdapter(context),\n getActivePage: () => webPage.underlyingPage as PlaywrightPage,\n setActivePageValue: (page) => {\n webPage.underlyingPage = page;\n },\n autoFollowNewPage: runtimeOptions.autoFollowNewPage,\n newPageTimeout: runtimeOptions.newPageTimeout,\n debug,\n });\n super(webPage, agentOpts);\n this.pageManager = pageManager;\n\n applyForceChromeSelectRendering(\n initialPage,\n 'playwright',\n forceChromeSelectRendering,\n );\n }\n\n static async create(\n context: PlaywrightBrowserContext,\n opts?: PlaywrightBrowserAgentCreateOpt,\n ) {\n const { initialPage, ...agentOpts } = opts ?? {};\n const page = initialPage ?? context.pages()[0] ?? (await context.newPage());\n\n return new PlaywrightBrowserAgent(context, page, agentOpts);\n }\n\n get activePage() {\n return this.pageManager.activePage;\n }\n\n pages() {\n return this.pageManager.pages();\n }\n\n async newPage() {\n return this.pageManager.newPage();\n }\n\n async setActivePage(page: PlaywrightPage) {\n await this.pageManager.setActivePage(page);\n }\n\n async waitForNewPage(\n action?: () => Promise<unknown> | unknown,\n opts?: { timeout?: number },\n ) {\n return this.pageManager.waitForNewPage(action, opts);\n }\n\n async destroy() {\n this.pageManager.destroy();\n await super.destroy();\n }\n}\n"],"names":["debug","getDebug","createPlaywrightBrowserAdapter","context","page","handler","PlaywrightBrowserAgent","WebAgentCore","opts","initialPage","agentOpts","action","Error","autoFollowNewPage","newPageTimeout","runtimeOptions","resolveBrowserAgentRuntimeOptions","forceChromeSelectRendering","webPage","PlaywrightWebPage","pageManager","BrowserPageManager","applyForceChromeSelectRendering"],"mappings":";;;;;;;;;;;;;;AAeA,MAAMA,QAAQC,SAAS;AAEvB,MAAMC,iCAAiC,CACrCC,UACyD;QACzD,OAAO,IAAMA,QAAQ,KAAK;QAC1B,SAAS,IAAMA,QAAQ,OAAO;QAC9B,cAAc,CAACC,OAASA,KAAK,QAAQ;QACrC,cAAc,CAACA,OAASA,KAAK,YAAY;QACzC,WAAW,CAACC,UAAYF,QAAQ,EAAE,CAAC,QAAQE;QAC3C,YAAY,CAACA,UAAYF,QAAQ,GAAG,CAAC,QAAQE;QAC7C,gBAAgB,CAACD,OAASA;IAC5B;AAcO,MAAME,+BAA+BC;IAyD1C,aAAa,OACXJ,OAAiC,EACjCK,IAAsC,EACtC;QACA,MAAM,EAAEC,WAAW,EAAE,GAAGC,WAAW,GAAGF,QAAQ,CAAC;QAC/C,MAAMJ,OAAOK,eAAeN,QAAQ,KAAK,EAAE,CAAC,EAAE,IAAK,MAAMA,QAAQ,OAAO;QAExE,OAAO,IAAIG,uBAAuBH,SAASC,MAAMM;IACnD;IAEA,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU;IACpC;IAEA,QAAQ;QACN,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK;IAC/B;IAEA,MAAM,UAAU;QACd,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO;IACjC;IAEA,MAAM,cAAcN,IAAoB,EAAE;QACxC,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAACA;IACvC;IAEA,MAAM,eACJO,MAAyC,EACzCH,IAA2B,EAC3B;QACA,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAACG,QAAQH;IACjD;IAEA,MAAM,UAAU;QACd,IAAI,CAAC,WAAW,CAAC,OAAO;QACxB,MAAM,KAAK,CAAC;IACd;IAvFA,YACEL,OAAiC,EACjCM,WAA2B,EAC3BD,IAAgC,CAChC;QACA,IAAI,CAACL,SACH,MAAM,IAAIS,MACR;QAGJ,IAAI,CAACH,aACH,MAAM,IAAIG,MACR;QAIJ,MAAM,EAAEC,iBAAiB,EAAEC,cAAc,EAAE,GAAGJ,WAAW,GAAGF,QAAQ,CAAC;QACrE,MAAMO,iBAAiBC,kCAAkC;YACvD,WAAW;YACX,WAAW;YACX,wBAAyBR,MACrB;YACJK;YACAC;QACF;QACA,MAAM,EAAEG,0BAA0B,EAAE,GAAGP;QACvC,MAAMQ,UAAU,IAAIC,QAAkBV,aAAa;YACjD,GAAGC,SAAS;YACZ,wBAAwBK,eAAe,sBAAsB;QAC/D;QACA,MAAMK,cAAc,IAAIC,mBAAmB;YACzC,WAAW;YACX,SAASnB,+BAA+BC;YACxC,eAAe,IAAMe,QAAQ,cAAc;YAC3C,oBAAoB,CAACd;gBACnBc,QAAQ,cAAc,GAAGd;YAC3B;YACA,mBAAmBW,eAAe,iBAAiB;YACnD,gBAAgBA,eAAe,cAAc;YAC7Cf;QACF;QACA,KAAK,CAACkB,SAASR,YA9CjB,uBAAiB,eAAjB;QA+CE,IAAI,CAAC,WAAW,GAAGU;QAEnBE,gCACEb,aACA,cACAQ;IAEJ;AAuCF"}
@@ -1,40 +1,6 @@
1
- import { Agent } from "@midscene/core/agent";
2
- import { WebPage } from "./page.mjs";
3
1
  import { PlaywrightAiFixture } from "./ai-fixture.mjs";
4
2
  import { overrideAIConfig } from "@midscene/shared/env";
5
- import { getDebug } from "@midscene/shared/logger";
6
- import semver from "semver";
7
- import { BROWSER_NAVIGATION_ERROR_PATTERN, forceChromeSelectRendering as base_page_mjs_forceChromeSelectRendering, forceClosePopup } from "../puppeteer/base-page.mjs";
8
- import { getWebpackRequire } from "../utils.mjs";
9
- const debug = getDebug('playwright:agent');
10
- function getPlaywrightVersion() {
11
- try {
12
- const playwrightPkg = getWebpackRequire()('playwright/package.json');
13
- return playwrightPkg.version || null;
14
- } catch (error) {
15
- console.error('[midscene:error] Failed to get Playwright version', error);
16
- return null;
17
- }
18
- }
19
- class PlaywrightAgent extends Agent {
20
- isRetryableContextError(error) {
21
- return error instanceof Error && BROWSER_NAVIGATION_ERROR_PATTERN.test(error.message);
22
- }
23
- constructor(page, opts){
24
- if (!page) throw new Error('[midscene] PlaywrightAgent requires a valid Playwright page instance. Please make sure to pass a valid page object.');
25
- const webPage = new WebPage(page, opts);
26
- super(webPage, opts);
27
- const { forceSameTabNavigation = true, forceChromeSelectRendering = true } = opts ?? {};
28
- if (forceSameTabNavigation) forceClosePopup(page, debug);
29
- if (forceChromeSelectRendering) {
30
- if (opts?.forceChromeSelectRendering === true) {
31
- const playwrightVersion = getPlaywrightVersion();
32
- if (playwrightVersion && !semver.gte(playwrightVersion, '1.52.0')) console.warn(`[midscene:error] forceChromeSelectRendering requires Playwright >= 1.52.0, but current version is ${playwrightVersion}. This feature may not work correctly.`);
33
- }
34
- base_page_mjs_forceChromeSelectRendering(page);
35
- }
36
- }
37
- }
38
- export { PlaywrightAgent, PlaywrightAiFixture, WebPage as PlaywrightWebPage, overrideAIConfig };
39
-
40
- //# sourceMappingURL=index.mjs.map
3
+ import { WebPage } from "./page.mjs";
4
+ import { PlaywrightAgent, PlaywrightPageAgent } from "./page-agent.mjs";
5
+ import { PlaywrightBrowserAgent } from "./browser-agent.mjs";
6
+ export { PlaywrightAgent, PlaywrightAiFixture, PlaywrightBrowserAgent, PlaywrightPageAgent, WebPage as PlaywrightWebPage, overrideAIConfig };