playwright-core 1.58.0-alpha-2025-12-07 → 1.58.0-alpha-2025-12-08
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/browsers.json +1 -1
- package/lib/client/page.js +4 -3
- package/lib/client/platform.js +3 -0
- package/lib/protocol/validator.js +19 -5
- package/lib/server/agent/actionRunner.js +58 -0
- package/lib/server/agent/actions.js +16 -0
- package/lib/server/agent/agent.js +123 -0
- package/lib/server/agent/backend.js +77 -0
- package/lib/server/agent/context.js +91 -0
- package/lib/server/agent/tools.js +187 -0
- package/lib/server/browserContext.js +1 -1
- package/lib/server/chromium/chromium.js +1 -3
- package/lib/server/dispatchers/browserDispatcher.js +1 -0
- package/lib/server/dispatchers/pageDispatcher.js +7 -0
- package/lib/server/page.js +1 -1
- package/lib/server/utils/nodePlatform.js +2 -0
- package/lib/utils/isomorphic/protocolMetainfo.js +2 -0
- package/lib/vite/traceViewer/assets/{codeMirrorModule-JphNwIdM.js → codeMirrorModule-CPNe-I5g.js} +1 -1
- package/lib/vite/traceViewer/assets/{defaultSettingsView-C7iHYOsw.js → defaultSettingsView-V7hnXDpz.js} +3 -3
- package/lib/vite/traceViewer/{index.C5w1selH.js → index.YskCIlQ-.js} +1 -1
- package/lib/vite/traceViewer/index.html +2 -2
- package/lib/vite/traceViewer/{uiMode.CCu4MMfA.js → uiMode.CmFFBCQb.js} +1 -1
- package/lib/vite/traceViewer/uiMode.html +2 -2
- package/package.json +1 -1
- package/types/types.d.ts +2 -2
package/browsers.json
CHANGED
package/lib/client/page.js
CHANGED
|
@@ -675,10 +675,11 @@ class Page extends import_channelOwner.ChannelOwner {
|
|
|
675
675
|
return result.pdf;
|
|
676
676
|
}
|
|
677
677
|
async perform(task, options = {}) {
|
|
678
|
-
|
|
678
|
+
await this._channel.perform({ task, ...options });
|
|
679
679
|
}
|
|
680
|
-
extract(query, schema, options = {}) {
|
|
681
|
-
|
|
680
|
+
async extract(query, schema, options = {}) {
|
|
681
|
+
const { result } = await this._channel.extract({ query, schema: this._platform.zodToJsonSchema(schema), ...options });
|
|
682
|
+
return result;
|
|
682
683
|
}
|
|
683
684
|
async _snapshotForAI(options = {}) {
|
|
684
685
|
return await this._channel.snapshotForAI({ timeout: this._timeoutSettings.timeout(options), track: options.track });
|
package/lib/client/platform.js
CHANGED
|
@@ -66,6 +66,9 @@ const emptyPlatform = {
|
|
|
66
66
|
streamWritable: (channel) => {
|
|
67
67
|
throw new Error("Streams are not available");
|
|
68
68
|
},
|
|
69
|
+
zodToJsonSchema: (schema) => {
|
|
70
|
+
throw new Error("Zod is not available");
|
|
71
|
+
},
|
|
69
72
|
zones: { empty: noopZone, current: () => noopZone }
|
|
70
73
|
};
|
|
71
74
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -611,7 +611,7 @@ import_validatorPrimitives.scheme.BrowserTypeLaunchPersistentContextParams = (0,
|
|
|
611
611
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
612
612
|
provider: import_validatorPrimitives.tString,
|
|
613
613
|
model: import_validatorPrimitives.tString,
|
|
614
|
-
|
|
614
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
615
615
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
616
616
|
})),
|
|
617
617
|
userDataDir: import_validatorPrimitives.tString,
|
|
@@ -709,7 +709,7 @@ import_validatorPrimitives.scheme.BrowserNewContextParams = (0, import_validator
|
|
|
709
709
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
710
710
|
provider: import_validatorPrimitives.tString,
|
|
711
711
|
model: import_validatorPrimitives.tString,
|
|
712
|
-
|
|
712
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
713
713
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
714
714
|
})),
|
|
715
715
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
@@ -786,7 +786,7 @@ import_validatorPrimitives.scheme.BrowserNewContextForReuseParams = (0, import_v
|
|
|
786
786
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
787
787
|
provider: import_validatorPrimitives.tString,
|
|
788
788
|
model: import_validatorPrimitives.tString,
|
|
789
|
-
|
|
789
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
790
790
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
791
791
|
})),
|
|
792
792
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
@@ -908,7 +908,7 @@ import_validatorPrimitives.scheme.BrowserContextInitializer = (0, import_validat
|
|
|
908
908
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
909
909
|
provider: import_validatorPrimitives.tString,
|
|
910
910
|
model: import_validatorPrimitives.tString,
|
|
911
|
-
|
|
911
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
912
912
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
913
913
|
}))
|
|
914
914
|
})
|
|
@@ -1512,6 +1512,20 @@ import_validatorPrimitives.scheme.PageUpdateSubscriptionParams = (0, import_vali
|
|
|
1512
1512
|
enabled: import_validatorPrimitives.tBoolean
|
|
1513
1513
|
});
|
|
1514
1514
|
import_validatorPrimitives.scheme.PageUpdateSubscriptionResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
1515
|
+
import_validatorPrimitives.scheme.PagePerformParams = (0, import_validatorPrimitives.tObject)({
|
|
1516
|
+
task: import_validatorPrimitives.tString,
|
|
1517
|
+
key: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
1518
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1519
|
+
});
|
|
1520
|
+
import_validatorPrimitives.scheme.PagePerformResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
1521
|
+
import_validatorPrimitives.scheme.PageExtractParams = (0, import_validatorPrimitives.tObject)({
|
|
1522
|
+
query: import_validatorPrimitives.tString,
|
|
1523
|
+
schema: import_validatorPrimitives.tAny,
|
|
1524
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1525
|
+
});
|
|
1526
|
+
import_validatorPrimitives.scheme.PageExtractResult = (0, import_validatorPrimitives.tObject)({
|
|
1527
|
+
result: import_validatorPrimitives.tAny
|
|
1528
|
+
});
|
|
1515
1529
|
import_validatorPrimitives.scheme.FrameInitializer = (0, import_validatorPrimitives.tObject)({
|
|
1516
1530
|
url: import_validatorPrimitives.tString,
|
|
1517
1531
|
name: import_validatorPrimitives.tString,
|
|
@@ -2803,7 +2817,7 @@ import_validatorPrimitives.scheme.AndroidDeviceLaunchBrowserParams = (0, import_
|
|
|
2803
2817
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
2804
2818
|
provider: import_validatorPrimitives.tString,
|
|
2805
2819
|
model: import_validatorPrimitives.tString,
|
|
2806
|
-
|
|
2820
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2807
2821
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
2808
2822
|
})),
|
|
2809
2823
|
pkg: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
@@ -0,0 +1,58 @@
|
|
|
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 actionRunner_exports = {};
|
|
20
|
+
__export(actionRunner_exports, {
|
|
21
|
+
runAction: () => runAction
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(actionRunner_exports);
|
|
24
|
+
async function runAction(progress, page, action) {
|
|
25
|
+
const frame = page.mainFrame();
|
|
26
|
+
switch (action.method) {
|
|
27
|
+
case "click":
|
|
28
|
+
await frame.click(progress, action.selector, { ...action.options, ...strictTrue });
|
|
29
|
+
break;
|
|
30
|
+
case "drag":
|
|
31
|
+
await frame.dragAndDrop(progress, action.sourceSelector, action.targetSelector, { ...strictTrue });
|
|
32
|
+
break;
|
|
33
|
+
case "hover":
|
|
34
|
+
await frame.hover(progress, action.selector, { ...action.options, ...strictTrue });
|
|
35
|
+
break;
|
|
36
|
+
case "selectOption":
|
|
37
|
+
await frame.selectOption(progress, action.selector, [], action.values.map((a) => ({ value: a })), { ...strictTrue });
|
|
38
|
+
break;
|
|
39
|
+
case "pressKey":
|
|
40
|
+
await page.keyboard.press(progress, action.key);
|
|
41
|
+
break;
|
|
42
|
+
case "pressSequentially":
|
|
43
|
+
await frame.type(progress, action.selector, action.text, { ...strictTrue });
|
|
44
|
+
if (action.submit)
|
|
45
|
+
await page.keyboard.press(progress, "Enter");
|
|
46
|
+
break;
|
|
47
|
+
case "fill":
|
|
48
|
+
await frame.fill(progress, action.selector, action.text, { ...strictTrue });
|
|
49
|
+
if (action.submit)
|
|
50
|
+
await page.keyboard.press(progress, "Enter");
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const strictTrue = { strict: true };
|
|
55
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
56
|
+
0 && (module.exports = {
|
|
57
|
+
runAction
|
|
58
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var actions_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(actions_exports);
|
|
@@ -0,0 +1,123 @@
|
|
|
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 agent_exports = {};
|
|
30
|
+
__export(agent_exports, {
|
|
31
|
+
pageExtract: () => pageExtract,
|
|
32
|
+
pagePerform: () => pagePerform
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(agent_exports);
|
|
35
|
+
var import_fs = __toESM(require("fs"));
|
|
36
|
+
var import_backend = require("./backend");
|
|
37
|
+
var import_utilsBundle = require("../../utilsBundle");
|
|
38
|
+
var import_mcpBundle = require("../../mcpBundle");
|
|
39
|
+
var import_actionRunner = require("./actionRunner");
|
|
40
|
+
var import_context = require("./context");
|
|
41
|
+
async function pagePerform(progress, page, options) {
|
|
42
|
+
const context = new import_context.Context(progress, page);
|
|
43
|
+
if (await cachedPerform(context, options))
|
|
44
|
+
return;
|
|
45
|
+
await perform(context, options.task, (0, import_mcpBundle.zodToJsonSchema)(import_mcpBundle.z.object({
|
|
46
|
+
error: import_mcpBundle.z.string().optional().describe("An error message if the task could not be completed successfully")
|
|
47
|
+
})), options);
|
|
48
|
+
await updateCache(context, options);
|
|
49
|
+
}
|
|
50
|
+
async function pageExtract(progress, page, options) {
|
|
51
|
+
const context = new import_context.Context(progress, page);
|
|
52
|
+
const task = `
|
|
53
|
+
### Instructions
|
|
54
|
+
Extract the following information from the page. Do not perform any actions, just extract the information.
|
|
55
|
+
|
|
56
|
+
### Query
|
|
57
|
+
${options.query}`;
|
|
58
|
+
return await perform(context, task, options.schema, options);
|
|
59
|
+
}
|
|
60
|
+
async function perform(context, userTask, resultSchema, options = {}) {
|
|
61
|
+
const { progress, page } = context;
|
|
62
|
+
const browserContext = page.browserContext;
|
|
63
|
+
if (!browserContext._options.agent)
|
|
64
|
+
throw new Error(`page.perform() and page.extract() require the agent to be set on the browser context`);
|
|
65
|
+
const { full } = await page.snapshotForAI(progress);
|
|
66
|
+
const { tools, callTool } = (0, import_backend.toolsForLoop)(context);
|
|
67
|
+
const loop = new import_mcpBundle.Loop(browserContext._options.agent.provider, {
|
|
68
|
+
model: browserContext._options.agent.model,
|
|
69
|
+
summarize: true,
|
|
70
|
+
debug: import_utilsBundle.debug,
|
|
71
|
+
callTool,
|
|
72
|
+
tools,
|
|
73
|
+
...options
|
|
74
|
+
});
|
|
75
|
+
const task = `${userTask}
|
|
76
|
+
|
|
77
|
+
### Page snapshot
|
|
78
|
+
${full}
|
|
79
|
+
`;
|
|
80
|
+
return await loop.run(task, {
|
|
81
|
+
resultSchema
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
const allCaches = /* @__PURE__ */ new Map();
|
|
85
|
+
async function cachedPerform(context, options) {
|
|
86
|
+
const agentSettings = context.page.browserContext._options.agent;
|
|
87
|
+
if (!agentSettings?.cacheFile || agentSettings.cacheMode === "ignore")
|
|
88
|
+
return false;
|
|
89
|
+
const cache = await cachedActions(agentSettings.cacheFile);
|
|
90
|
+
const cacheKey = options.key ?? options.task;
|
|
91
|
+
const actions = cache[cacheKey];
|
|
92
|
+
if (!actions) {
|
|
93
|
+
if (agentSettings.cacheMode === "force")
|
|
94
|
+
throw new Error(`No cached actions for key "${cacheKey}", but cache mode is set to "force"`);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
for (const action of actions)
|
|
98
|
+
await (0, import_actionRunner.runAction)(context.progress, context.page, action);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
async function updateCache(context, options) {
|
|
102
|
+
const cacheFile = context.page.browserContext._options.agent?.cacheFile;
|
|
103
|
+
if (!cacheFile)
|
|
104
|
+
return;
|
|
105
|
+
const cache = await cachedActions(cacheFile);
|
|
106
|
+
const cacheKey = options.key ?? options.task;
|
|
107
|
+
cache[cacheKey] = context.actions;
|
|
108
|
+
await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(cache, void 0, 2));
|
|
109
|
+
}
|
|
110
|
+
async function cachedActions(cacheFile) {
|
|
111
|
+
let cache = allCaches.get(cacheFile);
|
|
112
|
+
if (!cache) {
|
|
113
|
+
const text = await import_fs.default.promises.readFile(cacheFile, "utf-8").catch(() => "{}");
|
|
114
|
+
cache = JSON.parse(text);
|
|
115
|
+
allCaches.set(cacheFile, cache);
|
|
116
|
+
}
|
|
117
|
+
return cache;
|
|
118
|
+
}
|
|
119
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
120
|
+
0 && (module.exports = {
|
|
121
|
+
pageExtract,
|
|
122
|
+
pagePerform
|
|
123
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
toolsForLoop: () => toolsForLoop
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(backend_exports);
|
|
34
|
+
var import_tools = __toESM(require("./tools"));
|
|
35
|
+
var import_progress = require("../progress");
|
|
36
|
+
var import_mcpBundle = require("../../mcpBundle");
|
|
37
|
+
function toolsForLoop(context) {
|
|
38
|
+
const tools = import_tools.default.map((tool) => {
|
|
39
|
+
const result = {
|
|
40
|
+
name: tool.schema.name,
|
|
41
|
+
description: tool.schema.description,
|
|
42
|
+
inputSchema: (0, import_mcpBundle.zodToJsonSchema)(tool.schema.inputSchema)
|
|
43
|
+
};
|
|
44
|
+
return result;
|
|
45
|
+
});
|
|
46
|
+
const callTool = async (params) => {
|
|
47
|
+
const tool = import_tools.default.find((t) => t.schema.name === params.name);
|
|
48
|
+
if (!tool) {
|
|
49
|
+
return {
|
|
50
|
+
content: [{
|
|
51
|
+
type: "text",
|
|
52
|
+
text: `Tool ${params.name} not found. Available tools: ${import_tools.default.map((t) => t.schema.name)}`
|
|
53
|
+
}],
|
|
54
|
+
isError: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const progressController = new import_progress.ProgressController();
|
|
58
|
+
try {
|
|
59
|
+
return await progressController.run(async (progress) => {
|
|
60
|
+
return await tool.handle(context, params.arguments);
|
|
61
|
+
});
|
|
62
|
+
} catch (error) {
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: error.message }],
|
|
65
|
+
isError: true
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
tools,
|
|
71
|
+
callTool
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
75
|
+
0 && (module.exports = {
|
|
76
|
+
toolsForLoop
|
|
77
|
+
});
|
|
@@ -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 context_exports = {};
|
|
20
|
+
__export(context_exports, {
|
|
21
|
+
Context: () => Context
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(context_exports);
|
|
24
|
+
var import_browserContext = require("../browserContext");
|
|
25
|
+
var import_actionRunner = require("./actionRunner");
|
|
26
|
+
class Context {
|
|
27
|
+
constructor(progress, page) {
|
|
28
|
+
this.actions = [];
|
|
29
|
+
this.progress = progress;
|
|
30
|
+
this.page = page;
|
|
31
|
+
}
|
|
32
|
+
async runAction(action) {
|
|
33
|
+
await this.waitForCompletion(() => (0, import_actionRunner.runAction)(this.progress, this.page, action));
|
|
34
|
+
this.actions.push(action);
|
|
35
|
+
return await this.snapshotResult();
|
|
36
|
+
}
|
|
37
|
+
async waitForCompletion(callback) {
|
|
38
|
+
const requests = [];
|
|
39
|
+
const requestListener = (request) => requests.push(request);
|
|
40
|
+
const disposeListeners = () => {
|
|
41
|
+
this.page.browserContext.off(import_browserContext.BrowserContext.Events.Request, requestListener);
|
|
42
|
+
};
|
|
43
|
+
let result;
|
|
44
|
+
try {
|
|
45
|
+
result = await callback();
|
|
46
|
+
await this.progress.wait(500);
|
|
47
|
+
} finally {
|
|
48
|
+
disposeListeners();
|
|
49
|
+
}
|
|
50
|
+
const requestedNavigation = requests.some((request) => request.isNavigationRequest());
|
|
51
|
+
if (requestedNavigation) {
|
|
52
|
+
await this.page.performActionPreChecks(this.progress);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
const fiveSeconds = new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
56
|
+
for (const request of requests) {
|
|
57
|
+
if (request.failure())
|
|
58
|
+
continue;
|
|
59
|
+
const response = Promise.race([request.response(), fiveSeconds]);
|
|
60
|
+
await this.progress.race(response);
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
async snapshotResult() {
|
|
65
|
+
const { full } = await this.page.snapshotForAI(this.progress);
|
|
66
|
+
const text = [`# Page snapshot
|
|
67
|
+
${full}`];
|
|
68
|
+
return {
|
|
69
|
+
_meta: {
|
|
70
|
+
"dev.lowire/state": {
|
|
71
|
+
"Page snapshot": full
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
content: [{ type: "text", text: text.join("\n\n") }]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async refSelectors(params) {
|
|
78
|
+
return Promise.all(params.map(async (param) => {
|
|
79
|
+
try {
|
|
80
|
+
const { resolvedSelector } = await this.page.mainFrame().resolveSelector(this.progress, `aria-ref=${param.ref}`);
|
|
81
|
+
return resolvedSelector;
|
|
82
|
+
} catch (e) {
|
|
83
|
+
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
|
84
|
+
}
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
89
|
+
0 && (module.exports = {
|
|
90
|
+
Context
|
|
91
|
+
});
|
|
@@ -0,0 +1,187 @@
|
|
|
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 tools_exports = {};
|
|
20
|
+
__export(tools_exports, {
|
|
21
|
+
default: () => tools_default
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(tools_exports);
|
|
24
|
+
var import_mcpBundle = require("../../mcpBundle");
|
|
25
|
+
function defineTool(tool) {
|
|
26
|
+
return tool;
|
|
27
|
+
}
|
|
28
|
+
const snapshot = defineTool({
|
|
29
|
+
schema: {
|
|
30
|
+
name: "browser_snapshot",
|
|
31
|
+
title: "Page snapshot",
|
|
32
|
+
description: "Capture accessibility snapshot of the current page, this is better than screenshot",
|
|
33
|
+
inputSchema: import_mcpBundle.z.object({})
|
|
34
|
+
},
|
|
35
|
+
handle: async (context, params) => {
|
|
36
|
+
return await context.snapshotResult();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
const elementSchema = import_mcpBundle.z.object({
|
|
40
|
+
element: import_mcpBundle.z.string().describe("Human-readable element description used to obtain permission to interact with the element"),
|
|
41
|
+
ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
|
|
42
|
+
});
|
|
43
|
+
const clickSchema = elementSchema.extend({
|
|
44
|
+
doubleClick: import_mcpBundle.z.boolean().optional().describe("Whether to perform a double click instead of a single click"),
|
|
45
|
+
button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to click, defaults to left"),
|
|
46
|
+
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
|
|
47
|
+
});
|
|
48
|
+
const click = defineTool({
|
|
49
|
+
schema: {
|
|
50
|
+
name: "browser_click",
|
|
51
|
+
title: "Click",
|
|
52
|
+
description: "Perform click on a web page",
|
|
53
|
+
inputSchema: clickSchema
|
|
54
|
+
},
|
|
55
|
+
handle: async (context, params) => {
|
|
56
|
+
const [selector] = await context.refSelectors([params]);
|
|
57
|
+
return await context.runAction({
|
|
58
|
+
method: "click",
|
|
59
|
+
selector,
|
|
60
|
+
options: {
|
|
61
|
+
button: params.button,
|
|
62
|
+
modifiers: params.modifiers,
|
|
63
|
+
clickCount: params.doubleClick ? 2 : void 0
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const drag = defineTool({
|
|
69
|
+
schema: {
|
|
70
|
+
name: "browser_drag",
|
|
71
|
+
title: "Drag mouse",
|
|
72
|
+
description: "Perform drag and drop between two elements",
|
|
73
|
+
inputSchema: import_mcpBundle.z.object({
|
|
74
|
+
startElement: import_mcpBundle.z.string().describe("Human-readable source element description used to obtain the permission to interact with the element"),
|
|
75
|
+
startRef: import_mcpBundle.z.string().describe("Exact source element reference from the page snapshot"),
|
|
76
|
+
endElement: import_mcpBundle.z.string().describe("Human-readable target element description used to obtain the permission to interact with the element"),
|
|
77
|
+
endRef: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
|
|
78
|
+
})
|
|
79
|
+
},
|
|
80
|
+
handle: async (context, params) => {
|
|
81
|
+
const [sourceSelector, targetSelector] = await context.refSelectors([
|
|
82
|
+
{ ref: params.startRef, element: params.startElement },
|
|
83
|
+
{ ref: params.endRef, element: params.endElement }
|
|
84
|
+
]);
|
|
85
|
+
return await context.runAction({
|
|
86
|
+
method: "drag",
|
|
87
|
+
sourceSelector,
|
|
88
|
+
targetSelector
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
const hoverSchema = elementSchema.extend({
|
|
93
|
+
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
|
|
94
|
+
});
|
|
95
|
+
const hover = defineTool({
|
|
96
|
+
schema: {
|
|
97
|
+
name: "browser_hover",
|
|
98
|
+
title: "Hover mouse",
|
|
99
|
+
description: "Hover over element on page",
|
|
100
|
+
inputSchema: hoverSchema
|
|
101
|
+
},
|
|
102
|
+
handle: async (context, params) => {
|
|
103
|
+
const [selector] = await context.refSelectors([params]);
|
|
104
|
+
return await context.runAction({
|
|
105
|
+
method: "hover",
|
|
106
|
+
selector,
|
|
107
|
+
options: {
|
|
108
|
+
modifiers: params.modifiers
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
const selectOptionSchema = elementSchema.extend({
|
|
114
|
+
values: import_mcpBundle.z.array(import_mcpBundle.z.string()).describe("Array of values to select in the dropdown. This can be a single value or multiple values.")
|
|
115
|
+
});
|
|
116
|
+
const selectOption = defineTool({
|
|
117
|
+
schema: {
|
|
118
|
+
name: "browser_select_option",
|
|
119
|
+
title: "Select option",
|
|
120
|
+
description: "Select an option in a dropdown",
|
|
121
|
+
inputSchema: selectOptionSchema
|
|
122
|
+
},
|
|
123
|
+
handle: async (context, params) => {
|
|
124
|
+
const [selector] = await context.refSelectors([params]);
|
|
125
|
+
return await context.runAction({
|
|
126
|
+
method: "selectOption",
|
|
127
|
+
selector,
|
|
128
|
+
values: params.values
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
const pressKey = defineTool({
|
|
133
|
+
schema: {
|
|
134
|
+
name: "browser_press_key",
|
|
135
|
+
title: "Press a key",
|
|
136
|
+
description: "Press a key on the keyboard",
|
|
137
|
+
inputSchema: import_mcpBundle.z.object({
|
|
138
|
+
key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`")
|
|
139
|
+
})
|
|
140
|
+
},
|
|
141
|
+
handle: async (context, params) => {
|
|
142
|
+
return await context.runAction({
|
|
143
|
+
method: "pressKey",
|
|
144
|
+
key: params.key
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
const typeSchema = elementSchema.extend({
|
|
149
|
+
text: import_mcpBundle.z.string().describe("Text to type into the element"),
|
|
150
|
+
submit: import_mcpBundle.z.boolean().optional().describe("Whether to submit entered text (press Enter after)"),
|
|
151
|
+
slowly: import_mcpBundle.z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
|
|
152
|
+
});
|
|
153
|
+
const type = defineTool({
|
|
154
|
+
schema: {
|
|
155
|
+
name: "browser_type",
|
|
156
|
+
title: "Type text",
|
|
157
|
+
description: "Type text into editable element",
|
|
158
|
+
inputSchema: typeSchema
|
|
159
|
+
},
|
|
160
|
+
handle: async (context, params) => {
|
|
161
|
+
const [selector] = await context.refSelectors([params]);
|
|
162
|
+
if (params.slowly) {
|
|
163
|
+
return await context.runAction({
|
|
164
|
+
method: "pressSequentially",
|
|
165
|
+
selector,
|
|
166
|
+
text: params.text,
|
|
167
|
+
submit: params.submit
|
|
168
|
+
});
|
|
169
|
+
} else {
|
|
170
|
+
return await context.runAction({
|
|
171
|
+
method: "fill",
|
|
172
|
+
selector,
|
|
173
|
+
text: params.text,
|
|
174
|
+
submit: params.submit
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
var tools_default = [
|
|
180
|
+
snapshot,
|
|
181
|
+
click,
|
|
182
|
+
drag,
|
|
183
|
+
hover,
|
|
184
|
+
selectOption,
|
|
185
|
+
pressKey,
|
|
186
|
+
type
|
|
187
|
+
];
|
|
@@ -145,7 +145,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
|
|
|
145
145
|
return true;
|
|
146
146
|
}
|
|
147
147
|
static reusableContextHash(params) {
|
|
148
|
-
const paramsCopy = { ...params
|
|
148
|
+
const paramsCopy = { ...params };
|
|
149
149
|
if (paramsCopy.selectorEngines?.length === 0)
|
|
150
150
|
delete paramsCopy.selectorEngines;
|
|
151
151
|
for (const k of Object.keys(paramsCopy)) {
|
|
@@ -279,9 +279,7 @@ class Chromium extends import_browserType.BrowserType {
|
|
|
279
279
|
if (args.find((arg) => !arg.startsWith("-")))
|
|
280
280
|
throw new Error("Arguments can not specify page to be opened");
|
|
281
281
|
const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
|
|
282
|
-
|
|
283
|
-
chromeArguments.push("--enable-unsafe-swiftshader");
|
|
284
|
-
}
|
|
282
|
+
chromeArguments.push("--enable-unsafe-swiftshader");
|
|
285
283
|
if (options.headless) {
|
|
286
284
|
chromeArguments.push("--headless");
|
|
287
285
|
chromeArguments.push(
|