2727 AssessmentConfig ,
2828 AssessmentResults ,
2929 BudgetConstrainedTask ,
30+ ErrorRecoveryTask ,
3031 EvaluationResult ,
3132 NegativeConstraintTask ,
3233 PreferenceMemoryTask ,
33- SessionState ,
3434 Task ,
3535 TaskType ,
3636 TaskUpdate ,
3737)
3838from .purple_client import PurpleAgentClient , TaskResult , PurpleAgentClientError
39- from .state_manager import StateManager
4039from .task_generator import TaskGenerator
40+ from .webshop_mcp .session_state import SessionState as MCPSessionState
4141from .webshop_wrapper import WebShopWrapper
4242
4343if TYPE_CHECKING :
@@ -100,7 +100,6 @@ def __init__(
100100 self ,
101101 config : Optional [AgentConfig ] = None ,
102102 task_generator : Optional [TaskGenerator ] = None ,
103- state_manager : Optional [StateManager ] = None ,
104103 webshop : Optional [WebShopWrapper ] = None ,
105104 evaluator : Optional [Evaluator ] = None ,
106105 llm_client : Optional [LLMClient ] = None ,
@@ -112,7 +111,6 @@ def __init__(
112111 Args:
113112 config: Agent configuration.
114113 task_generator: Task generator instance (creates default if None).
115- state_manager: State manager instance (creates default if None).
116114 webshop: WebShop wrapper instance (creates default if None).
117115 evaluator: Evaluator instance (creates default if None).
118116 llm_client: LLM client for evaluation (creates default if None).
@@ -122,7 +120,6 @@ def __init__(
122120
123121 # Components - lazy initialization
124122 self ._task_generator = task_generator
125- self ._state_manager = state_manager
126123 self ._webshop = webshop
127124 self ._evaluator = evaluator
128125 self ._llm_client = llm_client
@@ -138,12 +135,6 @@ def task_generator(self) -> TaskGenerator:
138135 self ._task_generator = TaskGenerator ()
139136 return self ._task_generator
140137
141- @property
142- def state_manager (self ) -> StateManager :
143- if self ._state_manager is None :
144- self ._state_manager = StateManager ()
145- return self ._state_manager
146-
147138 @property
148139 def webshop (self ) -> WebShopWrapper :
149140 if self ._webshop is None :
@@ -575,41 +566,55 @@ async def _dispatch_task_to_purple(
575566 session_id = "" ,
576567 )
577568
578- # Create session for tracking
579- session = self .state_manager .create_session (task .task_id , agent_id )
580- result .session_id = session .session_id
581-
582- # Get agent memory for preference tasks
583- memory : Optional [AgentMemory ] = None
584- if isinstance (task , PreferenceMemoryTask ):
585- memory = self .state_manager .get_agent_memory (agent_id )
586-
587- try :
588- # Extract task data for kickoff
589- goal , budget , constraints = self ._extract_task_kickoff_data (task )
590-
591- # Create MCP session if session manager is available
592- mcp_session_id : Optional [str ] = None
593- mcp_uri : Optional [str ] = None
594-
595- if self ._session_manager is not None :
596- mcp_session_id = str (uuid .uuid4 ())
597- await self ._session_manager .create_session (
598- session_id = mcp_session_id ,
599- goal = goal ,
600- budget = budget ,
601- constraints = constraints ,
602- max_turns = self .config .max_actions_per_task ,
603- )
604- mcp_uri = self ._get_mcp_uri (mcp_session_id )
605-
569+ # Extract task data for kickoff
570+ goal , budget , constraints = self ._extract_task_kickoff_data (task )
571+
572+ # Create MCP session
573+ mcp_session_id : Optional [str ] = None
574+ mcp_uri : Optional [str ] = None
575+ mcp_state : Optional [MCPSessionState ] = None
576+
577+ if self ._session_manager is not None :
578+ mcp_session_id = str (uuid .uuid4 ())
579+ result .session_id = mcp_session_id # Use MCP session ID as result session ID
580+
581+ # Extract initial cart for error_recovery tasks
582+ initial_cart = None
583+ if isinstance (task , ErrorRecoveryTask ) and task .setup .cart_contents :
584+ initial_cart = [
585+ {
586+ "product_id" : item .product_id ,
587+ "name" : item .product_name ,
588+ "price" : item .price ,
589+ "quantity" : item .quantity ,
590+ "options" : item .attributes ,
591+ }
592+ for item in task .setup .cart_contents
593+ ]
606594 logger .info (
607- "Created MCP session for task" ,
595+ "Pre-populating cart for error_recovery task" ,
608596 task_id = task .task_id ,
609- mcp_session_id = mcp_session_id ,
610- mcp_uri = mcp_uri ,
597+ cart_items = len (initial_cart ),
611598 )
612599
600+ await self ._session_manager .create_session (
601+ session_id = mcp_session_id ,
602+ goal = goal ,
603+ budget = budget ,
604+ constraints = constraints ,
605+ max_turns = self .config .max_actions_per_task ,
606+ initial_cart = initial_cart ,
607+ )
608+ mcp_uri = self ._get_mcp_uri (mcp_session_id )
609+
610+ logger .info (
611+ "Created MCP session for task" ,
612+ task_id = task .task_id ,
613+ mcp_session_id = mcp_session_id ,
614+ mcp_uri = mcp_uri ,
615+ )
616+
617+ try :
613618 # Send task to purple agent via PurpleAgentClient
614619 async with PurpleAgentClient (shopper_endpoint ) as client :
615620 task_result = await client .send_task (
@@ -651,43 +656,31 @@ async def _dispatch_task_to_purple(
651656 error = task_result .error ,
652657 )
653658
654- # Get final result from MCP session if available
659+ # Get final MCP session state for evaluation
660+ mcp_state : Optional [MCPSessionState ] = None
655661 if mcp_session_id and self ._session_manager :
656- session_completed = self ._session_manager .is_session_completed (mcp_session_id )
657- logger .info (
658- "Checking MCP session completion" ,
659- mcp_session_id = mcp_session_id ,
660- session_completed = session_completed ,
661- task_id = task .task_id ,
662- )
663- if session_completed :
664- mcp_result = self ._session_manager .get_final_result (mcp_session_id )
662+ mcp_state = await self ._session_manager .get_session (mcp_session_id )
663+
664+ if mcp_state :
665665 logger .info (
666- "Retrieved MCP final result" ,
667- mcp_session_id = mcp_session_id ,
668- has_result = mcp_result is not None ,
669- result_keys = list (mcp_result .keys ()) if mcp_result else [],
670- task_id = task .task_id ,
671- )
672- if mcp_result :
673- # Merge MCP result into task execution result
674- if "turns_used" in mcp_result :
675- logger .info (
676- "Setting actions_taken from MCP result" ,
677- turns_used = mcp_result ["turns_used" ],
678- task_id = task .task_id ,
679- )
680- result .actions_taken = mcp_result ["turns_used" ]
681- if "success" in mcp_result :
682- result .completed = mcp_result ["success" ]
683- if "reward" in mcp_result :
684- result .total_reward = mcp_result ["reward" ]
685- else :
686- logger .warning (
687- "MCP session not marked as completed" ,
666+ "Retrieved MCP state for evaluation" ,
688667 mcp_session_id = mcp_session_id ,
668+ history_len = len (mcp_state .history ),
669+ cart_len = len (mcp_state .cart ),
670+ turns_used = mcp_state .turn_count ,
689671 task_id = task .task_id ,
690672 )
673+ # Update result with MCP metrics
674+ result .actions_taken = mcp_state .turn_count
675+
676+ # Attach reasoning from purple agent for evaluation
677+ if task_result .result_data and "reasoning_summary" in task_result .result_data :
678+ mcp_state .reasoning_summary = task_result .result_data ["reasoning_summary" ]
679+ logger .info (
680+ "Attached reasoning_summary to MCP state" ,
681+ reasoning_len = len (mcp_state .reasoning_summary ),
682+ task_id = task .task_id ,
683+ )
691684
692685 # Clean up MCP session
693686 await self ._session_manager .cleanup_session (mcp_session_id )
@@ -702,7 +695,7 @@ async def _dispatch_task_to_purple(
702695 result .error = f"Task execution error: { str (e )} "
703696 logger .error ("MCP task execution error" , task_id = task .task_id , error = str (e ))
704697
705- return self ._finalize_task (result , session , task , memory )
698+ return self ._finalize_task (result , task , mcp_state )
706699
707700 async def _execute_task (
708701 self ,
@@ -726,24 +719,20 @@ async def _execute_task(
726719 def _finalize_task (
727720 self ,
728721 result : TaskExecutionResult ,
729- session : SessionState ,
730722 task : Task ,
731- memory : Optional [AgentMemory ],
723+ mcp_state : Optional [MCPSessionState ],
732724 ) -> TaskExecutionResult :
733- """Finalize task execution and evaluate."""
734- # Update session with actions_taken from result
735- # (result.actions_taken was set from MCP final result)
736- session .set_action_count (result .actions_taken )
737-
738- # Complete session
739- session_summary = self .state_manager .complete_session (
740- session .session_id ,
741- task_type = task .task_type .value ,
742- )
743-
744- # Evaluate
745- evaluation = self .evaluator .evaluate (session , task , memory )
746- result .evaluation = evaluation
725+ """Finalize task execution and evaluate using MCP state."""
726+ # Evaluate using MCP state directly
727+ if mcp_state :
728+ evaluation = self .evaluator .evaluate (mcp_state , task )
729+ result .evaluation = evaluation
730+ else :
731+ logger .warning (
732+ "No MCP state available for evaluation" ,
733+ task_id = task .task_id ,
734+ )
735+ result .error = result .error or "No MCP state available for evaluation"
747736
748737 return result
749738
0 commit comments