@@ -157,7 +157,10 @@ const runAction = async (
157157 } ;
158158
159159 if ( ctx . cdpActions ) {
160- const { cdpClient, frameContextManager } = await initializeRuntimeContext ( page , ctx . debug ) ;
160+ const { cdpClient, frameContextManager } = await initializeRuntimeContext (
161+ page ,
162+ ctx . debug
163+ ) ;
161164 actionCtx . cdp = {
162165 resolveElement,
163166 dispatchCDPAction,
@@ -233,27 +236,32 @@ export const runAgentTask = async (
233236 ] ;
234237
235238 let output = "" ;
236- const page = taskState . startingPage ;
239+ let page = taskState . startingPage ;
237240 const useDomCache = params ?. useDomCache === true ;
238241 const enableDomStreaming = params ?. enableDomStreaming === true ;
239-
242+
240243 // Track schema validation errors across steps
241244 if ( ! ctx . schemaErrors ) {
242245 ctx . schemaErrors = [ ] ;
243246 }
244-
247+
245248 const navigationDirtyHandler = ( ) : void => {
246249 markDomSnapshotDirty ( page ) ;
247250 } ;
248- page . on ( "framenavigated" , navigationDirtyHandler ) ;
249- page . on ( "framedetached" , navigationDirtyHandler ) ;
250- page . on ( "load" , navigationDirtyHandler ) ;
251-
252- const cleanupDomListeners = ( ) : void => {
253- page . off ?.( "framenavigated" , navigationDirtyHandler ) ;
254- page . off ?.( "framedetached" , navigationDirtyHandler ) ;
255- page . off ?.( "load" , navigationDirtyHandler ) ;
251+
252+ const setupDomListeners = ( p : Page ) => {
253+ p . on ( "framenavigated" , navigationDirtyHandler ) ;
254+ p . on ( "framedetached" , navigationDirtyHandler ) ;
255+ p . on ( "load" , navigationDirtyHandler ) ;
256+ } ;
257+
258+ const cleanupDomListeners = ( p : Page ) => {
259+ p . off ?.( "framenavigated" , navigationDirtyHandler ) ;
260+ p . off ?.( "framedetached" , navigationDirtyHandler ) ;
261+ p . off ?.( "load" , navigationDirtyHandler ) ;
256262 } ;
263+
264+ setupDomListeners ( page ) ;
257265 let currStep = 0 ;
258266 let consecutiveFailuresOrWaits = 0 ;
259267 const MAX_CONSECUTIVE_FAILURES_OR_WAITS = 5 ;
@@ -263,8 +271,23 @@ export const runAgentTask = async (
263271 try {
264272 // Initialize context at the start of the task
265273 await initializeRuntimeContext ( page , ctx . debug ) ;
266-
274+
267275 while ( true ) {
276+ // Check for page context switch
277+ if ( ctx . activePage ) {
278+ const newPage = await ctx . activePage ( ) ;
279+ if ( newPage && newPage !== page ) {
280+ if ( ctx . debug ) {
281+ console . log ( `[Agent] Switching active page context to ${ newPage . url ( ) } ` ) ;
282+ }
283+ cleanupDomListeners ( page ) ;
284+ page = newPage ;
285+ setupDomListeners ( page ) ;
286+ await initializeRuntimeContext ( page , ctx . debug ) ;
287+ markDomSnapshotDirty ( page ) ;
288+ }
289+ }
290+
268291 // Status Checks
269292 const status : TaskStatus = taskState . status ;
270293 if ( status === TaskStatus . PAUSED ) {
@@ -292,16 +315,19 @@ export const runAgentTask = async (
292315 const domChunks : string | null = null ;
293316 try {
294317 const domFetchStart = performance . now ( ) ;
295-
318+
319+ await waitForSettledDOM ( page ) ;
296320 domState = await captureDOMState ( page , {
297321 useCache : useDomCache ,
298322 debug : ctx . debug ,
299323 enableVisualMode : params ?. enableVisualMode ?? false ,
300324 debugStepDir : ctx . debug ? debugStepDir : undefined ,
301325 enableStreaming : enableDomStreaming ,
302- onFrameChunk : enableDomStreaming ? ( ) => {
303- // captureDOMState handles aggregation
304- } : undefined
326+ onFrameChunk : enableDomStreaming
327+ ? ( ) => {
328+ // captureDOMState handles aggregation
329+ }
330+ : undefined ,
305331 } ) ;
306332
307333 const domDuration = performance . now ( ) - domFetchStart ;
@@ -366,14 +392,14 @@ export const runAgentTask = async (
366392 trimmedScreenshot ,
367393 Object . values ( ctx . variables )
368394 ) ;
369-
395+
370396 // Append accumulated schema errors from previous steps
371397 if ( ctx . schemaErrors && ctx . schemaErrors . length > 0 ) {
372398 const errorSummary = ctx . schemaErrors
373399 . slice ( - 3 ) // Only keep last 3 errors to avoid context bloat
374- . map ( err => `Step ${ err . stepIndex } : ${ err . error } ` )
375- . join ( '\n' ) ;
376-
400+ . map ( ( err ) => `Step ${ err . stepIndex } : ${ err . error } ` )
401+ . join ( "\n" ) ;
402+
377403 msgs = [
378404 ...msgs ,
379405 {
@@ -395,7 +421,7 @@ export const runAgentTask = async (
395421 const agentOutput = await ( async ( ) => {
396422 const maxAttempts = 3 ;
397423 let currentMsgs = msgs ;
398-
424+
399425 for ( let attempt = 0 ; attempt < maxAttempts ; attempt ++ ) {
400426 const structuredResult = await retry ( {
401427 func : ( ) =>
@@ -431,7 +457,7 @@ export const runAgentTask = async (
431457
432458 const providerId = ctx . llm ?. getProviderId ?.( ) ?? "unknown-provider" ;
433459 const modelId = ctx . llm ?. getModelId ?.( ) ?? "unknown-model" ;
434-
460+
435461 // Try to get detailed Zod validation error
436462 let validationError = "Unknown validation error" ;
437463 if ( structuredResult . rawText ) {
@@ -446,27 +472,28 @@ export const runAgentTask = async (
446472 }
447473 }
448474 }
449-
475+
450476 console . error (
451477 `[LLM][StructuredOutput] Failed to parse response from ${ providerId } (${ modelId } ). Raw response: ${
452478 structuredResult . rawText ?. trim ( ) || "<empty>"
453479 } (attempt ${ attempt + 1 } /${ maxAttempts } )`
454480 ) ;
455-
481+
456482 // Store error for cross-step learning
457483 ctx . schemaErrors ?. push ( {
458484 stepIndex : currStep ,
459485 error : validationError ,
460486 rawResponse : structuredResult . rawText || "" ,
461487 } ) ;
462-
488+
463489 // Append error feedback for next retry
464490 if ( attempt < maxAttempts - 1 ) {
465491 currentMsgs = [
466492 ...currentMsgs ,
467493 {
468494 role : "assistant" ,
469- content : structuredResult . rawText || "Failed to generate response" ,
495+ content :
496+ structuredResult . rawText || "Failed to generate response" ,
470497 } ,
471498 {
472499 role : "user" ,
@@ -629,7 +656,7 @@ export const runAgentTask = async (
629656
630657 logPerf ( ctx . debug , `[Perf][runAgentTask] Task ${ taskId } ` , taskStart ) ;
631658 } finally {
632- cleanupDomListeners ( ) ;
659+ cleanupDomListeners ( page ) ;
633660 }
634661
635662 const taskOutput : TaskOutput = {
0 commit comments