Files
temp/tests/features/steps/custom_code_tool_steps.py
T

186 lines
5.9 KiB
Python

import asyncio
import json
import yaml
from behave import given
from behave import then
from behave import when
from cleveragents.agents.factory import AgentFactory
from cleveragents.core.config import ConfigurationManager
from cleveragents.core.exceptions import ConfigurationError
from cleveragents.core.exceptions import ExecutionError
from cleveragents.templates.renderer import TemplateRenderer
def _setup_context_from_text(context, config_text: str):
"""Helper to load configuration from a string."""
context.config_manager = ConfigurationManager()
config = yaml.safe_load(config_text)
context.config_manager.config = config
if not hasattr(context, "template_renderer"):
context.template_renderer = TemplateRenderer()
context.agent_factory = AgentFactory(
context.config_manager.to_dict(), context.template_renderer
)
@given("a TemplateRenderer is initialized")
def step_init_renderer(context):
context.template_renderer = TemplateRenderer()
@given(
"a configuration for a ToolAgent with a custom code tool that concatenates input with a fixed string"
)
def step_config_concat_tool(context):
_setup_context_from_text(context, context.text)
@given("a configuration for a ToolAgent with a custom code tool that accesses context")
def step_config_context_tool(context):
_setup_context_from_text(context, context.text)
@given(
"a configuration for a ToolAgent with a custom code tool that does not assign to result"
)
def step_config_no_result_tool(context):
_setup_context_from_text(context, context.text)
@given(
"a configuration for a ToolAgent with a custom code tool containing invalid Python code"
)
def step_config_error_tool(context):
_setup_context_from_text(context, context.text)
@given(
"a configuration for a ToolAgent with an invalid custom code tool config '{config_json}'"
)
def step_config_invalid_tool(context, config_json):
config_dict = json.loads(config_json)
context.config_manager = ConfigurationManager()
context.config_manager.config = config_dict
if not hasattr(context, "template_renderer"):
context.template_renderer = TemplateRenderer()
context.agent_factory = AgentFactory(
context.config_manager.to_dict(), context.template_renderer
)
@given('I create the ToolAgent named "{agent_name}"')
@when('I create the ToolAgent named "{agent_name}"')
def step_create_tool_agent(context, agent_name):
context.error = None
try:
context.agent = context.agent_factory.create_agent(agent_name)
assert context.agent is not None
except Exception as e:
context.error = e
raise AssertionError(f"Agent creation failed unexpectedly: {e}")
@when('I try to create the ToolAgent named "{agent_name}"')
def step_try_create_tool_agent(context, agent_name):
context.error = None
try:
context.agent = context.agent_factory.create_agent(agent_name)
except Exception as e:
context.error = e
@when('I process this message "{message}" with the agent')
def step_process_message(context, message):
context.response = None
context.error = None
async def run():
try:
context.response = await context.agent.process(message)
except Exception as e:
context.error = e
asyncio.run(run())
@when('I process this message "{message}" with the agent with context')
def step_process_message_with_context(context, message):
context.response = None
context.error = None
message_context = json.loads(context.text)
async def run():
try:
context.response = await context.agent.process(
message, context=message_context
)
except Exception as e:
context.error = e
asyncio.run(run())
@when('I try to process the message "{message}" with the agent')
def step_try_process_message(context, message):
context.response = None
context.error = None
async def run():
try:
context.response = await context.agent.process(message)
except Exception as e:
context.error = e
asyncio.run(run())
@then('the response should be the following "{expected_response}"')
def step_assert_response(context, expected_response):
assert context.error is None, f"Expected no error, but got {context.error}"
assert (
context.response == expected_response
), f"Expected '{expected_response}', but got '{context.response}'"
@then('the response should be the following ""')
def step_assert_response_empty(context):
"""
Step definition for asserting an empty string response.
Using an explicit pattern without a parameter avoids issues where
behave cannot capture an empty string argument.
"""
expected_response = ""
assert context.error is None, f"Expected no error, but got {context.error}"
assert (
context.response == expected_response
), f"Expected '{expected_response}', but got '{context.response}'"
@then('an ExecutionError should be raised with the message containing "{text}"')
def step_assert_execution_error(context, text):
assert (
context.error is not None
), "Expected an ExecutionError but no exception was raised."
assert isinstance(
context.error, ExecutionError
), f"Expected ExecutionError, but got {type(context.error).__name__}"
assert text in str(
context.error
), f"Expected error message to contain '{text}', but it was '{str(context.error)}'"
@then('a ConfigurationError should be raised with the message containing "{text}"')
def step_assert_configuration_error(context, text):
assert (
context.error is not None
), "Expected a ConfigurationError but no exception was raised."
assert isinstance(
context.error, ConfigurationError
), f"Expected ConfigurationError, but got {type(context.error).__name__}"
assert text in str(
context.error
), f"Expected error message to contain '{text}', but it was '{str(context.error)}'"