playwright 1.58.0-alpha-2025-12-06 → 1.58.0-alpha-2025-12-07

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -14,4 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- module.exports = require('playwright-core');
17
+ const playwright = require('playwright-core');
18
+ const { decoratePage } = require('./lib/agents/pageDecorator');
19
+ decoratePage(playwright);
20
+ module.exports = playwright;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var pageDecorator_exports = {};
20
+ __export(pageDecorator_exports, {
21
+ decoratePage: () => decoratePage
22
+ });
23
+ module.exports = __toCommonJS(pageDecorator_exports);
24
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
25
+ var import_mcpBundle = require("playwright-core/lib/mcpBundle");
26
+ var import_browserContextFactory = require("../mcp/browser/browserContextFactory");
27
+ var import_browserServerBackend = require("../mcp/browser/browserServerBackend");
28
+ var import_config = require("../mcp/browser/config");
29
+ var import_server = require("../mcp/sdk/server");
30
+ function decoratePage(playwright) {
31
+ playwright._instrumentation.addListener({
32
+ onPage: (page) => {
33
+ page.perform = pagePerform.bind(null, page);
34
+ page.extract = pageExtract.bind(null, page);
35
+ }
36
+ });
37
+ }
38
+ async function pagePerform(page, userTask, options = {}) {
39
+ const resultSchema = {
40
+ type: "object",
41
+ properties: {
42
+ code: { type: "string" }
43
+ },
44
+ required: ["code"]
45
+ };
46
+ await perform(page, userTask, resultSchema, options);
47
+ }
48
+ async function pageExtract(page, query, schema, options = {}) {
49
+ const task = `
50
+ ### Instructions
51
+ Extract the following information from the page. Do not perform any actions, just extract the information.
52
+
53
+ ### Query
54
+ ${query}`;
55
+ return await perform(page, task, (0, import_mcpBundle.zodToJsonSchema)(schema), options);
56
+ }
57
+ async function perform(page, userTask, resultSchema, options = {}) {
58
+ const context = page.context();
59
+ if (!context._options.agent)
60
+ throw new Error(`page.perform() and page.extract() require the agent to be set on the browser context`);
61
+ const { full } = await page._snapshotForAI();
62
+ const backend = new import_browserServerBackend.BrowserServerBackend(import_config.defaultConfig, (0, import_browserContextFactory.identityBrowserContextFactory)(context));
63
+ const client = await (0, import_server.wrapInClient)(backend, { name: "Internal", version: "0.0.0" });
64
+ const callTool = async (params) => {
65
+ return await client.callTool(params);
66
+ };
67
+ const loop = new import_mcpBundle.Loop(context._options.agent.provider, {
68
+ model: context._options.agent.model,
69
+ summarize: true,
70
+ debug: import_utilsBundle.debug,
71
+ callTool,
72
+ tools: await backend.listTools(),
73
+ ...options
74
+ });
75
+ const task = `${userTask}
76
+
77
+ ### Page snapshot
78
+ ${full}
79
+ `;
80
+ try {
81
+ return await loop.run(task, {
82
+ resultSchema
83
+ });
84
+ } finally {
85
+ await client.close();
86
+ }
87
+ }
88
+ // Annotate the CommonJS export names for ESM import in node:
89
+ 0 && (module.exports = {
90
+ decoratePage
91
+ });
package/lib/index.js CHANGED
@@ -33,7 +33,6 @@ __export(index_exports, {
33
33
  expect: () => import_expect.expect,
34
34
  mergeExpects: () => import_expect2.mergeExpects,
35
35
  mergeTests: () => import_testType2.mergeTests,
36
- performCache: () => import_performTask2.performCache,
37
36
  test: () => test
38
37
  });
39
38
  module.exports = __toCommonJS(index_exports);
@@ -44,12 +43,10 @@ var import_utils = require("playwright-core/lib/utils");
44
43
  var import_globals = require("./common/globals");
45
44
  var import_testType = require("./common/testType");
46
45
  var import_browserBackend = require("./mcp/test/browserBackend");
47
- var import_performTask = require("./agents/performTask");
48
46
  var import_expect = require("./matchers/expect");
49
47
  var import_configLoader = require("./common/configLoader");
50
48
  var import_testType2 = require("./common/testType");
51
49
  var import_expect2 = require("./matchers/expect");
52
- var import_performTask2 = require("./agents/performTask");
53
50
  const _baseTest = import_testType.rootTestType.test;
54
51
  (0, import_utils.setBoxedStackPrefixes)([import_path.default.dirname(require.resolve("../package.json"))]);
55
52
  if (process["__pw_initiator__"]) {
@@ -114,6 +111,7 @@ const playwrightFixtures = {
114
111
  await browser.close({ reason: "Test ended." });
115
112
  }, { scope: "worker", timeout: 0 }],
