"""Step definitions for actor-first agent and LangGraph port.""" import json from behave import given, then, when @given("the agent system is initialized with actor-first configuration") def init_agent_system(context): """Initialize the agent system for actor-first operation.""" context.agent_system_initialized = True context.agents = {} context.graphs = {} context.factories = {} @given("I have a stateful LangGraph configuration:") def create_stateful_graph_config(context): """Create stateful LangGraph configuration.""" config_text = context.text.strip() context.graph_config = json.loads(config_text) @when("I create the stateful graph") def create_stateful_graph(context): """Create stateful graph from configuration.""" config = context.graph_config # Simulate graph creation with actor context.created_graph = { "name": config["name"], "actor": config.get("actor"), "checkpointing": config.get("checkpointing", False), "enable_time_travel": config.get("enable_time_travel", False), "nodes": config.get("nodes", {}), "edges": config.get("edges", []), "state": {}, "state_history": [], } context.graphs[config["name"]] = context.created_graph @then('the graph should be created with actor "{actor}"') def verify_graph_actor(context, actor): """Verify graph uses specified actor.""" assert context.created_graph["actor"] == actor @then("the graph state should be persisted") def verify_graph_persistence(context): """Verify graph state persistence.""" assert context.created_graph["checkpointing"] is True assert "state" in context.created_graph assert "state_history" in context.created_graph @then("time travel should be enabled") def verify_time_travel(context): """Verify time travel is enabled.""" assert context.created_graph["enable_time_travel"] is True @given("I have an agent configuration:") def create_agent_config(context): """Create agent configuration.""" config_text = context.text.strip() context.agent_config = json.loads(config_text) @when("I create an agent from the configuration") def create_agent(context): """Create agent from configuration.""" config = context.agent_config # Simulate agent creation context.created_agent = { "name": config["name"], "type": config["type"], "actor": config.get("actor"), "module_accessible": True, } context.agents[config["name"]] = context.created_agent @then("the agent should be created successfully") def verify_agent_creation(context): """Verify agent was created successfully.""" assert context.created_agent is not None assert context.created_agent["name"] == context.agent_config["name"] @then('the agent should use actor "{actor}"') def verify_agent_actor(context, actor): """Verify agent uses specified actor.""" assert context.created_agent["actor"] == actor @then("the agent module should be accessible") def verify_agent_module(context): """Verify agent module is accessible.""" assert context.created_agent["module_accessible"] is True @given("I have a chain agent configuration:") def create_chain_config(context): """Create chain agent configuration.""" config_text = context.text.strip() context.chain_config = json.loads(config_text) @when("I create a chain agent from the configuration") def create_chain_agent(context): """Create chain agent from configuration.""" config = context.chain_config # Simulate chain agent creation context.created_chain = { "name": config["name"], "type": config["type"], "actor": config.get("actor"), "steps": config.get("steps", []), "prompt": config.get("prompt"), } context.agents[config["name"]] = context.created_chain @then("the chain agent should be created successfully") def verify_chain_creation(context): """Verify chain agent was created successfully.""" assert context.created_chain is not None assert context.created_chain["name"] == context.chain_config["name"] @then("the chain agent should have {count:d} steps") def verify_chain_steps(context, count): """Verify chain agent has expected number of steps.""" assert len(context.created_chain["steps"]) == count @then('the chain agent should use actor "{actor}"') def verify_chain_actor(context, actor): """Verify chain agent uses specified actor.""" assert context.created_chain["actor"] == actor @given('I have a chain agent with actor "{actor}"') def create_chain_with_actor(context, actor): """Create chain agent with specific actor.""" context.chain_agent = { "name": "test_chain", "type": "chain", "actor": actor, "steps": [], } @given("the chain has steps {steps}") def add_chain_steps(context, steps): """Add steps to chain agent.""" # Parse steps list from string like '["parse", "analyze", "format"]' import ast step_list = ast.literal_eval(steps) context.chain_agent["steps"] = step_list @when('I process the message "{message}"') def process_message(context, message): """Process message through chain agent.""" agent = context.chain_agent # Simulate message processing result = f"Processed with {agent['actor']}: {message}" for step in agent["steps"]: result += f" -> {step}" context.processing_result = result @then("the chain should use the specified actor") def verify_chain_uses_actor(context): """Verify chain uses specified actor.""" assert context.chain_agent["actor"] in context.processing_result @then("the result should show processing through all steps") def verify_all_steps_processed(context): """Verify all steps were processed.""" for step in context.chain_agent["steps"]: assert step in context.processing_result @given("I have a composite agent configuration:") def create_composite_config(context): """Create composite agent configuration.""" config_text = context.text.strip() context.composite_config = json.loads(config_text) @when("I create a composite agent from the configuration") def create_composite_agent(context): """Create composite agent from configuration.""" config = context.composite_config # Simulate composite agent creation context.created_composite = { "name": config["name"], "type": config["type"], "agents": config.get("agents", []), "parallel_enabled": True, } context.agents[config["name"]] = context.created_composite @then("the composite agent should have {count:d} sub-agents") def verify_subagent_count(context, count): """Verify composite agent has expected number of sub-agents.""" assert len(context.created_composite["agents"]) == count @then("each sub-agent should use its configured actor") def verify_subagent_actors(context): """Verify each sub-agent uses its configured actor.""" for agent in context.created_composite["agents"]: assert "actor" in agent assert agent["actor"] is not None @then("parallel processing should work with all actors") def verify_parallel_processing(context): """Verify parallel processing is enabled.""" assert context.created_composite["parallel_enabled"] is True @given("I have a reactive agent configuration:") def create_reactive_config(context): """Create reactive agent configuration.""" config_text = context.text.strip() context.reactive_config = json.loads(config_text) @when("I create a reactive agent from the configuration") def create_reactive_agent(context): """Create reactive agent from configuration.""" config = context.reactive_config # Simulate reactive agent creation context.created_reactive = { "name": config["name"], "type": config["type"], "actor": config.get("actor"), "stream_config": config.get("stream_config", {}), "supports_streaming": True, } context.agents[config["name"]] = context.created_reactive @then("the agent should support reactive streaming") def verify_reactive_streaming(context): """Verify agent supports reactive streaming.""" assert context.created_reactive["supports_streaming"] is True @then('the stream should use actor "{actor}"') def verify_stream_actor(context, actor): """Verify stream uses specified actor.""" assert context.created_reactive["actor"] == actor @then("operators should transform data through the actor") def verify_operators(context): """Verify operators are configured.""" stream_config = context.created_reactive.get("stream_config", {}) assert "operators" in stream_config assert len(stream_config["operators"]) > 0 @given("I have a tool agent configuration:") def create_tool_config(context): """Create tool agent configuration.""" config_text = context.text.strip() context.tool_config = json.loads(config_text) @when("I create a tool agent from the configuration") def create_tool_agent(context): """Create tool agent from configuration.""" config = context.tool_config # Simulate tool agent creation context.created_tool = { "name": config["name"], "type": config["type"], "actor": config.get("actor"), "tools": config.get("tools", []), } context.agents[config["name"]] = context.created_tool @then("the tool agent should have {count:d} tools available") def verify_tool_count(context, count): """Verify tool agent has expected number of tools.""" assert len(context.created_tool["tools"]) == count @then('the tool agent should use actor "{actor}"') def verify_tool_agent_actor(context, actor): """Verify tool agent uses specified actor.""" assert context.created_tool["actor"] == actor @then("tool calls should be routed through the actor") def verify_tool_routing(context): """Verify tool calls are routed through actor.""" # In a real implementation, this would verify the routing mechanism assert context.created_tool["actor"] is not None assert len(context.created_tool["tools"]) > 0 @given("I have a complex LangGraph with multiple actors:") def create_complex_graph(context): """Create complex LangGraph with multiple actors.""" config_text = context.text.strip() context.visualization_config = json.loads(config_text) @when("I visualize the graph") def visualize_graph(context): """Visualize the graph.""" config = context.visualization_config # Simulate graph visualization context.visualization = { "name": config["name"], "nodes": [], "edges": config.get("edges", []), "actor_transitions": [], } # Extract node information with actors for node_name, node_data in config["nodes"].items(): context.visualization["nodes"].append( { "name": node_name, "type": node_data["type"], "actor": node_data.get("actor"), } ) # Identify actor transitions for edge in context.visualization["edges"]: source_node = next( n for n in context.visualization["nodes"] if n["name"] == edge["source"] ) target_node = next( n for n in context.visualization["nodes"] if n["name"] == edge["target"] ) if source_node.get("actor") != target_node.get("actor"): context.visualization["actor_transitions"].append( {"from": source_node["actor"], "to": target_node["actor"], "edge": edge} ) @then("the visualization should show all nodes with their actors") def verify_visualization_nodes(context): """Verify visualization shows all nodes with actors.""" for node in context.visualization["nodes"]: assert "actor" in node assert node["actor"] is not None @then("the edge flow should be clearly represented") def verify_edge_flow(context): """Verify edge flow is represented.""" assert len(context.visualization["edges"]) > 0 # Verify all edges have source and target for edge in context.visualization["edges"]: assert "source" in edge assert "target" in edge @then("actor transitions should be highlighted") def verify_actor_transitions(context): """Verify actor transitions are highlighted.""" assert len(context.visualization["actor_transitions"]) > 0 @given('I have an agent factory with default actor "{actor}"') def create_agent_factory(context, actor): """Create agent factory with default actor.""" context.agent_factory = {"default_actor": actor, "created_agents": []} @when("I create multiple agents using the factory:") def create_multiple_agents(context): """Create multiple agents using factory.""" # Store table data for later verification context.agent_table_data = [] # Parse table data for row in context.table: agent = { "name": row["agent_name"], "type": row["agent_type"], "actor": context.agent_factory["default_actor"], } context.agent_factory["created_agents"].append(agent) context.agents[agent["name"]] = agent # Store table row for later verification context.agent_table_data.append( {"agent_name": row["agent_name"], "agent_type": row["agent_type"]} ) @then('all agents should use the default actor "{actor}"') def verify_default_actor(context, actor): """Verify all agents use default actor.""" for agent in context.agent_factory["created_agents"]: assert agent["actor"] == actor @then("each agent should have the correct type") def verify_agent_types(context): """Verify each agent has correct type.""" for row in context.agent_table_data: agent = context.agents[row["agent_name"]] assert agent["type"] == row["agent_type"] @given("I have a LangGraph with conditional routing:") def create_conditional_graph(context): """Create LangGraph with conditional routing.""" config_text = context.text.strip() context.conditional_config = json.loads(config_text) @when("I route a request that needs vision") def route_vision_request(context): """Route a request that needs vision.""" config = context.conditional_config # Simulate routing decision context.routing_context = {"needs_vision": True} # Find router node router_node = config["nodes"]["router"] # Evaluate conditions for condition in router_node["conditions"]: if condition.get("if") == "needs_vision" and context.routing_context.get( "needs_vision" ): context.selected_route = { "target": condition.get("then"), "actor": condition.get("actor"), } break @then('the request should be routed to "{actor}"') def verify_routing_actor(context, actor): """Verify request is routed to correct actor.""" assert context.selected_route["actor"] == actor @then("the routing decision should be based on actor capabilities") def verify_capability_routing(context): """Verify routing is based on actor capabilities.""" # In a real implementation, this would check capability matching assert context.selected_route is not None assert "actor" in context.selected_route