playwright-core 1.58.0-alpha-2025-12-07 → 1.58.0-alpha-2025-12-09
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 +3 -3
- package/lib/client/browserContext.js +7 -0
- package/lib/client/page.js +4 -3
- package/lib/client/platform.js +3 -0
- package/lib/protocol/validator.js +29 -10
- package/lib/server/agent/actionRunner.js +68 -0
- package/lib/server/agent/actions.js +16 -0
- package/lib/server/agent/agent.js +122 -0
- package/lib/server/agent/backend.js +77 -0
- package/lib/server/agent/context.js +115 -0
- package/lib/server/agent/tools.js +229 -0
- package/lib/server/bidi/bidiNetworkManager.js +1 -1
- package/lib/server/bidi/bidiPage.js +3 -1
- package/lib/server/browserContext.js +2 -2
- package/lib/server/chromium/chromium.js +1 -3
- package/lib/server/chromium/chromiumSwitches.js +0 -2
- package/lib/server/chromium/crBrowser.js +1 -1
- package/lib/server/chromium/crNetworkManager.js +39 -2
- package/lib/server/chromium/crPage.js +14 -81
- package/lib/server/deviceDescriptorsSource.json +2 -2
- package/lib/server/dispatchers/browserDispatcher.js +1 -0
- package/lib/server/dispatchers/pageDispatcher.js +7 -0
- package/lib/server/firefox/ffNetworkManager.js +2 -2
- package/lib/server/firefox/ffPage.js +9 -8
- package/lib/server/frames.js +2 -2
- package/lib/server/network.js +3 -0
- package/lib/server/page.js +5 -65
- package/lib/server/progress.js +3 -2
- package/lib/server/registry/index.js +1 -1
- package/lib/server/screencast.js +191 -0
- package/lib/server/trace/recorder/tracing.js +5 -5
- package/lib/server/utils/nodePlatform.js +2 -0
- package/lib/server/{chromium/videoRecorder.js → videoRecorder.js} +3 -3
- package/lib/server/webkit/wkBrowser.js +1 -1
- package/lib/server/webkit/wkInterceptableRequest.js +29 -1
- package/lib/server/webkit/wkPage.js +20 -40
- 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 +10 -5
package/browsers.json
CHANGED
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"name": "firefox",
|
|
34
|
-
"revision": "
|
|
34
|
+
"revision": "1504",
|
|
35
35
|
"installByDefault": true,
|
|
36
|
-
"browserVersion": "145.0.
|
|
36
|
+
"browserVersion": "145.0.2",
|
|
37
37
|
"title": "Firefox"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "webkit",
|
|
48
|
-
"revision": "
|
|
48
|
+
"revision": "2237",
|
|
49
49
|
"installByDefault": true,
|
|
50
50
|
"revisionOverrides": {
|
|
51
51
|
"debian11-x64": "2105",
|
|
@@ -493,6 +493,7 @@ async function prepareBrowserContextParams(platform, options) {
|
|
|
493
493
|
network.validateHeaders(options.extraHTTPHeaders);
|
|
494
494
|
const contextParams = {
|
|
495
495
|
...options,
|
|
496
|
+
agent: toAgentProtocol(options.agent),
|
|
496
497
|
viewport: options.viewport === null ? void 0 : options.viewport,
|
|
497
498
|
noDefaultViewport: options.viewport === null,
|
|
498
499
|
extraHTTPHeaders: options.extraHTTPHeaders ? (0, import_headers.headersObjectToArray)(options.extraHTTPHeaders) : void 0,
|
|
@@ -515,6 +516,12 @@ async function prepareBrowserContextParams(platform, options) {
|
|
|
515
516
|
contextParams.recordVideo.dir = platform.path().resolve(contextParams.recordVideo.dir);
|
|
516
517
|
return contextParams;
|
|
517
518
|
}
|
|
519
|
+
function toAgentProtocol(agent) {
|
|
520
|
+
if (!agent)
|
|
521
|
+
return void 0;
|
|
522
|
+
const secrets = agent.secrets ? Object.entries(agent.secrets).map(([name, value]) => ({ name, value })) : void 0;
|
|
523
|
+
return { ...agent, secrets };
|
|
524
|
+
}
|
|
518
525
|
function toAcceptDownloadsProtocol(acceptDownloads) {
|
|
519
526
|
if (acceptDownloads === void 0)
|
|
520
527
|
return void 0;
|
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,8 +611,9 @@ 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
|
-
|
|
615
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
614
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
615
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
616
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
616
617
|
})),
|
|
617
618
|
userDataDir: import_validatorPrimitives.tString,
|
|
618
619
|
slowMo: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tFloat)
|
|
@@ -709,8 +710,9 @@ import_validatorPrimitives.scheme.BrowserNewContextParams = (0, import_validator
|
|
|
709
710
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
710
711
|
provider: import_validatorPrimitives.tString,
|
|
711
712
|
model: import_validatorPrimitives.tString,
|
|
712
|
-
|
|
713
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
713
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
714
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
715
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
714
716
|
})),
|
|
715
717
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
716
718
|
server: import_validatorPrimitives.tString,
|
|
@@ -786,8 +788,9 @@ import_validatorPrimitives.scheme.BrowserNewContextForReuseParams = (0, import_v
|
|
|
786
788
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
787
789
|
provider: import_validatorPrimitives.tString,
|
|
788
790
|
model: import_validatorPrimitives.tString,
|
|
789
|
-
|
|
790
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
791
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
792
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
793
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
791
794
|
})),
|
|
792
795
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
793
796
|
server: import_validatorPrimitives.tString,
|
|
@@ -908,8 +911,9 @@ import_validatorPrimitives.scheme.BrowserContextInitializer = (0, import_validat
|
|
|
908
911
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
909
912
|
provider: import_validatorPrimitives.tString,
|
|
910
913
|
model: import_validatorPrimitives.tString,
|
|
911
|
-
|
|
912
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
914
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
915
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
916
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
913
917
|
}))
|
|
914
918
|
})
|
|
915
919
|
});
|
|
@@ -1512,6 +1516,20 @@ import_validatorPrimitives.scheme.PageUpdateSubscriptionParams = (0, import_vali
|
|
|
1512
1516
|
enabled: import_validatorPrimitives.tBoolean
|
|
1513
1517
|
});
|
|
1514
1518
|
import_validatorPrimitives.scheme.PageUpdateSubscriptionResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
1519
|
+
import_validatorPrimitives.scheme.PagePerformParams = (0, import_validatorPrimitives.tObject)({
|
|
1520
|
+
task: import_validatorPrimitives.tString,
|
|
1521
|
+
key: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
1522
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1523
|
+
});
|
|
1524
|
+
import_validatorPrimitives.scheme.PagePerformResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
1525
|
+
import_validatorPrimitives.scheme.PageExtractParams = (0, import_validatorPrimitives.tObject)({
|
|
1526
|
+
query: import_validatorPrimitives.tString,
|
|
1527
|
+
schema: import_validatorPrimitives.tAny,
|
|
1528
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1529
|
+
});
|
|
1530
|
+
import_validatorPrimitives.scheme.PageExtractResult = (0, import_validatorPrimitives.tObject)({
|
|
1531
|
+
result: import_validatorPrimitives.tAny
|
|
1532
|
+
});
|
|
1515
1533
|
import_validatorPrimitives.scheme.FrameInitializer = (0, import_validatorPrimitives.tObject)({
|
|
1516
1534
|
url: import_validatorPrimitives.tString,
|
|
1517
1535
|
name: import_validatorPrimitives.tString,
|
|
@@ -2803,8 +2821,9 @@ import_validatorPrimitives.scheme.AndroidDeviceLaunchBrowserParams = (0, import_
|
|
|
2803
2821
|
agent: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
2804
2822
|
provider: import_validatorPrimitives.tString,
|
|
2805
2823
|
model: import_validatorPrimitives.tString,
|
|
2806
|
-
|
|
2807
|
-
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"]))
|
|
2824
|
+
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2825
|
+
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
2826
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
2808
2827
|
})),
|
|
2809
2828
|
pkg: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2810
2829
|
args: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)(import_validatorPrimitives.tString)),
|
|
@@ -0,0 +1,68 @@
|
|
|
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, secrets) {
|
|
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.labels.map((a) => ({ label: a })), { ...strictTrue });
|
|
38
|
+
break;
|
|
39
|
+
case "pressKey":
|
|
40
|
+
await page.keyboard.press(progress, action.key);
|
|
41
|
+
break;
|
|
42
|
+
case "pressSequentially": {
|
|
43
|
+
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
|
44
|
+
await frame.type(progress, action.selector, secret, { ...strictTrue });
|
|
45
|
+
if (action.submit)
|
|
46
|
+
await page.keyboard.press(progress, "Enter");
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case "fill": {
|
|
50
|
+
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
|
|
51
|
+
await frame.fill(progress, action.selector, secret, { ...strictTrue });
|
|
52
|
+
if (action.submit)
|
|
53
|
+
await page.keyboard.press(progress, "Enter");
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "setChecked":
|
|
57
|
+
if (action.checked)
|
|
58
|
+
await frame.check(progress, action.selector, { ...strictTrue });
|
|
59
|
+
else
|
|
60
|
+
await frame.uncheck(progress, action.selector, { ...strictTrue });
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const strictTrue = { strict: true };
|
|
65
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
66
|
+
0 && (module.exports = {
|
|
67
|
+
runAction
|
|
68
|
+
});
|
|
@@ -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,122 @@
|
|
|
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
|
+
if (!context.options?.cacheFile || context.options.cacheMode === "ignore")
|
|
87
|
+
return false;
|
|
88
|
+
const cache = await cachedActions(context.options.cacheFile);
|
|
89
|
+
const cacheKey = options.key ?? options.task;
|
|
90
|
+
const actions = cache[cacheKey];
|
|
91
|
+
if (!actions) {
|
|
92
|
+
if (context.options.cacheMode === "force")
|
|
93
|
+
throw new Error(`No cached actions for key "${cacheKey}", but cache mode is set to "force"`);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
for (const action of actions)
|
|
97
|
+
await (0, import_actionRunner.runAction)(context.progress, context.page, action, context.options.secrets ?? []);
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
async function updateCache(context, options) {
|
|
101
|
+
const cacheFile = context.options?.cacheFile;
|
|
102
|
+
if (!cacheFile)
|
|
103
|
+
return;
|
|
104
|
+
const cache = await cachedActions(cacheFile);
|
|
105
|
+
const cacheKey = options.key ?? options.task;
|
|
106
|
+
cache[cacheKey] = context.actions;
|
|
107
|
+
await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(cache, void 0, 2));
|
|
108
|
+
}
|
|
109
|
+
async function cachedActions(cacheFile) {
|
|
110
|
+
let cache = allCaches.get(cacheFile);
|
|
111
|
+
if (!cache) {
|
|
112
|
+
const text = await import_fs.default.promises.readFile(cacheFile, "utf-8").catch(() => "{}");
|
|
113
|
+
cache = JSON.parse(text);
|
|
114
|
+
allCaches.set(cacheFile, cache);
|
|
115
|
+
}
|
|
116
|
+
return cache;
|
|
117
|
+
}
|
|
118
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
119
|
+
0 && (module.exports = {
|
|
120
|
+
pageExtract,
|
|
121
|
+
pagePerform
|
|
122
|
+
});
|
|
@@ -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,115 @@
|
|
|
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
|
+
this.options = page.browserContext._options.agent;
|
|
32
|
+
}
|
|
33
|
+
async runActionAndWait(action) {
|
|
34
|
+
return await this.runActionsAndWait([action]);
|
|
35
|
+
}
|
|
36
|
+
async runActionsAndWait(action) {
|
|
37
|
+
await this.waitForCompletion(async () => {
|
|
38
|
+
for (const a of action) {
|
|
39
|
+
await (0, import_actionRunner.runAction)(this.progress, this.page, a, this.options?.secrets ?? []);
|
|
40
|
+
this.actions.push(a);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return await this.snapshotResult();
|
|
44
|
+
}
|
|
45
|
+
async waitForCompletion(callback) {
|
|
46
|
+
const requests = [];
|
|
47
|
+
const requestListener = (request) => requests.push(request);
|
|
48
|
+
const disposeListeners = () => {
|
|
49
|
+
this.page.browserContext.off(import_browserContext.BrowserContext.Events.Request, requestListener);
|
|
50
|
+
};
|
|
51
|
+
this.page.browserContext.on(import_browserContext.BrowserContext.Events.Request, requestListener);
|
|
52
|
+
let result;
|
|
53
|
+
try {
|
|
54
|
+
result = await callback();
|
|
55
|
+
await this.progress.wait(500);
|
|
56
|
+
} finally {
|
|
57
|
+
disposeListeners();
|
|
58
|
+
}
|
|
59
|
+
const requestedNavigation = requests.some((request) => request.isNavigationRequest());
|
|
60
|
+
if (requestedNavigation) {
|
|
61
|
+
await this.page.mainFrame().waitForLoadState(this.progress, "load");
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
const promises = [];
|
|
65
|
+
for (const request of requests) {
|
|
66
|
+
if (["document", "stylesheet", "script", "xhr", "fetch"].includes(request.resourceType()))
|
|
67
|
+
promises.push(request.response().then((r) => r?.finished()));
|
|
68
|
+
else
|
|
69
|
+
promises.push(request.response());
|
|
70
|
+
}
|
|
71
|
+
await this.progress.race(promises, { timeout: 5e3 });
|
|
72
|
+
if (requests.length)
|
|
73
|
+
await this.progress.wait(500);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
async snapshotResult() {
|
|
77
|
+
let { full } = await this.page.snapshotForAI(this.progress);
|
|
78
|
+
full = this._redactText(full);
|
|
79
|
+
const text = [`# Page snapshot
|
|
80
|
+
${full}`];
|
|
81
|
+
return {
|
|
82
|
+
_meta: {
|
|
83
|
+
"dev.lowire/state": {
|
|
84
|
+
"Page snapshot": full
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
content: [{ type: "text", text: text.join("\n\n") }]
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async refSelectors(params) {
|
|
91
|
+
return Promise.all(params.map(async (param) => {
|
|
92
|
+
try {
|
|
93
|
+
const { resolvedSelector } = await this.page.mainFrame().resolveSelector(this.progress, `aria-ref=${param.ref}`);
|
|
94
|
+
return resolvedSelector;
|
|
95
|
+
} catch (e) {
|
|
96
|
+
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
|
|
97
|
+
}
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
_redactText(text) {
|
|
101
|
+
const secrets = this.options?.secrets;
|
|
102
|
+
if (!secrets)
|
|
103
|
+
return text;
|
|
104
|
+
const redactText = (text2) => {
|
|
105
|
+
for (const { name, value } of secrets)
|
|
106
|
+
text2 = text2.replaceAll(value, `<secret>${name}</secret>`);
|
|
107
|
+
return text2;
|
|
108
|
+
};
|
|
109
|
+
return redactText(text);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
113
|
+
0 && (module.exports = {
|
|
114
|
+
Context
|
|
115
|
+
});
|