forked from HAL9000/cleveragents-core
186 lines
5.9 KiB
Python
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)}'"
|