@roxybrowser/playwright 2.0.2-beta.2 → 2.0.2-beta.4
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/browser.d.ts +33 -5
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +127 -15
- package/dist/browser.js.map +1 -1
- package/dist/browserType.d.ts.map +1 -1
- package/dist/browserType.js +2 -1
- package/dist/browserType.js.map +1 -1
- package/dist/mcp/backend/network.d.ts.map +1 -1
- package/dist/mcp/backend/network.js +30 -4
- package/dist/mcp/backend/network.js.map +1 -1
- package/dist/mcp/backend/response.d.ts +2 -0
- package/dist/mcp/backend/response.d.ts.map +1 -1
- package/dist/mcp/backend/response.js +28 -4
- package/dist/mcp/backend/response.js.map +1 -1
- package/dist/mcp/connectedBrowser.d.ts.map +1 -1
- package/dist/mcp/connectedBrowser.js +327 -18
- package/dist/mcp/connectedBrowser.js.map +1 -1
- package/dist/mcp/runtime.d.ts +2 -0
- package/dist/mcp/runtime.d.ts.map +1 -1
- package/dist/mcp/runtime.js +20 -1
- package/dist/mcp/runtime.js.map +1 -1
- package/dist/mcp/types.d.ts +3 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/page.d.ts +2 -0
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +12 -0
- package/dist/page.js.map +1 -1
- package/dist/roxybrowser.bundle.js +437 -38
- package/dist/roxybrowser.bundle.js.map +1 -1
- package/dist/types/api.d.ts +21 -2
- package/dist/types/api.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -5124,6 +5124,7 @@ var RoxyPage = class RoxyPage {
|
|
|
5124
5124
|
closed = false;
|
|
5125
5125
|
closePromise = null;
|
|
5126
5126
|
closeReason;
|
|
5127
|
+
ownedContext;
|
|
5127
5128
|
defaultTimeoutMs = DEFAULT_EVENT_TIMEOUT_MS;
|
|
5128
5129
|
defaultNavigationTimeoutMs = DEFAULT_EVENT_TIMEOUT_MS;
|
|
5129
5130
|
currentViewportSize = null;
|
|
@@ -6111,6 +6112,10 @@ waiting for navigation${navigationTargetDescription} until "${waitUntil}"\n=====
|
|
|
6111
6112
|
}
|
|
6112
6113
|
this.closeReason = options.reason;
|
|
6113
6114
|
this.closePromise = (async () => {
|
|
6115
|
+
if (this.ownedContext) {
|
|
6116
|
+
await this.ownedContext.close().catch(() => {});
|
|
6117
|
+
return;
|
|
6118
|
+
}
|
|
6114
6119
|
await this.dismissActiveDialogsForClose();
|
|
6115
6120
|
await this.finalizeVideoRecording();
|
|
6116
6121
|
await this.adapter.close(options).catch(() => {});
|
|
@@ -6122,6 +6127,9 @@ waiting for navigation${navigationTargetDescription} until "${waitUntil}"\n=====
|
|
|
6122
6127
|
this.closePromise = null;
|
|
6123
6128
|
}
|
|
6124
6129
|
}
|
|
6130
|
+
setOwnedContext(context) {
|
|
6131
|
+
this.ownedContext = context;
|
|
6132
|
+
}
|
|
6125
6133
|
defaultTimeout() {
|
|
6126
6134
|
return this.defaultTimeoutMs;
|
|
6127
6135
|
}
|
|
@@ -10650,12 +10658,74 @@ var RoxyBrowser = class {
|
|
|
10650
10658
|
session;
|
|
10651
10659
|
adapter;
|
|
10652
10660
|
humanDefaults;
|
|
10653
|
-
|
|
10654
|
-
|
|
10661
|
+
_browserName;
|
|
10662
|
+
_browserType;
|
|
10663
|
+
_version;
|
|
10664
|
+
_contexts = [];
|
|
10665
|
+
_listeners = /* @__PURE__ */ new Map();
|
|
10666
|
+
_connected = true;
|
|
10667
|
+
constructor(session, adapter, humanDefaults, _browserName, _browserType, _version) {
|
|
10655
10668
|
this.session = session;
|
|
10656
10669
|
this.adapter = adapter;
|
|
10657
10670
|
this.humanDefaults = humanDefaults;
|
|
10658
|
-
this.
|
|
10671
|
+
this._browserName = _browserName;
|
|
10672
|
+
this._browserType = _browserType;
|
|
10673
|
+
this._version = _version;
|
|
10674
|
+
}
|
|
10675
|
+
on(event, listener) {
|
|
10676
|
+
return this._addListenerInternal(event, listener);
|
|
10677
|
+
}
|
|
10678
|
+
once(event, listener) {
|
|
10679
|
+
const wrapped = (payload) => {
|
|
10680
|
+
this._removeListenerInternal(event, listener);
|
|
10681
|
+
listener(payload);
|
|
10682
|
+
};
|
|
10683
|
+
this._ensureListenerSet(event).add({
|
|
10684
|
+
original: listener,
|
|
10685
|
+
wrapped
|
|
10686
|
+
});
|
|
10687
|
+
return this;
|
|
10688
|
+
}
|
|
10689
|
+
addListener(event, listener) {
|
|
10690
|
+
return this._addListenerInternal(event, listener);
|
|
10691
|
+
}
|
|
10692
|
+
removeListener(event, listener) {
|
|
10693
|
+
return this._removeListenerInternal(event, listener);
|
|
10694
|
+
}
|
|
10695
|
+
off(event, listener) {
|
|
10696
|
+
return this._removeListenerInternal(event, listener);
|
|
10697
|
+
}
|
|
10698
|
+
prependListener(event, listener) {
|
|
10699
|
+
const entry = {
|
|
10700
|
+
original: listener,
|
|
10701
|
+
wrapped: listener
|
|
10702
|
+
};
|
|
10703
|
+
const existing = this._listeners.get(event);
|
|
10704
|
+
if (!existing) {
|
|
10705
|
+
const s = new Set([entry]);
|
|
10706
|
+
this._listeners.set(event, s);
|
|
10707
|
+
} else {
|
|
10708
|
+
const s = new Set([entry, ...Array.from(existing)]);
|
|
10709
|
+
this._listeners.set(event, s);
|
|
10710
|
+
}
|
|
10711
|
+
return this;
|
|
10712
|
+
}
|
|
10713
|
+
removeAllListeners(type) {
|
|
10714
|
+
if (type === void 0) this._listeners.clear();
|
|
10715
|
+
else this._listeners.delete(type);
|
|
10716
|
+
return this;
|
|
10717
|
+
}
|
|
10718
|
+
browserType() {
|
|
10719
|
+
return this._browserType;
|
|
10720
|
+
}
|
|
10721
|
+
contexts() {
|
|
10722
|
+
return [...this._contexts];
|
|
10723
|
+
}
|
|
10724
|
+
isConnected() {
|
|
10725
|
+
return this._connected;
|
|
10726
|
+
}
|
|
10727
|
+
version() {
|
|
10728
|
+
return this._version;
|
|
10659
10729
|
}
|
|
10660
10730
|
async newContext(options = {}) {
|
|
10661
10731
|
const normalizedOptions = {
|
|
@@ -10666,26 +10736,66 @@ var RoxyBrowser = class {
|
|
|
10666
10736
|
...options.recordVideo.dir ? { dir: resolve(options.recordVideo.dir) } : {}
|
|
10667
10737
|
} } : {}
|
|
10668
10738
|
};
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10739
|
+
const context = new RoxyBrowserContext(await this.session.newContext(normalizedOptions), resolveHumanizationOptions(normalizedOptions.human, this.humanDefaults), normalizedOptions, this._browserName);
|
|
10740
|
+
this._contexts.push(context);
|
|
10741
|
+
context.on("close", () => {
|
|
10742
|
+
const index = this._contexts.indexOf(context);
|
|
10743
|
+
if (index !== -1) this._contexts.splice(index, 1);
|
|
10744
|
+
});
|
|
10745
|
+
this._emit("context", context);
|
|
10746
|
+
return context;
|
|
10747
|
+
}
|
|
10748
|
+
async newPage(options) {
|
|
10749
|
+
const context = await this.newContext(options);
|
|
10750
|
+
const page = await context.newPage();
|
|
10751
|
+
const roxyPage = page;
|
|
10752
|
+
if (typeof roxyPage.setOwnedContext === "function") roxyPage.setOwnedContext(context);
|
|
10753
|
+
else page.once("close", () => context.close().catch(() => {}));
|
|
10754
|
+
return page;
|
|
10673
10755
|
}
|
|
10674
|
-
async close() {
|
|
10756
|
+
async close(options) {
|
|
10757
|
+
if (!this._connected) return;
|
|
10758
|
+
this._connected = false;
|
|
10675
10759
|
try {
|
|
10676
10760
|
await withCloseTimeout$1(this.session.close(), BROWSER_SESSION_CLOSE_TIMEOUT_MS);
|
|
10677
10761
|
} finally {
|
|
10678
10762
|
await this.adapter.close();
|
|
10763
|
+
this._emit("disconnected", this);
|
|
10679
10764
|
}
|
|
10680
10765
|
}
|
|
10766
|
+
_addListenerInternal(event, listener) {
|
|
10767
|
+
this._ensureListenerSet(event).add({
|
|
10768
|
+
original: listener,
|
|
10769
|
+
wrapped: listener
|
|
10770
|
+
});
|
|
10771
|
+
return this;
|
|
10772
|
+
}
|
|
10773
|
+
_removeListenerInternal(event, listener) {
|
|
10774
|
+
const entries = this._listeners.get(event);
|
|
10775
|
+
if (!entries) return this;
|
|
10776
|
+
for (const entry of Array.from(entries)) if (entry.original === listener) entries.delete(entry);
|
|
10777
|
+
if (entries.size === 0) this._listeners.delete(event);
|
|
10778
|
+
return this;
|
|
10779
|
+
}
|
|
10780
|
+
_ensureListenerSet(event) {
|
|
10781
|
+
const existing = this._listeners.get(event);
|
|
10782
|
+
if (existing) return existing;
|
|
10783
|
+
const created = /* @__PURE__ */ new Set();
|
|
10784
|
+
this._listeners.set(event, created);
|
|
10785
|
+
return created;
|
|
10786
|
+
}
|
|
10787
|
+
_emit(event, payload) {
|
|
10788
|
+
const entries = this._listeners.get(event);
|
|
10789
|
+
if (!entries?.size) return false;
|
|
10790
|
+
for (const entry of Array.from(entries)) entry.wrapped(payload);
|
|
10791
|
+
return true;
|
|
10792
|
+
}
|
|
10681
10793
|
};
|
|
10682
10794
|
async function withCloseTimeout$1(promise, timeoutMs) {
|
|
10683
10795
|
let timer;
|
|
10684
10796
|
try {
|
|
10685
10797
|
return await Promise.race([promise, new Promise((_, reject) => {
|
|
10686
|
-
timer = setTimeout(() => {
|
|
10687
|
-
reject(/* @__PURE__ */ new Error(`Timed out closing browser session after ${timeoutMs}ms.`));
|
|
10688
|
-
}, timeoutMs);
|
|
10798
|
+
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Timed out closing browser session after ${timeoutMs}ms.`)), timeoutMs);
|
|
10689
10799
|
})]);
|
|
10690
10800
|
} finally {
|
|
10691
10801
|
if (timer) clearTimeout(timer);
|
|
@@ -53334,7 +53444,9 @@ var RoxyBrowserType = class {
|
|
|
53334
53444
|
protocol
|
|
53335
53445
|
});
|
|
53336
53446
|
await adapter.connect();
|
|
53337
|
-
|
|
53447
|
+
const session = await adapter.browser();
|
|
53448
|
+
const versionStr = await session.version();
|
|
53449
|
+
return new RoxyBrowser(session, adapter, resolveHumanizationOptions(options.human), options.browserName ?? this.browserName, this, versionStr);
|
|
53338
53450
|
}
|
|
53339
53451
|
};
|
|
53340
53452
|
var chromium = new RoxyBrowserType("chromium", {
|
|
@@ -73317,6 +73429,7 @@ var Response$1 = class {
|
|
|
73317
73429
|
includeSnapshot = "none";
|
|
73318
73430
|
fullSnapshot;
|
|
73319
73431
|
isClose = false;
|
|
73432
|
+
rawResults = false;
|
|
73320
73433
|
constructor(context, toolName, toolArgs) {
|
|
73321
73434
|
this.context = context;
|
|
73322
73435
|
this.toolName = toolName;
|
|
@@ -73340,6 +73453,9 @@ var Response$1 = class {
|
|
|
73340
73453
|
setClose() {
|
|
73341
73454
|
this.isClose = true;
|
|
73342
73455
|
}
|
|
73456
|
+
setRawResults() {
|
|
73457
|
+
this.rawResults = true;
|
|
73458
|
+
}
|
|
73343
73459
|
setIncludeSnapshot() {
|
|
73344
73460
|
this.includeSnapshot = this.context.config.snapshot?.mode ?? "full";
|
|
73345
73461
|
}
|
|
@@ -73355,6 +73471,21 @@ var Response$1 = class {
|
|
|
73355
73471
|
async serialize() {
|
|
73356
73472
|
const sections = [];
|
|
73357
73473
|
if (this.errors.length) sections.push("### Error", ...this.errors);
|
|
73474
|
+
if (this.rawResults) {
|
|
73475
|
+
if (this.results.length) sections.push(...this.results);
|
|
73476
|
+
return {
|
|
73477
|
+
content: [{
|
|
73478
|
+
type: "text",
|
|
73479
|
+
text: sections.join("\n")
|
|
73480
|
+
}, ...this.images.map((image) => ({
|
|
73481
|
+
type: "image",
|
|
73482
|
+
data: image.data,
|
|
73483
|
+
mimeType: image.mimeType
|
|
73484
|
+
}))],
|
|
73485
|
+
...this.isClose ? { isClose: true } : {},
|
|
73486
|
+
...this.errors.length ? { isError: true } : {}
|
|
73487
|
+
};
|
|
73488
|
+
}
|
|
73358
73489
|
if (this.results.length) {
|
|
73359
73490
|
if (sections.length) sections.push("");
|
|
73360
73491
|
sections.push("### Result", ...this.results);
|
|
@@ -73364,9 +73495,11 @@ var Response$1 = class {
|
|
|
73364
73495
|
sections.push("### Code", "```js", ...this.code, "```");
|
|
73365
73496
|
}
|
|
73366
73497
|
if (this.includeSnapshot === "full") {
|
|
73367
|
-
|
|
73368
|
-
|
|
73369
|
-
|
|
73498
|
+
if (!await this.context.runtime.hasDialog()) {
|
|
73499
|
+
const snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot());
|
|
73500
|
+
if (sections.length) sections.push("");
|
|
73501
|
+
sections.push(formatSnapshot(snapshot));
|
|
73502
|
+
}
|
|
73370
73503
|
}
|
|
73371
73504
|
if (this.fullSnapshot) {
|
|
73372
73505
|
let snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot({
|
|
@@ -73374,7 +73507,7 @@ var Response$1 = class {
|
|
|
73374
73507
|
...this.fullSnapshot.depth !== void 0 ? { depth: this.fullSnapshot.depth } : {},
|
|
73375
73508
|
...this.fullSnapshot.boxes !== void 0 ? { boxes: this.fullSnapshot.boxes } : {}
|
|
73376
73509
|
}));
|
|
73377
|
-
if (!this.fullSnapshot.filename && snapshot.text.trim().length === 0 && snapshot.url && snapshot.url !== "about:blank") snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot({
|
|
73510
|
+
if (!this.fullSnapshot.filename && snapshot.retryable && snapshot.text.trim().length === 0 && snapshot.url && snapshot.url !== "about:blank") snapshot = await reconcileSnapshotWithTabs(this.context, await this.context.runtime.snapshot({
|
|
73378
73511
|
...this.fullSnapshot.target !== void 0 ? { target: this.fullSnapshot.target } : {},
|
|
73379
73512
|
...this.fullSnapshot.depth !== void 0 ? { depth: this.fullSnapshot.depth } : {},
|
|
73380
73513
|
...this.fullSnapshot.boxes !== void 0 ? { boxes: this.fullSnapshot.boxes } : {}
|
|
@@ -73968,7 +74101,17 @@ var networkRequest = defineTool$1({
|
|
|
73968
74101
|
response.addError(`Request #${args.index} not found. Use browser_network_requests to see available indexes.`);
|
|
73969
74102
|
return;
|
|
73970
74103
|
}
|
|
73971
|
-
|
|
74104
|
+
if (args.part) {
|
|
74105
|
+
response.setRawResults();
|
|
74106
|
+
const partText = args.part === "response-body" ? await context.runtime.fetchResponseBody(args.index) ?? "" : renderRequestPart(request, args.part);
|
|
74107
|
+
if (args.filename) {
|
|
74108
|
+
const resolvedFilename = await context.resolveOutputFile(args.filename);
|
|
74109
|
+
await writeFile(resolvedFilename, partText);
|
|
74110
|
+
response.addTextResult(`Saved network request to "${resolvedFilename}".`);
|
|
74111
|
+
} else response.addTextResult(partText);
|
|
74112
|
+
return;
|
|
74113
|
+
}
|
|
74114
|
+
const text = renderRequestDetails(request);
|
|
73972
74115
|
if (args.filename) {
|
|
73973
74116
|
const resolvedFilename = await context.resolveOutputFile(args.filename);
|
|
73974
74117
|
await writeFile(resolvedFilename, text);
|
|
@@ -74002,8 +74145,10 @@ function renderRequestDetails(request) {
|
|
|
74002
74145
|
if (request.mimeType) lines.push(` mimeType: ${request.mimeType}`);
|
|
74003
74146
|
appendHeaders(lines, "Request headers", request.requestHeaders);
|
|
74004
74147
|
if (request.responseHeaders) appendHeaders(lines, "Response headers", request.responseHeaders);
|
|
74005
|
-
|
|
74006
|
-
if (request.
|
|
74148
|
+
const hints = [];
|
|
74149
|
+
if (request.requestBody) hints.push(`Call browser_network_request with part="request-body" to read the request body.`);
|
|
74150
|
+
if (canHaveResponseBody(request)) hints.push(`Call browser_network_request with part="response-body" to read the response body.`);
|
|
74151
|
+
if (hints.length) lines.push("", ...hints);
|
|
74007
74152
|
return lines.join("\n");
|
|
74008
74153
|
}
|
|
74009
74154
|
function renderRequestPart(request, part) {
|
|
@@ -74022,6 +74167,10 @@ function appendHeaders(lines, title, headers) {
|
|
|
74022
74167
|
function renderHeaders(headers) {
|
|
74023
74168
|
return Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join("\n");
|
|
74024
74169
|
}
|
|
74170
|
+
function canHaveResponseBody(request) {
|
|
74171
|
+
if (request.failureText || request.status === void 0) return false;
|
|
74172
|
+
return request.status !== 204 && request.status !== 304 && !(request.status >= 100 && request.status < 200);
|
|
74173
|
+
}
|
|
74025
74174
|
var network_default = [networkRequests, networkRequest];
|
|
74026
74175
|
var runCode_default = [defineTool$1({
|
|
74027
74176
|
capability: "devtools",
|
|
@@ -74759,6 +74908,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
74759
74908
|
pageConsoleStates = /* @__PURE__ */ new Map();
|
|
74760
74909
|
pageNetworkStates = /* @__PURE__ */ new Map();
|
|
74761
74910
|
pageDialogStates = /* @__PURE__ */ new Map();
|
|
74911
|
+
dialogWaiters = /* @__PURE__ */ new Map();
|
|
74762
74912
|
activeTabId;
|
|
74763
74913
|
versionString = "Chromium/unknown";
|
|
74764
74914
|
constructor(browserClient, connection) {
|
|
@@ -74774,7 +74924,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
74774
74924
|
});
|
|
74775
74925
|
const session = new CdpConnectedBrowserSession(await chromeRemoteInterface({ target: connection.browserWsEndpoint }), connection);
|
|
74776
74926
|
session.versionString = version.Browser;
|
|
74777
|
-
|
|
74927
|
+
await session.refreshTabs();
|
|
74778
74928
|
await session.getActivePageClient().catch(() => void 0);
|
|
74779
74929
|
return session;
|
|
74780
74930
|
}
|
|
@@ -74826,6 +74976,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
74826
74976
|
async click(target, options) {
|
|
74827
74977
|
const pageClient = await this.getActivePageClient();
|
|
74828
74978
|
const contextId = await this.getActiveUtilityContextId(pageClient);
|
|
74979
|
+
const tabId = await this.getActiveTabId();
|
|
74829
74980
|
const point = await evaluateCdp(pageClient, "nodeToken" in target ? ACTION_POINT_EVALUATE_SOURCE : ACTION_POINT_BY_SELECTOR_SOURCE, "nodeToken" in target ? { nodeToken: target.nodeToken } : { selector: target.selector }, contextId);
|
|
74830
74981
|
if (!point.ok || point.x === void 0 || point.y === void 0) {
|
|
74831
74982
|
const isSelector = "selector" in target;
|
|
@@ -74859,7 +75010,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
74859
75010
|
modifiers: modifiersMask
|
|
74860
75011
|
});
|
|
74861
75012
|
await delay$1(options.clickHoldMs);
|
|
74862
|
-
|
|
75013
|
+
const releasePromise = pageClient.Input.dispatchMouseEvent({
|
|
74863
75014
|
type: "mouseReleased",
|
|
74864
75015
|
x: point.x,
|
|
74865
75016
|
y: point.y,
|
|
@@ -74867,6 +75018,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
74867
75018
|
clickCount,
|
|
74868
75019
|
modifiers: modifiersMask
|
|
74869
75020
|
});
|
|
75021
|
+
await Promise.race([releasePromise, this.waitForDialog(tabId, options.clickHoldMs + 1e3)]);
|
|
74870
75022
|
}
|
|
74871
75023
|
}
|
|
74872
75024
|
async drag(start, end, options) {
|
|
@@ -75122,24 +75274,72 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75122
75274
|
}
|
|
75123
75275
|
}
|
|
75124
75276
|
async handleDialog(accept, promptText) {
|
|
75125
|
-
const tabId =
|
|
75277
|
+
const tabId = this.dialogTabId();
|
|
75126
75278
|
if (!this.pageDialogStates.has(tabId)) throw new McpToolError("no_dialog", "No dialog visible.");
|
|
75127
|
-
const pageClient = await this.getActivePageClient();
|
|
75279
|
+
const pageClient = this.pageClients.get(tabId) ?? await this.getActivePageClient();
|
|
75128
75280
|
this.pageDialogStates.delete(tabId);
|
|
75129
75281
|
await pageClient.Page.handleJavaScriptDialog({
|
|
75130
75282
|
accept,
|
|
75131
75283
|
...promptText !== void 0 ? { promptText } : {}
|
|
75132
75284
|
});
|
|
75133
75285
|
}
|
|
75286
|
+
async hasDialog() {
|
|
75287
|
+
return this.pageDialogStates.size > 0;
|
|
75288
|
+
}
|
|
75289
|
+
waitForDialog(tabId, timeoutMs) {
|
|
75290
|
+
if (this.pageDialogStates.has(tabId)) return Promise.resolve();
|
|
75291
|
+
return new Promise((resolve) => {
|
|
75292
|
+
const waiter = { resolve: () => {
|
|
75293
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
75294
|
+
this.removeDialogWaiter(tabId, waiter);
|
|
75295
|
+
resolve();
|
|
75296
|
+
} };
|
|
75297
|
+
waiter.timer = setTimeout(() => waiter.resolve(), timeoutMs);
|
|
75298
|
+
const waiters = this.dialogWaiters.get(tabId) ?? /* @__PURE__ */ new Set();
|
|
75299
|
+
waiters.add(waiter);
|
|
75300
|
+
this.dialogWaiters.set(tabId, waiters);
|
|
75301
|
+
});
|
|
75302
|
+
}
|
|
75303
|
+
resolveDialogWaiters(tabId) {
|
|
75304
|
+
const waiters = this.dialogWaiters.get(tabId);
|
|
75305
|
+
if (!waiters) return;
|
|
75306
|
+
this.dialogWaiters.delete(tabId);
|
|
75307
|
+
for (const waiter of waiters) waiter.resolve();
|
|
75308
|
+
}
|
|
75309
|
+
removeDialogWaiter(tabId, waiter) {
|
|
75310
|
+
const waiters = this.dialogWaiters.get(tabId);
|
|
75311
|
+
if (!waiters) return;
|
|
75312
|
+
waiters.delete(waiter);
|
|
75313
|
+
if (waiters.size === 0) this.dialogWaiters.delete(tabId);
|
|
75314
|
+
}
|
|
75134
75315
|
async networkRequests() {
|
|
75135
75316
|
const tabId = await this.getActiveTabId();
|
|
75317
|
+
await this.hydratePerformanceResourceRequests(tabId);
|
|
75136
75318
|
return this.ensureNetworkState(tabId).requests.map(cloneNetworkRequest);
|
|
75137
75319
|
}
|
|
75138
75320
|
async networkRequest(index) {
|
|
75139
75321
|
const tabId = await this.getActiveTabId();
|
|
75322
|
+
await this.hydratePerformanceResourceRequests(tabId);
|
|
75140
75323
|
const request = this.ensureNetworkState(tabId).requests[index - 1];
|
|
75141
75324
|
return request ? cloneNetworkRequest(request) : void 0;
|
|
75142
75325
|
}
|
|
75326
|
+
async fetchResponseBody(index) {
|
|
75327
|
+
const tabId = await this.getActiveTabId();
|
|
75328
|
+
const state = this.ensureNetworkState(tabId);
|
|
75329
|
+
const request = state.requests[index - 1];
|
|
75330
|
+
if (!request || !request.requestId) return request?.responseBody;
|
|
75331
|
+
if (!canReadResponseBody(request)) return;
|
|
75332
|
+
if (request.responseBody !== void 0) return request.responseBody;
|
|
75333
|
+
await waitForLoadingDone(state, request.requestId, 5e3).catch(() => void 0);
|
|
75334
|
+
if (request.responseBody !== void 0) return request.responseBody;
|
|
75335
|
+
if (state.bodyRead.has(request.requestId)) return;
|
|
75336
|
+
state.bodyRead.add(request.requestId);
|
|
75337
|
+
const clientNetwork = (this.pageClients.get(tabId) ?? await this.getActivePageClient()).Network;
|
|
75338
|
+
if (!clientNetwork) return;
|
|
75339
|
+
const body = await clientNetwork.getResponseBody({ requestId: request.requestId }).catch(() => void 0);
|
|
75340
|
+
if (body) request.responseBody = body.base64Encoded ? Buffer.from(body.body, "base64").toString("utf8") : body.body;
|
|
75341
|
+
return request.responseBody;
|
|
75342
|
+
}
|
|
75143
75343
|
async runCodeUnsafe(code) {
|
|
75144
75344
|
const pageClient = await this.getActivePageClient();
|
|
75145
75345
|
const contextId = await this.getActiveUtilityContextId(pageClient);
|
|
@@ -75199,6 +75399,12 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75199
75399
|
if (!activeTab) throw new McpToolError("no_active_tab", "No active tab is available.");
|
|
75200
75400
|
return activeTab.id;
|
|
75201
75401
|
}
|
|
75402
|
+
dialogTabId() {
|
|
75403
|
+
if (this.activeTabId && this.pageDialogStates.has(this.activeTabId)) return this.activeTabId;
|
|
75404
|
+
const tabId = this.pageDialogStates.keys().next().value;
|
|
75405
|
+
if (!tabId) throw new McpToolError("no_dialog", "No dialog visible.");
|
|
75406
|
+
return tabId;
|
|
75407
|
+
}
|
|
75202
75408
|
async getActivePageClient() {
|
|
75203
75409
|
const activeTab = (await this.refreshTabs()).find((tab) => tab.active);
|
|
75204
75410
|
if (!activeTab) throw new McpToolError("no_active_tab", "No active tab is available.");
|
|
@@ -75280,6 +75486,7 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75280
75486
|
...event.defaultPrompt !== void 0 ? { defaultPrompt: event.defaultPrompt } : {},
|
|
75281
75487
|
...event.url !== void 0 ? { url: event.url } : {}
|
|
75282
75488
|
});
|
|
75489
|
+
this.resolveDialogWaiters(tabId);
|
|
75283
75490
|
});
|
|
75284
75491
|
this.installNetworkCollection(tabId, client);
|
|
75285
75492
|
}
|
|
@@ -75318,20 +75525,29 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75318
75525
|
});
|
|
75319
75526
|
client.Network.loadingFinished(async (event) => {
|
|
75320
75527
|
const request = state.byRequestId.get(event.requestId);
|
|
75321
|
-
if (!request)
|
|
75528
|
+
if (!request) {
|
|
75529
|
+
resolveLoadingDone(state, event.requestId, true);
|
|
75530
|
+
return;
|
|
75531
|
+
}
|
|
75322
75532
|
const startedAt = state.startedAt.get(event.requestId);
|
|
75323
75533
|
if (startedAt !== void 0 && event.timestamp !== void 0) request.durationMs = Math.round(event.timestamp * 1e3 - startedAt);
|
|
75324
|
-
if (canReadResponseBody(request)) {
|
|
75534
|
+
if (canReadResponseBody(request) && !state.bodyRead.has(event.requestId)) {
|
|
75535
|
+
state.bodyRead.add(event.requestId);
|
|
75325
75536
|
const body = await client.Network?.getResponseBody({ requestId: event.requestId }).catch(() => void 0);
|
|
75326
75537
|
if (body) request.responseBody = body.base64Encoded ? Buffer.from(body.body, "base64").toString("utf8") : body.body;
|
|
75327
75538
|
}
|
|
75539
|
+
resolveLoadingDone(state, event.requestId, true);
|
|
75328
75540
|
});
|
|
75329
75541
|
client.Network.loadingFailed((event) => {
|
|
75330
75542
|
const request = state.byRequestId.get(event.requestId);
|
|
75331
|
-
if (!request)
|
|
75543
|
+
if (!request) {
|
|
75544
|
+
resolveLoadingDone(state, event.requestId, false);
|
|
75545
|
+
return;
|
|
75546
|
+
}
|
|
75332
75547
|
request.failureText = event.errorText ?? "Unknown error";
|
|
75333
75548
|
const startedAt = state.startedAt.get(event.requestId);
|
|
75334
75549
|
if (startedAt !== void 0 && event.timestamp !== void 0) request.durationMs = Math.round(event.timestamp * 1e3 - startedAt);
|
|
75550
|
+
resolveLoadingDone(state, event.requestId, false);
|
|
75335
75551
|
});
|
|
75336
75552
|
}
|
|
75337
75553
|
ensureConsoleState(tabId) {
|
|
@@ -75353,7 +75569,10 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75353
75569
|
state = {
|
|
75354
75570
|
requests: [],
|
|
75355
75571
|
byRequestId: /* @__PURE__ */ new Map(),
|
|
75356
|
-
startedAt: /* @__PURE__ */ new Map()
|
|
75572
|
+
startedAt: /* @__PURE__ */ new Map(),
|
|
75573
|
+
hydratedPerformanceResources: false,
|
|
75574
|
+
loadingDone: /* @__PURE__ */ new Map(),
|
|
75575
|
+
bodyRead: /* @__PURE__ */ new Set()
|
|
75357
75576
|
};
|
|
75358
75577
|
this.pageNetworkStates.set(tabId, state);
|
|
75359
75578
|
}
|
|
@@ -75369,10 +75588,79 @@ var CdpConnectedBrowserSession = class CdpConnectedBrowserSession {
|
|
|
75369
75588
|
this.pageNetworkStates.set(tabId, {
|
|
75370
75589
|
requests: [],
|
|
75371
75590
|
byRequestId: /* @__PURE__ */ new Map(),
|
|
75372
|
-
startedAt: /* @__PURE__ */ new Map()
|
|
75591
|
+
startedAt: /* @__PURE__ */ new Map(),
|
|
75592
|
+
hydratedPerformanceResources: false,
|
|
75593
|
+
loadingDone: /* @__PURE__ */ new Map(),
|
|
75594
|
+
bodyRead: /* @__PURE__ */ new Set()
|
|
75373
75595
|
});
|
|
75374
75596
|
this.pageDialogStates.delete(tabId);
|
|
75375
75597
|
}
|
|
75598
|
+
async hydratePerformanceResourceRequests(tabId) {
|
|
75599
|
+
const state = this.ensureNetworkState(tabId);
|
|
75600
|
+
if (state.hydratedPerformanceResources) return;
|
|
75601
|
+
state.hydratedPerformanceResources = true;
|
|
75602
|
+
const pageClient = await this.getActivePageClient();
|
|
75603
|
+
const contextId = await this.getActiveUtilityContextId(pageClient);
|
|
75604
|
+
const documentRequest = await evaluateCdp(pageClient, String.raw`() => {
|
|
75605
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
75606
|
+
return {
|
|
75607
|
+
url: String(location.href || ""),
|
|
75608
|
+
duration: navigation ? Math.round(Number(navigation.duration || 0)) : undefined
|
|
75609
|
+
};
|
|
75610
|
+
}`, void 0, contextId).catch(() => void 0);
|
|
75611
|
+
if (documentRequest?.url && !Array.from(state.byRequestId.values()).some((request) => request.url === documentRequest.url)) {
|
|
75612
|
+
const requestId = `performance:navigation:${documentRequest.url}`;
|
|
75613
|
+
const request = {
|
|
75614
|
+
index: state.requests.length + 1,
|
|
75615
|
+
requestId,
|
|
75616
|
+
method: "GET",
|
|
75617
|
+
url: documentRequest.url,
|
|
75618
|
+
resourceType: "document",
|
|
75619
|
+
requestHeaders: {},
|
|
75620
|
+
status: 200,
|
|
75621
|
+
statusText: "OK",
|
|
75622
|
+
...documentRequest.duration !== void 0 ? { durationMs: documentRequest.duration } : {}
|
|
75623
|
+
};
|
|
75624
|
+
state.requests.push(request);
|
|
75625
|
+
state.byRequestId.set(requestId, request);
|
|
75626
|
+
}
|
|
75627
|
+
const resources = await evaluateCdp(pageClient, String.raw`() => performance.getEntriesByType("resource").map((entry) => ({
|
|
75628
|
+
name: String(entry.name || ""),
|
|
75629
|
+
initiatorType: String(entry.initiatorType || "other"),
|
|
75630
|
+
duration: Math.round(Number(entry.duration || 0)),
|
|
75631
|
+
responseStatus: typeof entry.responseStatus === "number" ? entry.responseStatus : undefined
|
|
75632
|
+
}))`, void 0, contextId).catch(() => []);
|
|
75633
|
+
for (const resource of resources) {
|
|
75634
|
+
if (!resource.name || Array.from(state.byRequestId.values()).some((request) => request.url === resource.name)) continue;
|
|
75635
|
+
const status = resource.responseStatus && resource.responseStatus > 0 ? resource.responseStatus : await this.probeResourceStatus(pageClient, contextId, resource.name);
|
|
75636
|
+
const requestId = `performance:${resource.name}`;
|
|
75637
|
+
const request = {
|
|
75638
|
+
index: state.requests.length + 1,
|
|
75639
|
+
requestId,
|
|
75640
|
+
method: "GET",
|
|
75641
|
+
url: resource.name,
|
|
75642
|
+
resourceType: normalizeResourceType(resource.initiatorType),
|
|
75643
|
+
requestHeaders: {},
|
|
75644
|
+
...status !== void 0 ? {
|
|
75645
|
+
status,
|
|
75646
|
+
statusText: statusTextForStatus(status)
|
|
75647
|
+
} : {},
|
|
75648
|
+
...resource.duration !== void 0 ? { durationMs: resource.duration } : {}
|
|
75649
|
+
};
|
|
75650
|
+
state.requests.push(request);
|
|
75651
|
+
state.byRequestId.set(requestId, request);
|
|
75652
|
+
}
|
|
75653
|
+
}
|
|
75654
|
+
async probeResourceStatus(pageClient, contextId, url) {
|
|
75655
|
+
return evaluateCdp(pageClient, String.raw`async (url) => {
|
|
75656
|
+
try {
|
|
75657
|
+
const response = await fetch(url, { method: "HEAD", cache: "no-store" });
|
|
75658
|
+
return response.status;
|
|
75659
|
+
} catch {
|
|
75660
|
+
return undefined;
|
|
75661
|
+
}
|
|
75662
|
+
}`, url, contextId).catch(() => void 0);
|
|
75663
|
+
}
|
|
75376
75664
|
addConsoleMessage(tabId, message) {
|
|
75377
75665
|
const state = this.ensureConsoleState(tabId);
|
|
75378
75666
|
if (!shouldIncludeConsoleMessage(message.type)) return;
|
|
@@ -75506,6 +75794,45 @@ function canReadResponseBody(request) {
|
|
|
75506
75794
|
if (request.failureText || request.status === void 0) return false;
|
|
75507
75795
|
return request.status !== 204 && request.status !== 304 && !(request.status >= 100 && request.status < 200);
|
|
75508
75796
|
}
|
|
75797
|
+
function loadingDoneEntry(state, requestId) {
|
|
75798
|
+
let entry = state.loadingDone.get(requestId);
|
|
75799
|
+
if (!entry) {
|
|
75800
|
+
let resolve;
|
|
75801
|
+
let reject;
|
|
75802
|
+
entry = {
|
|
75803
|
+
promise: new Promise((res, rej) => {
|
|
75804
|
+
resolve = res;
|
|
75805
|
+
reject = rej;
|
|
75806
|
+
}),
|
|
75807
|
+
resolve,
|
|
75808
|
+
reject
|
|
75809
|
+
};
|
|
75810
|
+
state.loadingDone.set(requestId, entry);
|
|
75811
|
+
}
|
|
75812
|
+
return entry;
|
|
75813
|
+
}
|
|
75814
|
+
function resolveLoadingDone(state, requestId, success) {
|
|
75815
|
+
const entry = state.loadingDone.get(requestId);
|
|
75816
|
+
if (!entry) return;
|
|
75817
|
+
state.loadingDone.delete(requestId);
|
|
75818
|
+
if (success) entry.resolve();
|
|
75819
|
+
else entry.reject(/* @__PURE__ */ new Error("Request failed before the response body was available."));
|
|
75820
|
+
}
|
|
75821
|
+
async function waitForLoadingDone(state, requestId, timeoutMs) {
|
|
75822
|
+
const entry = loadingDoneEntry(state, requestId);
|
|
75823
|
+
await Promise.race([entry.promise, new Promise((resolve) => setTimeout(resolve, timeoutMs))]);
|
|
75824
|
+
}
|
|
75825
|
+
function statusTextForStatus(status) {
|
|
75826
|
+
if (status === 200) return "OK";
|
|
75827
|
+
if (status === 204) return "No Content";
|
|
75828
|
+
if (status === 304) return "Not Modified";
|
|
75829
|
+
if (status === 400) return "Bad Request";
|
|
75830
|
+
if (status === 401) return "Unauthorized";
|
|
75831
|
+
if (status === 403) return "Forbidden";
|
|
75832
|
+
if (status === 404) return "Not Found";
|
|
75833
|
+
if (status === 500) return "Internal Server Error";
|
|
75834
|
+
return "";
|
|
75835
|
+
}
|
|
75509
75836
|
function cloneNetworkRequest(request) {
|
|
75510
75837
|
return {
|
|
75511
75838
|
...request,
|
|
@@ -75584,6 +75911,7 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
75584
75911
|
pageConsoleStates = /* @__PURE__ */ new Map();
|
|
75585
75912
|
pageNetworkStates = /* @__PURE__ */ new Map();
|
|
75586
75913
|
pageDialogStates = /* @__PURE__ */ new Map();
|
|
75914
|
+
dialogWaiters = /* @__PURE__ */ new Map();
|
|
75587
75915
|
bidiListeners = /* @__PURE__ */ new Map();
|
|
75588
75916
|
responseDataCollector;
|
|
75589
75917
|
activeTabId;
|
|
@@ -75602,7 +75930,7 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
75602
75930
|
const session = new BidiConnectedBrowserSession(client);
|
|
75603
75931
|
session.ownsSession = await ensureMcpBiDiSession(client, args.endpoint, args.sessionId);
|
|
75604
75932
|
await session.initialize();
|
|
75605
|
-
|
|
75933
|
+
await session.refreshTabs();
|
|
75606
75934
|
return session;
|
|
75607
75935
|
}
|
|
75608
75936
|
async version() {
|
|
@@ -75645,10 +75973,13 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
75645
75973
|
}
|
|
75646
75974
|
async snapshot(request = {}) {
|
|
75647
75975
|
const tabId = await this.getActiveTabId();
|
|
75648
|
-
return
|
|
75649
|
-
|
|
75650
|
-
|
|
75651
|
-
|
|
75976
|
+
return {
|
|
75977
|
+
...toBrowserSnapshot(await retryUntilReady(() => evaluateBiDi(this.client, tabId, PLAYWRIGHT_ARIA_SNAPSHOT_EVALUATE_SOURCE, toAriaSnapshotPayload(request))), request, {
|
|
75978
|
+
console: this.consoleSummary(tabId),
|
|
75979
|
+
consoleLink: await this.takeConsoleLink(tabId)
|
|
75980
|
+
}),
|
|
75981
|
+
retryable: true
|
|
75982
|
+
};
|
|
75652
75983
|
}
|
|
75653
75984
|
async consoleMessages(level = "info", all = false) {
|
|
75654
75985
|
const activeTabId = await this.getActiveTabId();
|
|
@@ -76055,7 +76386,7 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76055
76386
|
}
|
|
76056
76387
|
}
|
|
76057
76388
|
async handleDialog(accept, promptText) {
|
|
76058
|
-
const tabId =
|
|
76389
|
+
const tabId = this.dialogTabId();
|
|
76059
76390
|
if (!this.pageDialogStates.has(tabId)) throw new McpToolError("no_dialog", "No dialog visible.");
|
|
76060
76391
|
this.pageDialogStates.delete(tabId);
|
|
76061
76392
|
await this.client.browsingContextHandleUserPrompt({
|
|
@@ -76064,6 +76395,9 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76064
76395
|
...promptText !== void 0 ? { userText: promptText } : {}
|
|
76065
76396
|
});
|
|
76066
76397
|
}
|
|
76398
|
+
async hasDialog() {
|
|
76399
|
+
return this.pageDialogStates.size > 0;
|
|
76400
|
+
}
|
|
76067
76401
|
async networkRequests() {
|
|
76068
76402
|
const tabId = await this.getActiveTabId();
|
|
76069
76403
|
return this.ensureNetworkState(tabId).requests.map(cloneNetworkRequest);
|
|
@@ -76073,6 +76407,15 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76073
76407
|
const request = this.ensureNetworkState(tabId).requests[index - 1];
|
|
76074
76408
|
return request ? cloneNetworkRequest(request) : void 0;
|
|
76075
76409
|
}
|
|
76410
|
+
async fetchResponseBody(index) {
|
|
76411
|
+
const tabId = await this.getActiveTabId();
|
|
76412
|
+
const request = this.ensureNetworkState(tabId).requests[index - 1];
|
|
76413
|
+
if (!request || !request.requestId) return request?.responseBody;
|
|
76414
|
+
if (request.responseBody !== void 0) return request.responseBody;
|
|
76415
|
+
const body = await this.getResponseBody(request.requestId).catch(() => void 0);
|
|
76416
|
+
if (body !== void 0) request.responseBody = body;
|
|
76417
|
+
return request.responseBody;
|
|
76418
|
+
}
|
|
76076
76419
|
async runCodeUnsafe(code) {
|
|
76077
76420
|
return this.evaluate(`async () => {
|
|
76078
76421
|
const fn = eval(${JSON.stringify(`(${code})`)});
|
|
@@ -76136,6 +76479,45 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76136
76479
|
targetArg(target) {
|
|
76137
76480
|
return "nodeToken" in target ? { nodeToken: target.nodeToken } : { selector: target.selector };
|
|
76138
76481
|
}
|
|
76482
|
+
dialogTabId() {
|
|
76483
|
+
if (this.activeTabId && this.pageDialogStates.has(this.activeTabId)) return this.activeTabId;
|
|
76484
|
+
const tabId = this.pageDialogStates.keys().next().value;
|
|
76485
|
+
if (!tabId) throw new McpToolError("no_dialog", "No dialog visible.");
|
|
76486
|
+
return tabId;
|
|
76487
|
+
}
|
|
76488
|
+
waitForDialog(tabId, timeoutMs) {
|
|
76489
|
+
if (this.pageDialogStates.has(tabId)) return Promise.resolve();
|
|
76490
|
+
return new Promise((resolve, reject) => {
|
|
76491
|
+
const waiter = {
|
|
76492
|
+
resolve: () => {
|
|
76493
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
76494
|
+
this.removeDialogWaiter(tabId, waiter);
|
|
76495
|
+
resolve();
|
|
76496
|
+
},
|
|
76497
|
+
reject: (error) => {
|
|
76498
|
+
if (waiter.timer) clearTimeout(waiter.timer);
|
|
76499
|
+
this.removeDialogWaiter(tabId, waiter);
|
|
76500
|
+
reject(error);
|
|
76501
|
+
}
|
|
76502
|
+
};
|
|
76503
|
+
waiter.timer = setTimeout(() => waiter.reject?.(/* @__PURE__ */ new Error("Timed out waiting for dialog.")), timeoutMs);
|
|
76504
|
+
const waiters = this.dialogWaiters.get(tabId) ?? /* @__PURE__ */ new Set();
|
|
76505
|
+
waiters.add(waiter);
|
|
76506
|
+
this.dialogWaiters.set(tabId, waiters);
|
|
76507
|
+
});
|
|
76508
|
+
}
|
|
76509
|
+
resolveDialogWaiters(tabId) {
|
|
76510
|
+
const waiters = this.dialogWaiters.get(tabId);
|
|
76511
|
+
if (!waiters) return;
|
|
76512
|
+
this.dialogWaiters.delete(tabId);
|
|
76513
|
+
for (const waiter of waiters) waiter.resolve();
|
|
76514
|
+
}
|
|
76515
|
+
removeDialogWaiter(tabId, waiter) {
|
|
76516
|
+
const waiters = this.dialogWaiters.get(tabId);
|
|
76517
|
+
if (!waiters) return;
|
|
76518
|
+
waiters.delete(waiter);
|
|
76519
|
+
if (waiters.size === 0) this.dialogWaiters.delete(tabId);
|
|
76520
|
+
}
|
|
76139
76521
|
async actionPoint(tabId, target) {
|
|
76140
76522
|
const source = "nodeToken" in target ? ACTION_POINT_EVALUATE_SOURCE : ACTION_POINT_BY_SELECTOR_SOURCE;
|
|
76141
76523
|
const point = await evaluateBiDi(this.client, tabId, source, this.targetArg(target));
|
|
@@ -76294,7 +76676,10 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76294
76676
|
state = {
|
|
76295
76677
|
requests: [],
|
|
76296
76678
|
byRequestId: /* @__PURE__ */ new Map(),
|
|
76297
|
-
startedAt: /* @__PURE__ */ new Map()
|
|
76679
|
+
startedAt: /* @__PURE__ */ new Map(),
|
|
76680
|
+
hydratedPerformanceResources: false,
|
|
76681
|
+
loadingDone: /* @__PURE__ */ new Map(),
|
|
76682
|
+
bodyRead: /* @__PURE__ */ new Set()
|
|
76298
76683
|
};
|
|
76299
76684
|
this.pageNetworkStates.set(tabId, state);
|
|
76300
76685
|
}
|
|
@@ -76310,7 +76695,10 @@ var BidiConnectedBrowserSession = class BidiConnectedBrowserSession {
|
|
|
76310
76695
|
this.pageNetworkStates.set(tabId, {
|
|
76311
76696
|
requests: [],
|
|
76312
76697
|
byRequestId: /* @__PURE__ */ new Map(),
|
|
76313
|
-
startedAt: /* @__PURE__ */ new Map()
|
|
76698
|
+
startedAt: /* @__PURE__ */ new Map(),
|
|
76699
|
+
hydratedPerformanceResources: false,
|
|
76700
|
+
loadingDone: /* @__PURE__ */ new Map(),
|
|
76701
|
+
bodyRead: /* @__PURE__ */ new Set()
|
|
76314
76702
|
});
|
|
76315
76703
|
this.pageDialogStates.delete(tabId);
|
|
76316
76704
|
}
|
|
@@ -76519,7 +76907,7 @@ var McpRuntime = class {
|
|
|
76519
76907
|
snapshot
|
|
76520
76908
|
};
|
|
76521
76909
|
lastAttempt = captured;
|
|
76522
|
-
if (snapshot.text.trim().length > 0 || currentActiveTab.url === "about:blank") return captured;
|
|
76910
|
+
if (!snapshot.retryable || snapshot.text.trim().length > 0 || currentActiveTab.url === "about:blank") return captured;
|
|
76523
76911
|
await delay(150 * (attempt + 1));
|
|
76524
76912
|
}
|
|
76525
76913
|
if (!lastAttempt) throw new McpToolError("action_failed", "Unable to capture page snapshot.");
|
|
@@ -76542,6 +76930,7 @@ var McpRuntime = class {
|
|
|
76542
76930
|
this.invalidateSnapshot();
|
|
76543
76931
|
this.pendingFileUploadTarget = opensFileChooser ? resolved : void 0;
|
|
76544
76932
|
if (this.snapshotMode === "none") return;
|
|
76933
|
+
if (await session.hasDialog()) return;
|
|
76545
76934
|
return this.snapshot();
|
|
76546
76935
|
}
|
|
76547
76936
|
async hover(target) {
|
|
@@ -76551,13 +76940,16 @@ var McpRuntime = class {
|
|
|
76551
76940
|
this.invalidateSnapshot();
|
|
76552
76941
|
this.pendingFileUploadTarget = void 0;
|
|
76553
76942
|
if (this.snapshotMode === "none") return;
|
|
76943
|
+
if (await session.hasDialog()) return;
|
|
76554
76944
|
return this.snapshot();
|
|
76555
76945
|
}
|
|
76556
76946
|
async navigate(url) {
|
|
76557
|
-
|
|
76947
|
+
const session = this.requireConnected();
|
|
76948
|
+
await session.navigate(normalizeNavigationUrl(url));
|
|
76558
76949
|
this.invalidateSnapshot();
|
|
76559
76950
|
this.pendingFileUploadTarget = void 0;
|
|
76560
76951
|
if (this.snapshotMode === "none") return;
|
|
76952
|
+
if (await session.hasDialog()) return;
|
|
76561
76953
|
return this.snapshot();
|
|
76562
76954
|
}
|
|
76563
76955
|
async type(ref, text, opts) {
|
|
@@ -76706,6 +77098,9 @@ var McpRuntime = class {
|
|
|
76706
77098
|
async networkRequest(index) {
|
|
76707
77099
|
return this.requireConnected().networkRequest(index);
|
|
76708
77100
|
}
|
|
77101
|
+
async fetchResponseBody(index) {
|
|
77102
|
+
return this.requireConnected().fetchResponseBody(index);
|
|
77103
|
+
}
|
|
76709
77104
|
async runCodeUnsafe(code) {
|
|
76710
77105
|
const result = await this.requireConnected().runCodeUnsafe(code);
|
|
76711
77106
|
this.invalidateSnapshot();
|
|
@@ -76742,6 +77137,10 @@ var McpRuntime = class {
|
|
|
76742
77137
|
hasPendingFileUploadTarget() {
|
|
76743
77138
|
return !!this.pendingFileUploadTarget;
|
|
76744
77139
|
}
|
|
77140
|
+
async hasDialog() {
|
|
77141
|
+
if (!this.connection) return false;
|
|
77142
|
+
return this.connection.session.hasDialog();
|
|
77143
|
+
}
|
|
76745
77144
|
async close() {
|
|
76746
77145
|
this.invalidateSnapshot();
|
|
76747
77146
|
this.pendingFileUploadTarget = void 0;
|