@@ -103,40 +103,44 @@ export class WebHarness { // implements StateComponent
103103 /**
104104 * Get b64 encoded string of screenshot (PNG) with screen dimensions
105105 */
106- const dpr = await this . page . evaluate ( ( ) => window . devicePixelRatio ) ;
107- //console.log("DPR:", dpr);
108- //const viewportSize = this.page.viewportSize();
109- const buffer = await this . page . screenshot ( { type : 'png' , ...options } , ) ;
110-
111- // if (!viewportSize) {
112- // throw Error("Invalid viewport for screenshot");
113- // }
114-
106+
107+ // Target page, context or browser has been closed
108+
109+ let dpr ! : number ;
110+ let buffer ! : Buffer < ArrayBufferLike > ;
111+
112+ const retries = 3 ;
113+
114+ for ( let attempt = 0 ; attempt <= retries ; attempt ++ ) {
115+ try {
116+ dpr = await this . page . evaluate ( ( ) => window . devicePixelRatio )
117+ buffer = await this . page . screenshot ( { type : 'png' , ...options } , ) ;
118+ } catch ( err ) {
119+ // A few possibilities:
120+ // 1. Target page, context or browser has been closed
121+ // 2. Page navigation in progress
122+ // In theory 2 shouldn't shouldn't happen during typical execution as we wait for page load - unless screenshot is triggered at an usual time.
123+ const error = err as Error ;
124+ if ( error . message . includes ( 'Target page, context or browser has been closed' ) ) {
125+ // Irrecoverable, no point in retrying
126+ throw new Error ( "Attempted to take screenshot but page, context or browser is closed" ) ;
127+ }
128+ if ( attempt >= retries ) {
129+ throw new Error ( `Unable to capture screenshot after retries, error: ${ error . message } ` ) ;
130+ }
131+ }
132+ }
115133 const base64data = buffer . toString ( 'base64' ) ;
116134
117- //console.log("Screenshot DATA:", base64data.substring(0, 100));
118135 const image = Image . fromBase64 ( base64data ) ;
119136
120137 // Now, need to rescale the image based on DPR. This is so that:
121138 // (1) Save on tokens, dont need huge high res images
122139 // (2) More importantly, clicks happen in the standard resolution space, so need to do this for coordinates to be correct
123140 // for any agent not using a virtual screen space (e.g. those that aren't Claude)
124141 const { width, height } = await image . getDimensions ( ) ;
125- //console.log("Original screenshot dims:", { width, height });
126- //console.log("DPR-scaled dims:", { width: width / dpr, height: height / dpr });
127142 const rescaledImage = await image . resize ( width / dpr , height / dpr ) ;
128- //console.log("screenshot() final dims:", await rescaledImage.getDimensions());
129-
130- //console.log("_locateTarget dims:", await screenshot.getDimensions());
131143 return rescaledImage ;
132-
133- // return {
134- // image: `data:image/png;base64,${base64data}`,//buffer.toString('base64'),
135- // dimensions: {
136- // width: viewportSize.width,
137- // height: viewportSize.height
138- // }
139- // };
140144 }
141145
142146 // async goto(url: string) {
0 commit comments