@@ -255,6 +255,8 @@ export class WorkflowBlockHandler implements BlockHandler {
255255 let childSessionStarted = false
256256 /** Set once the child's session reached a terminal state, so the catch doesn't re-complete it. */
257257 let childSessionFinalized = false
258+ /** Large-value id list shared with the child (and any nested custom blocks). */
259+ let sharedLargeValueIds : string [ ] | undefined
258260 let childCancellation : { signal : AbortSignal ; dispose : ( ) => void } | undefined
259261 try {
260262 // A custom block runs the source's latest deployment; if the source has been
@@ -467,10 +469,16 @@ export class WorkflowBlockHandler implements BlockHandler {
467469 parentExecutionId : ctx . executionId ,
468470 } )
469471 // Large values are scoped by execution id, so the parent must be able to
470- // read a large exposed output the child produced.
471- ctx . largeValueExecutionIds = Array . from (
472- new Set ( [ ...( ctx . largeValueExecutionIds ?? [ ] ) , childExecutionId ] )
473- )
472+ // read a large exposed output the child produced. ONE array is shared down
473+ // the whole chain rather than copied per hop: a nested custom block pushes
474+ // its own child id into this same list, so a grandchild's large output is
475+ // still materializable at the top level. Copying would strand those ids at
476+ // the depth that created them.
477+ ctx . largeValueExecutionIds ??= [ ]
478+ sharedLargeValueIds = ctx . largeValueExecutionIds
479+ for ( const id of [ ctx . executionId , childExecutionId ] ) {
480+ if ( id && ! sharedLargeValueIds . includes ( id ) ) sharedLargeValueIds . push ( id )
481+ }
474482 }
475483
476484 // Trusted run metadata for the child's Start block. Every field describes
@@ -525,15 +533,8 @@ export class WorkflowBlockHandler implements BlockHandler {
525533 executionId : childExecutionId ?? ctx . executionId ,
526534 // Large values are cached per execution id, so a child running under its
527535 // own id still needs the invoking run's id to read values in its inputs.
528- ...( childExecutionId
529- ? {
530- largeValueExecutionIds : Array . from (
531- new Set ( [
532- ...( ctx . executionId ? [ ctx . executionId ] : [ ] ) ,
533- ...( ctx . largeValueExecutionIds ?? [ ] ) ,
534- ] )
535- ) ,
536- }
536+ ...( childExecutionId && sharedLargeValueIds
537+ ? { largeValueExecutionIds : sharedLargeValueIds }
537538 : { } ) ,
538539 // Same-workspace children share the parent's frozen payer decision so
539540 // internal tool calls (knowledge, guardrails, MCP, Mothership) can
0 commit comments