@runcofactor/cli 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{account-ZMV7NEFM.js → account-ZSM2Q3RB.js} +4 -4
- package/dist/{api-catalog-6HNOGVPA.js → api-catalog-MMPFWS52.js} +4 -4
- package/dist/{attachment-QAHR54HQ.js → attachment-NSYL5X3S.js} +4 -4
- package/dist/{augmentor-7T3L6ZR4.js → augmentor-LSJLMJYP.js} +4 -4
- package/dist/{auth-DURHUZDW.js → auth-OYF5A4BY.js} +4 -2
- package/dist/{chunk-RGDIVW3O.js → chunk-2R6544Z3.js} +2 -2
- package/dist/{chunk-AI3Y3AZH.js → chunk-7OO3RJYR.js} +1396 -185
- package/dist/chunk-7OO3RJYR.js.map +1 -0
- package/dist/{chunk-4NRDONSC.js → chunk-A6TH5VUI.js} +209 -79
- package/dist/chunk-A6TH5VUI.js.map +1 -0
- package/dist/{chunk-CEXV3MOC.js → chunk-E2FUQJVO.js} +4 -4
- package/dist/{chunk-D6AVOPOS.js → chunk-GFP4UEUT.js} +3 -3
- package/dist/{chunk-G5SXUXSU.js → chunk-H7ZML5QL.js} +2 -2
- package/dist/{chunk-LFFWD5JZ.js → chunk-IHCPMYKU.js} +3 -3
- package/dist/{chunk-UAJUZLDE.js → chunk-PVWG3V62.js} +3 -3
- package/dist/{chunk-3CZU7XCS.js → chunk-PWZ4ULCB.js} +20 -14
- package/dist/chunk-PWZ4ULCB.js.map +1 -0
- package/dist/{chunk-A4ISG3VX.js → chunk-U7OMQJ7V.js} +52 -4
- package/dist/chunk-U7OMQJ7V.js.map +1 -0
- package/dist/{chunk-DT2CEH2V.js → chunk-VHVOTGBQ.js} +3 -3
- package/dist/{chunk-IGHDIWZU.js → chunk-VYTIJ6HJ.js} +17 -2
- package/dist/{chunk-IGHDIWZU.js.map → chunk-VYTIJ6HJ.js.map} +1 -1
- package/dist/{credential-X6QKX473.js → credential-WOATCWOU.js} +4 -4
- package/dist/{credential-template-GD3D4MBI.js → credential-template-Q3DQE2AH.js} +4 -4
- package/dist/{debug-workflow-AAEOAME2.js → debug-workflow-ZNP5XZQF.js} +4 -4
- package/dist/{dist-QLTVBUMD.js → dist-4COOAKY3.js} +22 -2
- package/dist/{docs-BVUEXBY3.js → docs-XVU4LA7G.js} +4 -4
- package/dist/{doctor-RHMKD4W5.js → doctor-PGNHD3TI.js} +3 -3
- package/dist/{environment-WE7VVE6I.js → environment-MRDNWU47.js} +4 -4
- package/dist/{feature-flag-VJO2TJFT.js → feature-flag-D3DQZ6DX.js} +4 -4
- package/dist/index.js +51 -48
- package/dist/index.js.map +1 -1
- package/dist/{init-RQHHKJJD.js → init-DHWKUYIR.js} +4 -4
- package/dist/{install-CQLHNZ6U.js → install-DMEFGQHD.js} +4 -4
- package/dist/{issues-HK2JA5JS.js → issues-E4YQ4DVC.js} +4 -4
- package/dist/{knobs-ETJAV6YM.js → knobs-NA6SPLHX.js} +4 -4
- package/dist/{list-F6DGGW3Z.js → list-GJNGFQMC.js} +4 -4
- package/dist/{local-CMAY54I5.js → local-NSKOZHHA.js} +6 -6
- package/dist/{login-6CKG664C.js → login-AMSRVPXG.js} +4 -4
- package/dist/{mcp-GC2WOOZO.js → mcp-57VVZTXM.js} +5 -5
- package/dist/{metrics-IXICURAA.js → metrics-DM4YQQZN.js} +4 -4
- package/dist/{product-BUJWPYKB.js → product-WGOLTBRI.js} +4 -4
- package/dist/{property-4EXPWRNT.js → property-B7QMGLVW.js} +4 -4
- package/dist/{psql-XGLBI6T7.js → psql-4JHPJ2CO.js} +3 -3
- package/dist/{record-HL4QA7OX.js → record-RWVGZZSW.js} +5 -5
- package/dist/{redis-VJGCUJPV.js → redis-N44ZZ6VB.js} +3 -3
- package/dist/{release-2SMK5Y3V.js → release-R7GKLEAI.js} +4 -4
- package/dist/{sandbox-ORAPKOH3.js → sandbox-6D54ZQCG.js} +5 -5
- package/dist/{scenarios-DM5FDCAF.js → scenarios-WUUUKP2S.js} +4 -4
- package/dist/{session-X6IYGWYG.js → session-GDCMTNB3.js} +6 -6
- package/dist/{skill-ZU5V2EE5.js → skill-3SP7MAA4.js} +153 -2
- package/dist/skill-3SP7MAA4.js.map +1 -0
- package/dist/skills/optimize-cache/SKILL.md +25 -0
- package/dist/{spec-KO5QD6AY.js → spec-ESPA3H26.js} +3 -3
- package/dist/{src-DSD34JIX.js → src-5YXGM2KB.js} +18 -2
- package/dist/src-5YXGM2KB.js.map +1 -0
- package/dist/{src-PDYXACRP.js → src-B7CPYFLS.js} +4 -2
- package/dist/{src-HTGNKBUF.js → src-GRO2QR7U.js} +61 -23
- package/dist/{src-HTGNKBUF.js.map → src-GRO2QR7U.js.map} +1 -1
- package/dist/{start-2ECN4LX5.js → start-KDDRLUFN.js} +4 -4
- package/dist/{tag-R5I72HJ6.js → tag-DAGHQZAR.js} +5 -5
- package/dist/{task-V3JMSJIM.js → task-PRR75HI4.js} +4 -4
- package/dist/{test-suite-NOYVK6YX.js → test-suite-O3UY7EER.js} +6 -6
- package/dist/{trace-NOYEKNO4.js → trace-7LRHSPWN.js} +4 -4
- package/dist/{triage-4RFATHBE.js → triage-2BKUBMMX.js} +5 -5
- package/dist/{utilities-3WMXE743.js → utilities-O3OO64T5.js} +4 -4
- package/dist/{workflow-DC7WOTTW.js → workflow-5BFRS4CE.js} +10 -11
- package/dist/workflow-5BFRS4CE.js.map +1 -0
- package/dist/{workflow-cache-SDSI6SMF.js → workflow-cache-VVP3SPFM.js} +7 -7
- package/dist/{workflow-debug-6UQYP67Q.js → workflow-debug-XGOHNZ4E.js} +7 -7
- package/dist/{workflow-proposals-67AVGMHX.js → workflow-proposals-PGURJ6ZI.js} +4 -4
- package/package.json +5 -5
- package/dist/chunk-3CZU7XCS.js.map +0 -1
- package/dist/chunk-4NRDONSC.js.map +0 -1
- package/dist/chunk-A4ISG3VX.js.map +0 -1
- package/dist/chunk-AI3Y3AZH.js.map +0 -1
- package/dist/skill-ZU5V2EE5.js.map +0 -1
- package/dist/src-DSD34JIX.js.map +0 -1
- package/dist/workflow-DC7WOTTW.js.map +0 -1
- /package/dist/{account-ZMV7NEFM.js.map → account-ZSM2Q3RB.js.map} +0 -0
- /package/dist/{api-catalog-6HNOGVPA.js.map → api-catalog-MMPFWS52.js.map} +0 -0
- /package/dist/{attachment-QAHR54HQ.js.map → attachment-NSYL5X3S.js.map} +0 -0
- /package/dist/{augmentor-7T3L6ZR4.js.map → augmentor-LSJLMJYP.js.map} +0 -0
- /package/dist/{auth-DURHUZDW.js.map → auth-OYF5A4BY.js.map} +0 -0
- /package/dist/{chunk-RGDIVW3O.js.map → chunk-2R6544Z3.js.map} +0 -0
- /package/dist/{chunk-CEXV3MOC.js.map → chunk-E2FUQJVO.js.map} +0 -0
- /package/dist/{chunk-D6AVOPOS.js.map → chunk-GFP4UEUT.js.map} +0 -0
- /package/dist/{chunk-G5SXUXSU.js.map → chunk-H7ZML5QL.js.map} +0 -0
- /package/dist/{chunk-LFFWD5JZ.js.map → chunk-IHCPMYKU.js.map} +0 -0
- /package/dist/{chunk-UAJUZLDE.js.map → chunk-PVWG3V62.js.map} +0 -0
- /package/dist/{chunk-DT2CEH2V.js.map → chunk-VHVOTGBQ.js.map} +0 -0
- /package/dist/{credential-X6QKX473.js.map → credential-WOATCWOU.js.map} +0 -0
- /package/dist/{credential-template-GD3D4MBI.js.map → credential-template-Q3DQE2AH.js.map} +0 -0
- /package/dist/{debug-workflow-AAEOAME2.js.map → debug-workflow-ZNP5XZQF.js.map} +0 -0
- /package/dist/{dist-QLTVBUMD.js.map → dist-4COOAKY3.js.map} +0 -0
- /package/dist/{docs-BVUEXBY3.js.map → docs-XVU4LA7G.js.map} +0 -0
- /package/dist/{doctor-RHMKD4W5.js.map → doctor-PGNHD3TI.js.map} +0 -0
- /package/dist/{environment-WE7VVE6I.js.map → environment-MRDNWU47.js.map} +0 -0
- /package/dist/{feature-flag-VJO2TJFT.js.map → feature-flag-D3DQZ6DX.js.map} +0 -0
- /package/dist/{init-RQHHKJJD.js.map → init-DHWKUYIR.js.map} +0 -0
- /package/dist/{install-CQLHNZ6U.js.map → install-DMEFGQHD.js.map} +0 -0
- /package/dist/{issues-HK2JA5JS.js.map → issues-E4YQ4DVC.js.map} +0 -0
- /package/dist/{knobs-ETJAV6YM.js.map → knobs-NA6SPLHX.js.map} +0 -0
- /package/dist/{list-F6DGGW3Z.js.map → list-GJNGFQMC.js.map} +0 -0
- /package/dist/{local-CMAY54I5.js.map → local-NSKOZHHA.js.map} +0 -0
- /package/dist/{login-6CKG664C.js.map → login-AMSRVPXG.js.map} +0 -0
- /package/dist/{mcp-GC2WOOZO.js.map → mcp-57VVZTXM.js.map} +0 -0
- /package/dist/{metrics-IXICURAA.js.map → metrics-DM4YQQZN.js.map} +0 -0
- /package/dist/{product-BUJWPYKB.js.map → product-WGOLTBRI.js.map} +0 -0
- /package/dist/{property-4EXPWRNT.js.map → property-B7QMGLVW.js.map} +0 -0
- /package/dist/{psql-XGLBI6T7.js.map → psql-4JHPJ2CO.js.map} +0 -0
- /package/dist/{record-HL4QA7OX.js.map → record-RWVGZZSW.js.map} +0 -0
- /package/dist/{redis-VJGCUJPV.js.map → redis-N44ZZ6VB.js.map} +0 -0
- /package/dist/{release-2SMK5Y3V.js.map → release-R7GKLEAI.js.map} +0 -0
- /package/dist/{sandbox-ORAPKOH3.js.map → sandbox-6D54ZQCG.js.map} +0 -0
- /package/dist/{scenarios-DM5FDCAF.js.map → scenarios-WUUUKP2S.js.map} +0 -0
- /package/dist/{session-X6IYGWYG.js.map → session-GDCMTNB3.js.map} +0 -0
- /package/dist/{spec-KO5QD6AY.js.map → spec-ESPA3H26.js.map} +0 -0
- /package/dist/{src-PDYXACRP.js.map → src-B7CPYFLS.js.map} +0 -0
- /package/dist/{start-2ECN4LX5.js.map → start-KDDRLUFN.js.map} +0 -0
- /package/dist/{tag-R5I72HJ6.js.map → tag-DAGHQZAR.js.map} +0 -0
- /package/dist/{task-V3JMSJIM.js.map → task-PRR75HI4.js.map} +0 -0
- /package/dist/{test-suite-NOYVK6YX.js.map → test-suite-O3UY7EER.js.map} +0 -0
- /package/dist/{trace-NOYEKNO4.js.map → trace-7LRHSPWN.js.map} +0 -0
- /package/dist/{triage-4RFATHBE.js.map → triage-2BKUBMMX.js.map} +0 -0
- /package/dist/{utilities-3WMXE743.js.map → utilities-O3OO64T5.js.map} +0 -0
- /package/dist/{workflow-cache-SDSI6SMF.js.map → workflow-cache-VVP3SPFM.js.map} +0 -0
- /package/dist/{workflow-debug-6UQYP67Q.js.map → workflow-debug-XGOHNZ4E.js.map} +0 -0
- /package/dist/{workflow-proposals-67AVGMHX.js.map → workflow-proposals-PGURJ6ZI.js.map} +0 -0
|
@@ -3877,13 +3877,13 @@ var require_gifutil = __commonJS({
|
|
|
3877
3877
|
}
|
|
3878
3878
|
_quantize(imageOrImages, "WuQuant", maxColorIndexes, significantBits, dither);
|
|
3879
3879
|
};
|
|
3880
|
-
exports.read = function(source,
|
|
3881
|
-
|
|
3880
|
+
exports.read = function(source, decoder2) {
|
|
3881
|
+
decoder2 = decoder2 || defaultCodec;
|
|
3882
3882
|
if (Buffer.isBuffer(source)) {
|
|
3883
|
-
return
|
|
3883
|
+
return decoder2.decodeGif(source);
|
|
3884
3884
|
}
|
|
3885
3885
|
return _readBinary(source).then((buffer) => {
|
|
3886
|
-
return
|
|
3886
|
+
return decoder2.decodeGif(buffer);
|
|
3887
3887
|
});
|
|
3888
3888
|
};
|
|
3889
3889
|
exports.shareAsJimp = function(jimp, bitmapImageToShare) {
|
|
@@ -3895,13 +3895,13 @@ var require_gifutil = __commonJS({
|
|
|
3895
3895
|
jimpImage.bitmap.data = bitmapImageToShare.bitmap.data;
|
|
3896
3896
|
return jimpImage;
|
|
3897
3897
|
};
|
|
3898
|
-
exports.write = function(path6, frames, spec,
|
|
3899
|
-
|
|
3898
|
+
exports.write = function(path6, frames, spec, encoder2) {
|
|
3899
|
+
encoder2 = encoder2 || defaultCodec;
|
|
3900
3900
|
const matches = path6.match(/\.[a-zA-Z]+$/);
|
|
3901
3901
|
if (matches !== null && INVALID_SUFFIXES.includes(matches[0].toLowerCase())) {
|
|
3902
3902
|
throw new Error(`GIF '${path6}' has an unexpected suffix`);
|
|
3903
3903
|
}
|
|
3904
|
-
return
|
|
3904
|
+
return encoder2.encodeGif(frames, spec).then((gif2) => {
|
|
3905
3905
|
return _writeBinary(path6, gif2.buffer).then(() => {
|
|
3906
3906
|
return gif2;
|
|
3907
3907
|
});
|
|
@@ -5449,8 +5449,8 @@ var require_encoder = __commonJS({
|
|
|
5449
5449
|
}
|
|
5450
5450
|
function encode3(imgData, qu) {
|
|
5451
5451
|
if (typeof qu === "undefined") qu = 50;
|
|
5452
|
-
var
|
|
5453
|
-
var data2 =
|
|
5452
|
+
var encoder2 = new JPEGEncoder(qu);
|
|
5453
|
+
var data2 = encoder2.encode(imgData, qu);
|
|
5454
5454
|
return {
|
|
5455
5455
|
data: data2,
|
|
5456
5456
|
width: imgData.width,
|
|
@@ -6489,22 +6489,22 @@ var require_decoder = __commonJS({
|
|
|
6489
6489
|
};
|
|
6490
6490
|
var opts = { ...defaultOpts, ...userOpts };
|
|
6491
6491
|
var arr = new Uint8Array(jpegData);
|
|
6492
|
-
var
|
|
6493
|
-
|
|
6492
|
+
var decoder2 = new JpegImage();
|
|
6493
|
+
decoder2.opts = opts;
|
|
6494
6494
|
JpegImage.resetMaxMemoryUsage(opts.maxMemoryUsageInMB * 1024 * 1024);
|
|
6495
|
-
|
|
6495
|
+
decoder2.parse(arr);
|
|
6496
6496
|
var channels = opts.formatAsRGBA ? 4 : 3;
|
|
6497
|
-
var bytesNeeded =
|
|
6497
|
+
var bytesNeeded = decoder2.width * decoder2.height * channels;
|
|
6498
6498
|
try {
|
|
6499
6499
|
JpegImage.requestMemoryAllocation(bytesNeeded);
|
|
6500
6500
|
var image2 = {
|
|
6501
|
-
width:
|
|
6502
|
-
height:
|
|
6503
|
-
exifBuffer:
|
|
6501
|
+
width: decoder2.width,
|
|
6502
|
+
height: decoder2.height,
|
|
6503
|
+
exifBuffer: decoder2.exifBuffer,
|
|
6504
6504
|
data: opts.useTArray ? new Uint8Array(bytesNeeded) : Buffer.alloc(bytesNeeded)
|
|
6505
6505
|
};
|
|
6506
|
-
if (
|
|
6507
|
-
image2["comments"] =
|
|
6506
|
+
if (decoder2.comments.length > 0) {
|
|
6507
|
+
image2["comments"] = decoder2.comments;
|
|
6508
6508
|
}
|
|
6509
6509
|
} catch (err) {
|
|
6510
6510
|
if (err instanceof RangeError) {
|
|
@@ -6517,7 +6517,7 @@ var require_decoder = __commonJS({
|
|
|
6517
6517
|
}
|
|
6518
6518
|
throw err;
|
|
6519
6519
|
}
|
|
6520
|
-
|
|
6520
|
+
decoder2.copyToImageData(image2, opts.formatAsRGBA);
|
|
6521
6521
|
return image2;
|
|
6522
6522
|
}
|
|
6523
6523
|
}
|
|
@@ -24616,14 +24616,14 @@ var require_merge_deep = __commonJS({
|
|
|
24616
24616
|
}
|
|
24617
24617
|
});
|
|
24618
24618
|
|
|
24619
|
-
// ../../node_modules/.bun/puppeteer-extra-plugin@3.2.3+
|
|
24619
|
+
// ../../node_modules/.bun/puppeteer-extra-plugin@3.2.3+174067defc7674c7/node_modules/puppeteer-extra-plugin/dist/index.esm.js
|
|
24620
24620
|
var index_esm_exports = {};
|
|
24621
24621
|
__export(index_esm_exports, {
|
|
24622
24622
|
PuppeteerExtraPlugin: () => PuppeteerExtraPlugin
|
|
24623
24623
|
});
|
|
24624
24624
|
var import_debug2, merge, PuppeteerExtraPlugin;
|
|
24625
24625
|
var init_index_esm = __esm({
|
|
24626
|
-
"../../node_modules/.bun/puppeteer-extra-plugin@3.2.3+
|
|
24626
|
+
"../../node_modules/.bun/puppeteer-extra-plugin@3.2.3+174067defc7674c7/node_modules/puppeteer-extra-plugin/dist/index.esm.js"() {
|
|
24627
24627
|
"use strict";
|
|
24628
24628
|
import_debug2 = __toESM(require_src());
|
|
24629
24629
|
merge = require_merge_deep();
|
|
@@ -25086,9 +25086,9 @@ var init_index_esm = __esm({
|
|
|
25086
25086
|
}
|
|
25087
25087
|
});
|
|
25088
25088
|
|
|
25089
|
-
// ../../node_modules/.bun/puppeteer-extra-plugin-stealth@2.11.2+
|
|
25089
|
+
// ../../node_modules/.bun/puppeteer-extra-plugin-stealth@2.11.2+174067defc7674c7/node_modules/puppeteer-extra-plugin-stealth/index.js
|
|
25090
25090
|
var require_puppeteer_extra_plugin_stealth = __commonJS({
|
|
25091
|
-
"../../node_modules/.bun/puppeteer-extra-plugin-stealth@2.11.2+
|
|
25091
|
+
"../../node_modules/.bun/puppeteer-extra-plugin-stealth@2.11.2+174067defc7674c7/node_modules/puppeteer-extra-plugin-stealth/index.js"(exports, module) {
|
|
25092
25092
|
"use strict";
|
|
25093
25093
|
var { PuppeteerExtraPlugin: PuppeteerExtraPlugin2 } = (init_index_esm(), __toCommonJS(index_esm_exports));
|
|
25094
25094
|
var StealthPlugin2 = class extends PuppeteerExtraPlugin2 {
|
|
@@ -40257,11 +40257,17 @@ import * as path2 from "path";
|
|
|
40257
40257
|
import * as path3 from "path";
|
|
40258
40258
|
import * as fs22 from "fs/promises";
|
|
40259
40259
|
import * as crypto3 from "crypto";
|
|
40260
|
+
import { cpus } from "os";
|
|
40261
|
+
import { spawn as spawn2 } from "child_process";
|
|
40262
|
+
import { existsSync as existsSync2 } from "fs";
|
|
40263
|
+
import { createRequire } from "module";
|
|
40264
|
+
import { dirname, join as join2 } from "path";
|
|
40265
|
+
import { fileURLToPath } from "url";
|
|
40260
40266
|
import {
|
|
40261
40267
|
chromium as playwrightChromium
|
|
40262
40268
|
} from "playwright";
|
|
40263
40269
|
|
|
40264
|
-
// ../../node_modules/.bun/playwright-extra@4.3.6+
|
|
40270
|
+
// ../../node_modules/.bun/playwright-extra@4.3.6+0a2747ebf12ccdf9/node_modules/playwright-extra/dist/index.esm.js
|
|
40265
40271
|
var import_debug = __toESM(require_src());
|
|
40266
40272
|
var Loader = class {
|
|
40267
40273
|
constructor(moduleName, packageNames) {
|
|
@@ -41654,6 +41660,16 @@ var TIMEOUTS = {
|
|
|
41654
41660
|
GET_TITLE: 2e4,
|
|
41655
41661
|
GET_LINKS: 2e4,
|
|
41656
41662
|
SNAPSHOT: 3e4,
|
|
41663
|
+
// Driver-side hard cap for a single `page.ariaSnapshot()` call. ariaSnapshot
|
|
41664
|
+
// has NO Playwright timeout and ignores AbortSignal: on a jammed renderer
|
|
41665
|
+
// (blocked main thread / native dialog) the op parks for minutes, and the
|
|
41666
|
+
// per-tool timeout's abort can't cancel it — the orphan kept running until
|
|
41667
|
+
// the 1800s job-stall watchdog tore down the whole job (prod, June 2026).
|
|
41668
|
+
// This cap makes the *driver* give up and fall back to an empty snapshot so
|
|
41669
|
+
// the agent keeps moving; the wedged page is then reaped by step-level
|
|
41670
|
+
// force-recovery. Kept below POST_ACTION_SNAPSHOT (15s) and SNAPSHOT (30s) so
|
|
41671
|
+
// the inner cap wins; a healthy ariaSnapshot returns in <1s.
|
|
41672
|
+
ARIA_SNAPSHOT_CAP: 12e3,
|
|
41657
41673
|
CLICK: 1e4,
|
|
41658
41674
|
TYPE: 1e4,
|
|
41659
41675
|
FILL_FORM: 2e4,
|
|
@@ -42004,6 +42020,9 @@ function extractAndStripV2Fields(attributes) {
|
|
|
42004
42020
|
out.visibility = value;
|
|
42005
42021
|
}
|
|
42006
42022
|
break;
|
|
42023
|
+
case "~dialog-inert":
|
|
42024
|
+
if (value === "true") out.dialogInert = true;
|
|
42025
|
+
break;
|
|
42007
42026
|
case "~bbox": {
|
|
42008
42027
|
const parts = value.split(":").map((s2) => parseFloat(s2));
|
|
42009
42028
|
if (parts.length === 4 && parts.every((n2) => Number.isFinite(n2))) {
|
|
@@ -42348,6 +42367,192 @@ function appendAttrToLine(line, segment) {
|
|
|
42348
42367
|
function errorMessage(error) {
|
|
42349
42368
|
return error instanceof Error ? error.message : String(error);
|
|
42350
42369
|
}
|
|
42370
|
+
var ICON_FAMILY_PREFIXES = [
|
|
42371
|
+
// FontAwesome family + style tokens
|
|
42372
|
+
"fa-solid-",
|
|
42373
|
+
"fa-regular-",
|
|
42374
|
+
"fa-light-",
|
|
42375
|
+
"fa-thin-",
|
|
42376
|
+
"fa-duotone-",
|
|
42377
|
+
"fa-brands-",
|
|
42378
|
+
"fa-sharp-",
|
|
42379
|
+
"fa-",
|
|
42380
|
+
"fas-",
|
|
42381
|
+
"far-",
|
|
42382
|
+
"fal-",
|
|
42383
|
+
"fad-",
|
|
42384
|
+
"fab-",
|
|
42385
|
+
// Telerik / Kendo
|
|
42386
|
+
"k-svg-i-",
|
|
42387
|
+
"k-i-",
|
|
42388
|
+
// Bootstrap Icons, Material Design Icons, Glyphicons, Ionicons
|
|
42389
|
+
"bi-",
|
|
42390
|
+
"mdi-",
|
|
42391
|
+
"glyphicon-",
|
|
42392
|
+
"ion-",
|
|
42393
|
+
"material-icons-",
|
|
42394
|
+
// Generic convention
|
|
42395
|
+
"icon-"
|
|
42396
|
+
];
|
|
42397
|
+
var ICON_NOISE_TOKENS = /* @__PURE__ */ new Set([
|
|
42398
|
+
"fa",
|
|
42399
|
+
"fa-solid",
|
|
42400
|
+
"fa-regular",
|
|
42401
|
+
"fa-light",
|
|
42402
|
+
"fa-thin",
|
|
42403
|
+
"fa-duotone",
|
|
42404
|
+
"fa-brands",
|
|
42405
|
+
"fa-sharp",
|
|
42406
|
+
"fas",
|
|
42407
|
+
"far",
|
|
42408
|
+
"fal",
|
|
42409
|
+
"fad",
|
|
42410
|
+
"fab",
|
|
42411
|
+
"fa-lg",
|
|
42412
|
+
"fa-sm",
|
|
42413
|
+
"fa-xs",
|
|
42414
|
+
"fa-xl",
|
|
42415
|
+
"fa-fw",
|
|
42416
|
+
"fa-spin",
|
|
42417
|
+
"fa-pulse",
|
|
42418
|
+
"fa-border",
|
|
42419
|
+
"fa-pull-left",
|
|
42420
|
+
"fa-pull-right",
|
|
42421
|
+
"k-icon",
|
|
42422
|
+
"k-svg-icon",
|
|
42423
|
+
"k-button-icon"
|
|
42424
|
+
]);
|
|
42425
|
+
var ICON_NAME_MAP = {
|
|
42426
|
+
// export / data movement
|
|
42427
|
+
"file-export": "Export",
|
|
42428
|
+
"file-arrow-down": "Export",
|
|
42429
|
+
"arrow-up-from-bracket": "Export",
|
|
42430
|
+
export: "Export",
|
|
42431
|
+
download: "Download",
|
|
42432
|
+
"file-download": "Download",
|
|
42433
|
+
"cloud-arrow-down": "Download",
|
|
42434
|
+
"arrow-down-to-line": "Download",
|
|
42435
|
+
upload: "Upload",
|
|
42436
|
+
"file-upload": "Upload",
|
|
42437
|
+
"cloud-arrow-up": "Upload",
|
|
42438
|
+
"file-import": "Import",
|
|
42439
|
+
"file-arrow-up": "Import",
|
|
42440
|
+
import: "Import",
|
|
42441
|
+
// filtering / search / columns
|
|
42442
|
+
filter: "Filter",
|
|
42443
|
+
"filter-circle-xmark": "Clear filter",
|
|
42444
|
+
funnel: "Filter",
|
|
42445
|
+
sliders: "Filter",
|
|
42446
|
+
"magnifying-glass": "Search",
|
|
42447
|
+
search: "Search",
|
|
42448
|
+
"table-columns": "Columns",
|
|
42449
|
+
columns: "Columns",
|
|
42450
|
+
"table-cells": "Columns",
|
|
42451
|
+
table: "Columns",
|
|
42452
|
+
// settings
|
|
42453
|
+
gear: "Settings",
|
|
42454
|
+
gears: "Settings",
|
|
42455
|
+
cog: "Settings",
|
|
42456
|
+
cogs: "Settings",
|
|
42457
|
+
wrench: "Settings",
|
|
42458
|
+
sliders2: "Settings",
|
|
42459
|
+
// CRUD
|
|
42460
|
+
plus: "Add",
|
|
42461
|
+
"plus-circle": "Add",
|
|
42462
|
+
"circle-plus": "Add",
|
|
42463
|
+
add: "Add",
|
|
42464
|
+
pen: "Edit",
|
|
42465
|
+
pencil: "Edit",
|
|
42466
|
+
"pen-to-square": "Edit",
|
|
42467
|
+
"pencil-alt": "Edit",
|
|
42468
|
+
edit: "Edit",
|
|
42469
|
+
trash: "Delete",
|
|
42470
|
+
"trash-can": "Delete",
|
|
42471
|
+
"trash-alt": "Delete",
|
|
42472
|
+
delete: "Delete",
|
|
42473
|
+
"floppy-disk": "Save",
|
|
42474
|
+
save: "Save",
|
|
42475
|
+
copy: "Copy",
|
|
42476
|
+
clone: "Copy",
|
|
42477
|
+
// navigation / disclosure
|
|
42478
|
+
xmark: "Close",
|
|
42479
|
+
times: "Close",
|
|
42480
|
+
x: "Close",
|
|
42481
|
+
"circle-xmark": "Close",
|
|
42482
|
+
close: "Close",
|
|
42483
|
+
"chevron-down": "Expand",
|
|
42484
|
+
"chevron-up": "Collapse",
|
|
42485
|
+
"chevron-left": "Previous",
|
|
42486
|
+
"chevron-right": "Next",
|
|
42487
|
+
"angle-down": "Expand",
|
|
42488
|
+
"angle-up": "Collapse",
|
|
42489
|
+
"angle-left": "Previous",
|
|
42490
|
+
"angle-right": "Next",
|
|
42491
|
+
"caret-down": "Expand",
|
|
42492
|
+
"caret-up": "Collapse",
|
|
42493
|
+
"caret-left": "Previous",
|
|
42494
|
+
"caret-right": "Next",
|
|
42495
|
+
"arrow-left": "Back",
|
|
42496
|
+
"arrow-right": "Forward",
|
|
42497
|
+
// misc actions
|
|
42498
|
+
ellipsis: "More",
|
|
42499
|
+
"ellipsis-vertical": "More",
|
|
42500
|
+
"ellipsis-v": "More",
|
|
42501
|
+
"ellipsis-h": "More",
|
|
42502
|
+
bars: "Menu",
|
|
42503
|
+
bell: "Notifications",
|
|
42504
|
+
"circle-info": "Info",
|
|
42505
|
+
"info-circle": "Info",
|
|
42506
|
+
info: "Info",
|
|
42507
|
+
"circle-question": "Help",
|
|
42508
|
+
"question-circle": "Help",
|
|
42509
|
+
question: "Help",
|
|
42510
|
+
check: "Confirm",
|
|
42511
|
+
"circle-check": "Confirm",
|
|
42512
|
+
eye: "Show",
|
|
42513
|
+
"eye-slash": "Hide",
|
|
42514
|
+
"arrows-rotate": "Refresh",
|
|
42515
|
+
"arrow-rotate-right": "Refresh",
|
|
42516
|
+
rotate: "Refresh",
|
|
42517
|
+
refresh: "Refresh",
|
|
42518
|
+
sync: "Refresh",
|
|
42519
|
+
print: "Print",
|
|
42520
|
+
printer: "Print",
|
|
42521
|
+
share: "Share",
|
|
42522
|
+
"share-nodes": "Share",
|
|
42523
|
+
calendar: "Calendar",
|
|
42524
|
+
"calendar-days": "Calendar",
|
|
42525
|
+
star: "Favorite",
|
|
42526
|
+
print2: "Print"
|
|
42527
|
+
};
|
|
42528
|
+
function stripIconFamilyPrefix(raw) {
|
|
42529
|
+
let name = raw.trim().toLowerCase();
|
|
42530
|
+
if (!name) return void 0;
|
|
42531
|
+
let changed = true;
|
|
42532
|
+
while (changed) {
|
|
42533
|
+
changed = false;
|
|
42534
|
+
for (const prefix of ICON_FAMILY_PREFIXES) {
|
|
42535
|
+
if (name.startsWith(prefix) && name.length > prefix.length) {
|
|
42536
|
+
name = name.slice(prefix.length);
|
|
42537
|
+
changed = true;
|
|
42538
|
+
break;
|
|
42539
|
+
}
|
|
42540
|
+
}
|
|
42541
|
+
}
|
|
42542
|
+
if (!name || ICON_NOISE_TOKENS.has(name) || ICON_NOISE_TOKENS.has(raw.trim().toLowerCase())) {
|
|
42543
|
+
return void 0;
|
|
42544
|
+
}
|
|
42545
|
+
return name;
|
|
42546
|
+
}
|
|
42547
|
+
function resolveIconClassName(raw) {
|
|
42548
|
+
const name = stripIconFamilyPrefix(raw);
|
|
42549
|
+
if (!name) return void 0;
|
|
42550
|
+
const mapped = ICON_NAME_MAP[name];
|
|
42551
|
+
if (mapped) return mapped;
|
|
42552
|
+
const base = name.replace(/-\d+$/, "");
|
|
42553
|
+
if (base !== name && ICON_NAME_MAP[base]) return ICON_NAME_MAP[base];
|
|
42554
|
+
return name.split("-").filter(Boolean).map((part) => part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
42555
|
+
}
|
|
42351
42556
|
async function resolveRefs(scope, refs, fn) {
|
|
42352
42557
|
if (refs.length === 0) return {};
|
|
42353
42558
|
const handles = await Promise.all(
|
|
@@ -42438,20 +42643,31 @@ async function resolveRefsWithArgs(scope, items, globals, fn) {
|
|
|
42438
42643
|
);
|
|
42439
42644
|
}
|
|
42440
42645
|
}
|
|
42646
|
+
function isFrameworkMarkerClass(cls) {
|
|
42647
|
+
if (cls === "telerik-blazor") return true;
|
|
42648
|
+
return /^(k|mat|mdc|ng|chakra|ant|el|v|q)-/.test(cls) || /^mui[A-Z-]/.test(cls);
|
|
42649
|
+
}
|
|
42441
42650
|
function extractSemanticHint(className) {
|
|
42442
42651
|
if (!className) return void 0;
|
|
42443
42652
|
const classes = className.split(/\s+/).filter(Boolean);
|
|
42653
|
+
const isNoise = (cls) => {
|
|
42654
|
+
if (/^(css|sc|emotion|styled|svelte)-/.test(cls)) return true;
|
|
42655
|
+
if (/^(clickable-element|bubble-element|bubble-r-container|bubble-r-vertical-center)/.test(cls)) return true;
|
|
42656
|
+
if (/^_[a-zA-Z0-9]{4,}$/.test(cls)) return true;
|
|
42657
|
+
if (/^(p|m|w|h|gap|text|bg|border|rounded|shadow|opacity|z|flex|grid|block|inline|hidden|relative|absolute|fixed|sticky|overflow|cursor|transition|ring|outline|sr|not|group|peer|dark|hover|focus|active|disabled|data|aria)-/.test(cls)) return true;
|
|
42658
|
+
if (/^(items|justify|self|place|space|divide|whitespace|break|font|leading|tracking|decoration|underline|overline|line|list|placeholder|align|content|object|max|min|inset|top|right|bottom|left|order|auto|grow|shrink|basis|table|caption|scale|rotate|translate|skew|origin|select|snap|scroll|touch|resize|appearance|columns|aspect|accent|caret|fill|stroke|will|animate|delay|duration|ease)-./.test(cls)) return true;
|
|
42659
|
+
if (/^(flex|grid|block|inline|hidden|table|contents)$/.test(cls)) return true;
|
|
42660
|
+
if (isFrameworkMarkerClass(cls)) return true;
|
|
42661
|
+
return false;
|
|
42662
|
+
};
|
|
42663
|
+
const KEYWORD_RE = /delete|remove|trash|edit|save|close|submit|cancel|add|create|copy|refresh|back|forward|next|prev|menu|nav|icon|btn|button|action|toggle|collapse|expand|upload|download|export|import|filter|search|settings|help|info|warning|error/i;
|
|
42444
42664
|
for (const cls of classes) {
|
|
42445
|
-
if (
|
|
42446
|
-
if (
|
|
42447
|
-
|
|
42448
|
-
|
|
42449
|
-
if (
|
|
42450
|
-
if (/^(
|
|
42451
|
-
if (/delete|remove|trash|edit|save|close|submit|cancel|add|create|copy|refresh|back|forward|next|prev|menu|nav|icon|btn|button|action|toggle|collapse|expand|upload|download|settings|help|info|warning|error/i.test(cls)) {
|
|
42452
|
-
return cls;
|
|
42453
|
-
}
|
|
42454
|
-
if (/^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)+$/.test(cls) && cls.length >= 6) {
|
|
42665
|
+
if (isNoise(cls)) continue;
|
|
42666
|
+
if (KEYWORD_RE.test(cls)) return cls;
|
|
42667
|
+
}
|
|
42668
|
+
for (const cls of classes) {
|
|
42669
|
+
if (isNoise(cls)) continue;
|
|
42670
|
+
if (/^[a-z][a-z0-9]*((-{1,2}|__)[a-z][a-z0-9]*)+$/.test(cls) && cls.length >= 6) {
|
|
42455
42671
|
return cls;
|
|
42456
42672
|
}
|
|
42457
42673
|
}
|
|
@@ -42547,6 +42763,9 @@ function planChecks(elements, opts) {
|
|
|
42547
42763
|
if (opts.v2 && el.role === "generic" && hasInteractive(el)) {
|
|
42548
42764
|
addCheck(el.ref, "modalV2");
|
|
42549
42765
|
}
|
|
42766
|
+
if (el.role === "dialog" || el.role === "alertdialog") {
|
|
42767
|
+
addCheck(el.ref, "dialogModality");
|
|
42768
|
+
}
|
|
42550
42769
|
if ((el.role === "button" || el.role === "link") && (!el.text || hasOnlyPrivateUseGlyphs(el.text))) {
|
|
42551
42770
|
addCheck(el.ref, "iconButton");
|
|
42552
42771
|
}
|
|
@@ -42789,6 +43008,46 @@ function pageSideFn(el, _ref, args, G) {
|
|
|
42789
43008
|
}
|
|
42790
43009
|
}
|
|
42791
43010
|
}
|
|
43011
|
+
if (checks.has("dialogModality")) {
|
|
43012
|
+
out.dialogModality = { inert: false };
|
|
43013
|
+
try {
|
|
43014
|
+
const isVisibleStyle = (n2) => {
|
|
43015
|
+
const he = n2;
|
|
43016
|
+
if (he.offsetWidth === 0 && he.offsetHeight === 0 && he.getClientRects().length === 0) {
|
|
43017
|
+
return false;
|
|
43018
|
+
}
|
|
43019
|
+
const style = window.getComputedStyle(n2);
|
|
43020
|
+
if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse") {
|
|
43021
|
+
return false;
|
|
43022
|
+
}
|
|
43023
|
+
if (parseFloat(style.opacity || "1") === 0) return false;
|
|
43024
|
+
return true;
|
|
43025
|
+
};
|
|
43026
|
+
let visible = true;
|
|
43027
|
+
let cur = el;
|
|
43028
|
+
for (let i2 = 0; i2 < 25 && cur; i2++) {
|
|
43029
|
+
if (!isVisibleStyle(cur)) {
|
|
43030
|
+
visible = false;
|
|
43031
|
+
break;
|
|
43032
|
+
}
|
|
43033
|
+
cur = cur.parentElement;
|
|
43034
|
+
}
|
|
43035
|
+
let onScreen = true;
|
|
43036
|
+
if (visible) {
|
|
43037
|
+
const rect = el.getBoundingClientRect();
|
|
43038
|
+
const vw = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
43039
|
+
const vh = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
43040
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
43041
|
+
onScreen = false;
|
|
43042
|
+
} else if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= vw || rect.top >= vh) {
|
|
43043
|
+
onScreen = false;
|
|
43044
|
+
}
|
|
43045
|
+
}
|
|
43046
|
+
out.dialogModality = { inert: !(visible && onScreen) };
|
|
43047
|
+
} catch {
|
|
43048
|
+
out.dialogModality = null;
|
|
43049
|
+
}
|
|
43050
|
+
}
|
|
42792
43051
|
const extractSvgHint = (root) => {
|
|
42793
43052
|
const svg = root.querySelector("svg");
|
|
42794
43053
|
if (!svg) return {};
|
|
@@ -42815,6 +43074,38 @@ function pageSideFn(el, _ref, args, G) {
|
|
|
42815
43074
|
if (m) lucideIconClass = m[0].toLowerCase();
|
|
42816
43075
|
return { svgHint, lucideIconClass };
|
|
42817
43076
|
};
|
|
43077
|
+
const extractIconClass = (root) => {
|
|
43078
|
+
const FA_STYLE = /^fa-(solid|regular|light|thin|duotone|brands|sharp)$/;
|
|
43079
|
+
const FA_SIZE = /^fa-(2?xs|sm|lg|xl|2xl|fw|spin|pulse|border|inverse|stack(-[12]x)?|pull-left|pull-right|beat|fade|flip|shake|bounce|spin-pulse|rotate-[0-9a-z]+|flip-[a-z]+)$/;
|
|
43080
|
+
const classOf = (node) => typeof node.className === "string" ? node.className : node.getAttribute("class") || "";
|
|
43081
|
+
const pick = (raw, allowGeneric) => {
|
|
43082
|
+
const tokens = raw.split(/\s+/).filter(Boolean);
|
|
43083
|
+
for (const t2 of tokens) {
|
|
43084
|
+
if (/^fa-/.test(t2) && t2 !== "fa" && !FA_STYLE.test(t2) && !FA_SIZE.test(t2)) return t2;
|
|
43085
|
+
}
|
|
43086
|
+
for (const t2 of tokens) {
|
|
43087
|
+
if (/^k-svg-i-/.test(t2) || /^k-i-/.test(t2)) return t2;
|
|
43088
|
+
}
|
|
43089
|
+
if (allowGeneric) {
|
|
43090
|
+
for (const t2 of tokens) if (/^icon-[a-z]/.test(t2)) return t2;
|
|
43091
|
+
}
|
|
43092
|
+
return void 0;
|
|
43093
|
+
};
|
|
43094
|
+
const rootHit = pick(classOf(root), false);
|
|
43095
|
+
if (rootHit) return rootHit;
|
|
43096
|
+
let kids = [];
|
|
43097
|
+
try {
|
|
43098
|
+
kids = Array.from(root.querySelectorAll("i, svg, em, span"));
|
|
43099
|
+
} catch {
|
|
43100
|
+
kids = [];
|
|
43101
|
+
}
|
|
43102
|
+
for (const node of kids) {
|
|
43103
|
+
const tag = node.tagName;
|
|
43104
|
+
const hit = pick(classOf(node), tag === "I" || tag === "SVG" || tag === "EM");
|
|
43105
|
+
if (hit) return hit;
|
|
43106
|
+
}
|
|
43107
|
+
return void 0;
|
|
43108
|
+
};
|
|
42818
43109
|
if (checks.has("iconButton")) {
|
|
42819
43110
|
try {
|
|
42820
43111
|
const ariaLabel = el.getAttribute("aria-label") || void 0;
|
|
@@ -42872,6 +43163,7 @@ function pageSideFn(el, _ref, args, G) {
|
|
|
42872
43163
|
}
|
|
42873
43164
|
}
|
|
42874
43165
|
}
|
|
43166
|
+
const iconClass = extractIconClass(el);
|
|
42875
43167
|
out.iconButton = {
|
|
42876
43168
|
ariaLabel,
|
|
42877
43169
|
title,
|
|
@@ -42889,7 +43181,8 @@ function pageSideFn(el, _ref, args, G) {
|
|
|
42889
43181
|
reactComponentName,
|
|
42890
43182
|
id: el.id || void 0,
|
|
42891
43183
|
className: typeof el.className === "string" ? el.className : void 0,
|
|
42892
|
-
lucideIconClass
|
|
43184
|
+
lucideIconClass,
|
|
43185
|
+
iconClass
|
|
42893
43186
|
};
|
|
42894
43187
|
} catch {
|
|
42895
43188
|
out.iconButton = null;
|
|
@@ -42902,9 +43195,19 @@ function pageSideFn(el, _ref, args, G) {
|
|
|
42902
43195
|
const id = el.id || void 0;
|
|
42903
43196
|
const className = typeof el.className === "string" ? el.className : void 0;
|
|
42904
43197
|
const { svgHint, lucideIconClass } = extractSvgHint(el);
|
|
43198
|
+
const iconClass = extractIconClass(el);
|
|
42905
43199
|
const rawInnerText = el instanceof HTMLElement ? el.innerText : void 0;
|
|
42906
43200
|
const innerText = rawInnerText?.replace(/\n+/g, " ").trim().slice(0, 80) || void 0;
|
|
42907
|
-
out.genericClickable = {
|
|
43201
|
+
out.genericClickable = {
|
|
43202
|
+
title,
|
|
43203
|
+
ariaLabel,
|
|
43204
|
+
svgHint,
|
|
43205
|
+
id,
|
|
43206
|
+
className,
|
|
43207
|
+
innerText,
|
|
43208
|
+
lucideIconClass,
|
|
43209
|
+
iconClass
|
|
43210
|
+
};
|
|
42908
43211
|
} catch {
|
|
42909
43212
|
out.genericClickable = null;
|
|
42910
43213
|
}
|
|
@@ -43192,6 +43495,9 @@ async function runPerRefAugmentations(scope, yaml, logger2, opts = {}) {
|
|
|
43192
43495
|
if (r2.hclip) {
|
|
43193
43496
|
lines[i2] = appendAttributeIfMissing(lines[i2], "~hclip", r2.hclip);
|
|
43194
43497
|
}
|
|
43498
|
+
if (r2.dialogModality?.inert) {
|
|
43499
|
+
lines[i2] = appendAttributeIfMissing(lines[i2], "~dialog-inert", "true");
|
|
43500
|
+
}
|
|
43195
43501
|
if (r2.gridCellValue) {
|
|
43196
43502
|
const escaped = r2.gridCellValue.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
43197
43503
|
lines[i2] = appendValueTail(lines[i2], escaped);
|
|
@@ -43240,7 +43546,7 @@ async function runPerRefAugmentations(scope, yaml, logger2, opts = {}) {
|
|
|
43240
43546
|
const linePreLabel = lines[i2];
|
|
43241
43547
|
const role = linePreLabel.includes("- link") ? "link" : "button";
|
|
43242
43548
|
const pathnameLabel = role === "link" ? labelFromPathname(h.pathname) : void 0;
|
|
43243
|
-
const hint = h.title || h.ariaLabel || h.svgHint || h.srText || h.imgAlt || pathnameLabel || h.reactComponentName || (h.id || void 0) || extractSemanticHint(h.className);
|
|
43549
|
+
const hint = h.title || h.ariaLabel || h.svgHint || h.srText || h.imgAlt || (h.iconClass ? resolveIconClassName(h.iconClass) : void 0) || pathnameLabel || h.reactComponentName || (h.id || void 0) || extractSemanticHint(h.className);
|
|
43244
43550
|
if (hint) {
|
|
43245
43551
|
lines[i2] = injectElementLabel(lines[i2], role, hint);
|
|
43246
43552
|
tagAugmentedNameSource(i2);
|
|
@@ -43254,6 +43560,8 @@ async function runPerRefAugmentations(scope, yaml, logger2, opts = {}) {
|
|
|
43254
43560
|
if (h.ariaCurrent) line = appendAttributeIfMissing(line, "aria-current", h.ariaCurrent);
|
|
43255
43561
|
if (h.lucideIconClass) {
|
|
43256
43562
|
line = appendAttributeIfMissing(line, "~icon-class", h.lucideIconClass);
|
|
43563
|
+
} else if (h.iconClass) {
|
|
43564
|
+
line = appendAttributeIfMissing(line, "~icon-class", h.iconClass);
|
|
43257
43565
|
}
|
|
43258
43566
|
const semanticToken = extractSemanticHint(h.className);
|
|
43259
43567
|
if (semanticToken) {
|
|
@@ -43269,7 +43577,7 @@ async function runPerRefAugmentations(scope, yaml, logger2, opts = {}) {
|
|
|
43269
43577
|
}
|
|
43270
43578
|
if (r2.genericClickable) {
|
|
43271
43579
|
const h = r2.genericClickable;
|
|
43272
|
-
const hint = h.title || h.ariaLabel || h.innerText || h.svgHint || (h.id || void 0) || extractSemanticHint(h.className);
|
|
43580
|
+
const hint = h.title || h.ariaLabel || h.innerText || h.svgHint || (h.iconClass ? resolveIconClassName(h.iconClass) : void 0) || (h.id || void 0) || extractSemanticHint(h.className);
|
|
43273
43581
|
if (hint) {
|
|
43274
43582
|
lines[i2] = injectElementLabel(lines[i2], "generic", hint);
|
|
43275
43583
|
tagAugmentedNameSource(i2);
|
|
@@ -43277,6 +43585,8 @@ async function runPerRefAugmentations(scope, yaml, logger2, opts = {}) {
|
|
|
43277
43585
|
let line = lines[i2];
|
|
43278
43586
|
if (h.lucideIconClass) {
|
|
43279
43587
|
line = appendAttributeIfMissing(line, "~icon-class", h.lucideIconClass);
|
|
43588
|
+
} else if (h.iconClass) {
|
|
43589
|
+
line = appendAttributeIfMissing(line, "~icon-class", h.iconClass);
|
|
43280
43590
|
}
|
|
43281
43591
|
const semanticToken = extractSemanticHint(h.className);
|
|
43282
43592
|
if (semanticToken) {
|
|
@@ -44805,7 +45115,7 @@ var CdpScreencastManager = class {
|
|
|
44805
45115
|
return;
|
|
44806
45116
|
}
|
|
44807
45117
|
const framerate = Math.round(1e3 / this.legacyOptions.minIntervalMs);
|
|
44808
|
-
const
|
|
45118
|
+
const encoder2 = this.encoderFactory.create({
|
|
44809
45119
|
framerate,
|
|
44810
45120
|
onInitSegment: videoCallbacks.onInitSegment,
|
|
44811
45121
|
onMediaSegment: videoCallbacks.onMediaSegment,
|
|
@@ -44816,11 +45126,11 @@ var CdpScreencastManager = class {
|
|
|
44816
45126
|
videoCallbacks.onError?.(err);
|
|
44817
45127
|
}
|
|
44818
45128
|
});
|
|
44819
|
-
|
|
45129
|
+
encoder2.start();
|
|
44820
45130
|
const encoderSub = await this.subscribe(page, {
|
|
44821
45131
|
onJpeg: (jpeg2) => {
|
|
44822
45132
|
try {
|
|
44823
|
-
|
|
45133
|
+
encoder2.pushFrame(jpeg2);
|
|
44824
45134
|
} catch (err) {
|
|
44825
45135
|
getLogger().warn("[CdpScreencast] Failed to push frame to encoder", {
|
|
44826
45136
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -44834,7 +45144,7 @@ var CdpScreencastManager = class {
|
|
|
44834
45144
|
maxHeight: this.legacyOptions.maxHeight,
|
|
44835
45145
|
everyNthFrame: this.legacyOptions.everyNthFrame
|
|
44836
45146
|
});
|
|
44837
|
-
this.legacyEncoder =
|
|
45147
|
+
this.legacyEncoder = encoder2;
|
|
44838
45148
|
this.legacyEncoderSubscription = encoderSub;
|
|
44839
45149
|
this._videoEncodingActive = true;
|
|
44840
45150
|
getLogger().info("[CdpScreencast] Video encoding enabled", { framerate });
|
|
@@ -48168,7 +48478,11 @@ function buildSection(element, depth) {
|
|
|
48168
48478
|
if (dismissRef) {
|
|
48169
48479
|
section.dismissActionRef = dismissRef;
|
|
48170
48480
|
}
|
|
48171
|
-
|
|
48481
|
+
const inert = element.dialogInert === true || element.visibility === "hidden" || element.visibility === "off-screen";
|
|
48482
|
+
if (inert) {
|
|
48483
|
+
section.isInertDialog = true;
|
|
48484
|
+
}
|
|
48485
|
+
if (element.attributes["aria-modal"] === "true" && !inert) {
|
|
48172
48486
|
section.isBlockingModal = true;
|
|
48173
48487
|
}
|
|
48174
48488
|
}
|
|
@@ -48305,7 +48619,7 @@ function sortSectionsByFocus(sections) {
|
|
|
48305
48619
|
dialogStack.unshift(focusedDialog.heading);
|
|
48306
48620
|
}
|
|
48307
48621
|
for (const dialog of dialogs) {
|
|
48308
|
-
if (!dialog.containsActive) {
|
|
48622
|
+
if (!dialog.containsActive && !dialog.isInertDialog) {
|
|
48309
48623
|
dialogStack.push(dialog.heading);
|
|
48310
48624
|
}
|
|
48311
48625
|
}
|
|
@@ -50116,12 +50430,406 @@ async function extractElementMetadata(locator, ref2, _logger3) {
|
|
|
50116
50430
|
childImgAlt: domProps.childImgAlt
|
|
50117
50431
|
};
|
|
50118
50432
|
}
|
|
50433
|
+
init_logger();
|
|
50434
|
+
init_logger();
|
|
50435
|
+
var READY_ID = 0;
|
|
50436
|
+
var HEADER_BYTES = 4;
|
|
50437
|
+
var MAX_FRAME_BYTES = 64 * 1024 * 1024;
|
|
50438
|
+
var encoder = new TextEncoder();
|
|
50439
|
+
var decoder = new TextDecoder();
|
|
50440
|
+
function encodeFrame(obj) {
|
|
50441
|
+
const body = encoder.encode(JSON.stringify(obj));
|
|
50442
|
+
const frame = new Uint8Array(HEADER_BYTES + body.length);
|
|
50443
|
+
new DataView(frame.buffer).setUint32(0, body.length, false);
|
|
50444
|
+
frame.set(body, HEADER_BYTES);
|
|
50445
|
+
return frame;
|
|
50446
|
+
}
|
|
50447
|
+
var FrameDecoder = class {
|
|
50448
|
+
buf = new Uint8Array(0);
|
|
50449
|
+
/** Append a chunk and return every frame that is now complete. */
|
|
50450
|
+
push(chunk) {
|
|
50451
|
+
const next = new Uint8Array(this.buf.length + chunk.length);
|
|
50452
|
+
next.set(this.buf, 0);
|
|
50453
|
+
next.set(chunk, this.buf.length);
|
|
50454
|
+
this.buf = next;
|
|
50455
|
+
const out = [];
|
|
50456
|
+
let offset2 = 0;
|
|
50457
|
+
while (this.buf.length - offset2 >= HEADER_BYTES) {
|
|
50458
|
+
const len = new DataView(this.buf.buffer, this.buf.byteOffset + offset2).getUint32(0, false);
|
|
50459
|
+
if (len > MAX_FRAME_BYTES) {
|
|
50460
|
+
throw new Error(`cpu-offload frame length ${len} exceeds ${MAX_FRAME_BYTES} (corrupt stream)`);
|
|
50461
|
+
}
|
|
50462
|
+
if (this.buf.length - offset2 - HEADER_BYTES < len) break;
|
|
50463
|
+
const start = offset2 + HEADER_BYTES;
|
|
50464
|
+
const body = this.buf.subarray(start, start + len);
|
|
50465
|
+
out.push(JSON.parse(decoder.decode(body)));
|
|
50466
|
+
offset2 = start + len;
|
|
50467
|
+
}
|
|
50468
|
+
if (offset2 > 0) this.buf = this.buf.subarray(offset2);
|
|
50469
|
+
return out;
|
|
50470
|
+
}
|
|
50471
|
+
};
|
|
50472
|
+
var CpuOffloadTimeoutError = class extends Error {
|
|
50473
|
+
_tag = "CpuOffloadTimeoutError";
|
|
50474
|
+
constructor(task, timeoutMs) {
|
|
50475
|
+
super(`cpu-offload task '${task}' exceeded ${timeoutMs}ms and was terminated`);
|
|
50476
|
+
this.name = "CpuOffloadTimeoutError";
|
|
50477
|
+
}
|
|
50478
|
+
};
|
|
50479
|
+
var CpuOffloadWorkerError = class extends Error {
|
|
50480
|
+
_tag = "CpuOffloadWorkerError";
|
|
50481
|
+
constructor(message) {
|
|
50482
|
+
super(message);
|
|
50483
|
+
this.name = "CpuOffloadWorkerError";
|
|
50484
|
+
}
|
|
50485
|
+
};
|
|
50486
|
+
var READY_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
50487
|
+
function resolveCpuOffloadWorkerPath() {
|
|
50488
|
+
const candidates = [
|
|
50489
|
+
new URL("./worker-process.ts", import.meta.url),
|
|
50490
|
+
new URL("./worker-process.js", import.meta.url),
|
|
50491
|
+
new URL("./cpu-offload/worker-process.js", import.meta.url)
|
|
50492
|
+
].map((u2) => fileURLToPath(u2));
|
|
50493
|
+
const found = candidates.find((p2) => existsSync2(p2));
|
|
50494
|
+
if (found) return found;
|
|
50495
|
+
try {
|
|
50496
|
+
const pkgJson = createRequire(import.meta.url).resolve("@chatsdet/browser-core/package.json");
|
|
50497
|
+
const viaPkg = join2(dirname(pkgJson), "dist", "cpu-offload", "worker-process.js");
|
|
50498
|
+
if (existsSync2(viaPkg)) return viaPkg;
|
|
50499
|
+
candidates.push(viaPkg);
|
|
50500
|
+
} catch {
|
|
50501
|
+
}
|
|
50502
|
+
throw new CpuOffloadWorkerError(`worker entry not found; looked in: ${candidates.join(", ")}`);
|
|
50503
|
+
}
|
|
50504
|
+
var CpuOffloadPool = class {
|
|
50505
|
+
opts;
|
|
50506
|
+
logger;
|
|
50507
|
+
workers = /* @__PURE__ */ new Set();
|
|
50508
|
+
idle = [];
|
|
50509
|
+
waiters = [];
|
|
50510
|
+
nextId = 1;
|
|
50511
|
+
shuttingDown = false;
|
|
50512
|
+
constructor(options) {
|
|
50513
|
+
this.logger = options.logger ?? consoleLogger;
|
|
50514
|
+
this.opts = {
|
|
50515
|
+
size: Math.max(1, options.size),
|
|
50516
|
+
defaultTimeoutMs: options.defaultTimeoutMs,
|
|
50517
|
+
spawn: options.spawn ?? spawn2,
|
|
50518
|
+
workerPath: options.workerPath ?? resolveCpuOffloadWorkerPath(),
|
|
50519
|
+
execPath: options.execPath ?? process.execPath
|
|
50520
|
+
};
|
|
50521
|
+
}
|
|
50522
|
+
/** Run a registered task. Rejects with a typed error on timeout/crash. */
|
|
50523
|
+
async run(task, payload, runOpts) {
|
|
50524
|
+
if (this.shuttingDown) {
|
|
50525
|
+
throw new CpuOffloadWorkerError("pool is shutting down");
|
|
50526
|
+
}
|
|
50527
|
+
const worker = await this.acquire();
|
|
50528
|
+
const timeoutMs = runOpts?.timeoutMs ?? this.opts.defaultTimeoutMs;
|
|
50529
|
+
return new Promise((resolve, reject) => {
|
|
50530
|
+
const id = this.nextId++;
|
|
50531
|
+
const timer = setTimeout(() => this.onTimeout(worker), timeoutMs);
|
|
50532
|
+
worker.current = {
|
|
50533
|
+
id,
|
|
50534
|
+
task,
|
|
50535
|
+
timeoutMs,
|
|
50536
|
+
timer,
|
|
50537
|
+
resolve,
|
|
50538
|
+
reject
|
|
50539
|
+
};
|
|
50540
|
+
const req = { id, task, payload };
|
|
50541
|
+
const stdin = worker.child.stdin;
|
|
50542
|
+
if (!stdin) {
|
|
50543
|
+
this.retireWorker(worker, new CpuOffloadWorkerError("worker has no stdin"));
|
|
50544
|
+
return;
|
|
50545
|
+
}
|
|
50546
|
+
try {
|
|
50547
|
+
stdin.write(encodeFrame(req));
|
|
50548
|
+
} catch (err) {
|
|
50549
|
+
this.retireWorker(
|
|
50550
|
+
worker,
|
|
50551
|
+
new CpuOffloadWorkerError(
|
|
50552
|
+
`failed to write to worker: ${err instanceof Error ? err.message : String(err)}`
|
|
50553
|
+
)
|
|
50554
|
+
);
|
|
50555
|
+
}
|
|
50556
|
+
});
|
|
50557
|
+
}
|
|
50558
|
+
stats() {
|
|
50559
|
+
return {
|
|
50560
|
+
total: this.workers.size,
|
|
50561
|
+
idle: this.idle.length,
|
|
50562
|
+
busy: this.workers.size - this.idle.length,
|
|
50563
|
+
waiting: this.waiters.length
|
|
50564
|
+
};
|
|
50565
|
+
}
|
|
50566
|
+
async shutdown() {
|
|
50567
|
+
this.shuttingDown = true;
|
|
50568
|
+
for (const waiter of this.waiters) {
|
|
50569
|
+
waiter.reject(new CpuOffloadWorkerError("pool shutting down"));
|
|
50570
|
+
}
|
|
50571
|
+
this.waiters.length = 0;
|
|
50572
|
+
for (const w of this.workers) {
|
|
50573
|
+
w.retired = true;
|
|
50574
|
+
if (w.current) {
|
|
50575
|
+
clearTimeout(w.current.timer);
|
|
50576
|
+
w.current.reject(new CpuOffloadWorkerError("pool shutting down"));
|
|
50577
|
+
}
|
|
50578
|
+
w.child.kill("SIGKILL");
|
|
50579
|
+
}
|
|
50580
|
+
this.workers.clear();
|
|
50581
|
+
this.idle.length = 0;
|
|
50582
|
+
}
|
|
50583
|
+
// ── internals ──────────────────────────────────────────────────────────
|
|
50584
|
+
acquire() {
|
|
50585
|
+
const free = this.idle.pop();
|
|
50586
|
+
if (free) return Promise.resolve(free);
|
|
50587
|
+
if (this.workers.size < this.opts.size) return this.spawnWorker();
|
|
50588
|
+
return new Promise((resolve, reject) => this.waiters.push({ resolve, reject }));
|
|
50589
|
+
}
|
|
50590
|
+
release(worker) {
|
|
50591
|
+
if (worker.retired || this.shuttingDown) return;
|
|
50592
|
+
const waiter = this.waiters.shift();
|
|
50593
|
+
if (waiter) waiter.resolve(worker);
|
|
50594
|
+
else this.idle.push(worker);
|
|
50595
|
+
}
|
|
50596
|
+
spawnWorker() {
|
|
50597
|
+
const child = this.opts.spawn(this.opts.execPath, [this.opts.workerPath], {
|
|
50598
|
+
stdio: ["pipe", "pipe", "inherit"]
|
|
50599
|
+
});
|
|
50600
|
+
const worker = { child, decoder: new FrameDecoder(), current: null, retired: false };
|
|
50601
|
+
this.workers.add(worker);
|
|
50602
|
+
return new Promise((resolve, reject) => {
|
|
50603
|
+
let ready = false;
|
|
50604
|
+
let spawnFailed = false;
|
|
50605
|
+
const failSpawn = (err) => {
|
|
50606
|
+
if (ready || spawnFailed) return;
|
|
50607
|
+
spawnFailed = true;
|
|
50608
|
+
clearTimeout(readyTimer);
|
|
50609
|
+
this.workers.delete(worker);
|
|
50610
|
+
worker.child.kill("SIGKILL");
|
|
50611
|
+
reject(err);
|
|
50612
|
+
};
|
|
50613
|
+
const readyTimer = setTimeout(
|
|
50614
|
+
() => failSpawn(new CpuOffloadWorkerError("worker did not become ready in time")),
|
|
50615
|
+
READY_HANDSHAKE_TIMEOUT_MS
|
|
50616
|
+
);
|
|
50617
|
+
child.stdout?.on("data", (chunk) => {
|
|
50618
|
+
let frames;
|
|
50619
|
+
try {
|
|
50620
|
+
frames = worker.decoder.push(chunk);
|
|
50621
|
+
} catch (err) {
|
|
50622
|
+
const wrapped = new CpuOffloadWorkerError(
|
|
50623
|
+
`worker protocol error: ${err instanceof Error ? err.message : String(err)}`
|
|
50624
|
+
);
|
|
50625
|
+
if (ready) this.retireWorker(worker, wrapped);
|
|
50626
|
+
else failSpawn(wrapped);
|
|
50627
|
+
return;
|
|
50628
|
+
}
|
|
50629
|
+
for (const msg of frames) {
|
|
50630
|
+
const resp = msg;
|
|
50631
|
+
if (resp.id === READY_ID) {
|
|
50632
|
+
ready = true;
|
|
50633
|
+
clearTimeout(readyTimer);
|
|
50634
|
+
resolve(worker);
|
|
50635
|
+
} else {
|
|
50636
|
+
this.onResponse(worker, resp);
|
|
50637
|
+
}
|
|
50638
|
+
}
|
|
50639
|
+
});
|
|
50640
|
+
child.on("exit", (code, signal) => {
|
|
50641
|
+
if (!ready) {
|
|
50642
|
+
failSpawn(
|
|
50643
|
+
new CpuOffloadWorkerError(`worker exited before ready (code=${code}, signal=${signal})`)
|
|
50644
|
+
);
|
|
50645
|
+
return;
|
|
50646
|
+
}
|
|
50647
|
+
if (!worker.retired) {
|
|
50648
|
+
this.retireWorker(
|
|
50649
|
+
worker,
|
|
50650
|
+
new CpuOffloadWorkerError(`worker exited unexpectedly (code=${code}, signal=${signal})`)
|
|
50651
|
+
);
|
|
50652
|
+
}
|
|
50653
|
+
});
|
|
50654
|
+
child.on("error", (err) => {
|
|
50655
|
+
if (!ready) {
|
|
50656
|
+
failSpawn(new CpuOffloadWorkerError(`worker spawn failed: ${err.message}`));
|
|
50657
|
+
} else if (!worker.retired) {
|
|
50658
|
+
this.retireWorker(worker, new CpuOffloadWorkerError(`worker error: ${err.message}`));
|
|
50659
|
+
}
|
|
50660
|
+
});
|
|
50661
|
+
});
|
|
50662
|
+
}
|
|
50663
|
+
onResponse(worker, resp) {
|
|
50664
|
+
const call = worker.current;
|
|
50665
|
+
if (!call || call.id !== resp.id) return;
|
|
50666
|
+
clearTimeout(call.timer);
|
|
50667
|
+
worker.current = null;
|
|
50668
|
+
if (resp.ok) call.resolve(resp.result);
|
|
50669
|
+
else call.reject(new CpuOffloadWorkerError(resp.error.message));
|
|
50670
|
+
this.release(worker);
|
|
50671
|
+
}
|
|
50672
|
+
onTimeout(worker) {
|
|
50673
|
+
const call = worker.current;
|
|
50674
|
+
if (!call) return;
|
|
50675
|
+
this.retireWorker(worker, new CpuOffloadTimeoutError(call.task, call.timeoutMs));
|
|
50676
|
+
}
|
|
50677
|
+
/**
|
|
50678
|
+
* Reject any in-flight call, kill the process, drop the worker, and — unless
|
|
50679
|
+
* shutting down — spawn a replacement to keep capacity up and drain waiters.
|
|
50680
|
+
* Idempotent: the SIGKILL's own `exit` event re-enters here as a no-op.
|
|
50681
|
+
*/
|
|
50682
|
+
retireWorker(worker, error) {
|
|
50683
|
+
if (worker.retired) return;
|
|
50684
|
+
worker.retired = true;
|
|
50685
|
+
this.workers.delete(worker);
|
|
50686
|
+
const idx = this.idle.indexOf(worker);
|
|
50687
|
+
if (idx >= 0) this.idle.splice(idx, 1);
|
|
50688
|
+
this.logger.warn("[CpuOffloadPool] retiring worker", {
|
|
50689
|
+
pid: worker.child.pid,
|
|
50690
|
+
task: worker.current?.task,
|
|
50691
|
+
reason: error.message,
|
|
50692
|
+
timedOut: error instanceof CpuOffloadTimeoutError
|
|
50693
|
+
});
|
|
50694
|
+
if (worker.current) {
|
|
50695
|
+
clearTimeout(worker.current.timer);
|
|
50696
|
+
worker.current.reject(error);
|
|
50697
|
+
worker.current = null;
|
|
50698
|
+
}
|
|
50699
|
+
worker.child.kill("SIGKILL");
|
|
50700
|
+
if (this.shuttingDown) return;
|
|
50701
|
+
if (this.waiters.length > 0 || this.workers.size < this.opts.size) {
|
|
50702
|
+
this.spawnWorker().then((w) => this.release(w)).catch((err) => {
|
|
50703
|
+
this.logger.error("[CpuOffloadPool] failed to respawn worker; rejecting waiters", {
|
|
50704
|
+
error: err instanceof Error ? err.message : String(err),
|
|
50705
|
+
waiting: this.waiters.length
|
|
50706
|
+
});
|
|
50707
|
+
const drained = this.waiters.splice(0);
|
|
50708
|
+
for (const waiter of drained) {
|
|
50709
|
+
waiter.reject(
|
|
50710
|
+
new CpuOffloadWorkerError(
|
|
50711
|
+
`worker respawn failed: ${err instanceof Error ? err.message : String(err)}`
|
|
50712
|
+
)
|
|
50713
|
+
);
|
|
50714
|
+
}
|
|
50715
|
+
});
|
|
50716
|
+
}
|
|
50717
|
+
}
|
|
50718
|
+
};
|
|
50719
|
+
var DEFAULT_CPU_OFFLOAD_TIMEOUT_MS = 15e3;
|
|
50720
|
+
var defaultCpuOffloadSize = () => Math.min(8, Math.max(2, Math.floor(cpus().length / 2)));
|
|
50721
|
+
var config = { enabled: false };
|
|
50722
|
+
var pool = null;
|
|
50723
|
+
function configureCpuOffload(next) {
|
|
50724
|
+
config = next;
|
|
50725
|
+
if (typeof next.enabled === "boolean" && next.enabled === false) {
|
|
50726
|
+
void shutdownCpuOffload();
|
|
50727
|
+
}
|
|
50728
|
+
}
|
|
50729
|
+
function isCpuOffloadEnabled() {
|
|
50730
|
+
const { enabled } = config;
|
|
50731
|
+
return typeof enabled === "function" ? !!enabled() : enabled;
|
|
50732
|
+
}
|
|
50733
|
+
function getPool() {
|
|
50734
|
+
if (!pool) {
|
|
50735
|
+
pool = new CpuOffloadPool({
|
|
50736
|
+
size: config.size ?? defaultCpuOffloadSize(),
|
|
50737
|
+
defaultTimeoutMs: config.timeoutMs ?? DEFAULT_CPU_OFFLOAD_TIMEOUT_MS,
|
|
50738
|
+
logger: config.logger ?? consoleLogger
|
|
50739
|
+
});
|
|
50740
|
+
}
|
|
50741
|
+
return pool;
|
|
50742
|
+
}
|
|
50743
|
+
async function shutdownCpuOffload() {
|
|
50744
|
+
const p2 = pool;
|
|
50745
|
+
pool = null;
|
|
50746
|
+
if (p2) await p2.shutdown();
|
|
50747
|
+
}
|
|
50748
|
+
var TIMEOUT_MARKER = "---\nSEMANTIC SNAPSHOT - formatting timed out\nThe page was too large to format within the time budget. Narrow with browser_snapshot search=\u2026 or scroll to a region.\n---";
|
|
50749
|
+
async function formatSnapshotMaybeOffloaded(yaml, options) {
|
|
50750
|
+
if (!isCpuOffloadEnabled()) {
|
|
50751
|
+
return formatSemanticSnapshot(yaml, options);
|
|
50752
|
+
}
|
|
50753
|
+
const logger2 = config.logger ?? consoleLogger;
|
|
50754
|
+
try {
|
|
50755
|
+
const { elementHints, matchedHintIds: _drop, ...rest } = options ?? {};
|
|
50756
|
+
const payload = {
|
|
50757
|
+
yaml,
|
|
50758
|
+
options: rest,
|
|
50759
|
+
...elementHints ? { elementHints: [...elementHints] } : {}
|
|
50760
|
+
};
|
|
50761
|
+
const result = await getPool().run("format-snapshot", payload);
|
|
50762
|
+
if (options && result.matchedHintIds) {
|
|
50763
|
+
options.matchedHintIds = result.matchedHintIds;
|
|
50764
|
+
}
|
|
50765
|
+
return result.text;
|
|
50766
|
+
} catch (err) {
|
|
50767
|
+
if (err instanceof CpuOffloadTimeoutError) {
|
|
50768
|
+
logger2.warn("[CpuOffload] format-snapshot timed out; returning marker (NOT inlining)", {
|
|
50769
|
+
task: "format-snapshot",
|
|
50770
|
+
error: err.message
|
|
50771
|
+
});
|
|
50772
|
+
return TIMEOUT_MARKER;
|
|
50773
|
+
}
|
|
50774
|
+
logger2.warn("[CpuOffload] format-snapshot offload failed; running inline", {
|
|
50775
|
+
task: "format-snapshot",
|
|
50776
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50777
|
+
});
|
|
50778
|
+
return formatSemanticSnapshot(yaml, options);
|
|
50779
|
+
}
|
|
50780
|
+
}
|
|
50119
50781
|
var ToolAbortedError = class extends Error {
|
|
50120
50782
|
constructor(stage) {
|
|
50121
50783
|
super(`Browser action aborted at stage: ${stage}`);
|
|
50122
50784
|
this.name = "ToolAbortedError";
|
|
50123
50785
|
}
|
|
50124
50786
|
};
|
|
50787
|
+
function labelForContext(context) {
|
|
50788
|
+
return context.elementDesc ? `${context.elementDesc} (${context.ref})` : context.ref;
|
|
50789
|
+
}
|
|
50790
|
+
function elementDescription(context) {
|
|
50791
|
+
const role = context.role ? ` role=${context.role}` : "";
|
|
50792
|
+
const type = context.inputType ? ` type=${context.inputType}` : "";
|
|
50793
|
+
return `${context.tagName}${type}${role}`;
|
|
50794
|
+
}
|
|
50795
|
+
function formatFillTargetNotEditableMessage(context) {
|
|
50796
|
+
if (context.state === "not-fillable") {
|
|
50797
|
+
return `Cannot fill target ${labelForContext(context)}: ${elementDescription(context)} cannot accept text.`;
|
|
50798
|
+
}
|
|
50799
|
+
return `Cannot fill ${context.state} field ${labelForContext(context)}: ${elementDescription(context)} is not editable.`;
|
|
50800
|
+
}
|
|
50801
|
+
var FillTargetNotEditableError = class extends Error {
|
|
50802
|
+
fillTarget;
|
|
50803
|
+
constructor(context) {
|
|
50804
|
+
super(formatFillTargetNotEditableMessage(context));
|
|
50805
|
+
this.name = "FillTargetNotEditableError";
|
|
50806
|
+
this.fillTarget = context;
|
|
50807
|
+
}
|
|
50808
|
+
};
|
|
50809
|
+
function isRecord(value) {
|
|
50810
|
+
return typeof value === "object" && value !== null;
|
|
50811
|
+
}
|
|
50812
|
+
function isFillTargetNotEditableError(error) {
|
|
50813
|
+
if (error instanceof FillTargetNotEditableError) return true;
|
|
50814
|
+
if (!isRecord(error) || error.name !== "FillTargetNotEditableError") return false;
|
|
50815
|
+
if (!isRecord(error.fillTarget)) return false;
|
|
50816
|
+
const context = error.fillTarget;
|
|
50817
|
+
return typeof context.ref === "string" && typeof context.tagName === "string" && (context.state === "readonly" || context.state === "disabled" || context.state === "not-fillable");
|
|
50818
|
+
}
|
|
50819
|
+
function formatFillTargetNotEditableRecovery(error, toolName = "browser_fill_form") {
|
|
50820
|
+
const context = error.fillTarget;
|
|
50821
|
+
const action = toolName === "browser_type" ? "type into" : "fill";
|
|
50822
|
+
if (context.state === "not-fillable") {
|
|
50823
|
+
return [
|
|
50824
|
+
`Error: ${toolName} cannot ${action} target ${labelForContext(context)}: ${elementDescription(context)} cannot accept typed text.`,
|
|
50825
|
+
`Do not retry ${toolName} for this ref. Call browser_snapshot and choose the actual editable input or textarea. If the target is a dropdown, use browser_select_option or click the dropdown and select an option.`
|
|
50826
|
+
].join(" ");
|
|
50827
|
+
}
|
|
50828
|
+
return [
|
|
50829
|
+
`Error: ${toolName} cannot ${action} ${context.state} field ${labelForContext(context)}: ${elementDescription(context)} is not editable.`,
|
|
50830
|
+
`Do not retry ${toolName} for this ref. Call browser_snapshot and choose an editable input or textarea for the same requirement, or complete the prerequisite that unlocks this field first.`
|
|
50831
|
+
].join(" ");
|
|
50832
|
+
}
|
|
50125
50833
|
function isMCPContentWithImages(result) {
|
|
50126
50834
|
return typeof result === "object" && result !== null && "text" in result && "images" in result && Array.isArray(result.images) && result.images.length > 0;
|
|
50127
50835
|
}
|
|
@@ -50212,6 +50920,31 @@ function formatEmptyPressKeyRecovery() {
|
|
|
50212
50920
|
'Do not retry with an empty string. Use a Playwright key such as "Enter", "Escape", "Tab", "ArrowDown", or use browser_type when you need to enter text.'
|
|
50213
50921
|
].join(" ");
|
|
50214
50922
|
}
|
|
50923
|
+
function normalizeRef(ref2) {
|
|
50924
|
+
const trimmed = ref2?.trim();
|
|
50925
|
+
return trimmed ? trimmed : void 0;
|
|
50926
|
+
}
|
|
50927
|
+
function formatEmptyRefRecovery(toolName) {
|
|
50928
|
+
return [
|
|
50929
|
+
`Error: ${toolName} requires a non-empty element ref from the latest browser_snapshot.`,
|
|
50930
|
+
'Do not retry with an empty string. Call browser_snapshot and use a concrete ref such as "e42", or use the coordinate path when that tool supports coordinates.'
|
|
50931
|
+
].join(" ");
|
|
50932
|
+
}
|
|
50933
|
+
function extractWaitingAriaRef(error) {
|
|
50934
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50935
|
+
return message.match(/waiting for locator\('aria-ref=([^']+)'\)/)?.[1];
|
|
50936
|
+
}
|
|
50937
|
+
function isStaleAriaRefActionTimeout(error, action) {
|
|
50938
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50939
|
+
return message.includes(`${action}: Timeout`) && message.includes("waiting for locator('aria-ref=") && !message.includes("locator resolved to <");
|
|
50940
|
+
}
|
|
50941
|
+
function formatStaleRefActionRecovery(toolName, ref2, element) {
|
|
50942
|
+
const label = element ? ` for "${element}"` : "";
|
|
50943
|
+
return [
|
|
50944
|
+
`Error: ${toolName} could not find ref ${ref2}${label} in the current page snapshot.`,
|
|
50945
|
+
"Do not retry the same ref. Call browser_snapshot and choose a fresh ref, or use the coordinate path when that tool supports coordinates."
|
|
50946
|
+
].join(" ");
|
|
50947
|
+
}
|
|
50215
50948
|
function isSelectOptionNonSelectError(error) {
|
|
50216
50949
|
const message = error instanceof Error ? error.message : String(error);
|
|
50217
50950
|
return message.includes("selectOption:") && message.includes("Element is not a <select>");
|
|
@@ -50219,6 +50952,35 @@ function isSelectOptionNonSelectError(error) {
|
|
|
50219
50952
|
function isMissingDownloadTempFileError(message) {
|
|
50220
50953
|
return /\bENOENT:\s+no such file or directory,\s+open\b/.test(message) && message.includes("/playwright-downloads-");
|
|
50221
50954
|
}
|
|
50955
|
+
function isNavigateDownloadStartingError(error) {
|
|
50956
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50957
|
+
return /\bgoto:\s+Download is starting\b/.test(message);
|
|
50958
|
+
}
|
|
50959
|
+
function formatNavigateDownloadStartingRecovery() {
|
|
50960
|
+
return [
|
|
50961
|
+
"Error: browser_navigate started a file download instead of loading a page.",
|
|
50962
|
+
"Do not retry browser_navigate for the same URL. Call browser_list_downloads to find the captured file, then use browser_read_download or browser_pdf_read to inspect it."
|
|
50963
|
+
].join(" ");
|
|
50964
|
+
}
|
|
50965
|
+
function isRelativeNavigateTarget(url) {
|
|
50966
|
+
const trimmed = url.trim();
|
|
50967
|
+
return trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("?") || trimmed.startsWith("#");
|
|
50968
|
+
}
|
|
50969
|
+
function isHttpUrl(url) {
|
|
50970
|
+
try {
|
|
50971
|
+
const parsed = new URL(url);
|
|
50972
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
50973
|
+
} catch {
|
|
50974
|
+
return false;
|
|
50975
|
+
}
|
|
50976
|
+
}
|
|
50977
|
+
function formatRelativeNavigateRecovery(url, currentUrl) {
|
|
50978
|
+
const baseDescription = currentUrl ? `current page URL is "${currentUrl}"` : "current page URL is unavailable";
|
|
50979
|
+
return [
|
|
50980
|
+
`Error: browser_navigate received relative URL "${url}", but the ${baseDescription}.`,
|
|
50981
|
+
"Use an absolute http(s) URL, or call browser_snapshot first if the current page needs to be inspected before navigating."
|
|
50982
|
+
].join(" ");
|
|
50983
|
+
}
|
|
50222
50984
|
function formatSelectOptionNonSelectRecovery(ref2, value, element) {
|
|
50223
50985
|
return [
|
|
50224
50986
|
`Error: browser_select_option can only operate on native <select> elements; ref ${ref2} for "${element}" resolved to a custom dropdown or combobox.`,
|
|
@@ -50676,11 +51438,38 @@ var BrowserToolExecutor = class {
|
|
|
50676
51438
|
}
|
|
50677
51439
|
// ==================== Navigation ====================
|
|
50678
51440
|
async navigate(url) {
|
|
50679
|
-
|
|
50680
|
-
|
|
51441
|
+
const navigationUrl = await this.resolveNavigateUrl(url);
|
|
51442
|
+
if (navigationUrl.kind === "recovery") {
|
|
51443
|
+
return navigationUrl.message;
|
|
51444
|
+
}
|
|
51445
|
+
ensureAllowedHost(navigationUrl.url, this.allowedHosts);
|
|
51446
|
+
let rawResult;
|
|
51447
|
+
try {
|
|
51448
|
+
rawResult = await this.client.navigate(navigationUrl.url, { signal: this.currentSignal });
|
|
51449
|
+
} catch (error) {
|
|
51450
|
+
if (isNavigateDownloadStartingError(error)) {
|
|
51451
|
+
return formatNavigateDownloadStartingRecovery();
|
|
51452
|
+
}
|
|
51453
|
+
throw error;
|
|
51454
|
+
}
|
|
50681
51455
|
const result = withRecoveryNotice(this.client, rawResult, this.logger);
|
|
50682
51456
|
return this.formatNavigateResult(result);
|
|
50683
51457
|
}
|
|
51458
|
+
async resolveNavigateUrl(url) {
|
|
51459
|
+
const trimmedUrl = url.trim();
|
|
51460
|
+
if (!isRelativeNavigateTarget(trimmedUrl)) {
|
|
51461
|
+
return { kind: "url", url: trimmedUrl };
|
|
51462
|
+
}
|
|
51463
|
+
const currentUrl = await this.client.getCurrentUrl({ signal: this.currentSignal }).catch(() => void 0);
|
|
51464
|
+
if (!currentUrl || !isHttpUrl(currentUrl)) {
|
|
51465
|
+
return { kind: "recovery", message: formatRelativeNavigateRecovery(trimmedUrl, currentUrl) };
|
|
51466
|
+
}
|
|
51467
|
+
try {
|
|
51468
|
+
return { kind: "url", url: new URL(trimmedUrl, currentUrl).toString() };
|
|
51469
|
+
} catch {
|
|
51470
|
+
return { kind: "recovery", message: formatRelativeNavigateRecovery(trimmedUrl, currentUrl) };
|
|
51471
|
+
}
|
|
51472
|
+
}
|
|
50684
51473
|
async navigateBack() {
|
|
50685
51474
|
const result = await this.client.navigateBack({ signal: this.currentSignal });
|
|
50686
51475
|
return this.formatNavigateResult(result);
|
|
@@ -50930,7 +51719,7 @@ ${effectiveShowCoordinateGrid ? "Coordinate grid enabled - read coordinates from
|
|
|
50930
51719
|
elementHints,
|
|
50931
51720
|
matchedHintIds: void 0
|
|
50932
51721
|
};
|
|
50933
|
-
let semanticText =
|
|
51722
|
+
let semanticText = await formatSnapshotMaybeOffloaded(yaml, snapshotOpts);
|
|
50934
51723
|
const formattedRefs = extractFormattedSnapshotRefs(semanticText);
|
|
50935
51724
|
if (formattedRefs.length > LARGE_PAGE_REF_THRESHOLD) {
|
|
50936
51725
|
semanticText = `[Large page: ~${formattedRefs.length.toLocaleString()} interactive elements \u2014 scroll-position hints reduced for speed. Narrow with browser_snapshot search=\u2026 or scroll to a region.]
|
|
@@ -50985,6 +51774,10 @@ ${body}
|
|
|
50985
51774
|
* Returns a structured result with the message and optional created hint metadata.
|
|
50986
51775
|
*/
|
|
50987
51776
|
async hint(opts) {
|
|
51777
|
+
const ref2 = normalizeRef(opts.ref);
|
|
51778
|
+
if (!ref2) {
|
|
51779
|
+
return { message: formatEmptyRefRecovery("browser_hint") };
|
|
51780
|
+
}
|
|
50988
51781
|
if (!this.hintProvider) {
|
|
50989
51782
|
return { message: "Element hints are not available in this environment." };
|
|
50990
51783
|
}
|
|
@@ -50998,9 +51791,9 @@ ${body}
|
|
|
50998
51791
|
return { message: "Cannot create hint: no recent snapshot available. Take a snapshot first." };
|
|
50999
51792
|
}
|
|
51000
51793
|
const elements = parseSnapshot(lastYaml);
|
|
51001
|
-
const fpResult = fingerprintForHint(elements,
|
|
51794
|
+
const fpResult = fingerprintForHint(elements, ref2);
|
|
51002
51795
|
if (!fpResult) {
|
|
51003
|
-
return { message: `Cannot create hint: element ref "${
|
|
51796
|
+
return { message: `Cannot create hint: element ref "${ref2}" not found in the current snapshot.` };
|
|
51004
51797
|
}
|
|
51005
51798
|
if (opts.invalidate) {
|
|
51006
51799
|
if (!opts.reason) {
|
|
@@ -51019,7 +51812,7 @@ ${body}
|
|
|
51019
51812
|
fingerprintHash: fpResult.hash,
|
|
51020
51813
|
reason: opts.reason
|
|
51021
51814
|
});
|
|
51022
|
-
return { message: `Hint on [${
|
|
51815
|
+
return { message: `Hint on [${ref2}] invalidated: ${opts.reason}` };
|
|
51023
51816
|
}
|
|
51024
51817
|
if (!opts.frontmatter) {
|
|
51025
51818
|
return { message: "Cannot create hint: frontmatter is required." };
|
|
@@ -51064,7 +51857,7 @@ ${body}
|
|
|
51064
51857
|
});
|
|
51065
51858
|
const anchorNote = fpResult.anchoredToParent ? ` (anchored to ${fpResult.anchor.role} "${fpResult.anchor.text ?? ""}")` : "";
|
|
51066
51859
|
return {
|
|
51067
|
-
message: `Hint created on [${
|
|
51860
|
+
message: `Hint created on [${ref2}]${anchorNote}: (${category}: ${opts.frontmatter})`,
|
|
51068
51861
|
created: {
|
|
51069
51862
|
id: created.id,
|
|
51070
51863
|
frontmatter: opts.frontmatter,
|
|
@@ -51075,10 +51868,11 @@ ${body}
|
|
|
51075
51868
|
};
|
|
51076
51869
|
}
|
|
51077
51870
|
async screenshot(opts) {
|
|
51871
|
+
const ref2 = normalizeRef(opts?.ref);
|
|
51078
51872
|
const img = await this.client.takeScreenshot({
|
|
51079
51873
|
fullPage: opts?.fullPage,
|
|
51080
51874
|
element: opts?.element,
|
|
51081
|
-
ref:
|
|
51875
|
+
ref: ref2,
|
|
51082
51876
|
type: opts?.type ?? "jpeg",
|
|
51083
51877
|
label: opts?.label,
|
|
51084
51878
|
signal: this.currentSignal
|
|
@@ -51099,9 +51893,10 @@ ${body}
|
|
|
51099
51893
|
return `Screenshot captured${opts?.label ? ` (${opts.label})` : ""}: ${img ? "success" : "no screenshot"}`;
|
|
51100
51894
|
}
|
|
51101
51895
|
async evaluate(opts) {
|
|
51896
|
+
const ref2 = normalizeRef(opts.ref);
|
|
51102
51897
|
const result = await this.client.evaluate(opts.expression, {
|
|
51103
51898
|
label: opts.label,
|
|
51104
|
-
ref:
|
|
51899
|
+
ref: ref2,
|
|
51105
51900
|
signal: this.currentSignal
|
|
51106
51901
|
});
|
|
51107
51902
|
return typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
@@ -51119,7 +51914,7 @@ ${body}
|
|
|
51119
51914
|
}
|
|
51120
51915
|
// ==================== Interaction ====================
|
|
51121
51916
|
async click(opts) {
|
|
51122
|
-
const
|
|
51917
|
+
const ref2 = normalizeRef(opts.ref);
|
|
51123
51918
|
let x2 = opts.x;
|
|
51124
51919
|
let y2 = opts.y;
|
|
51125
51920
|
if (x2 === 0 && y2 === 0) {
|
|
@@ -51135,29 +51930,40 @@ ${body}
|
|
|
51135
51930
|
const useCoordinates = !ref2 && x2 !== void 0 && y2 !== void 0;
|
|
51136
51931
|
const clickVerb = opts.doubleClick ? "Double-clicked" : "Clicked";
|
|
51137
51932
|
const actionDesc = useCoordinates ? `${clickVerb} "${opts.element}" at (${x2}, ${y2})` : `${clickVerb} "${opts.element}" via ref ${ref2}`;
|
|
51138
|
-
this.lastReplayableAction = {
|
|
51933
|
+
this.lastReplayableAction = {
|
|
51934
|
+
description: actionDesc,
|
|
51935
|
+
thunk: () => this.click({ ...opts, ref: ref2 })
|
|
51936
|
+
};
|
|
51139
51937
|
let clickedElement;
|
|
51140
51938
|
let fallbackUsed = false;
|
|
51141
51939
|
const preClickUrl = useCoordinates && this.augmentorProvider ? await this.client.getCurrentUrl({ signal: this.currentSignal }).catch(() => void 0) : void 0;
|
|
51142
|
-
|
|
51143
|
-
|
|
51144
|
-
|
|
51145
|
-
|
|
51146
|
-
|
|
51147
|
-
|
|
51148
|
-
|
|
51149
|
-
|
|
51150
|
-
|
|
51151
|
-
|
|
51152
|
-
|
|
51153
|
-
|
|
51154
|
-
|
|
51155
|
-
|
|
51156
|
-
|
|
51157
|
-
|
|
51158
|
-
|
|
51940
|
+
let diffText;
|
|
51941
|
+
try {
|
|
51942
|
+
({ diffText } = await this.withSemanticDiff(actionDesc, async () => {
|
|
51943
|
+
if (useCoordinates) {
|
|
51944
|
+
const coordResult = await this.client.clickAtCoordinates(x2, y2, opts.element, {
|
|
51945
|
+
doubleClick: opts.doubleClick,
|
|
51946
|
+
modifiers: opts.modifiers,
|
|
51947
|
+
signal: this.currentSignal
|
|
51948
|
+
});
|
|
51949
|
+
clickedElement = coordResult.clickedElement;
|
|
51950
|
+
} else {
|
|
51951
|
+
const refResult = await this.client.click(ref2, opts.element, {
|
|
51952
|
+
doubleClick: opts.doubleClick,
|
|
51953
|
+
button: opts.button,
|
|
51954
|
+
modifiers: opts.modifiers,
|
|
51955
|
+
signal: this.currentSignal
|
|
51956
|
+
});
|
|
51957
|
+
clickedElement = refResult.clickedElement;
|
|
51958
|
+
fallbackUsed = refResult.fallbackUsed;
|
|
51959
|
+
}
|
|
51960
|
+
}));
|
|
51961
|
+
} catch (error) {
|
|
51962
|
+
if (!useCoordinates && ref2 && isStaleAriaRefActionTimeout(error, "click")) {
|
|
51963
|
+
return formatStaleRefActionRecovery("browser_click", ref2, opts.element);
|
|
51159
51964
|
}
|
|
51160
|
-
|
|
51965
|
+
throw error;
|
|
51966
|
+
}
|
|
51161
51967
|
if (useCoordinates) {
|
|
51162
51968
|
await this.emitAugmentorSignal("coordinate_click", x2, y2, preClickUrl ?? "");
|
|
51163
51969
|
} else {
|
|
@@ -51173,36 +51979,56 @@ ${body}
|
|
|
51173
51979
|
return withRecoveryNoticeMCP(this.client, result, this.logger);
|
|
51174
51980
|
}
|
|
51175
51981
|
async type(opts) {
|
|
51982
|
+
const ref2 = normalizeRef(opts.ref);
|
|
51983
|
+
if (!ref2) {
|
|
51984
|
+
return formatEmptyRefRecovery("browser_type");
|
|
51985
|
+
}
|
|
51176
51986
|
const submitNote = opts.submit ? " and submitted" : "";
|
|
51177
51987
|
const actionDesc = `Typed "${opts.text}" into "${opts.element}"${submitNote}`;
|
|
51178
|
-
this.lastReplayableAction = {
|
|
51179
|
-
|
|
51180
|
-
|
|
51181
|
-
|
|
51182
|
-
|
|
51183
|
-
|
|
51988
|
+
this.lastReplayableAction = {
|
|
51989
|
+
description: actionDesc,
|
|
51990
|
+
thunk: () => this.type({ ...opts, ref: ref2 })
|
|
51991
|
+
};
|
|
51992
|
+
try {
|
|
51993
|
+
if (opts.submit) {
|
|
51994
|
+
const { diffText } = await this.withSemanticDiff(actionDesc, async () => {
|
|
51995
|
+
await this.client.type(ref2, opts.text, opts.element, opts.submit, {
|
|
51996
|
+
delay: opts.delay,
|
|
51997
|
+
signal: this.currentSignal
|
|
51998
|
+
});
|
|
51184
51999
|
});
|
|
52000
|
+
return withRecoveryNoticeMCP(this.client, diffText, this.logger);
|
|
52001
|
+
}
|
|
52002
|
+
await this.client.type(ref2, opts.text, opts.element, opts.submit, {
|
|
52003
|
+
delay: opts.delay,
|
|
52004
|
+
signal: this.currentSignal
|
|
51185
52005
|
});
|
|
51186
|
-
return
|
|
52006
|
+
return withRecoveryNotice(this.client, actionDesc, this.logger);
|
|
52007
|
+
} catch (error) {
|
|
52008
|
+
if (isFillTargetNotEditableError(error)) {
|
|
52009
|
+
return formatFillTargetNotEditableRecovery(error, "browser_type");
|
|
52010
|
+
}
|
|
52011
|
+
throw error;
|
|
51187
52012
|
}
|
|
51188
|
-
await this.client.type(opts.ref, opts.text, opts.element, opts.submit, {
|
|
51189
|
-
delay: opts.delay,
|
|
51190
|
-
signal: this.currentSignal
|
|
51191
|
-
});
|
|
51192
|
-
return withRecoveryNotice(this.client, actionDesc, this.logger);
|
|
51193
52013
|
}
|
|
51194
52014
|
async hover(opts) {
|
|
52015
|
+
const ref2 = normalizeRef(opts.ref);
|
|
52016
|
+
if (!ref2) {
|
|
52017
|
+
return formatEmptyRefRecovery("browser_hover");
|
|
52018
|
+
}
|
|
51195
52019
|
const { diffText } = await this.withSemanticDiff(
|
|
51196
|
-
`Hovered over "${opts.element}" via ref ${
|
|
52020
|
+
`Hovered over "${opts.element}" via ref ${ref2}`,
|
|
51197
52021
|
async () => {
|
|
51198
|
-
await this.client.hover(
|
|
52022
|
+
await this.client.hover(ref2, opts.element, { signal: this.currentSignal });
|
|
51199
52023
|
}
|
|
51200
52024
|
);
|
|
51201
52025
|
return diffText;
|
|
51202
52026
|
}
|
|
51203
52027
|
async drag(opts) {
|
|
52028
|
+
const startRef = normalizeRef(opts.startRef);
|
|
52029
|
+
const endRef = normalizeRef(opts.endRef);
|
|
51204
52030
|
const useCoordinates = opts.startX !== void 0 && opts.startY !== void 0 && opts.endX !== void 0 && opts.endY !== void 0;
|
|
51205
|
-
const useRefs =
|
|
52031
|
+
const useRefs = startRef !== void 0 && endRef !== void 0;
|
|
51206
52032
|
if (!useCoordinates && !useRefs) {
|
|
51207
52033
|
return "Error: Provide either startRef + endRef, or all four coordinates (startX, startY, endX, endY)";
|
|
51208
52034
|
}
|
|
@@ -51221,7 +52047,7 @@ ${body}
|
|
|
51221
52047
|
{ signal: this.currentSignal }
|
|
51222
52048
|
);
|
|
51223
52049
|
} else {
|
|
51224
|
-
await this.client.drag(
|
|
52050
|
+
await this.client.drag(startRef, opts.startElement, endRef, opts.endElement, {
|
|
51225
52051
|
signal: this.currentSignal
|
|
51226
52052
|
});
|
|
51227
52053
|
}
|
|
@@ -51247,35 +52073,63 @@ ${body}
|
|
|
51247
52073
|
return withRecoveryNotice(this.client, `Pressed ${key}`, this.logger);
|
|
51248
52074
|
}
|
|
51249
52075
|
async fillForm(fields) {
|
|
51250
|
-
const
|
|
51251
|
-
|
|
51252
|
-
|
|
51253
|
-
|
|
52076
|
+
const normalizedFields = fields.map((field) => ({
|
|
52077
|
+
...field,
|
|
52078
|
+
ref: normalizeRef(field.ref) ?? ""
|
|
52079
|
+
}));
|
|
52080
|
+
if (normalizedFields.some((field) => field.ref.length === 0)) {
|
|
52081
|
+
return formatEmptyRefRecovery("browser_fill_form");
|
|
52082
|
+
}
|
|
52083
|
+
try {
|
|
52084
|
+
const { diffText } = await this.withSemanticDiff(
|
|
52085
|
+
`Filled ${fields.length} form field(s)`,
|
|
52086
|
+
async () => {
|
|
52087
|
+
await this.client.fillForm(normalizedFields, { signal: this.currentSignal });
|
|
52088
|
+
}
|
|
52089
|
+
);
|
|
52090
|
+
return diffText;
|
|
52091
|
+
} catch (error) {
|
|
52092
|
+
if (isFillTargetNotEditableError(error)) {
|
|
52093
|
+
return formatFillTargetNotEditableRecovery(error);
|
|
52094
|
+
}
|
|
52095
|
+
if (isStaleAriaRefActionTimeout(error, "fill")) {
|
|
52096
|
+
const staleRef = extractWaitingAriaRef(error);
|
|
52097
|
+
const field = normalizedFields.find((candidate) => candidate.ref === staleRef) ?? normalizedFields[0];
|
|
52098
|
+
return formatStaleRefActionRecovery(
|
|
52099
|
+
"browser_fill_form",
|
|
52100
|
+
staleRef ?? field?.ref ?? "unknown",
|
|
52101
|
+
field?.element
|
|
52102
|
+
);
|
|
51254
52103
|
}
|
|
51255
|
-
|
|
51256
|
-
|
|
52104
|
+
throw error;
|
|
52105
|
+
}
|
|
51257
52106
|
}
|
|
51258
52107
|
async selectOption(opts) {
|
|
52108
|
+
const ref2 = normalizeRef(opts.ref);
|
|
52109
|
+
if (!ref2) {
|
|
52110
|
+
return formatEmptyRefRecovery("browser_select_option");
|
|
52111
|
+
}
|
|
51259
52112
|
try {
|
|
51260
52113
|
const { diffText } = await this.withSemanticDiff(
|
|
51261
52114
|
`Selected "${opts.value}" in "${opts.element}"`,
|
|
51262
52115
|
async () => {
|
|
51263
|
-
await this.client.selectOption(
|
|
52116
|
+
await this.client.selectOption(ref2, opts.value, opts.element, { signal: this.currentSignal });
|
|
51264
52117
|
}
|
|
51265
52118
|
);
|
|
51266
52119
|
return diffText;
|
|
51267
52120
|
} catch (error) {
|
|
51268
52121
|
if (isSelectOptionNonSelectError(error)) {
|
|
51269
|
-
return formatSelectOptionNonSelectRecovery(
|
|
52122
|
+
return formatSelectOptionNonSelectRecovery(ref2, opts.value, opts.element);
|
|
51270
52123
|
}
|
|
51271
52124
|
throw error;
|
|
51272
52125
|
}
|
|
51273
52126
|
}
|
|
51274
52127
|
async fileUpload(paths, ref2) {
|
|
52128
|
+
const normalizedRef = normalizeRef(ref2);
|
|
51275
52129
|
const { diffText } = await this.withSemanticDiff(
|
|
51276
52130
|
`Uploaded ${paths.length} file(s)`,
|
|
51277
52131
|
async () => {
|
|
51278
|
-
await this.client.fileUpload(paths, { ref:
|
|
52132
|
+
await this.client.fileUpload(paths, { ref: normalizedRef, signal: this.currentSignal });
|
|
51279
52133
|
}
|
|
51280
52134
|
);
|
|
51281
52135
|
return diffText;
|
|
@@ -51284,15 +52138,17 @@ ${body}
|
|
|
51284
52138
|
async scroll(opts) {
|
|
51285
52139
|
let result;
|
|
51286
52140
|
let label;
|
|
51287
|
-
|
|
52141
|
+
const withinRef = normalizeRef(opts.withinRef);
|
|
52142
|
+
const toRef = normalizeRef(opts.toRef);
|
|
52143
|
+
if (toRef) {
|
|
51288
52144
|
result = await this.client.scroll(
|
|
51289
52145
|
opts.direction,
|
|
51290
52146
|
opts.amount,
|
|
51291
|
-
|
|
51292
|
-
|
|
52147
|
+
withinRef,
|
|
52148
|
+
toRef,
|
|
51293
52149
|
{ signal: this.currentSignal }
|
|
51294
52150
|
);
|
|
51295
|
-
label = `toRef=${
|
|
52151
|
+
label = `toRef=${toRef}`;
|
|
51296
52152
|
} else if (opts.x !== void 0 && opts.y !== void 0) {
|
|
51297
52153
|
if (opts.x === 0 && opts.y === 0) {
|
|
51298
52154
|
return "Error: Coordinate scroll at (0, 0) is invalid. The coordinates were likely defaulted instead of intentionally chosen. Use direction-based scroll, scroll to a ref, or provide real coordinates before retrying.";
|
|
@@ -51309,11 +52165,11 @@ ${body}
|
|
|
51309
52165
|
result = await this.client.scroll(
|
|
51310
52166
|
opts.direction,
|
|
51311
52167
|
opts.amount,
|
|
51312
|
-
|
|
52168
|
+
withinRef,
|
|
51313
52169
|
void 0,
|
|
51314
52170
|
{ signal: this.currentSignal }
|
|
51315
52171
|
);
|
|
51316
|
-
label = `direction=${opts.direction}${opts.amount ? `, amount=${opts.amount}` : ""}${
|
|
52172
|
+
label = `direction=${opts.direction}${opts.amount ? `, amount=${opts.amount}` : ""}${withinRef ? `, withinRef=${withinRef}` : ""}`;
|
|
51317
52173
|
}
|
|
51318
52174
|
const scrollInfo = typeof result === "object" && result !== null ? result.scrollInfo : void 0;
|
|
51319
52175
|
if (scrollInfo && !scrollInfo.moved) {
|
|
@@ -51467,6 +52323,9 @@ ${header}
|
|
|
51467
52323
|
if (message === "No downloads captured during this session.") {
|
|
51468
52324
|
return `${message} Use browser_list_downloads after triggering a download, or try browser_pdf_read if the file opened inline instead of downloading.`;
|
|
51469
52325
|
}
|
|
52326
|
+
if (downloadId === 0 && message === "Download #0 not found. Use browser_list_downloads to see available downloads.") {
|
|
52327
|
+
return "Download #0 was not found. Download ids start at 1; call browser_list_downloads and use the listed id, or omit downloadId to read the most recent download.";
|
|
52328
|
+
}
|
|
51470
52329
|
if (isMissingDownloadTempFileError(message)) {
|
|
51471
52330
|
const label = downloadId !== null && downloadId !== void 0 ? `Download #${downloadId}` : "The most recent download";
|
|
51472
52331
|
return `${label} was captured, but its temporary file is no longer available. Trigger the download again, then call browser_list_downloads and browser_read_download with the new id.`;
|
|
@@ -51684,7 +52543,7 @@ ${recoveryHint}`;
|
|
|
51684
52543
|
await fs22.writeFile(snapshotFilePath, yaml, "utf-8");
|
|
51685
52544
|
} catch {
|
|
51686
52545
|
}
|
|
51687
|
-
const semanticText =
|
|
52546
|
+
const semanticText = await formatSnapshotMaybeOffloaded(yaml, {
|
|
51688
52547
|
snapshotFilePath,
|
|
51689
52548
|
currentTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
51690
52549
|
capturedToasts: this.client.getCapturedToasts?.() ?? [],
|
|
@@ -54653,6 +55512,42 @@ function resolveBrowserContextRequestUrl(url, pageUrl) {
|
|
|
54653
55512
|
return url;
|
|
54654
55513
|
}
|
|
54655
55514
|
}
|
|
55515
|
+
function isRouteAlreadyHandledError(error) {
|
|
55516
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
55517
|
+
return message.includes("Route is already handled");
|
|
55518
|
+
}
|
|
55519
|
+
function createSingleUseContextRouteHandle(route, logger2) {
|
|
55520
|
+
let handled = false;
|
|
55521
|
+
const runOnce = async (action, fn) => {
|
|
55522
|
+
if (handled) {
|
|
55523
|
+
logger2.debug("[ContextRoute] Ignoring duplicate route action", { action });
|
|
55524
|
+
return;
|
|
55525
|
+
}
|
|
55526
|
+
handled = true;
|
|
55527
|
+
try {
|
|
55528
|
+
await fn();
|
|
55529
|
+
} catch (error) {
|
|
55530
|
+
if (isRouteAlreadyHandledError(error)) {
|
|
55531
|
+
logger2.debug("[ContextRoute] Route was already handled by Playwright", {
|
|
55532
|
+
action,
|
|
55533
|
+
error: error instanceof Error ? error.message : String(error)
|
|
55534
|
+
});
|
|
55535
|
+
return;
|
|
55536
|
+
}
|
|
55537
|
+
throw error;
|
|
55538
|
+
}
|
|
55539
|
+
};
|
|
55540
|
+
return {
|
|
55541
|
+
fulfill: (opts) => runOnce("fulfill", () => route.fulfill(opts)),
|
|
55542
|
+
continue: (opts) => runOnce("continue", () => route.continue(opts)),
|
|
55543
|
+
request: () => ({
|
|
55544
|
+
url: () => route.request().url(),
|
|
55545
|
+
method: () => route.request().method(),
|
|
55546
|
+
postData: () => route.request().postData(),
|
|
55547
|
+
headers: () => route.request().headers()
|
|
55548
|
+
})
|
|
55549
|
+
};
|
|
55550
|
+
}
|
|
54656
55551
|
var TOAST_SNAPSHOT_TTL = 5;
|
|
54657
55552
|
function formatMcpResponse(input) {
|
|
54658
55553
|
const lines = [];
|
|
@@ -54842,6 +55737,16 @@ function normalizeDateInputValue(value) {
|
|
|
54842
55737
|
}
|
|
54843
55738
|
return value;
|
|
54844
55739
|
}
|
|
55740
|
+
var OperationTimeoutError = class extends Error {
|
|
55741
|
+
label;
|
|
55742
|
+
timeoutMs;
|
|
55743
|
+
constructor(label, timeoutMs) {
|
|
55744
|
+
super(`${label} timed out after ${timeoutMs}ms`);
|
|
55745
|
+
this.name = "OperationTimeoutError";
|
|
55746
|
+
this.label = label;
|
|
55747
|
+
this.timeoutMs = timeoutMs;
|
|
55748
|
+
}
|
|
55749
|
+
};
|
|
54845
55750
|
function asEmitter(page) {
|
|
54846
55751
|
return page;
|
|
54847
55752
|
}
|
|
@@ -54861,6 +55766,15 @@ function stripNewListeners(page, event, baseline) {
|
|
|
54861
55766
|
}
|
|
54862
55767
|
return stripped;
|
|
54863
55768
|
}
|
|
55769
|
+
var runCodePageRequestMethods = /* @__PURE__ */ new Set([
|
|
55770
|
+
"delete",
|
|
55771
|
+
"fetch",
|
|
55772
|
+
"get",
|
|
55773
|
+
"head",
|
|
55774
|
+
"patch",
|
|
55775
|
+
"post",
|
|
55776
|
+
"put"
|
|
55777
|
+
]);
|
|
54864
55778
|
function logLateRunCodeWaitRejection(logger2, kind, promise) {
|
|
54865
55779
|
promise.catch((err) => {
|
|
54866
55780
|
logger2.debug(`[DirectPlaywright] runCode ${kind} wait rejected after call`, {
|
|
@@ -54868,6 +55782,95 @@ function logLateRunCodeWaitRejection(logger2, kind, promise) {
|
|
|
54868
55782
|
});
|
|
54869
55783
|
});
|
|
54870
55784
|
}
|
|
55785
|
+
function guardRunCodeFetch(logger2) {
|
|
55786
|
+
return (...args) => {
|
|
55787
|
+
const promise = globalThis.fetch(...args);
|
|
55788
|
+
promise.catch((err) => {
|
|
55789
|
+
logger2.debug("[DirectPlaywright] runCode fetch rejected after call", {
|
|
55790
|
+
error: err instanceof Error ? err.message : String(err)
|
|
55791
|
+
});
|
|
55792
|
+
});
|
|
55793
|
+
return promise;
|
|
55794
|
+
};
|
|
55795
|
+
}
|
|
55796
|
+
function isPromiseLike(value) {
|
|
55797
|
+
return typeof value === "object" && value !== null && typeof value.catch === "function";
|
|
55798
|
+
}
|
|
55799
|
+
function logLateRunCodePageRequestRejection(logger2, method, url, promise) {
|
|
55800
|
+
promise.catch((err) => {
|
|
55801
|
+
logger2.debug("[DirectPlaywright] runCode page.request rejected after call", {
|
|
55802
|
+
method,
|
|
55803
|
+
url: url.slice(0, 200),
|
|
55804
|
+
error: err instanceof Error ? err.message : String(err)
|
|
55805
|
+
});
|
|
55806
|
+
});
|
|
55807
|
+
}
|
|
55808
|
+
function guardRunCodePageRequestContext(request2, getPageUrl, logger2) {
|
|
55809
|
+
if (request2 === null || typeof request2 !== "object" && typeof request2 !== "function") {
|
|
55810
|
+
return request2;
|
|
55811
|
+
}
|
|
55812
|
+
const functionCache = /* @__PURE__ */ new Map();
|
|
55813
|
+
return new Proxy(request2, {
|
|
55814
|
+
get(target, property, receiver) {
|
|
55815
|
+
const value = Reflect.get(target, property, receiver);
|
|
55816
|
+
if (typeof value !== "function") {
|
|
55817
|
+
return value;
|
|
55818
|
+
}
|
|
55819
|
+
const cached = functionCache.get(property);
|
|
55820
|
+
if (cached) {
|
|
55821
|
+
return cached;
|
|
55822
|
+
}
|
|
55823
|
+
if (!runCodePageRequestMethods.has(property)) {
|
|
55824
|
+
const bound = value.bind(target);
|
|
55825
|
+
functionCache.set(property, bound);
|
|
55826
|
+
return bound;
|
|
55827
|
+
}
|
|
55828
|
+
const method = property;
|
|
55829
|
+
const guarded = (...args) => {
|
|
55830
|
+
const requestArgs = [...args];
|
|
55831
|
+
const originalUrl = requestArgs[0];
|
|
55832
|
+
let requestUrl = null;
|
|
55833
|
+
if (typeof originalUrl === "string") {
|
|
55834
|
+
requestUrl = resolveBrowserContextRequestUrl(originalUrl, getPageUrl());
|
|
55835
|
+
requestArgs[0] = requestUrl;
|
|
55836
|
+
}
|
|
55837
|
+
const result = value.apply(target, requestArgs);
|
|
55838
|
+
if (isPromiseLike(result) && requestUrl !== null) {
|
|
55839
|
+
logLateRunCodePageRequestRejection(logger2, method, requestUrl, result);
|
|
55840
|
+
}
|
|
55841
|
+
return result;
|
|
55842
|
+
};
|
|
55843
|
+
functionCache.set(property, guarded);
|
|
55844
|
+
return guarded;
|
|
55845
|
+
}
|
|
55846
|
+
});
|
|
55847
|
+
}
|
|
55848
|
+
function guardRunCodePageRequest(page, logger2) {
|
|
55849
|
+
const guardedRequest = guardRunCodePageRequestContext(
|
|
55850
|
+
page.request,
|
|
55851
|
+
() => page.url(),
|
|
55852
|
+
logger2
|
|
55853
|
+
);
|
|
55854
|
+
const functionCache = /* @__PURE__ */ new Map();
|
|
55855
|
+
return new Proxy(page, {
|
|
55856
|
+
get(target, property, receiver) {
|
|
55857
|
+
if (property === "request") {
|
|
55858
|
+
return guardedRequest;
|
|
55859
|
+
}
|
|
55860
|
+
const value = Reflect.get(target, property, receiver);
|
|
55861
|
+
if (typeof value !== "function") {
|
|
55862
|
+
return value;
|
|
55863
|
+
}
|
|
55864
|
+
const cached = functionCache.get(property);
|
|
55865
|
+
if (cached) {
|
|
55866
|
+
return cached;
|
|
55867
|
+
}
|
|
55868
|
+
const bound = value.bind(page);
|
|
55869
|
+
functionCache.set(property, bound);
|
|
55870
|
+
return bound;
|
|
55871
|
+
}
|
|
55872
|
+
});
|
|
55873
|
+
}
|
|
54871
55874
|
function guardFileChooserWaitForEvent(page, logger2) {
|
|
54872
55875
|
const originalWaitForEvent = page.waitForEvent;
|
|
54873
55876
|
let guarded = 0;
|
|
@@ -55297,10 +56300,7 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
55297
56300
|
return await Promise.race([
|
|
55298
56301
|
operation,
|
|
55299
56302
|
new Promise((_, reject) => {
|
|
55300
|
-
timer = setTimeout(
|
|
55301
|
-
() => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),
|
|
55302
|
-
timeoutMs
|
|
55303
|
-
);
|
|
56303
|
+
timer = setTimeout(() => reject(new OperationTimeoutError(label, timeoutMs)), timeoutMs);
|
|
55304
56304
|
})
|
|
55305
56305
|
]);
|
|
55306
56306
|
} finally {
|
|
@@ -55398,6 +56398,20 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
55398
56398
|
// Tracing state
|
|
55399
56399
|
tracingActive = false;
|
|
55400
56400
|
traceDir = null;
|
|
56401
|
+
// Flushed trace chunk paths (one per browser context). Tracing is bound to a
|
|
56402
|
+
// single Playwright context; when the context is swapped/recreated mid-run we
|
|
56403
|
+
// flush the in-progress trace to disk here and restart tracing on the new
|
|
56404
|
+
// context, so the run-level trace survives the swap instead of being discarded.
|
|
56405
|
+
traceChunks = [];
|
|
56406
|
+
// Every trace temp dir created this session (incl. chunks whose flush failed,
|
|
56407
|
+
// so they aren't in traceChunks) — swept on disconnect so none leak.
|
|
56408
|
+
allTraceDirs = /* @__PURE__ */ new Set();
|
|
56409
|
+
// Context routes (e.g. Cloudflare Access scoped-header injection) last applied
|
|
56410
|
+
// via setupContextRoutes(). Route interception is per-context and is dropped
|
|
56411
|
+
// when the context is recreated; we remember the routes so auto-recovery paths
|
|
56412
|
+
// (restoreBrowser) can re-arm them — otherwise the edge would bounce
|
|
56413
|
+
// post-recovery requests to a login page.
|
|
56414
|
+
storedContextRoutes = [];
|
|
55401
56415
|
// Video recording state.
|
|
55402
56416
|
// The screencast encoder is the single source of truth for the recorded
|
|
55403
56417
|
// file: while it lives, `videoDir`/`videoPath` derive from it. Before the
|
|
@@ -55649,6 +56663,17 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
55649
56663
|
supportsContextSwap() {
|
|
55650
56664
|
return !this.extensionsEnabled && (!!this.browser || !!this.browserLease);
|
|
55651
56665
|
}
|
|
56666
|
+
/**
|
|
56667
|
+
* Replace the browser context (e.g. to apply fresh storage state on re-auth),
|
|
56668
|
+
* keeping the same browser. Contract for context-bound state:
|
|
56669
|
+
* - Tracing AUTO-resumes here: the in-progress trace is flushed to a chunk
|
|
56670
|
+
* first (recoverable), then restarted on the new context.
|
|
56671
|
+
* - Context routes (e.g. CF Access scoped headers) are NOT re-armed here —
|
|
56672
|
+
* the caller must re-apply them via setupContextRoutes after the swap,
|
|
56673
|
+
* because the swap may intentionally change the headers (new credential).
|
|
56674
|
+
* (Crash-recovery in restoreBrowser DOES auto re-arm from stored routes,
|
|
56675
|
+
* since the headers are unchanged there.)
|
|
56676
|
+
*/
|
|
55652
56677
|
async swapContext(options) {
|
|
55653
56678
|
if (!this.supportsContextSwap()) {
|
|
55654
56679
|
throw new Error(
|
|
@@ -55672,14 +56697,9 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
55672
56697
|
this.logger.info("[DirectPlaywright] Stopping screencast frame delivery for context swap");
|
|
55673
56698
|
await this._stopScreencastFrameDelivery();
|
|
55674
56699
|
}
|
|
55675
|
-
|
|
55676
|
-
|
|
55677
|
-
|
|
55678
|
-
} catch {
|
|
55679
|
-
} finally {
|
|
55680
|
-
this.tracingActive = false;
|
|
55681
|
-
this.traceDir = null;
|
|
55682
|
-
}
|
|
56700
|
+
const resumeTracingAfterSwap = this.tracingActive && !!this.context;
|
|
56701
|
+
if (resumeTracingAfterSwap) {
|
|
56702
|
+
await this.flushTraceChunk();
|
|
55683
56703
|
}
|
|
55684
56704
|
this.contextClosedIntentionally = true;
|
|
55685
56705
|
this.pageClosedIntentionally = true;
|
|
@@ -55771,6 +56791,13 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
55771
56791
|
if (wasScreencasting && this.page && this.screencastHandler) {
|
|
55772
56792
|
await this.startScreencast(this.screencastHandler);
|
|
55773
56793
|
}
|
|
56794
|
+
if (resumeTracingAfterSwap) {
|
|
56795
|
+
await this.beginTracingOnContext().catch((err) => {
|
|
56796
|
+
this.logger.warn("[DirectPlaywright] Failed to resume tracing after context swap", {
|
|
56797
|
+
error: err instanceof Error ? err.message : String(err)
|
|
56798
|
+
});
|
|
56799
|
+
});
|
|
56800
|
+
}
|
|
55774
56801
|
this.logger.info("[DirectPlaywright] Context swapped successfully");
|
|
55775
56802
|
}
|
|
55776
56803
|
/**
|
|
@@ -56103,20 +57130,22 @@ var PlaywrightClient = class _PlaywrightClient {
|
|
|
56103
57130
|
}
|
|
56104
57131
|
this._downloadDir = null;
|
|
56105
57132
|
}
|
|
56106
|
-
|
|
56107
|
-
|
|
56108
|
-
|
|
56109
|
-
|
|
56110
|
-
|
|
56111
|
-
|
|
56112
|
-
|
|
56113
|
-
|
|
56114
|
-
|
|
56115
|
-
|
|
56116
|
-
|
|
56117
|
-
|
|
56118
|
-
|
|
56119
|
-
|
|
57133
|
+
const traceDirsToClean = new Set(this.allTraceDirs);
|
|
57134
|
+
if (this.traceDir) traceDirsToClean.add(this.traceDir);
|
|
57135
|
+
await Promise.allSettled(
|
|
57136
|
+
[...traceDirsToClean].map(
|
|
57137
|
+
(dir) => fs4.rm(dir, { recursive: true, force: true }).catch(
|
|
57138
|
+
(err) => this.logger.warn("[DirectPlaywright] Failed to clean up trace directory", {
|
|
57139
|
+
traceDir: dir,
|
|
57140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
57141
|
+
})
|
|
57142
|
+
)
|
|
57143
|
+
)
|
|
57144
|
+
);
|
|
57145
|
+
this.traceDir = null;
|
|
57146
|
+
this.traceChunks = [];
|
|
57147
|
+
this.allTraceDirs.clear();
|
|
57148
|
+
this.storedContextRoutes = [];
|
|
56120
57149
|
this._capturedDownloads = [];
|
|
56121
57150
|
this._downloadCounter = 0;
|
|
56122
57151
|
this._lastReportedDownloadIndex = 0;
|
|
@@ -56469,9 +57498,11 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
|
|
|
56469
57498
|
let threwError = null;
|
|
56470
57499
|
let aborted = runController.signal.aborted;
|
|
56471
57500
|
let guardedWaits = { fileChooser: 0, request: 0, response: 0 };
|
|
57501
|
+
const guardedFetch = guardRunCodeFetch(this.logger);
|
|
57502
|
+
const guardedPage = guardRunCodePageRequest(page, this.logger);
|
|
56472
57503
|
try {
|
|
56473
57504
|
if (!aborted) {
|
|
56474
|
-
const fn = new Function("page", `return (async () => { ${code} })()`);
|
|
57505
|
+
const fn = new Function("page", "fetch", `return (async () => { ${code} })()`);
|
|
56475
57506
|
const abortPromise = new Promise((_, reject) => {
|
|
56476
57507
|
runController.signal.addEventListener(
|
|
56477
57508
|
"abort",
|
|
@@ -56479,7 +57510,7 @@ Use coordinate-based clicking (x, y) to interact with elements visible in the sc
|
|
|
56479
57510
|
{ once: true }
|
|
56480
57511
|
);
|
|
56481
57512
|
});
|
|
56482
|
-
const inner = fn(
|
|
57513
|
+
const inner = fn(guardedPage, guardedFetch);
|
|
56483
57514
|
inner.catch((err) => {
|
|
56484
57515
|
this.logger.debug("[DirectPlaywright] runCode orphan rejected after race", {
|
|
56485
57516
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -56698,6 +57729,16 @@ ${warning}` : ""}`,
|
|
|
56698
57729
|
}
|
|
56699
57730
|
} catch (err) {
|
|
56700
57731
|
const message = err instanceof Error ? err.message : String(err);
|
|
57732
|
+
if (isPlaywrightTargetClosedError(err)) {
|
|
57733
|
+
throw toBrowserActionTargetClosedError(err, {
|
|
57734
|
+
operation: "click",
|
|
57735
|
+
ref: ref2,
|
|
57736
|
+
elementDesc,
|
|
57737
|
+
lastKnownUrl: this.lastKnownUrl,
|
|
57738
|
+
pendingCrashType: this._pendingCrashType,
|
|
57739
|
+
pendingCrashUrl: this._pendingCrashUrl
|
|
57740
|
+
});
|
|
57741
|
+
}
|
|
56701
57742
|
const isTimeout = message.includes("Timeout") || message.includes("timeout");
|
|
56702
57743
|
if (isTimeout && preClickBox) {
|
|
56703
57744
|
const centerX = Math.round(preClickBox.x + preClickBox.width / 2);
|
|
@@ -56849,6 +57890,7 @@ ${warning}` : ""}`,
|
|
|
56849
57890
|
const dialogMsg = this.getPendingDialogMessage();
|
|
56850
57891
|
if (dialogMsg) throw new Error(dialogMsg);
|
|
56851
57892
|
const locator = await this.resolveRef(ref2);
|
|
57893
|
+
await assertFillTargetEditable(locator, ref2, elementDesc);
|
|
56852
57894
|
const timeout = opts?.timeoutMs ?? TIMEOUTS.TYPE;
|
|
56853
57895
|
const inputType = await locator.evaluate((node) => node instanceof HTMLInputElement ? node.type : null).catch((err) => {
|
|
56854
57896
|
this.logger.debug("[DirectPlaywright] Failed to inspect input type before typing", {
|
|
@@ -57840,13 +58882,58 @@ ${warning}` : ""}`,
|
|
|
57840
58882
|
}
|
|
57841
58883
|
// ================ TRACING ================
|
|
57842
58884
|
async startTracing(_opts) {
|
|
57843
|
-
const context = await this.getContext();
|
|
57844
58885
|
this.logger.info("[DirectPlaywright] Starting trace recording");
|
|
57845
|
-
this.
|
|
57846
|
-
|
|
57847
|
-
await
|
|
58886
|
+
this.traceChunks = [];
|
|
58887
|
+
this.allTraceDirs.clear();
|
|
58888
|
+
await this.beginTracingOnContext();
|
|
58889
|
+
}
|
|
58890
|
+
/**
|
|
58891
|
+
* Start a Playwright trace on the current context. Used both for the initial
|
|
58892
|
+
* `startTracing()` and to resume tracing after a context swap. `traceDir` /
|
|
58893
|
+
* `tracingActive` are set ONLY after `tracing.start()` resolves — a thrown
|
|
58894
|
+
* start must not leave `traceDir` set, or a later `stopTracing()` would target
|
|
58895
|
+
* a context that never started tracing ("Must start tracing before stopping").
|
|
58896
|
+
*/
|
|
58897
|
+
async beginTracingOnContext() {
|
|
58898
|
+
const context = await this.getContext();
|
|
58899
|
+
const traceDir = path5.join(
|
|
58900
|
+
this.tmpBaseDir,
|
|
58901
|
+
`playwright-trace-${Date.now()}-${this.traceChunks.length}`
|
|
58902
|
+
);
|
|
58903
|
+
await fs4.mkdir(traceDir, { recursive: true });
|
|
58904
|
+
try {
|
|
58905
|
+
await context.tracing.start({ screenshots: true, snapshots: true });
|
|
58906
|
+
} catch (err) {
|
|
58907
|
+
await fs4.rm(traceDir, { recursive: true, force: true }).catch(() => {
|
|
58908
|
+
});
|
|
58909
|
+
throw err;
|
|
58910
|
+
}
|
|
58911
|
+
this.traceDir = traceDir;
|
|
58912
|
+
this.allTraceDirs.add(traceDir);
|
|
57848
58913
|
this.tracingActive = true;
|
|
57849
58914
|
}
|
|
58915
|
+
/**
|
|
58916
|
+
* Flush the in-progress trace on the current context to disk and record the
|
|
58917
|
+
* chunk. Returns the chunk path, or null when tracing isn't active. Stopping
|
|
58918
|
+
* WITH a path preserves the trace; stopping without one discards it. Errors are
|
|
58919
|
+
* swallowed (best-effort) so a failed flush never blocks a context swap.
|
|
58920
|
+
*/
|
|
58921
|
+
async flushTraceChunk() {
|
|
58922
|
+
if (!this.tracingActive || !this.context || !this.traceDir) return null;
|
|
58923
|
+
const chunkPath = path5.join(this.traceDir, "trace.zip");
|
|
58924
|
+
try {
|
|
58925
|
+
await this.context.tracing.stop({ path: chunkPath });
|
|
58926
|
+
this.traceChunks.push(chunkPath);
|
|
58927
|
+
return chunkPath;
|
|
58928
|
+
} catch (err) {
|
|
58929
|
+
this.logger.warn("[DirectPlaywright] Failed to flush trace chunk", {
|
|
58930
|
+
error: err instanceof Error ? err.message : String(err)
|
|
58931
|
+
});
|
|
58932
|
+
return null;
|
|
58933
|
+
} finally {
|
|
58934
|
+
this.tracingActive = false;
|
|
58935
|
+
}
|
|
58936
|
+
}
|
|
57850
58937
|
async traceGroup(name) {
|
|
57851
58938
|
if (!this.tracingActive) return;
|
|
57852
58939
|
const context = await this.getContext();
|
|
@@ -57866,20 +58953,26 @@ ${warning}` : ""}`,
|
|
|
57866
58953
|
* The trace.zip can be viewed at https://trace.playwright.dev/
|
|
57867
58954
|
*/
|
|
57868
58955
|
async stopTracing(_opts) {
|
|
57869
|
-
const context = await this.getContext();
|
|
57870
|
-
if (!this.traceDir) throw new Error("Tracing not started");
|
|
57871
58956
|
this.logger.info("[DirectPlaywright] Stopping trace recording");
|
|
57872
|
-
|
|
57873
|
-
|
|
57874
|
-
|
|
58957
|
+
await this.flushTraceChunk();
|
|
58958
|
+
if (this.traceChunks.length === 0) {
|
|
58959
|
+
throw new Error("No trace chunks captured (tracing not started, or all flushes failed)");
|
|
58960
|
+
}
|
|
58961
|
+
const chunks = [...this.traceChunks];
|
|
58962
|
+
if (chunks.length > 1) {
|
|
58963
|
+
this.logger.info("[DirectPlaywright] Captured multiple trace chunks across context swaps", {
|
|
58964
|
+
chunkCount: chunks.length
|
|
58965
|
+
});
|
|
58966
|
+
}
|
|
57875
58967
|
return {
|
|
57876
|
-
trace:
|
|
58968
|
+
trace: chunks[0],
|
|
58969
|
+
traces: chunks,
|
|
57877
58970
|
network: "",
|
|
57878
58971
|
// Playwright bundles network data in trace.zip (not separate file)
|
|
57879
58972
|
resources: "",
|
|
57880
58973
|
// Playwright bundles resources in trace.zip (not separate file)
|
|
57881
|
-
directory:
|
|
57882
|
-
legend: `Trace saved to ${
|
|
58974
|
+
directory: path5.dirname(chunks[0]),
|
|
58975
|
+
legend: `Trace saved to ${chunks[0]}`
|
|
57883
58976
|
};
|
|
57884
58977
|
}
|
|
57885
58978
|
// ================ PRIVATE: Accessibility Snapshot ================
|
|
@@ -57998,11 +59091,22 @@ ${warning}` : ""}`,
|
|
|
57998
59091
|
result = await this.raceAgainstSignal(
|
|
57999
59092
|
"snapshot:aria",
|
|
58000
59093
|
signal,
|
|
58001
|
-
() =>
|
|
59094
|
+
() => this.withOperationTimeout(
|
|
59095
|
+
page.ariaSnapshot({ mode: "ai" }),
|
|
59096
|
+
TIMEOUTS.ARIA_SNAPSHOT_CAP,
|
|
59097
|
+
"snapshot:aria"
|
|
59098
|
+
)
|
|
58002
59099
|
);
|
|
58003
59100
|
break;
|
|
58004
59101
|
} catch (err) {
|
|
58005
59102
|
if (signal?.aborted) return void 0;
|
|
59103
|
+
if (err instanceof OperationTimeoutError && err.label === "snapshot:aria") {
|
|
59104
|
+
this.logger.warn(
|
|
59105
|
+
"[DirectPlaywright] ariaSnapshot exceeded driver cap, using empty fallback",
|
|
59106
|
+
{ capMs: TIMEOUTS.ARIA_SNAPSHOT_CAP, attempt }
|
|
59107
|
+
);
|
|
59108
|
+
break;
|
|
59109
|
+
}
|
|
58006
59110
|
if (attempt < maxRetries) {
|
|
58007
59111
|
this.logger.debug("[DirectPlaywright] Snapshot attempt failed, retrying", {
|
|
58008
59112
|
attempt,
|
|
@@ -59004,6 +60108,8 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59004
60108
|
this.browser = null;
|
|
59005
60109
|
this.attachContextListeners(this.context);
|
|
59006
60110
|
await this.createPageWithListeners(this.context, reason);
|
|
60111
|
+
await this.reapplyStoredContextRoutes();
|
|
60112
|
+
await this.resumeTracingOnRecreatedContext();
|
|
59007
60113
|
await this.restoreUrlAfterRecovery(urlToRestore, crashType);
|
|
59008
60114
|
await restartScreencastIfNeeded();
|
|
59009
60115
|
await restartScreencastRecordingIfNeeded();
|
|
@@ -59049,6 +60155,8 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59049
60155
|
this.attachBrowserListeners(this.browser);
|
|
59050
60156
|
}
|
|
59051
60157
|
await this.createPageWithListeners(this.context, reason);
|
|
60158
|
+
await this.reapplyStoredContextRoutes();
|
|
60159
|
+
await this.resumeTracingOnRecreatedContext();
|
|
59052
60160
|
await this.restoreUrlAfterRecovery(urlToRestore, crashType);
|
|
59053
60161
|
await restartScreencastIfNeeded();
|
|
59054
60162
|
await restartScreencastRecordingIfNeeded();
|
|
@@ -59222,8 +60330,8 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59222
60330
|
});
|
|
59223
60331
|
await Promise.allSettled(stopPromises);
|
|
59224
60332
|
this._screencastDisposables.clear();
|
|
59225
|
-
const
|
|
59226
|
-
if (!
|
|
60333
|
+
const encoder2 = this._screencastEncoder;
|
|
60334
|
+
if (!encoder2) {
|
|
59227
60335
|
this._screencastEncoder = null;
|
|
59228
60336
|
this.logger.warn("[DirectPlaywright] Screencast encoder was never started \u2014 no video produced", {
|
|
59229
60337
|
videoEnabled: this.videoEnabled,
|
|
@@ -59231,9 +60339,9 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59231
60339
|
});
|
|
59232
60340
|
return null;
|
|
59233
60341
|
}
|
|
59234
|
-
this._savedVideoPath =
|
|
60342
|
+
this._savedVideoPath = encoder2.outputFilePath;
|
|
59235
60343
|
this._screencastEncoder = null;
|
|
59236
|
-
const stopResult = await
|
|
60344
|
+
const stopResult = await encoder2.stop();
|
|
59237
60345
|
const {
|
|
59238
60346
|
durationMs,
|
|
59239
60347
|
receivedFrameCount,
|
|
@@ -59475,17 +60583,50 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59475
60583
|
// ================ EMULATION ROUTES ================
|
|
59476
60584
|
async setupContextRoutes(routes) {
|
|
59477
60585
|
const context = await this.getContext();
|
|
60586
|
+
await this.registerContextRoutes(routes, context);
|
|
60587
|
+
this.storedContextRoutes = routes;
|
|
60588
|
+
}
|
|
60589
|
+
async registerContextRoutes(routes, context) {
|
|
59478
60590
|
for (const route of routes) {
|
|
59479
60591
|
await context.route(route.urlPattern, async (pwRoute) => {
|
|
59480
|
-
await route.handler(
|
|
59481
|
-
|
|
59482
|
-
|
|
59483
|
-
|
|
59484
|
-
|
|
59485
|
-
|
|
59486
|
-
|
|
59487
|
-
|
|
59488
|
-
|
|
60592
|
+
await route.handler(createSingleUseContextRouteHandle(pwRoute, this.logger));
|
|
60593
|
+
});
|
|
60594
|
+
}
|
|
60595
|
+
}
|
|
60596
|
+
/**
|
|
60597
|
+
* Restart tracing on a freshly recreated (post-crash/recovery) context. The
|
|
60598
|
+
* pre-recovery trace died with the old context and cannot be flushed, so the
|
|
60599
|
+
* best we can do is capture post-recovery activity and ensure the final
|
|
60600
|
+
* stopTracing() targets a context that actually has tracing started.
|
|
60601
|
+
* Best-effort — no-op when tracing wasn't active.
|
|
60602
|
+
*/
|
|
60603
|
+
async resumeTracingOnRecreatedContext() {
|
|
60604
|
+
if (!this.tracingActive) return;
|
|
60605
|
+
this.tracingActive = false;
|
|
60606
|
+
await this.beginTracingOnContext().catch((err) => {
|
|
60607
|
+
this.logger.warn("[DirectPlaywright] Failed to resume tracing after browser recovery", {
|
|
60608
|
+
error: err instanceof Error ? err.message : String(err),
|
|
60609
|
+
chunksCapturedSoFar: this.traceChunks.length
|
|
60610
|
+
});
|
|
60611
|
+
});
|
|
60612
|
+
}
|
|
60613
|
+
/**
|
|
60614
|
+
* Re-arm the stored context routes on the current (freshly recreated) context.
|
|
60615
|
+
* Called from recovery paths that build a new context — without this, scoped
|
|
60616
|
+
* header injection (e.g. Cloudflare Access) silently stops after a restore and
|
|
60617
|
+
* the edge redirects subsequent requests to a login page. Best-effort.
|
|
60618
|
+
*/
|
|
60619
|
+
async reapplyStoredContextRoutes() {
|
|
60620
|
+
if (this.storedContextRoutes.length === 0 || !this.context) return;
|
|
60621
|
+
try {
|
|
60622
|
+
await this.registerContextRoutes(this.storedContextRoutes, this.context);
|
|
60623
|
+
this.logger.info("[DirectPlaywright] Re-armed context routes on recreated context", {
|
|
60624
|
+
routeCount: this.storedContextRoutes.length
|
|
60625
|
+
});
|
|
60626
|
+
} catch (err) {
|
|
60627
|
+
this.logger.warn("[DirectPlaywright] Failed to re-arm context routes after recreation", {
|
|
60628
|
+
error: err instanceof Error ? err.message : String(err),
|
|
60629
|
+
routeCount: this.storedContextRoutes.length
|
|
59489
60630
|
});
|
|
59490
60631
|
}
|
|
59491
60632
|
}
|
|
@@ -59497,33 +60638,93 @@ Legacy two-step (only if you need to change the action between calls): browser_h
|
|
|
59497
60638
|
return guessMimeType(filename);
|
|
59498
60639
|
}
|
|
59499
60640
|
};
|
|
59500
|
-
|
|
59501
|
-
const
|
|
59502
|
-
|
|
59503
|
-
|
|
59504
|
-
|
|
59505
|
-
|
|
59506
|
-
|
|
59507
|
-
|
|
59508
|
-
|
|
59509
|
-
|
|
59510
|
-
|
|
59511
|
-
|
|
59512
|
-
|
|
59513
|
-
|
|
59514
|
-
|
|
59515
|
-
|
|
59516
|
-
|
|
59517
|
-
|
|
59518
|
-
|
|
59519
|
-
};
|
|
60641
|
+
function isPlaywrightTargetClosedError(error) {
|
|
60642
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60643
|
+
return /Target page, context or browser has been closed/i.test(message);
|
|
60644
|
+
}
|
|
60645
|
+
function toBrowserActionTargetClosedError(error, context) {
|
|
60646
|
+
const label = context.elementDesc ? `${context.elementDesc} (${context.ref})` : context.ref;
|
|
60647
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60648
|
+
const wrapped = new Error(`Browser click target closed for ${label}: ${message}`, {
|
|
60649
|
+
cause: error instanceof Error ? error : void 0
|
|
60650
|
+
});
|
|
60651
|
+
wrapped.name = "BrowserActionTargetClosedError";
|
|
60652
|
+
Object.assign(wrapped, { browserActionTargetClosed: context });
|
|
60653
|
+
return wrapped;
|
|
60654
|
+
}
|
|
60655
|
+
function toFillTargetProbeError(error, context) {
|
|
60656
|
+
const label = context.elementDesc ? `${context.elementDesc} (${context.ref})` : context.ref;
|
|
60657
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60658
|
+
const wrapped = new Error(`Fill target editability probe failed for ${label}: ${message}`, {
|
|
60659
|
+
cause: error instanceof Error ? error : void 0
|
|
59520
60660
|
});
|
|
59521
|
-
|
|
59522
|
-
|
|
59523
|
-
|
|
60661
|
+
wrapped.name = "FillTargetProbeError";
|
|
60662
|
+
Object.assign(wrapped, { fillTargetProbe: context });
|
|
60663
|
+
return wrapped;
|
|
60664
|
+
}
|
|
60665
|
+
async function assertFillTargetEditable(locator, ref2, elementDesc) {
|
|
60666
|
+
let probe;
|
|
60667
|
+
try {
|
|
60668
|
+
probe = await locator.evaluate((el) => {
|
|
60669
|
+
const element = el;
|
|
60670
|
+
const htmlInput = element instanceof HTMLInputElement ? element : null;
|
|
60671
|
+
const htmlTextArea = element instanceof HTMLTextAreaElement ? element : null;
|
|
60672
|
+
const htmlSelect = element instanceof HTMLSelectElement ? element : null;
|
|
60673
|
+
const htmlButton = element instanceof HTMLButtonElement ? element : null;
|
|
60674
|
+
const ariaReadonly = element.getAttribute("aria-readonly") === "true";
|
|
60675
|
+
const ariaDisabled = element.getAttribute("aria-disabled") === "true";
|
|
60676
|
+
const contentEditableFalse = element.getAttribute("contenteditable") === "false";
|
|
60677
|
+
const inputType = htmlInput?.type.toLowerCase() ?? null;
|
|
60678
|
+
const fillableInputTypes = /* @__PURE__ */ new Set([
|
|
60679
|
+
"",
|
|
60680
|
+
"color",
|
|
60681
|
+
"date",
|
|
60682
|
+
"datetime-local",
|
|
60683
|
+
"email",
|
|
60684
|
+
"month",
|
|
60685
|
+
"number",
|
|
60686
|
+
"password",
|
|
60687
|
+
"range",
|
|
60688
|
+
"search",
|
|
60689
|
+
"tel",
|
|
60690
|
+
"text",
|
|
60691
|
+
"time",
|
|
60692
|
+
"url",
|
|
60693
|
+
"week"
|
|
60694
|
+
]);
|
|
60695
|
+
return {
|
|
60696
|
+
readonly: Boolean(
|
|
60697
|
+
htmlInput?.readOnly || htmlTextArea?.readOnly || ariaReadonly || contentEditableFalse
|
|
60698
|
+
),
|
|
60699
|
+
disabled: Boolean(
|
|
60700
|
+
htmlInput?.disabled || htmlTextArea?.disabled || htmlSelect?.disabled || htmlButton?.disabled || ariaDisabled
|
|
60701
|
+
),
|
|
60702
|
+
fillable: Boolean(
|
|
60703
|
+
htmlInput && fillableInputTypes.has(inputType ?? "") || htmlTextArea || element.isContentEditable
|
|
60704
|
+
),
|
|
60705
|
+
tagName: element.tagName.toLowerCase(),
|
|
60706
|
+
role: element.getAttribute("role"),
|
|
60707
|
+
inputType
|
|
60708
|
+
};
|
|
60709
|
+
});
|
|
60710
|
+
} catch (error) {
|
|
60711
|
+
throw toFillTargetProbeError(error, {
|
|
60712
|
+
ref: ref2,
|
|
60713
|
+
elementDesc,
|
|
60714
|
+
stage: "editability_probe"
|
|
60715
|
+
});
|
|
60716
|
+
}
|
|
60717
|
+
if (!probe.readonly && !probe.disabled && probe.fillable) return;
|
|
60718
|
+
const state = probe.disabled ? "disabled" : probe.readonly ? "readonly" : "not-fillable";
|
|
59524
60719
|
const tag = probe.tagName ?? "element";
|
|
59525
|
-
|
|
59526
|
-
|
|
60720
|
+
throw new FillTargetNotEditableError({
|
|
60721
|
+
ref: ref2,
|
|
60722
|
+
elementDesc,
|
|
60723
|
+
state,
|
|
60724
|
+
tagName: tag,
|
|
60725
|
+
role: probe.role,
|
|
60726
|
+
...probe.inputType ? { inputType: probe.inputType } : {}
|
|
60727
|
+
});
|
|
59527
60728
|
}
|
|
59528
60729
|
|
|
59529
60730
|
export {
|
|
@@ -59621,6 +60822,16 @@ export {
|
|
|
59621
60822
|
guessMimeType,
|
|
59622
60823
|
captureElementAtPoint,
|
|
59623
60824
|
extractElementMetadata,
|
|
60825
|
+
CpuOffloadTimeoutError,
|
|
60826
|
+
CpuOffloadWorkerError,
|
|
60827
|
+
resolveCpuOffloadWorkerPath,
|
|
60828
|
+
CpuOffloadPool,
|
|
60829
|
+
DEFAULT_CPU_OFFLOAD_TIMEOUT_MS,
|
|
60830
|
+
defaultCpuOffloadSize,
|
|
60831
|
+
configureCpuOffload,
|
|
60832
|
+
isCpuOffloadEnabled,
|
|
60833
|
+
shutdownCpuOffload,
|
|
60834
|
+
formatSnapshotMaybeOffloaded,
|
|
59624
60835
|
ToolAbortedError,
|
|
59625
60836
|
isMCPContentWithImages,
|
|
59626
60837
|
coerceResultText,
|
|
@@ -59921,4 +61132,4 @@ playwright-extra/dist/index.esm.js:
|
|
|
59921
61132
|
* @license MIT
|
|
59922
61133
|
*)
|
|
59923
61134
|
*/
|
|
59924
|
-
//# sourceMappingURL=chunk-
|
|
61135
|
+
//# sourceMappingURL=chunk-7OO3RJYR.js.map
|