dsh-browser-playwright-codex 0.5.1 → 0.5.3
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/CHANGELOG.md +54 -1
- package/lib/browser-lifecycle.d.ts +12 -0
- package/lib/browser-lifecycle.js +186 -0
- package/lib/challenge.d.ts +20 -0
- package/lib/challenge.js +40 -0
- package/lib/config.d.ts +81 -0
- package/lib/config.js +61 -0
- package/lib/extract.d.ts +13 -0
- package/lib/extract.js +34 -0
- package/lib/index.d.ts +4 -2
- package/lib/index.js +3 -1
- package/lib/login-state.d.ts +10 -0
- package/lib/login-state.js +83 -0
- package/lib/page-actions.d.ts +134 -0
- package/lib/page-actions.js +725 -0
- package/lib/page-diagnostics.d.ts +65 -0
- package/lib/page-diagnostics.js +181 -0
- package/lib/page-probes.d.ts +78 -0
- package/lib/page-probes.js +281 -0
- package/lib/page-snapshot.d.ts +96 -0
- package/lib/page-snapshot.js +280 -0
- package/lib/playwright.d.ts +5 -636
- package/lib/playwright.js +28 -2494
- package/lib/provider.d.ts +157 -0
- package/lib/provider.js +352 -0
- package/lib/session.d.ts +410 -0
- package/lib/session.js +633 -0
- package/lib/tool-render.d.ts +20 -0
- package/lib/tool-render.js +137 -0
- package/lib/tool-schemas.d.ts +76 -0
- package/lib/tool-schemas.js +46 -0
- package/lib/tool-types.d.ts +82 -0
- package/lib/tool-types.js +1 -0
- package/lib/tool.d.ts +2 -26
- package/lib/tool.js +5 -252
- package/lib/url-policy.d.ts +2 -0
- package/lib/url-policy.js +26 -0
- package/lib/window-focus.d.ts +27 -0
- package/lib/window-focus.js +54 -0
- package/package.json +4 -4
- package/scripts/dsh-browser-verify.mjs +2 -1
- package/scripts/prompt-cost.mjs +1 -1
package/lib/session.d.ts
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一次浏览器会话:持有 page/context、处理弹窗、截图、页面数据、evaluate/CDP 等交互,并把
|
|
3
|
+
* 动作、快照、诊断三块转发给对应模块(page-actions / page-snapshot / page-diagnostics)。
|
|
4
|
+
* @module dsh-browser-playwright-codex/session
|
|
5
|
+
*/
|
|
6
|
+
import type { BrowserContext, CDPSession, Locator, Page, Request } from 'playwright-core';
|
|
7
|
+
import type { PlaywrightProvider } from './provider.ts';
|
|
8
|
+
import type { BrowserNode, BrowserSnapshot, DiagnosticsEntry, LoadState } from './types.ts';
|
|
9
|
+
import type { RefSignature } from './page-snapshot.ts';
|
|
10
|
+
import type { ActionResult, PendingDialogRecord } from './provider.ts';
|
|
11
|
+
/** Live session over one browser context owned by one caller. */
|
|
12
|
+
export declare class PlaywrightSession {
|
|
13
|
+
provider: PlaywrightProvider;
|
|
14
|
+
owner: string;
|
|
15
|
+
context: BrowserContext;
|
|
16
|
+
currentIndex: number;
|
|
17
|
+
closed: boolean;
|
|
18
|
+
/** Set while answering a dialog or reporting it: page access must not be refused then. */
|
|
19
|
+
bypassDialogGuard: boolean;
|
|
20
|
+
/** Reused CDP session for the current page (DOM nodeIds are session-bound). */
|
|
21
|
+
cdpSession: CDPSession | undefined;
|
|
22
|
+
/** The page the cached CDP session is attached to. */
|
|
23
|
+
cdpPage: Page | undefined;
|
|
24
|
+
/** Pages already wired for console/network capture (WeakSet: pages stay collectable). */
|
|
25
|
+
trackedPages: WeakSet<Page>;
|
|
26
|
+
/** Stable id per page, so diagnostics can be reported for one page only. */
|
|
27
|
+
pageIds: WeakMap<Page, number>;
|
|
28
|
+
/** Ids handed out so far (monotonic within the session). */
|
|
29
|
+
pageIdSeq: number;
|
|
30
|
+
/** Bounded console + pageerror ring, shared by every tracked page of this session. */
|
|
31
|
+
consoleLog: DiagnosticsEntry[];
|
|
32
|
+
/** Bounded network ring, shared by every tracked page of this session. */
|
|
33
|
+
networkLog: DiagnosticsEntry[];
|
|
34
|
+
/** Monotonic sequence handed to each captured entry. */
|
|
35
|
+
diagSeq: number;
|
|
36
|
+
/** Evicted entries, so truncation is visible instead of silent. */
|
|
37
|
+
diagDropped: {
|
|
38
|
+
console: number;
|
|
39
|
+
network: number;
|
|
40
|
+
};
|
|
41
|
+
/** In-flight requests keyed by request object, for status and duration attribution. */
|
|
42
|
+
requestEntries: WeakMap<Request, {
|
|
43
|
+
entry: DiagnosticsEntry;
|
|
44
|
+
startedAt: number;
|
|
45
|
+
}>;
|
|
46
|
+
/** Ring capacity per stream. */
|
|
47
|
+
diagLimit: number;
|
|
48
|
+
/** ref -> feature signature of the previous capture (diff baseline). */
|
|
49
|
+
lastRefSignatures: Map<string, RefSignature> | undefined;
|
|
50
|
+
/** Nonce of the baseline ref space; a change means navigation reset. */
|
|
51
|
+
lastRefNonce: string | undefined;
|
|
52
|
+
constructor(provider: PlaywrightProvider, owner: string, context: BrowserContext);
|
|
53
|
+
/** Run one operation under busy tracking: idle disposal defers until it settles. */
|
|
54
|
+
run<T>(operation: () => Promise<T>): Promise<T>;
|
|
55
|
+
/** Fast actionability pre-check (visible/enabled/editable) before an action. */
|
|
56
|
+
assertActionable(locator: Locator, options?: {
|
|
57
|
+
editable?: boolean;
|
|
58
|
+
}): Promise<void>;
|
|
59
|
+
/** Wait for an in-flight navigation (started by a click) to settle. */
|
|
60
|
+
settleNavigation(page: Page): Promise<void>;
|
|
61
|
+
/** Page-level render stability, bounded — a busy page never stalls the agent. */
|
|
62
|
+
waitForPageStable(page: Page, timeoutMs?: number): Promise<void>;
|
|
63
|
+
/** Element-level stability before a pointer/keyboard action, bounded. Returns true when stable. */
|
|
64
|
+
waitForElementStable(locator: Locator): Promise<boolean>;
|
|
65
|
+
/** Post-action settle: wait out a real navigation, then render-stabilize before snapshotting. */
|
|
66
|
+
settleAndSnapshot(page: Page, navChanged: boolean): Promise<BrowserSnapshot>;
|
|
67
|
+
/**
|
|
68
|
+
* Snapshot substitute while a native dialog blocks the page: only locally
|
|
69
|
+
* cached data (page.url() needs no round trip) — page.evaluate() and
|
|
70
|
+
* page.title() would both stall behind the dialog.
|
|
71
|
+
*/
|
|
72
|
+
blockedSnapshot(page: Page, pending: PendingDialogRecord | undefined): {
|
|
73
|
+
url: string;
|
|
74
|
+
title: string;
|
|
75
|
+
nodes: never[];
|
|
76
|
+
totalRefs: number;
|
|
77
|
+
truncated: boolean;
|
|
78
|
+
dialogNote: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Run one page action that may raise a native dialog. Such an action never
|
|
82
|
+
* resolves while the dialog is up, so race it against the dialog appearing
|
|
83
|
+
* and hand the caller the pending state instead (Playwright-MCP pattern).
|
|
84
|
+
*/
|
|
85
|
+
runAction(page: Page, action: () => Promise<unknown>): Promise<ActionResult>;
|
|
86
|
+
/**
|
|
87
|
+
* Answer the pending native dialog and let the action blocked behind it
|
|
88
|
+
* finish. This is the only place a dialog is ever accepted or dismissed.
|
|
89
|
+
*/
|
|
90
|
+
resolveDialog(accept: boolean, promptText: string | undefined, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
91
|
+
/** Read the snapshot tree from one page (must run inside a run()). */
|
|
92
|
+
capture(page: Page, opts: {
|
|
93
|
+
interactiveOnly?: boolean;
|
|
94
|
+
} | undefined): Promise<BrowserSnapshot>;
|
|
95
|
+
/**
|
|
96
|
+
* Semantic-tree capture via Playwright's official ariaSnapshot(mode:'ai').
|
|
97
|
+
* An unavailable or unreadable aria tree (`missing`) degrades to the legacy
|
|
98
|
+
* DOM walker instead of returning an empty snapshot: the model must never
|
|
99
|
+
* receive "the page has no elements" because the engine failed to parse.
|
|
100
|
+
*/
|
|
101
|
+
captureAria(page: Page, opts: {
|
|
102
|
+
interactiveOnly?: boolean;
|
|
103
|
+
} | undefined): Promise<{
|
|
104
|
+
engineNote: string;
|
|
105
|
+
url: string;
|
|
106
|
+
title: string;
|
|
107
|
+
nodes: BrowserNode[];
|
|
108
|
+
totalRefs: number;
|
|
109
|
+
truncated: boolean;
|
|
110
|
+
} | {
|
|
111
|
+
url: string;
|
|
112
|
+
title: string;
|
|
113
|
+
nodes: BrowserNode[];
|
|
114
|
+
totalRefs: number;
|
|
115
|
+
truncated: boolean;
|
|
116
|
+
}>;
|
|
117
|
+
/** Legacy capture: injected DOM walker (default engine, byte-identical output). */
|
|
118
|
+
captureLegacy(page: Page, opts: {
|
|
119
|
+
interactiveOnly?: boolean;
|
|
120
|
+
} | undefined): Promise<{
|
|
121
|
+
url: string;
|
|
122
|
+
title: string;
|
|
123
|
+
nodes: BrowserNode[];
|
|
124
|
+
totalRefs: number;
|
|
125
|
+
truncated: boolean;
|
|
126
|
+
}>;
|
|
127
|
+
/**
|
|
128
|
+
* Attach an incremental diff when snapshot.diff is enabled. Absence of the
|
|
129
|
+
* diff field means "full snapshot follows": first capture of the session,
|
|
130
|
+
* navigation reset, or a truncated tree. The diff is keyed by the stable
|
|
131
|
+
* data-dsh-ref, so legacy and aria engines share the same contract.
|
|
132
|
+
*/
|
|
133
|
+
attachDiff(snap: BrowserSnapshot): BrowserSnapshot;
|
|
134
|
+
/** Build ref -> feature signature map from a captured tree, with parent refs. */
|
|
135
|
+
buildRefSignatures(nodes: readonly BrowserNode[]): Map<string, RefSignature>;
|
|
136
|
+
/** The document nonce shared by this snapshot's refs, or undefined. */
|
|
137
|
+
refNonce(nodes: readonly BrowserNode[]): string | undefined;
|
|
138
|
+
navigate(url: string, waitUntil: LoadState, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
139
|
+
url: string;
|
|
140
|
+
title: string;
|
|
141
|
+
nodes: never[];
|
|
142
|
+
totalRefs: number;
|
|
143
|
+
truncated: boolean;
|
|
144
|
+
dialogNote: string;
|
|
145
|
+
}>;
|
|
146
|
+
snapshot(opts?: {
|
|
147
|
+
interactiveOnly?: boolean;
|
|
148
|
+
}): Promise<BrowserSnapshot | {
|
|
149
|
+
url: string;
|
|
150
|
+
title: string;
|
|
151
|
+
nodes: never[];
|
|
152
|
+
totalRefs: number;
|
|
153
|
+
truncated: boolean;
|
|
154
|
+
dialogNote: string;
|
|
155
|
+
}>;
|
|
156
|
+
/**
|
|
157
|
+
* Codex-style click-point resolution. Tries a scroll-alignment ladder
|
|
158
|
+
* (centre, then end, then start). For each alignment: scroll the element
|
|
159
|
+
* into view with a native scrollIntoView, wait for its bounding rect to
|
|
160
|
+
* stop moving, sample the rect centre in-page (sub-pixel, no screenshot
|
|
161
|
+
* measurement), then hit-test that exact point with elementFromPoint — so
|
|
162
|
+
* an overlaying element can never swallow the click silently. Returns the
|
|
163
|
+
* first unobstructed {x, y}, or throws describing what intercepted it.
|
|
164
|
+
*/
|
|
165
|
+
resolveClickPoint(locator: Locator, signal: AbortSignal | undefined): Promise<{
|
|
166
|
+
x: number;
|
|
167
|
+
y: number;
|
|
168
|
+
hitDesc: string;
|
|
169
|
+
hitSelf: boolean;
|
|
170
|
+
}>;
|
|
171
|
+
click(ref: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
172
|
+
url: string;
|
|
173
|
+
title: string;
|
|
174
|
+
nodes: never[];
|
|
175
|
+
totalRefs: number;
|
|
176
|
+
truncated: boolean;
|
|
177
|
+
dialogNote: string;
|
|
178
|
+
}>;
|
|
179
|
+
/**
|
|
180
|
+
* Click an element the snapshot gave no ref, addressed by its visible label
|
|
181
|
+
* (e.g. a menu item revealed by browser_hover that is plain text). The
|
|
182
|
+
* label must equal an element's own direct text; the deepest match wins,
|
|
183
|
+
* and the landing note names what was actually clicked plus how many
|
|
184
|
+
* elements shared the label.
|
|
185
|
+
*/
|
|
186
|
+
clickText(text: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
187
|
+
url: string;
|
|
188
|
+
title: string;
|
|
189
|
+
nodes: never[];
|
|
190
|
+
totalRefs: number;
|
|
191
|
+
truncated: boolean;
|
|
192
|
+
dialogNote: string;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Enforce the navigation policy for the link a click is about to follow.
|
|
196
|
+
* Click navigation does not run through navigate(), so this is the only place
|
|
197
|
+
* the rule lives and every click path (ref, text, geometric ref, raw x/y)
|
|
198
|
+
* calls it — a new path cannot quietly skip the allow-list.
|
|
199
|
+
*
|
|
200
|
+
* The policy is about which HOSTS this browser may visit, so it applies to
|
|
201
|
+
* http(s) destinations. An in-page `javascript:` link runs the page's own
|
|
202
|
+
* code without navigating anywhere and is allowed (refusing it made ordinary
|
|
203
|
+
* JS links unclickable); every other scheme — file:, data:, mailto:, tel:,
|
|
204
|
+
* custom ones — stays refused.
|
|
205
|
+
*/
|
|
206
|
+
assertClickTargetAllowed(href: string | null): void;
|
|
207
|
+
/**
|
|
208
|
+
* Enforce the host policy on a tab before this session starts driving it. A
|
|
209
|
+
* page can open a tab by itself (`target="_blank"`, `window.open`) and the
|
|
210
|
+
* plugin never sees that navigation, so the policy is applied at the point of
|
|
211
|
+
* use instead: a tab outside the allow-list stays open — the user may well be
|
|
212
|
+
* using it — but this agent refuses to switch to it.
|
|
213
|
+
*
|
|
214
|
+
* http(s) is checked against allowedDomains; `about:blank` is allowed because
|
|
215
|
+
* it is the plugin's own interim state and has no host; every other scheme
|
|
216
|
+
* (file:, data:, chrome:, devtools:) is refused outright.
|
|
217
|
+
*/
|
|
218
|
+
assertTabAllowed(page: Page): void;
|
|
219
|
+
/**
|
|
220
|
+
* Shared click core: enforce the URL policy for link targets, run the
|
|
221
|
+
* Codex-style geometry ladder with the Playwright actionability fallback,
|
|
222
|
+
* then report what actually received the click. The label names the target
|
|
223
|
+
* in the landing note; shared is how many elements matched it (0 for refs).
|
|
224
|
+
*/
|
|
225
|
+
clickLocator(locator: Locator, signal: AbortSignal | undefined, label: string, shared: number): Promise<BrowserSnapshot | {
|
|
226
|
+
url: string;
|
|
227
|
+
title: string;
|
|
228
|
+
nodes: never[];
|
|
229
|
+
totalRefs: number;
|
|
230
|
+
truncated: boolean;
|
|
231
|
+
dialogNote: string;
|
|
232
|
+
}>;
|
|
233
|
+
clickAt(x: number, y: number, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
234
|
+
url: string;
|
|
235
|
+
title: string;
|
|
236
|
+
nodes: never[];
|
|
237
|
+
totalRefs: number;
|
|
238
|
+
truncated: boolean;
|
|
239
|
+
dialogNote: string;
|
|
240
|
+
}>;
|
|
241
|
+
clickAtRef(ref: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
242
|
+
url: string;
|
|
243
|
+
title: string;
|
|
244
|
+
nodes: never[];
|
|
245
|
+
totalRefs: number;
|
|
246
|
+
truncated: boolean;
|
|
247
|
+
dialogNote: string;
|
|
248
|
+
}>;
|
|
249
|
+
fill(ref: string, text: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
250
|
+
/** Read the field back and decide whether the fill landed. */
|
|
251
|
+
verifyFill(locator: Locator, tag: string, text: string): Promise<boolean>;
|
|
252
|
+
press(ref: string, key: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
253
|
+
url: string;
|
|
254
|
+
title: string;
|
|
255
|
+
nodes: never[];
|
|
256
|
+
totalRefs: number;
|
|
257
|
+
truncated: boolean;
|
|
258
|
+
dialogNote: string;
|
|
259
|
+
}>;
|
|
260
|
+
/**
|
|
261
|
+
* Hover the referenced element: rest the pointer on it so hover-revealed
|
|
262
|
+
* content appears (CSS :hover rules, JS mouseenter handlers, submenus,
|
|
263
|
+
* tooltips, chart values, player controls). Hover never activates
|
|
264
|
+
* anything: it only reveals. The ref count before and after the pointer
|
|
265
|
+
* moves is the only cheap proof that something appeared, so the returned
|
|
266
|
+
* snapshot carries a note comparing them.
|
|
267
|
+
*/
|
|
268
|
+
hover(ref: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
269
|
+
/**
|
|
270
|
+
* Hover a trigger the snapshot gave no ref, addressed by its visible label
|
|
271
|
+
* (e.g. a plain span that reveals a menu on mouseenter). The label must
|
|
272
|
+
* equal an element's own direct text; the deepest match wins, and the
|
|
273
|
+
* landing note names what was hovered plus how many elements shared it.
|
|
274
|
+
*/
|
|
275
|
+
hoverText(text: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
276
|
+
/**
|
|
277
|
+
* Shared hover core: rest the pointer on a resolved locator, then report
|
|
278
|
+
* what the actionable ref count did. The label names the target in the
|
|
279
|
+
* landing note; shared is how many elements matched that label (0 when the
|
|
280
|
+
* target came from a ref).
|
|
281
|
+
*/
|
|
282
|
+
hoverLocator(locator: Locator, signal: AbortSignal | undefined, label: string, shared: number): Promise<BrowserSnapshot>;
|
|
283
|
+
scroll(direction: 'up' | 'down', amount: number, ref: string, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
284
|
+
back(signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
285
|
+
forward(signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
286
|
+
wait(ms: number, signal: AbortSignal | undefined): Promise<void>;
|
|
287
|
+
tabs(): Promise<{
|
|
288
|
+
index: number;
|
|
289
|
+
url: string;
|
|
290
|
+
title: string;
|
|
291
|
+
active: boolean;
|
|
292
|
+
}[]>;
|
|
293
|
+
switchTab(index: number, signal: AbortSignal | undefined): Promise<BrowserSnapshot | {
|
|
294
|
+
url: string;
|
|
295
|
+
title: string;
|
|
296
|
+
nodes: never[];
|
|
297
|
+
totalRefs: number;
|
|
298
|
+
truncated: boolean;
|
|
299
|
+
dialogNote: string;
|
|
300
|
+
}>;
|
|
301
|
+
openTab(url: string, waitUntil: LoadState, signal: AbortSignal | undefined): Promise<BrowserSnapshot>;
|
|
302
|
+
closeTab(index: number, signal: AbortSignal | undefined): Promise<void>;
|
|
303
|
+
/**
|
|
304
|
+
* Screenshots get their own floor instead of reusing the navigation budget: a
|
|
305
|
+
* full-page capture is sized by the page and encoded by the CPU, so a loaded machine
|
|
306
|
+
* legitimately needs seconds (2026-10-05: the Windows runner blew through the then-2500ms
|
|
307
|
+
* navigation-timeout budget while encoding a full-page PNG — a slow runner, not a defect).
|
|
308
|
+
* The floor only bounds failures; a capture that is ready returns immediately.
|
|
309
|
+
*/
|
|
310
|
+
screenshotTimeoutMs(): number;
|
|
311
|
+
screenshot(opts: {
|
|
312
|
+
fullPage?: boolean;
|
|
313
|
+
ref?: string;
|
|
314
|
+
} | undefined, signal: AbortSignal | undefined): Promise<{
|
|
315
|
+
mime: "image/png";
|
|
316
|
+
bytes: Buffer<ArrayBufferLike>;
|
|
317
|
+
}>;
|
|
318
|
+
pageData(): Promise<unknown>;
|
|
319
|
+
evaluate(expression: string, signal: AbortSignal | undefined): Promise<unknown>;
|
|
320
|
+
/**
|
|
321
|
+
* Send one raw CDP command on the current page's session and return its
|
|
322
|
+
* result. This is the "direct protocol" escape hatch behind every other
|
|
323
|
+
* tool — the model can inspect geometry, dispatch trusted input events or
|
|
324
|
+
* query the DOM the same way Chrome DevTools does. Policy (which methods
|
|
325
|
+
* are allowed) lives in the tool layer via lib/cdp-policy.js; this method
|
|
326
|
+
* itself performs no filtering so internal callers keep full control.
|
|
327
|
+
*/
|
|
328
|
+
cdp(method: string, params: Record<string, unknown>, signal: AbortSignal | undefined): Promise<unknown>;
|
|
329
|
+
close(): Promise<void>;
|
|
330
|
+
timeoutMs(): number;
|
|
331
|
+
ensurePage(): Promise<Page>;
|
|
332
|
+
/**
|
|
333
|
+
* Wire bounded console/network capture onto one page, exactly once. Capture is
|
|
334
|
+
* best-effort observation for the model: it must never throw into a page that is
|
|
335
|
+
* otherwise healthy, and it must never grow without a bound.
|
|
336
|
+
*/
|
|
337
|
+
trackPage(page: Page): void;
|
|
338
|
+
/** Stable id for one page of this session (used to scope diagnostics). */
|
|
339
|
+
pageIdFor(page: Page): number;
|
|
340
|
+
/** Id of the page this session is driving, or undefined when there is none. */
|
|
341
|
+
currentPageId(): number | undefined;
|
|
342
|
+
/**
|
|
343
|
+
* Split diagnostics into "the page this session is driving" and "everything
|
|
344
|
+
* else". The rings keep every page's entries so chronology and eviction stay
|
|
345
|
+
* honest, but a reader that promises one tab must not serve another tab's
|
|
346
|
+
* lines: that is how a model diagnoses an error that belongs to a page it is
|
|
347
|
+
* not even looking at.
|
|
348
|
+
*/
|
|
349
|
+
scopeToCurrentPage(entries: readonly DiagnosticsEntry[]): {
|
|
350
|
+
kept: DiagnosticsEntry[];
|
|
351
|
+
otherPages: number;
|
|
352
|
+
};
|
|
353
|
+
/** URL of the tab this session is driving right now, or null. */
|
|
354
|
+
currentUrl(): string | null;
|
|
355
|
+
/** Recent console messages and uncaught page errors, newest last. */
|
|
356
|
+
consoleMessages(args: {
|
|
357
|
+
level?: string;
|
|
358
|
+
limit?: number;
|
|
359
|
+
}): {
|
|
360
|
+
url: string | null;
|
|
361
|
+
level: string;
|
|
362
|
+
total: number;
|
|
363
|
+
returned: number;
|
|
364
|
+
dropped: number;
|
|
365
|
+
otherPages: number;
|
|
366
|
+
note: string;
|
|
367
|
+
entries: {
|
|
368
|
+
n: number;
|
|
369
|
+
level: string | undefined;
|
|
370
|
+
text: string;
|
|
371
|
+
source: string;
|
|
372
|
+
}[];
|
|
373
|
+
};
|
|
374
|
+
/** Recent network requests, newest last, with status and duration where known. */
|
|
375
|
+
networkRequests(args: {
|
|
376
|
+
urlContains?: string;
|
|
377
|
+
failedOnly?: boolean;
|
|
378
|
+
limit?: number;
|
|
379
|
+
}): {
|
|
380
|
+
url: string | null;
|
|
381
|
+
total: number;
|
|
382
|
+
returned: number;
|
|
383
|
+
dropped: number;
|
|
384
|
+
otherPages: number;
|
|
385
|
+
note: string;
|
|
386
|
+
entries: {
|
|
387
|
+
n: number;
|
|
388
|
+
method: string | undefined;
|
|
389
|
+
url: string;
|
|
390
|
+
status: number | null | undefined;
|
|
391
|
+
kind: string | undefined;
|
|
392
|
+
ms: number | null | undefined;
|
|
393
|
+
failure: string | null | undefined;
|
|
394
|
+
}[];
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* Refuse page access while a native dialog blocks the page: every call
|
|
398
|
+
* would otherwise stall until the action timeout. Only browser_dialog and
|
|
399
|
+
* the blocked-snapshot report are allowed through (DIALOG-POLICY.md).
|
|
400
|
+
*/
|
|
401
|
+
guardBlockedDialog(page: Page): void;
|
|
402
|
+
/** Refuse context-wide tab work while any page in it has a parked dialog. */
|
|
403
|
+
guardBlockedContext(): void;
|
|
404
|
+
/** Run one internal step with the dialog guard lifted. */
|
|
405
|
+
withDialogGuardLifted<T>(fn: () => Promise<T>): Promise<T>;
|
|
406
|
+
pageAt(index: number): Page | undefined;
|
|
407
|
+
refLocator(ref: string): Promise<Locator>;
|
|
408
|
+
currentPageSync(): Page;
|
|
409
|
+
assertLive(): void;
|
|
410
|
+
}
|