@@ -476,6 +476,72 @@ async def _run_impl(
476476 assert 'original:my original input' in outputs
477477
478478
479+ @pytest .mark .asyncio
480+ async def test_resume_populates_invocation_user_content ():
481+ """On resume via a function response, ic.user_content is the original turn."""
482+ seen : list [Any ] = []
483+
484+ class _Node (BaseNode ):
485+
486+ async def _run_impl (
487+ self , * , ctx : Context , node_input : Any
488+ ) -> AsyncGenerator [Any , None ]:
489+ if ctx .resume_inputs and 'fc-1' in ctx .resume_inputs :
490+ user_content = ctx .get_invocation_context ().user_content
491+ seen .append (user_content .parts [0 ].text if user_content else None )
492+ yield 'resumed'
493+ return
494+ yield _make_interrupt_event (fc_name = 'tool' )
495+
496+ await _run_two_turns (
497+ _Node (name = 'node' ),
498+ 'remember me' ,
499+ _make_resume_message (fc_name = 'tool' , response = {'v' : 1 }),
500+ )
501+
502+ assert seen == ['remember me' ]
503+
504+
505+ @pytest .mark .asyncio
506+ async def test_resume_by_invocation_id_populates_user_content ():
507+ """Resuming by invocation_id alone recovers the original user_content."""
508+ seen : list [Any ] = []
509+
510+ class _Node (BaseNode ):
511+
512+ async def _run_impl (
513+ self , * , ctx : Context , node_input : Any
514+ ) -> AsyncGenerator [Any , None ]:
515+ user_content = ctx .get_invocation_context ().user_content
516+ seen .append (user_content .parts [0 ].text if user_content else None )
517+ yield _make_interrupt_event (fc_name = 'tool' )
518+
519+ ss = InMemorySessionService ()
520+ runner = Runner (app_name = 'test' , node = _Node (name = 'node' ), session_service = ss )
521+ session = await ss .create_session (app_name = 'test' , user_id = 'u' )
522+
523+ async for _ in runner .run_async (
524+ user_id = 'u' ,
525+ session_id = session .id ,
526+ new_message = types .Content (
527+ parts = [types .Part (text = 'original text' )], role = 'user'
528+ ),
529+ ):
530+ pass
531+
532+ updated = await ss .get_session (
533+ app_name = 'test' , user_id = 'u' , session_id = session .id
534+ )
535+ invocation_id = updated .events [0 ].invocation_id
536+
537+ async for _ in runner .run_async (
538+ user_id = 'u' , session_id = session .id , invocation_id = invocation_id
539+ ):
540+ pass
541+
542+ assert seen == ['original text' , 'original text' ]
543+
544+
479545@pytest .mark .asyncio
480546async def test_plain_text_does_not_trigger_resume ():
481547 """Sending plain text (no FR) starts fresh, does not enter resume path."""
0 commit comments