116
113
  acceptDownloads: [({ contextOptions }, use) => use(contextOptions.acceptDownloads ?? true), { option: true, box: true }],
114
+ agent: [({ contextOptions }, use) => use(contextOptions.agent), { option: true, box: true }],
117
115
  bypassCSP: [({ contextOptions }, use) => use(contextOptions.bypassCSP ?? false), { option: true, box: true }],
118
116
  colorScheme: [({ contextOptions }, use) => use(contextOptions.colorScheme === void 0 ? "light" : contextOptions.colorScheme), { option: true, box: true }],
119
117
  deviceScaleFactor: [({ contextOptions }, use) => use(contextOptions.deviceScaleFactor), { option: true, box: true }],
@@ -143,6 +141,7 @@ const playwrightFixtures = {
143
141
  contextOptions: [{}, { option: true, box: true }],
144
142
  _combinedContextOptions: [async ({
145
143
  acceptDownloads,
144
+ agent,
146
145
  bypassCSP,
147
146
  clientCertificates,
148
147
  colorScheme,
@@ -169,6 +168,8 @@ const playwrightFixtures = {
169
168
  const options = {};
170
169
  if (acceptDownloads !== void 0)
171
170
  options.acceptDownloads = acceptDownloads;
171
+ if (agent !== void 0)
172
+ options.agent = agent;
172
173
  if (bypassCSP !== void 0)
173
174
  options.bypassCSP = bypassCSP;
174
175
  if (colorScheme !== void 0)
@@ -418,11 +419,6 @@ const playwrightFixtures = {
418
419
  } else {
419
420
  await request.dispose();
420
421
  }
421
- },
422
- _perform: async ({ context }, use, testInfo) => {
423
- await use(async (task, options) => {
424
- await (0, import_performTask.performTask)(testInfo, context, task, options ?? {});
425
- });
426
422
  }
427
423
  };
428
424
  function normalizeVideoMode(video) {
@@ -686,6 +682,5 @@ const test = _baseTest.extend(playwrightFixtures);
686
682
  expect,
687
683
  mergeExpects,
688
684
  mergeTests,
689
- performCache,
690
685
  test
691
686
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.58.0-alpha-2025-12-06",
3
+ "version": "1.58.0-alpha-2025-12-07",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "license": "Apache-2.0",
66
66
  "dependencies": {
67
- "playwright-core": "1.58.0-alpha-2025-12-06"
67
+ "playwright-core": "1.58.0-alpha-2025-12-07"
68
68
  },
69
69
  "optionalDependencies": {
70
70
  "fsevents": "2.3.2"
package/types/test.d.ts CHANGED
@@ -6644,6 +6644,7 @@ export type Fixtures<T extends {} = {}, W extends {} = {}, PT extends {} = {}, P
6644
6644
  [K in Exclude<keyof T, keyof PW | keyof PT>]?: TestFixtureValue<T[K], T & W & PT & PW> | [TestFixtureValue<T[K], T & W & PT & PW>, { scope?: 'test', auto?: boolean, option?: boolean, timeout?: number | undefined, title?: string, box?: boolean | 'self' }];
6645
6645
  };
6646
6646
 
6647
+ type Agent = Exclude<BrowserContextOptions['agent'], undefined> | undefined;
6647
6648
  type BrowserName = 'chromium' | 'firefox' | 'webkit';
6648
6649
  type BrowserChannel = Exclude<LaunchOptions['channel'], undefined>;
6649
6650
  type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
@@ -6974,6 +6975,11 @@ export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
6974
6975
  *
6975
6976
  */
6976
6977
  export interface PlaywrightTestOptions {
6978
+ /**
6979
+ * Agent settings for [page.perform(task[, options])](https://playwright.dev/docs/api/class-page#page-perform) and
6980
+ * [page.extract(query, schema[, options])](https://playwright.dev/docs/api/class-page#page-extract).
6981
+ */
6982
+ agent: Agent;
6977
6983
  /**
6978
6984
  * Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
6979
6985
  *
@@ -1,163 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var performTask_exports = {};
30
- __export(performTask_exports, {
31
- performCache: () => performCache,
32
- performTask: () => performTask
33
- });
34
- module.exports = __toCommonJS(performTask_exports);
35
- var import_fs = __toESM(require("fs"));
36
- var import_path = __toESM(require("path"));
37
- var import_utilsBundle = require("playwright-core/lib/utilsBundle");
38
- var import_mcpBundle = require("playwright-core/lib/mcpBundle");
39
- var import_browserContextFactory = require("../mcp/browser/browserContextFactory");
40
- var import_browserServerBackend = require("../mcp/browser/browserServerBackend");
41
- var import_config = require("../mcp/browser/config");
42
- var import_server = require("../mcp/sdk/server");
43
- const resultSchema = import_mcpBundle.z.object({
44
- code: import_mcpBundle.z.string().optional().describe(`
45
- Generated code to perform the task using Playwright API.
46
- Check out the <code> blocks and combine them. Should be presented in the following form:
47
-
48
- perform(async ({ page }) => {
49
- // generated code here.
50
- });
51
- `),
52
- error: import_mcpBundle.z.string().optional().describe("The error that occurred if execution failed.").optional()
53
- });
54
- async function performTask(testInfo, context, userTask, options) {
55
- const cacheStatus = await performTaskFromCache(testInfo, context, userTask);
56
- if (cacheStatus === "success")
57
- return;
58
- const backend = new import_browserServerBackend.BrowserServerBackend(import_config.defaultConfig, (0, import_browserContextFactory.identityBrowserContextFactory)(context));
59
- const client = await (0, import_server.wrapInClient)(backend, { name: "Internal", version: "0.0.0" });
60
- const callTool = async (params) => {
61
- return await client.callTool(params);
62
- };
63
- const loop = new import_mcpBundle.Loop(options.provider ?? "github", {
64
- model: options.model ?? "claude-sonnet-4.5",
65
- reasoning: options.reasoning,
66
- temperature: options.temperature,
67
- maxTokens: options.maxTokens,
68
- summarize: true,
69
- debug: import_utilsBundle.debug,
70
- callTool,
71
- tools: await backend.listTools()
72
- });
73
- try {
74
- const result = await loop.run(userTask, { resultSchema: (0, import_mcpBundle.zodToJsonSchema)(resultSchema) });
75
- if (result.code)
76
- await updatePerformFile(testInfo, userTask, result.code, options);
77
- } finally {
78
- await client.close();
79
- }
80
- }
81
- async function updatePerformFile(testInfo, userTask, taskCode, options) {
82
- const relativeFile = import_path.default.relative(testInfo.project.testDir, testInfo.file);
83
- const promptCacheFile = testInfo.file.replace(".spec.ts", ".cache.ts");
84
- const testTitle = testInfo.title;
85
- const loop = new import_mcpBundle.Loop(options.provider ?? "github", {
86
- model: options.model ?? "claude-sonnet-4.5",
87
- reasoning: options.reasoning,
88
- temperature: options.temperature,
89
- maxTokens: options.maxTokens,
90
- summarize: true,
91
- debug: import_utilsBundle.debug,
92
- callTool: async () => ({ content: [] }),
93
- tools: []
94
- });
95
- const resultSchema2 = import_mcpBundle.z.object({
96
- code: import_mcpBundle.z.string().optional().describe(`
97
- Generated code with all the perofrm routines combined or updated into the following format:
98
-
99
- import { performCache } from '@playwright/test';
100
-
101
- performCache({
102
- file: 'tests/page/perform-task.spec.ts',
103
- test: 'perform task',
104
- task: 'Click the learn more button',
105
- code: async ({ page }) => {
106
- await page.getByRole('link', { name: 'Learn more' }).click();
107
- },
108
- });
109
- `)
110
- });
111
- const existingCode = await import_fs.default.promises.readFile(promptCacheFile, "utf8").catch(() => "");
112
- const task = `
113
- - Create or update a perform file to include performCache block for the given task and code.
114
- - Dedupe items with the same file, test, and task.
115
- - Should produce code in the following format
116
-
117
- import { performCache } from '@playwright/test';
118
-
119
- performCache({
120
- file: '<file>',
121
- test: '<test>',
122
- task: '<task>',
123
- code: async ({ page }) => {
124
- <code>
125
- },
126
- });
127
-
128
- performCache({
129
- ...
130
-
131
- ## Params for the new or updated performCache block
132
- <file-content>${existingCode}</file-content>
133
- <file>${relativeFile}</file>
134
- <test>${testTitle}</test>
135
- <task>${userTask}</task>
136
- <code>${taskCode}</code>
137
- `;
138
- const result = await loop.run(task, { resultSchema: (0, import_mcpBundle.zodToJsonSchema)(resultSchema2) });
139
- if (result.code)
140
- await import_fs.default.promises.writeFile(promptCacheFile, result.code);
141
- }
142
- const performCacheMap = /* @__PURE__ */ new Map();
143
- function performCache(entry) {
144
- performCacheMap.set(JSON.stringify({ ...entry, code: void 0 }), entry);
145
- }
146
- async function performTaskFromCache(testInfo, context, userTask) {
147
- const relativeFile = import_path.default.relative(testInfo.project.testDir, testInfo.file);
148
- const key = JSON.stringify({ file: relativeFile, test: testInfo.title, task: userTask });
149
- const entry = performCacheMap.get(key);
150
- if (!entry)
151
- return "cache-miss";
152
- try {
153
- await entry.code({ page: context.pages()[0] });
154
- return "success";
155
- } catch (error) {
156
- return error;
157
- }
158
- }
159
- // Annotate the CommonJS export names for ESM import in node:
160
- 0 && (module.exports = {
161
- performCache,
162
- performTask
163
- });