playwright 1.55.0 → 1.56.0-alpha-2025-08-21
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/lib/index.js +45 -4
- package/lib/isomorphic/testServerConnection.js +0 -7
- package/lib/matchers/expect.js +7 -19
- package/lib/matchers/toBeTruthy.js +2 -0
- package/lib/matchers/toEqual.js +2 -0
- package/lib/matchers/toMatchText.js +3 -0
- package/lib/mcp/browser/backend.js +88 -0
- package/lib/mcp/browser/tool.js +30 -0
- package/lib/mcp/browser/tools.js +132 -0
- package/lib/mcp/{bundle.js → sdk/bundle.js} +5 -2
- package/lib/mcp/sdk/call.js +49 -0
- package/lib/mcp/{exports.js → sdk/exports.js} +12 -10
- package/lib/mcp/{transport.js → sdk/http.js} +51 -68
- package/lib/mcp/sdk/mdb.js +195 -0
- package/lib/mcp/{proxyBackend.js → sdk/proxyBackend.js} +8 -10
- package/lib/mcp/{server.js → sdk/server.js} +43 -14
- package/lib/mcp/{tool.js → sdk/tool.js} +6 -1
- package/lib/mcp/test/backend.js +68 -0
- package/lib/mcp/test/context.js +43 -0
- package/lib/mcp/test/listTests.js +88 -0
- package/lib/mcp/test/program.js +42 -0
- package/lib/mcp/test/runTests.js +82 -0
- package/lib/mcp/test/streams.js +41 -0
- package/lib/mcp/test/tool.js +30 -0
- package/lib/mcpBundleImpl.js +17 -13
- package/lib/runner/dispatcher.js +1 -22
- package/lib/runner/failureTracker.js +0 -14
- package/lib/runner/testRunner.js +2 -25
- package/lib/runner/testServer.js +2 -8
- package/lib/runner/watchMode.js +1 -53
- package/lib/runner/workerHost.js +2 -6
- package/lib/worker/testInfo.js +1 -24
- package/lib/worker/workerMain.js +0 -5
- package/package.json +3 -3
- /package/lib/mcp/{inProcessTransport.js → sdk/inProcessTransport.js} +0 -0
package/lib/index.js
CHANGED
|
@@ -42,6 +42,9 @@ var playwrightLibrary = __toESM(require("playwright-core"));
|
|
|
42
42
|
var import_utils = require("playwright-core/lib/utils");
|
|
43
43
|
var import_globals = require("./common/globals");
|
|
44
44
|
var import_testType = require("./common/testType");
|
|
45
|
+
var import_backend = require("./mcp/browser/backend");
|
|
46
|
+
var import_babelBundle = require("./transform/babelBundle");
|
|
47
|
+
var import_util = require("./util");
|
|
45
48
|
var import_expect = require("./matchers/expect");
|
|
46
49
|
var import_configLoader = require("./common/configLoader");
|
|
47
50
|
var import_testType2 = require("./common/testType");
|
|
@@ -219,7 +222,7 @@ const playwrightFixtures = {
|
|
|
219
222
|
if ((0, import_utils.debugMode)() === "inspector")
|
|
220
223
|
testInfo._setDebugMode();
|
|
221
224
|
playwright._defaultContextOptions = _combinedContextOptions;
|
|
222
|
-
playwright._defaultContextTimeout = actionTimeout || 0;
|
|
225
|
+
playwright._defaultContextTimeout = process.env.PLAYWRIGHT_TEST_DEBUGGER_MCP ? 5e3 : actionTimeout || 0;
|
|
223
226
|
playwright._defaultContextNavigationTimeout = navigationTimeout || 0;
|
|
224
227
|
await use();
|
|
225
228
|
playwright._defaultContextOptions = void 0;
|
|
@@ -258,10 +261,18 @@ const playwrightFixtures = {
|
|
|
258
261
|
if (data.apiName === "tracing.group")
|
|
259
262
|
tracingGroupSteps.push(step);
|
|
260
263
|
},
|
|
261
|
-
onApiCallRecovery: (data, error, recoveryHandlers) => {
|
|
264
|
+
onApiCallRecovery: (data, error, channelOwner, recoveryHandlers) => {
|
|
262
265
|
const step = data.userData;
|
|
263
|
-
if (step)
|
|
264
|
-
|
|
266
|
+
if (!step)
|
|
267
|
+
return;
|
|
268
|
+
const page = channelToPage(channelOwner);
|
|
269
|
+
if (!page)
|
|
270
|
+
return;
|
|
271
|
+
recoveryHandlers.push(async () => {
|
|
272
|
+
await (0, import_backend.runBrowserBackendOnError)(page, () => {
|
|
273
|
+
return (0, import_util.stripAnsiEscapes)(createErrorCodeframe(error.message, step.location));
|
|
274
|
+
});
|
|
275
|
+
});
|
|
265
276
|
},
|
|
266
277
|
onApiCallEnd: (data) => {
|
|
267
278
|
if (data.apiName === "tracing.group")
|
|
@@ -672,6 +683,36 @@ function tracing() {
|
|
|
672
683
|
return test.info()._tracing;
|
|
673
684
|
}
|
|
674
685
|
const test = _baseTest.extend(playwrightFixtures);
|
|
686
|
+
function channelToPage(channelOwner) {
|
|
687
|
+
if (channelOwner._type === "Page")
|
|
688
|
+
return channelOwner;
|
|
689
|
+
if (channelOwner._type === "Frame")
|
|
690
|
+
return channelOwner.page();
|
|
691
|
+
return void 0;
|
|
692
|
+
}
|
|
693
|
+
function createErrorCodeframe(message, location) {
|
|
694
|
+
let source;
|
|
695
|
+
try {
|
|
696
|
+
source = import_fs.default.readFileSync(location.file, "utf-8") + "\n//";
|
|
697
|
+
} catch (e) {
|
|
698
|
+
return "";
|
|
699
|
+
}
|
|
700
|
+
return (0, import_babelBundle.codeFrameColumns)(
|
|
701
|
+
source,
|
|
702
|
+
{
|
|
703
|
+
start: {
|
|
704
|
+
line: location.line,
|
|
705
|
+
column: location.column
|
|
706
|
+
}
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
highlightCode: true,
|
|
710
|
+
linesAbove: 5,
|
|
711
|
+
linesBelow: 5,
|
|
712
|
+
message: message.split("\n")[0] || void 0
|
|
713
|
+
}
|
|
714
|
+
);
|
|
715
|
+
}
|
|
675
716
|
// Annotate the CommonJS export names for ESM import in node:
|
|
676
717
|
0 && (module.exports = {
|
|
677
718
|
_baseTest,
|
|
@@ -63,7 +63,6 @@ class TestServerConnection {
|
|
|
63
63
|
this._onStdioEmitter = new events.EventEmitter();
|
|
64
64
|
this._onTestFilesChangedEmitter = new events.EventEmitter();
|
|
65
65
|
this._onLoadTraceRequestedEmitter = new events.EventEmitter();
|
|
66
|
-
this._onRecoverFromStepErrorEmitter = new events.EventEmitter();
|
|
67
66
|
this._lastId = 0;
|
|
68
67
|
this._callbacks = /* @__PURE__ */ new Map();
|
|
69
68
|
this._isClosed = false;
|
|
@@ -72,7 +71,6 @@ class TestServerConnection {
|
|
|
72
71
|
this.onStdio = this._onStdioEmitter.event;
|
|
73
72
|
this.onTestFilesChanged = this._onTestFilesChangedEmitter.event;
|
|
74
73
|
this.onLoadTraceRequested = this._onLoadTraceRequestedEmitter.event;
|
|
75
|
-
this.onRecoverFromStepError = this._onRecoverFromStepErrorEmitter.event;
|
|
76
74
|
this._transport = transport;
|
|
77
75
|
this._transport.onmessage((data) => {
|
|
78
76
|
const message = JSON.parse(data);
|
|
@@ -129,8 +127,6 @@ class TestServerConnection {
|
|
|
129
127
|
this._onTestFilesChangedEmitter.fire(params);
|
|
130
128
|
else if (method === "loadTraceRequested")
|
|
131
129
|
this._onLoadTraceRequestedEmitter.fire(params);
|
|
132
|
-
else if (method === "recoverFromStepError")
|
|
133
|
-
this._onRecoverFromStepErrorEmitter.fire(params);
|
|
134
130
|
}
|
|
135
131
|
async initialize(params) {
|
|
136
132
|
await this._sendMessage("initialize", params);
|
|
@@ -201,9 +197,6 @@ class TestServerConnection {
|
|
|
201
197
|
async closeGracefully(params) {
|
|
202
198
|
await this._sendMessage("closeGracefully", params);
|
|
203
199
|
}
|
|
204
|
-
async resumeAfterStepError(params) {
|
|
205
|
-
await this._sendMessage("resumeAfterStepError", params);
|
|
206
|
-
}
|
|
207
200
|
close() {
|
|
208
201
|
try {
|
|
209
202
|
this._transport.close();
|
package/lib/matchers/expect.js
CHANGED
|
@@ -234,7 +234,7 @@ class ExpectMetaInfoProxyHandler {
|
|
|
234
234
|
infectParentStepsWithError: this._info.isSoft
|
|
235
235
|
};
|
|
236
236
|
const step = testInfo._addStep(stepInfo);
|
|
237
|
-
const reportStepError = (
|
|
237
|
+
const reportStepError = (e) => {
|
|
238
238
|
const jestError = (0, import_matcherHint.isJestError)(e) ? e : null;
|
|
239
239
|
const expectError = jestError ? new import_matcherHint.ExpectError(jestError, customMessage, stackFrames) : void 0;
|
|
240
240
|
if (jestError?.matcherResult.suggestedRebaseline) {
|
|
@@ -243,22 +243,10 @@ class ExpectMetaInfoProxyHandler {
|
|
|
243
243
|
}
|
|
244
244
|
const error = expectError ?? e;
|
|
245
245
|
step.complete({ error });
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
throw error;
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
return (async () => {
|
|
254
|
-
const recoveryResult = await step.recoverFromStepError(expectError);
|
|
255
|
-
if (recoveryResult.status === "recovered")
|
|
256
|
-
return recoveryResult.value;
|
|
257
|
-
if (this._info.isSoft)
|
|
258
|
-
testInfo._failWithError(expectError);
|
|
259
|
-
else
|
|
260
|
-
throw expectError;
|
|
261
|
-
})();
|
|
246
|
+
if (this._info.isSoft)
|
|
247
|
+
testInfo._failWithError(error);
|
|
248
|
+
else
|
|
249
|
+
throw error;
|
|
262
250
|
};
|
|
263
251
|
const finalizer = () => {
|
|
264
252
|
step.complete({});
|
|
@@ -268,11 +256,11 @@ class ExpectMetaInfoProxyHandler {
|
|
|
268
256
|
const callback = () => matcher.call(target, ...args);
|
|
269
257
|
const result = (0, import_utils.currentZone)().with("stepZone", step).run(callback);
|
|
270
258
|
if (result instanceof Promise)
|
|
271
|
-
return result.then(finalizer).catch(reportStepError
|
|
259
|
+
return result.then(finalizer).catch(reportStepError);
|
|
272
260
|
finalizer();
|
|
273
261
|
return result;
|
|
274
262
|
} catch (e) {
|
|
275
|
-
void reportStepError(
|
|
263
|
+
void reportStepError(e);
|
|
276
264
|
}
|
|
277
265
|
};
|
|
278
266
|
}
|
|
@@ -23,6 +23,7 @@ __export(toBeTruthy_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(toBeTruthy_exports);
|
|
24
24
|
var import_util = require("../util");
|
|
25
25
|
var import_matcherHint = require("./matcherHint");
|
|
26
|
+
var import_backend = require("../mcp/browser/backend");
|
|
26
27
|
async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, query, options = {}) {
|
|
27
28
|
(0, import_util.expectTypes)(receiver, [receiverType], matcherName);
|
|
28
29
|
const matcherOptions = {
|
|
@@ -55,6 +56,7 @@ ${printedReceived}`);
|
|
|
55
56
|
const logText = (0, import_util.callLogText)(log);
|
|
56
57
|
return `${header}${logText}`;
|
|
57
58
|
};
|
|
59
|
+
await (0, import_backend.runBrowserBackendOnError)(receiver.page(), message);
|
|
58
60
|
return {
|
|
59
61
|
message,
|
|
60
62
|
pass,
|
package/lib/matchers/toEqual.js
CHANGED
|
@@ -24,6 +24,7 @@ module.exports = __toCommonJS(toEqual_exports);
|
|
|
24
24
|
var import_utils = require("playwright-core/lib/utils");
|
|
25
25
|
var import_util = require("../util");
|
|
26
26
|
var import_matcherHint = require("./matcherHint");
|
|
27
|
+
var import_backend = require("../mcp/browser/backend");
|
|
27
28
|
const EXPECTED_LABEL = "Expected";
|
|
28
29
|
const RECEIVED_LABEL = "Received";
|
|
29
30
|
async function toEqual(matcherName, receiver, receiverType, query, expected, options = {}, messagePreventExtraStatIndent) {
|
|
@@ -78,6 +79,7 @@ ${printedReceived}`;
|
|
|
78
79
|
const header = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", void 0, matcherOptions, timedOut ? timeout : void 0, details, messagePreventExtraStatIndent);
|
|
79
80
|
return `${header}${(0, import_util.callLogText)(log)}`;
|
|
80
81
|
};
|
|
82
|
+
await (0, import_backend.runBrowserBackendOnError)(receiver.page(), message);
|
|
81
83
|
return {
|
|
82
84
|
actual: received,
|
|
83
85
|
expected,
|
|
@@ -26,6 +26,7 @@ var import_util = require("../util");
|
|
|
26
26
|
var import_expect = require("./expect");
|
|
27
27
|
var import_matcherHint = require("./matcherHint");
|
|
28
28
|
var import_expectBundle = require("../common/expectBundle");
|
|
29
|
+
var import_backend = require("../mcp/browser/backend");
|
|
29
30
|
async function toMatchText(matcherName, receiver, receiverType, query, expected, options = {}) {
|
|
30
31
|
(0, import_util.expectTypes)(receiver, [receiverType], matcherName);
|
|
31
32
|
const matcherOptions = {
|
|
@@ -89,6 +90,8 @@ async function toMatchText(matcherName, receiver, receiverType, query, expected,
|
|
|
89
90
|
const hints = (0, import_matcherHint.matcherHint)(this, receiverType === "Locator" ? receiver : void 0, matcherName, options.receiverLabel ?? "locator", void 0, matcherOptions, timedOut ? timeout : void 0, resultDetails, true);
|
|
90
91
|
return hints + (0, import_util.callLogText)(log);
|
|
91
92
|
};
|
|
93
|
+
if (receiverType === "Locator")
|
|
94
|
+
await (0, import_backend.runBrowserBackendOnError)(receiver.page(), message);
|
|
92
95
|
return {
|
|
93
96
|
name: matcherName,
|
|
94
97
|
expected,
|
|
@@ -0,0 +1,88 @@
|
|
|
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 backend_exports = {};
|
|
30
|
+
__export(backend_exports, {
|
|
31
|
+
BrowserBackend: () => BrowserBackend,
|
|
32
|
+
runBrowserBackendOnError: () => runBrowserBackendOnError
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(backend_exports);
|
|
35
|
+
var mcp = __toESM(require("../sdk/exports"));
|
|
36
|
+
var mcpBundle = __toESM(require("../sdk/bundle"));
|
|
37
|
+
var import_tools = require("./tools");
|
|
38
|
+
var import_exports = require("../sdk/exports");
|
|
39
|
+
var import_mdb = require("../sdk/mdb");
|
|
40
|
+
var import_util = require("../../util");
|
|
41
|
+
class BrowserBackend {
|
|
42
|
+
constructor(page) {
|
|
43
|
+
this.name = "Playwright";
|
|
44
|
+
this.version = "0.0.1";
|
|
45
|
+
this._tools = [import_tools.snapshot, import_tools.pickLocator, import_tools.evaluate];
|
|
46
|
+
this._page = page;
|
|
47
|
+
}
|
|
48
|
+
async initialize() {
|
|
49
|
+
}
|
|
50
|
+
async listTools() {
|
|
51
|
+
return [...this._tools.map((tool) => mcp.toMcpTool(tool.schema)), mcp.toMcpTool(doneToolSchema)];
|
|
52
|
+
}
|
|
53
|
+
async callTool(name, args) {
|
|
54
|
+
if (name === "done") {
|
|
55
|
+
this.requestSelfDestruct?.();
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: "Done" }]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const tool = this._tools.find((tool2) => tool2.schema.name === name);
|
|
61
|
+
if (!tool)
|
|
62
|
+
throw new Error(`Tool not found: ${name}. Available tools: ${this._tools.map((tool2) => tool2.schema.name).join(", ")}`);
|
|
63
|
+
const parsedArguments = tool.schema.inputSchema.parse(args || {});
|
|
64
|
+
return await tool.handle(this._page, parsedArguments);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const doneToolSchema = (0, import_exports.defineToolSchema)({
|
|
68
|
+
name: "done",
|
|
69
|
+
title: "Done",
|
|
70
|
+
description: "Done",
|
|
71
|
+
inputSchema: mcpBundle.z.object({}),
|
|
72
|
+
type: "destructive"
|
|
73
|
+
});
|
|
74
|
+
async function runBrowserBackendOnError(page, message) {
|
|
75
|
+
if (!process.env.PLAYWRIGHT_TEST_DEBUGGER_MCP)
|
|
76
|
+
return;
|
|
77
|
+
const introMessage = `Paused on error:
|
|
78
|
+
|
|
79
|
+
${(0, import_util.stripAnsiEscapes)(message())}
|
|
80
|
+
|
|
81
|
+
Try recovering from the error prior to continuing.`;
|
|
82
|
+
await (0, import_mdb.runOnPauseBackendLoop)(process.env.PLAYWRIGHT_TEST_DEBUGGER_MCP, new BrowserBackend(page), introMessage);
|
|
83
|
+
}
|
|
84
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
85
|
+
0 && (module.exports = {
|
|
86
|
+
BrowserBackend,
|
|
87
|
+
runBrowserBackendOnError
|
|
88
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
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 tool_exports = {};
|
|
20
|
+
__export(tool_exports, {
|
|
21
|
+
defineTool: () => defineTool
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(tool_exports);
|
|
24
|
+
function defineTool(tool) {
|
|
25
|
+
return tool;
|
|
26
|
+
}
|
|
27
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
28
|
+
0 && (module.exports = {
|
|
29
|
+
defineTool
|
|
30
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
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 tools_exports = {};
|
|
30
|
+
__export(tools_exports, {
|
|
31
|
+
elementSchema: () => elementSchema,
|
|
32
|
+
evaluate: () => evaluate,
|
|
33
|
+
pickLocator: () => pickLocator,
|
|
34
|
+
snapshot: () => snapshot
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(tools_exports);
|
|
37
|
+
var import_utils = require("playwright-core/lib/utils");
|
|
38
|
+
var import_tool = require("./tool.js");
|
|
39
|
+
var mcp = __toESM(require("../sdk/bundle"));
|
|
40
|
+
const snapshot = (0, import_tool.defineTool)({
|
|
41
|
+
schema: {
|
|
42
|
+
name: "browser_snapshot",
|
|
43
|
+
title: "Page snapshot",
|
|
44
|
+
description: "Capture accessibility snapshot of the current page, this is better than screenshot",
|
|
45
|
+
inputSchema: mcp.z.object({}),
|
|
46
|
+
type: "readOnly"
|
|
47
|
+
},
|
|
48
|
+
handle: async (page, params) => {
|
|
49
|
+
const snapshot2 = await page._snapshotForAI();
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: snapshot2
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const elementSchema = mcp.z.object({
|
|
61
|
+
element: mcp.z.string().describe("Human-readable element description used to obtain permission to interact with the element"),
|
|
62
|
+
ref: mcp.z.string().describe("Exact target element reference from the page snapshot")
|
|
63
|
+
});
|
|
64
|
+
const pickLocator = (0, import_tool.defineTool)({
|
|
65
|
+
schema: {
|
|
66
|
+
name: "browser_pick_locator",
|
|
67
|
+
title: "Pick locator",
|
|
68
|
+
description: "Pick a locator for the given element",
|
|
69
|
+
inputSchema: elementSchema,
|
|
70
|
+
type: "readOnly"
|
|
71
|
+
},
|
|
72
|
+
handle: async (page, params) => {
|
|
73
|
+
const locator = await refLocator(page, params);
|
|
74
|
+
const locatorString = await generateLocator(locator);
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: locatorString
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
const evaluateSchema = mcp.z.object({
|
|
86
|
+
function: mcp.z.string().describe("() => { /* code */ } or (element) => { /* code */ } when element is provided"),
|
|
87
|
+
element: mcp.z.string().optional().describe("Human-readable element description used to obtain permission to interact with the element"),
|
|
88
|
+
ref: mcp.z.string().optional().describe("Exact target element reference from the page snapshot")
|
|
89
|
+
});
|
|
90
|
+
const evaluate = (0, import_tool.defineTool)({
|
|
91
|
+
schema: {
|
|
92
|
+
name: "browser_evaluate",
|
|
93
|
+
title: "Evaluate JavaScript",
|
|
94
|
+
description: "Evaluate JavaScript expression on page or element",
|
|
95
|
+
inputSchema: evaluateSchema,
|
|
96
|
+
type: "destructive"
|
|
97
|
+
},
|
|
98
|
+
handle: async (page, params) => {
|
|
99
|
+
if (params.ref && params.element) {
|
|
100
|
+
const locator = await refLocator(page, { ref: params.ref, element: params.element });
|
|
101
|
+
const result2 = await locator.evaluate(params.function);
|
|
102
|
+
return {
|
|
103
|
+
content: [{ type: "text", text: JSON.stringify(result2, null, 2) || "undefined" }]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const result = await page.evaluate(params.function);
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) || "undefined" }]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
async function refLocator(page, elementRef) {
|
|
113
|
+
const snapshot2 = await page._snapshotForAI();
|
|
114
|
+
if (!snapshot2.includes(`[ref=${elementRef.ref}]`))
|
|
115
|
+
throw new Error(`Ref ${elementRef.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
|
116
|
+
return page.locator(`aria-ref=${elementRef.ref}`).describe(elementRef.element);
|
|
117
|
+
}
|
|
118
|
+
async function generateLocator(locator) {
|
|
119
|
+
try {
|
|
120
|
+
const { resolvedSelector } = await locator._resolveSelector();
|
|
121
|
+
return (0, import_utils.asLocator)("javascript", resolvedSelector);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
throw new Error("Ref not found, likely because element was removed. Use browser_snapshot to see what elements are currently on the page.");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
127
|
+
0 && (module.exports = {
|
|
128
|
+
elementSchema,
|
|
129
|
+
evaluate,
|
|
130
|
+
pickLocator,
|
|
131
|
+
snapshot
|
|
132
|
+
});
|
|
@@ -26,18 +26,20 @@ __export(bundle_exports, {
|
|
|
26
26
|
SSEServerTransport: () => SSEServerTransport,
|
|
27
27
|
Server: () => Server,
|
|
28
28
|
StdioServerTransport: () => StdioServerTransport,
|
|
29
|
+
StreamableHTTPClientTransport: () => StreamableHTTPClientTransport,
|
|
29
30
|
StreamableHTTPServerTransport: () => StreamableHTTPServerTransport,
|
|
30
31
|
z: () => z,
|
|
31
32
|
zodToJsonSchema: () => zodToJsonSchema
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(bundle_exports);
|
|
34
|
-
const bundle = require("
|
|
35
|
-
const zodToJsonSchema =
|
|
35
|
+
const bundle = require("../../mcpBundleImpl");
|
|
36
|
+
const zodToJsonSchema = bundle.zodToJsonSchema;
|
|
36
37
|
const Client = bundle.Client;
|
|
37
38
|
const Server = bundle.Server;
|
|
38
39
|
const SSEServerTransport = bundle.SSEServerTransport;
|
|
39
40
|
const StdioServerTransport = bundle.StdioServerTransport;
|
|
40
41
|
const StreamableHTTPServerTransport = bundle.StreamableHTTPServerTransport;
|
|
42
|
+
const StreamableHTTPClientTransport = bundle.StreamableHTTPClientTransport;
|
|
41
43
|
const CallToolRequestSchema = bundle.CallToolRequestSchema;
|
|
42
44
|
const ListRootsRequestSchema = bundle.ListRootsRequestSchema;
|
|
43
45
|
const ListToolsRequestSchema = bundle.ListToolsRequestSchema;
|
|
@@ -53,6 +55,7 @@ const z = bundle.z;
|
|
|
53
55
|
SSEServerTransport,
|
|
54
56
|
Server,
|
|
55
57
|
StdioServerTransport,
|
|
58
|
+
StreamableHTTPClientTransport,
|
|
56
59
|
StreamableHTTPServerTransport,
|
|
57
60
|
z,
|
|
58
61
|
zodToJsonSchema
|
|
@@ -0,0 +1,49 @@
|
|
|
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 call_exports = {};
|
|
30
|
+
__export(call_exports, {
|
|
31
|
+
callTool: () => callTool
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(call_exports);
|
|
34
|
+
var mcpBundle = __toESM(require("./bundle.js"));
|
|
35
|
+
async function callTool(mcpUrl, name, params) {
|
|
36
|
+
const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(mcpUrl));
|
|
37
|
+
const client = new mcpBundle.Client({ name: "Internal", version: "0.0.0" });
|
|
38
|
+
await client.connect(transport);
|
|
39
|
+
try {
|
|
40
|
+
return await client.callTool({ name, arguments: params });
|
|
41
|
+
} finally {
|
|
42
|
+
await transport.terminateSession();
|
|
43
|
+
await client.close();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
callTool
|
|
49
|
+
});
|
|
@@ -15,16 +15,18 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
15
15
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
16
|
var exports_exports = {};
|
|
17
17
|
module.exports = __toCommonJS(exports_exports);
|
|
18
|
-
__reExport(exports_exports, require("./inProcessTransport
|
|
19
|
-
__reExport(exports_exports, require("./proxyBackend
|
|
20
|
-
__reExport(exports_exports, require("./server
|
|
21
|
-
__reExport(exports_exports, require("./tool
|
|
22
|
-
__reExport(exports_exports, require("./
|
|
18
|
+
__reExport(exports_exports, require("./inProcessTransport"), module.exports);
|
|
19
|
+
__reExport(exports_exports, require("./proxyBackend"), module.exports);
|
|
20
|
+
__reExport(exports_exports, require("./server"), module.exports);
|
|
21
|
+
__reExport(exports_exports, require("./tool"), module.exports);
|
|
22
|
+
__reExport(exports_exports, require("./http"), module.exports);
|
|
23
|
+
__reExport(exports_exports, require("./call"), module.exports);
|
|
23
24
|
// Annotate the CommonJS export names for ESM import in node:
|
|
24
25
|
0 && (module.exports = {
|
|
25
|
-
...require("./inProcessTransport
|
|
26
|
-
...require("./proxyBackend
|
|
27
|
-
...require("./server
|
|
28
|
-
...require("./tool
|
|
29
|
-
...require("./
|
|
26
|
+
...require("./inProcessTransport"),
|
|
27
|
+
...require("./proxyBackend"),
|
|
28
|
+
...require("./server"),
|
|
29
|
+
...require("./tool"),
|
|
30
|
+
...require("./http"),
|
|
31
|
+
...require("./call")
|
|
30
32
|
});
|