@@ -23,7 +23,6 @@ import type {
2323 BrowserContext ,
2424 ConsoleMessage ,
2525 Debugger ,
26- ElementHandle ,
2726 HTTPRequest ,
2827 Page ,
2928 ScreenRecorder ,
@@ -34,7 +33,6 @@ import type {
3433import { Locator } from './third_party/index.js' ;
3534import { PredefinedNetworkConditions } from './third_party/index.js' ;
3635import { listPages } from './tools/pages.js' ;
37- import { takeSnapshot } from './tools/snapshot.js' ;
3836import { CLOSE_PAGE_ERROR } from './tools/ToolDefinition.js' ;
3937import type {
4038 Context ,
@@ -109,7 +107,7 @@ export class McpContext implements Context {
109107 #extensionServiceWorkers: ExtensionServiceWorker [ ] = [ ] ;
110108
111109 #mcpPages = new Map < Page , McpPage > ( ) ;
112- #selectedPage?: Page ;
110+ #selectedPage?: McpPage ;
113111 #networkCollector: NetworkCollector ;
114112 #consoleCollector: ConsoleCollector ;
115113 #devtoolsUniverseManager: UniverseManager ;
@@ -290,7 +288,7 @@ export class McpContext implements Context {
290288 page = await this . browser . newPage ( { background} ) ;
291289 }
292290 await this . createPagesSnapshot ( ) ;
293- this . selectPage ( page ) ;
291+ this . selectPage ( this . #getMcpPage ( page ) ) ;
294292 this . #networkCollector. addPage ( page ) ;
295293 this . #consoleCollector. addPage ( page ) ;
296294 return this . #getMcpPage( page ) ;
@@ -300,16 +298,15 @@ export class McpContext implements Context {
300298 throw new Error ( CLOSE_PAGE_ERROR ) ;
301299 }
302300 const page = this . getPageById ( pageId ) ;
303- const mcpPage = this . #mcpPages. get ( page ) ;
304- if ( mcpPage ) {
305- mcpPage . dispose ( ) ;
306- this . #mcpPages. delete ( page ) ;
301+ if ( page ) {
302+ page . dispose ( ) ;
303+ this . #mcpPages. delete ( page . pptrPage ) ;
307304 }
308- const ctx = page . browserContext ( ) ;
309- if ( this . #focusedPagePerContext. get ( ctx ) === page ) {
305+ const ctx = page . pptrPage . browserContext ( ) ;
306+ if ( this . #focusedPagePerContext. get ( ctx ) === page . pptrPage ) {
310307 this . #focusedPagePerContext. delete ( ctx ) ;
311308 }
312- await page . close ( { runBeforeUnload : false } ) ;
309+ await page . pptrPage . close ( { runBeforeUnload : false } ) ;
313310 }
314311
315312 getNetworkRequestById ( page : McpPage , reqid : number ) : HTTPRequest {
@@ -461,29 +458,21 @@ export class McpContext implements Context {
461458 if ( ! page ) {
462459 throw new Error ( 'No page selected' ) ;
463460 }
464- if ( page . isClosed ( ) ) {
461+ if ( page . pptrPage . isClosed ( ) ) {
465462 throw new Error (
466463 `The selected page has been closed. Call ${ listPages ( ) . name } to see open pages.` ,
467464 ) ;
468465 }
469- return page ;
466+ return page . pptrPage ;
470467 }
471468
472469 getSelectedMcpPage ( ) : McpPage {
473470 const page = this . getSelectedPptrPage ( ) ;
474471 return this . #getMcpPage( page ) ;
475472 }
476473
477- resolvePageById ( pageId ?: number ) : McpPage {
478- if ( pageId === undefined ) {
479- return this . getSelectedMcpPage ( ) ;
480- }
481- const page = this . getPageById ( pageId ) ;
482- return this . #getMcpPage( page ) ;
483- }
484-
485- getPageById ( pageId : number ) : Page {
486- const page = this . #pages. find ( p => this . #mcpPages. get ( p ) ?. id === pageId ) ;
474+ getPageById ( pageId : number ) : McpPage {
475+ const page = this . #mcpPages. values ( ) . find ( mcpPage => mcpPage . id === pageId ) ;
487476 if ( ! page ) {
488477 throw new Error ( 'No page found' ) ;
489478 }
@@ -507,7 +496,7 @@ export class McpContext implements Context {
507496 }
508497
509498 isPageSelected ( page : Page ) : boolean {
510- return this . #selectedPage === page ;
499+ return this . #selectedPage?. pptrPage === page ;
511500 }
512501
513502 assertPageIsFocused ( pageToCheck : Page | ContextPage ) : void {
@@ -524,20 +513,22 @@ export class McpContext implements Context {
524513 }
525514 }
526515
527- selectPage ( pageToSelect : Page | ContextPage ) : void {
528- const newPage =
529- 'pptrPage' in pageToSelect ? pageToSelect . pptrPage : pageToSelect ;
530- const ctx = newPage . browserContext ( ) ;
516+ selectPage ( newPage : McpPage ) : void {
517+ const ctx = newPage . pptrPage . browserContext ( ) ;
531518 const oldFocused = this . #focusedPagePerContext. get ( ctx ) ;
532- if ( oldFocused && oldFocused !== newPage && ! oldFocused . isClosed ( ) ) {
519+ if (
520+ oldFocused &&
521+ oldFocused !== newPage . pptrPage &&
522+ ! oldFocused . isClosed ( )
523+ ) {
533524 void oldFocused . emulateFocusedPage ( false ) . catch ( error => {
534525 this . logger ( 'Error turning off focused page emulation' , error ) ;
535526 } ) ;
536527 }
537- this . #focusedPagePerContext. set ( ctx , newPage ) ;
528+ this . #focusedPagePerContext. set ( ctx , newPage . pptrPage ) ;
538529 this . #selectedPage = newPage ;
539530 this . #updateSelectedPageTimeouts( ) ;
540- void newPage . emulateFocusedPage ( true ) . catch ( error => {
531+ void newPage . pptrPage . emulateFocusedPage ( true ) . catch ( error => {
541532 this . logger ( 'Error turning on focused page emulation' , error ) ;
542533 } ) ;
543534 }
@@ -572,63 +563,6 @@ export class McpContext implements Context {
572563 return undefined ;
573564 }
574565
575- async getElementByUid (
576- uid : string ,
577- page ?: Page ,
578- ) : Promise < ElementHandle < Element > > {
579- if ( page ) {
580- // Scoped search: only look in the target page's snapshot.
581- const mcpPage = this . #mcpPages. get ( page ) ;
582- if ( ! mcpPage ?. textSnapshot ) {
583- throw new Error (
584- `No snapshot found for page ${ mcpPage ?. id ?? '?' } . Use ${ takeSnapshot . name } to capture one.` ,
585- ) ;
586- }
587- const node = mcpPage . textSnapshot . idToNode . get ( uid ) ;
588- if ( ! node ) {
589- throw new Error (
590- `Element uid "${ uid } " not found on page ${ mcpPage . id } .` ,
591- ) ;
592- }
593- return this . #resolveElementHandle( node , uid ) ;
594- }
595-
596- // Cross-page search with context-focus validation.
597- let anySnapshot = false ;
598- for ( const [ searchPage , mcpPage ] of this . #mcpPages. entries ( ) ) {
599- if ( ! mcpPage . textSnapshot ) {
600- continue ;
601- }
602- anySnapshot = true ;
603- const node = mcpPage . textSnapshot . idToNode . get ( uid ) ;
604- if ( node ) {
605- const ctx = searchPage . browserContext ( ) ;
606- const contextSelectedPage = this . #focusedPagePerContext. get ( ctx ) ;
607- if ( contextSelectedPage !== searchPage ) {
608- const targetId = mcpPage . id ;
609- const selectedId = contextSelectedPage
610- ? this . #mcpPages. get ( contextSelectedPage ) ?. id
611- : this . #getSelectedMcpPage( ) . id ;
612- throw new Error (
613- `Element uid "${ uid } " belongs to page ${ targetId } , but page ${ selectedId } is currently selected. ` +
614- `Call select_page with pageId ${ targetId } first.` ,
615- ) ;
616- }
617- // Align global #selectedPage for waitForEventsAfterAction etc.
618- if ( this . #selectedPage !== searchPage ) {
619- this . #selectedPage = searchPage ;
620- }
621- return this . #resolveElementHandle( node , uid ) ;
622- }
623- }
624- if ( ! anySnapshot ) {
625- throw new Error (
626- `No snapshot found. Use ${ takeSnapshot . name } to capture one.` ,
627- ) ;
628- }
629- throw new Error ( 'No such element found in any snapshot.' ) ;
630- }
631-
632566 /**
633567 * Creates a snapshot of the extension service workers.
634568 */
@@ -664,24 +598,6 @@ export class McpContext implements Context {
664598 return this . #extensionServiceWorkers;
665599 }
666600
667- async #resolveElementHandle(
668- node : TextSnapshotNode ,
669- uid : string ,
670- ) : Promise < ElementHandle < Element > > {
671- const message = `Element with uid ${ uid } no longer exists on the page.` ;
672- try {
673- const handle = await node . elementHandle ( ) ;
674- if ( ! handle ) {
675- throw new Error ( message ) ;
676- }
677- return handle ;
678- } catch ( error ) {
679- throw new Error ( message , {
680- cause : error ,
681- } ) ;
682- }
683- }
684-
685601 async createPagesSnapshot ( ) : Promise < Page [ ] > {
686602 const { pages : allPages , isolatedContextNames} = await this . #getAllPages( ) ;
687603
@@ -717,10 +633,11 @@ export class McpContext implements Context {
717633 } ) ;
718634
719635 if (
720- ( ! this . #selectedPage || this . #pages. indexOf ( this . #selectedPage) === - 1 ) &&
636+ ( ! this . #selectedPage ||
637+ this . #pages. indexOf ( this . #selectedPage. pptrPage ) === - 1 ) &&
721638 this . #pages[ 0 ]
722639 ) {
723- this . selectPage ( this . #pages[ 0 ] ) ;
640+ this . selectPage ( this . #getMcpPage ( this . # pages[ 0 ] ) ) ;
724641 }
725642
726643 await this . detectOpenDevToolsWindows ( ) ;
@@ -943,14 +860,6 @@ export class McpContext implements Context {
943860 }
944861 }
945862
946- getTextSnapshot ( targetPage ?: Page ) : TextSnapshot | null {
947- const page = targetPage ?? this . #selectedPage;
948- if ( ! page ) {
949- return null ;
950- }
951- return this . #mcpPages. get ( page ) ?. textSnapshot ?? null ;
952- }
953-
954863 async saveTemporaryFile (
955864 data : Uint8Array < ArrayBufferLike > ,
956865 filename : string ,
0 commit comments