@@ -141,7 +141,17 @@ export async function executeStep(
141141 case 'click' : {
142142 try {
143143 // Check if element exists first
144- const locator = locatorFor ( page , step . object_type as SelectorType | undefined , step . object ?? '' ) ;
144+ const locator = scopeLocator
145+ ? locatorFor (
146+ scopeLocator as any ,
147+ step . object_type as SelectorType | undefined ,
148+ step . object ?? ''
149+ )
150+ : locatorFor (
151+ page ,
152+ step . object_type as SelectorType | undefined ,
153+ step . object ?? ''
154+ ) ;
145155 const count = await locator . count ( ) ;
146156
147157 if ( count === 0 ) {
@@ -267,7 +277,17 @@ export async function executeStep(
267277 if ( ! step . subSteps || step . subSteps . length === 0 ) {
268278 throw new Error ( 'foreach step requires subSteps' ) ;
269279 }
270- const locatorAll = locatorFor ( page , step . object_type as SelectorType | undefined , step . object ) ;
280+ const locatorAll = scopeLocator
281+ ? locatorFor (
282+ scopeLocator as any ,
283+ step . object_type as SelectorType | undefined ,
284+ step . object
285+ )
286+ : locatorFor (
287+ page ,
288+ step . object_type as SelectorType | undefined ,
289+ step . object
290+ ) ;
271291 try {
272292 await locatorAll . first ( ) . waitFor ( { state : 'attached' , timeout : step . wait ?? 5000 } ) ;
273293 } catch { }
@@ -283,11 +303,20 @@ export async function executeStep(
283303 }
284304
285305 // Create a separate collector for each iteration
306+ // Initialize with parent context (non-item_* keys) to preserve metadata
286307 const itemCollector : Record < string , any > = { } ;
308+ Object . keys ( collector ) . forEach ( k => {
309+ if ( ! k . startsWith ( 'item_' ) ) {
310+ itemCollector [ k ] = collector [ k ] ;
311+ }
312+ } ) ;
313+
314+ // Use the specified index key or default to 'i'
315+ const indexKey = step . index_key || 'i' ;
287316
288317 // For each subStep clone and replace placeholders
289318 for ( const s of step . subSteps ) {
290- const cloned = cloneStepWithIndex ( s , idx ) ;
319+ const cloned = cloneStepWithIndex ( s , idx , indexKey ) ;
291320 try {
292321 await executeStep ( page , cloned , itemCollector , onResult , current ) ;
293322 } catch ( err : any ) {
@@ -307,8 +336,6 @@ export async function executeStep(
307336 ) ;
308337
309338 // Emit the result immediately for streaming
310- // We need to access the onResult callback from the parent context
311- // This is a bit of a hack, but it works for immediate streaming
312339 if ( ( global as any ) . onResultCallback ) {
313340 try {
314341 const flattenedResult = flattenNestedForeachResults ( itemCollector ) ;
@@ -329,7 +356,17 @@ export async function executeStep(
329356
330357 try {
331358 // locate link and check if it exists
332- const linkLoc = locatorFor ( page , step . object_type as SelectorType | undefined , step . object ) ;
359+ const linkLoc = scopeLocator
360+ ? locatorFor (
361+ scopeLocator as any ,
362+ step . object_type as SelectorType | undefined ,
363+ step . object
364+ )
365+ : locatorFor (
366+ page ,
367+ step . object_type as SelectorType | undefined ,
368+ step . object
369+ ) ;
333370 const count = await linkLoc . count ( ) ;
334371
335372 if ( count === 0 ) {
@@ -365,8 +402,13 @@ export async function executeStep(
365402 await newPage . waitForLoadState ( 'networkidle' ) ;
366403 }
367404
368- // Pass the parent collector data to subSteps so they can access meeting_title, meeting_date, etc.
369- const innerCollected : Record < string , any > = { ...collector } ;
405+ // Pass only the parent context (non-item keys) to subSteps
406+ const innerCollected : Record < string , any > = { } ;
407+ Object . keys ( collector ) . forEach ( k => {
408+ if ( ! k . startsWith ( 'item_' ) ) {
409+ innerCollected [ k ] = collector [ k ] ;
410+ }
411+ } ) ;
370412 for ( const s of step . subSteps ) {
371413 const cloned : BaseStep = { ...s } ;
372414 try {
@@ -673,7 +715,17 @@ export async function executeStep(
673715 // If object is provided, click it first (for backward compatibility)
674716 if ( step . object ) {
675717 try {
676- const locator = locatorFor ( page , step . object_type as SelectorType | undefined , step . object ) ;
718+ const locator = scopeLocator
719+ ? locatorFor (
720+ scopeLocator as any ,
721+ step . object_type as SelectorType | undefined ,
722+ step . object
723+ )
724+ : locatorFor (
725+ page ,
726+ step . object_type as SelectorType | undefined ,
727+ step . object
728+ ) ;
677729 const count = await locator . count ( ) ;
678730
679731 if ( count > 0 ) {
@@ -743,11 +795,17 @@ export async function executeStep(
743795
744796 try {
745797 // 1) Find the link and get its href
746- const link = locatorFor (
747- page ,
748- step . object_type as SelectorType | undefined ,
749- step . object
750- ) ;
798+ const link = scopeLocator
799+ ? locatorFor (
800+ scopeLocator as any ,
801+ step . object_type as SelectorType | undefined ,
802+ step . object
803+ )
804+ : locatorFor (
805+ page ,
806+ step . object_type as SelectorType | undefined ,
807+ step . object
808+ ) ;
751809 const present = ( await link . count ( ) ) > 0 ;
752810 if ( ! present ) {
753811 console . log ( ` ⚠️ PDF link not found: ${ step . object } ` ) ;
0 commit comments