forked from HAL9000/cleveragents-core
638 lines
23 KiB
Python
638 lines
23 KiB
Python
"""Step definitions for Tool Agent and Application Context Updates tests."""
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.agents.tool import _CONTEXT_UPDATES, ToolAgent
|
|
from cleveragents.context_manager import ContextManager
|
|
from cleveragents.core.application import ReactiveCleverAgentsApp
|
|
from cleveragents.reactive.stream_router import (
|
|
ReactiveStreamRouter,
|
|
StreamConfig,
|
|
StreamMessage,
|
|
)
|
|
|
|
|
|
@given("I have a configured CleverAgents application")
|
|
def step_configured_application(context: Context) -> None:
|
|
"""Set up a configured CleverAgents application."""
|
|
# Create a minimal configuration
|
|
config_content = """
|
|
agents:
|
|
test_agent:
|
|
type: tool
|
|
tool_type: python
|
|
code: |
|
|
result = "Test agent executed"
|
|
|
|
routes:
|
|
main:
|
|
type: stream
|
|
stream_type: cold
|
|
operators:
|
|
- type: map
|
|
params:
|
|
agent: test_agent
|
|
publications:
|
|
- __output__
|
|
|
|
merges:
|
|
- sources: [__input__]
|
|
target: main
|
|
"""
|
|
# Create temporary config file
|
|
import tempfile
|
|
|
|
with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
|
|
f.write(config_content)
|
|
config_path = Path(f.name)
|
|
|
|
context.app = ReactiveCleverAgentsApp([config_path], verbose=False, unsafe=True)
|
|
context.config_path = config_path
|
|
|
|
|
|
@given("I have a tool agent with Python code")
|
|
def step_tool_agent_with_code(context: Context) -> None:
|
|
"""Create a tool agent with Python code."""
|
|
from cleveragents.templates.renderer import TemplateRenderer
|
|
|
|
config = {"tools": [{"name": "test_tool", "code": 'result = "Executed"'}]}
|
|
template_renderer = TemplateRenderer()
|
|
context.tool_agent = ToolAgent(name="test_tool", config=config, template_renderer=template_renderer)
|
|
|
|
|
|
@when("the code updates the context dictionary")
|
|
def step_code_updates_context(context: Context) -> None:
|
|
"""Execute code that updates context."""
|
|
# Update the tool's code to modify context
|
|
new_code = """
|
|
context["updated_key"] = "updated_value"
|
|
context["counter"] = context.get("counter", 0) + 1
|
|
result = "Context updated"
|
|
"""
|
|
context.tool_agent.tools[0]["code"] = new_code
|
|
# Also update the python_tools dict which is actually used for execution
|
|
context.tool_agent.python_tools[context.tool_agent.tools[0]["name"]] = new_code
|
|
|
|
# Clear global updates
|
|
_CONTEXT_UPDATES.clear()
|
|
|
|
# Execute with context
|
|
context.test_context = {"initial": "value"}
|
|
|
|
async def run():
|
|
return await context.tool_agent.process_message(message="test", context=context.test_context)
|
|
|
|
context.result = asyncio.run(run())
|
|
|
|
|
|
@then("the context changes should be saved globally")
|
|
def step_context_saved_globally(context: Context) -> None:
|
|
"""Verify context changes are saved globally."""
|
|
# Check if context was modified
|
|
assert "updated_key" in context.test_context
|
|
assert context.test_context["updated_key"] == "updated_value"
|
|
|
|
|
|
@then("the changes should be available after execution")
|
|
def step_changes_available_after(context: Context) -> None:
|
|
"""Verify changes persist after execution."""
|
|
assert context.test_context.get("counter") == 1
|
|
assert context.test_context.get("initial") == "value"
|
|
|
|
|
|
@when("the code is executed without providing context")
|
|
def step_execute_without_context(context: Context) -> None:
|
|
"""Execute tool without context."""
|
|
_CONTEXT_UPDATES.clear()
|
|
|
|
async def run():
|
|
return await context.tool_agent.process_message(message="test", context=None)
|
|
|
|
context.result = asyncio.run(run())
|
|
|
|
|
|
@then("the execution should complete without errors")
|
|
def step_execution_completes_without_errors(context: Context) -> None:
|
|
"""Verify execution completes successfully."""
|
|
assert context.result is not None
|
|
|
|
|
|
@then("no context updates should be saved")
|
|
def step_no_context_updates_saved(context: Context) -> None:
|
|
"""Verify no context updates were saved."""
|
|
assert len(_CONTEXT_UPDATES) == 0
|
|
|
|
|
|
@given("I have multiple tool agents")
|
|
def step_multiple_tool_agents(context: Context) -> None:
|
|
"""Create multiple tool agents."""
|
|
from cleveragents.templates.renderer import TemplateRenderer
|
|
|
|
template_renderer = TemplateRenderer()
|
|
context.tool_agents = [
|
|
ToolAgent(
|
|
name="tool1",
|
|
config={
|
|
"tools": [
|
|
{
|
|
"name": "tool1",
|
|
"code": 'context["tool1_key"] = "value1"\nresult = "Tool 1"',
|
|
}
|
|
]
|
|
},
|
|
template_renderer=template_renderer,
|
|
),
|
|
ToolAgent(
|
|
name="tool2",
|
|
config={
|
|
"tools": [
|
|
{
|
|
"name": "tool2",
|
|
"code": 'context["tool2_key"] = "value2"\nresult = "Tool 2"',
|
|
}
|
|
]
|
|
},
|
|
template_renderer=template_renderer,
|
|
),
|
|
ToolAgent(
|
|
name="tool3",
|
|
config={
|
|
"tools": [
|
|
{
|
|
"name": "tool3",
|
|
"code": 'context["tool3_key"] = "value3"\nresult = "Tool 3"',
|
|
}
|
|
]
|
|
},
|
|
template_renderer=template_renderer,
|
|
),
|
|
]
|
|
|
|
|
|
@when("each tool updates different context keys")
|
|
def step_each_tool_updates_context(context: Context) -> None:
|
|
"""Execute each tool with context updates."""
|
|
_CONTEXT_UPDATES.clear()
|
|
context.shared_context = {}
|
|
|
|
async def run():
|
|
for agent in context.tool_agents:
|
|
await agent.process_message(message="test", context=context.shared_context)
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
@then("all context updates should be collected in _CONTEXT_UPDATES")
|
|
def step_all_updates_collected(context: Context) -> None:
|
|
"""Verify all updates are collected."""
|
|
# Updates might be collected in the shared context directly
|
|
assert "tool1_key" in context.shared_context
|
|
assert "tool2_key" in context.shared_context
|
|
assert "tool3_key" in context.shared_context
|
|
|
|
|
|
@then("the updates should be merged into the global context")
|
|
def step_updates_merged_global(context: Context) -> None:
|
|
"""Verify updates are merged into global context."""
|
|
assert context.shared_context["tool1_key"] == "value1"
|
|
assert context.shared_context["tool2_key"] == "value2"
|
|
assert context.shared_context["tool3_key"] == "value3"
|
|
|
|
|
|
@given("I have an application with context-aware agents")
|
|
def step_application_with_context_agents(context: Context) -> None:
|
|
"""Create application with context-aware agents."""
|
|
# Application already created in background
|
|
pass
|
|
|
|
|
|
@when("I run the application in single-shot mode")
|
|
def step_run_application_single_shot(context: Context) -> None:
|
|
"""Run application in single-shot mode."""
|
|
|
|
async def run_async():
|
|
return await context.app.run_single_shot("Test message")
|
|
|
|
context.single_shot_result = asyncio.run(run_async())
|
|
|
|
|
|
@then("context updates from all streams should be collected")
|
|
def step_context_updates_collected_from_streams(context: Context) -> None:
|
|
"""Verify context updates are collected from streams."""
|
|
# Check that the app's global context exists
|
|
assert context.app.config is not None
|
|
assert hasattr(context.app.config, "global_context")
|
|
|
|
|
|
@then("the global context should be updated with all changes")
|
|
def step_global_context_updated(context: Context) -> None:
|
|
"""Verify global context contains updates."""
|
|
# Global context should exist and be a dict
|
|
assert isinstance(context.app.config.global_context, dict)
|
|
|
|
|
|
@given("I have a StreamMessage with context metadata")
|
|
def step_stream_message_with_context(context: Context) -> None:
|
|
"""Create a StreamMessage with context metadata."""
|
|
context.original_context = {"key": "value", "mutable": [1, 2, 3]}
|
|
context.stream_message = StreamMessage(
|
|
content="Test content",
|
|
metadata={"context": context.original_context},
|
|
source_stream="test",
|
|
)
|
|
|
|
|
|
@when("the message is copied with modifications")
|
|
def step_message_copied_with_mods(context: Context) -> None:
|
|
"""Copy message with modifications."""
|
|
context.copied_message = context.stream_message.copy_with(content="Modified content")
|
|
|
|
|
|
@then("the context reference should be preserved")
|
|
def step_context_reference_preserved(context: Context) -> None:
|
|
"""Verify context reference is preserved."""
|
|
# Check that context in metadata points to same object
|
|
assert "context" in context.copied_message.metadata
|
|
assert context.copied_message.metadata["context"] is context.original_context
|
|
|
|
|
|
@then("modifications to the context should affect the original")
|
|
def step_context_mods_affect_original(context: Context) -> None:
|
|
"""Verify context modifications affect original."""
|
|
# Modify through copied message's context
|
|
context.copied_message.metadata["context"]["new_key"] = "new_value"
|
|
# Check original has the modification
|
|
assert context.original_context["new_key"] == "new_value"
|
|
|
|
|
|
@given("I have a stream router with global context")
|
|
def step_stream_router_with_global_context(context: Context) -> None:
|
|
"""Create stream router with global context."""
|
|
context.stream_router = ReactiveStreamRouter()
|
|
context.global_context_ref = {"global": "context"}
|
|
context.stream_router._global_context_ref = context.global_context_ref
|
|
|
|
|
|
@when("messages flow through the router")
|
|
def step_messages_flow_through_router(context: Context) -> None:
|
|
"""Send messages through the router."""
|
|
# Create streams
|
|
context.stream_router.create_stream(StreamConfig(name="input"))
|
|
context.stream_router.create_stream(StreamConfig(name="output"))
|
|
|
|
# Send message
|
|
context.stream_router.send_message("input", "Test message", {"context": context.global_context_ref})
|
|
|
|
|
|
@then("the global context reference should be maintained")
|
|
def step_global_context_ref_maintained(context: Context) -> None:
|
|
"""Verify global context reference is maintained."""
|
|
assert hasattr(context.stream_router, "_global_context_ref")
|
|
assert context.stream_router._global_context_ref is context.global_context_ref
|
|
|
|
|
|
@then("context updates should be applied to the same object")
|
|
def step_context_updates_same_object(context: Context) -> None:
|
|
"""Verify updates apply to same context object."""
|
|
# Modify the global context
|
|
context.global_context_ref["updated"] = True
|
|
# Check it's the same object
|
|
assert context.stream_router._global_context_ref["updated"] is True
|
|
|
|
|
|
@given("I have context updates with different writing_stage values")
|
|
def step_context_updates_with_writing_stages(context: Context) -> None:
|
|
"""Create context updates with various writing_stage values."""
|
|
context.context_updates = [
|
|
{"writing_stage": "intro", "data": "intro_data"},
|
|
{"writing_stage": "planning", "data": "planning_data"},
|
|
{"writing_stage": "drafting", "data": "drafting_data"},
|
|
{"writing_stage": "intro", "other": "value"},
|
|
{"writing_stage": "reviewing", "data": "reviewing_data"},
|
|
]
|
|
|
|
|
|
@when("the application processes the updates")
|
|
def step_application_processes_updates(context: Context) -> None:
|
|
"""Process context updates like the application does."""
|
|
context.merged_context = {}
|
|
|
|
for update in context.context_updates:
|
|
if update.get("writing_stage") != "intro":
|
|
context.merged_context.update(update)
|
|
|
|
|
|
@then("only non-intro writing_stage updates should be merged")
|
|
def step_non_intro_updates_merged(context: Context) -> None:
|
|
"""Verify only non-intro updates are merged."""
|
|
assert "intro_data" not in context.merged_context.values()
|
|
assert context.merged_context.get("writing_stage") != "intro"
|
|
|
|
|
|
@then("intro stage updates should be ignored")
|
|
def step_intro_updates_ignored(context: Context) -> None:
|
|
"""Verify intro updates are ignored."""
|
|
# Since each update overwrites the previous one (same keys),
|
|
# we should only have the last non-intro update
|
|
assert "intro_data" not in context.merged_context.values()
|
|
# The last update was 'reviewing' so we should have that
|
|
assert context.merged_context.get("writing_stage") == "reviewing"
|
|
assert context.merged_context.get("data") == "reviewing_data"
|
|
|
|
|
|
@given("I run the CLI with --context option")
|
|
def step_run_cli_with_context_option(context: Context) -> None:
|
|
"""Simulate running CLI with context option."""
|
|
import tempfile
|
|
|
|
context.temp_dir = Path(tempfile.mkdtemp())
|
|
context.cli_context_name = "test_cli_context"
|
|
context.cli_prompt = "Test prompt"
|
|
|
|
|
|
@when("the command completes successfully")
|
|
def step_cli_command_completes(context: Context) -> None:
|
|
"""Simulate successful CLI command completion."""
|
|
# Simulate context manager behavior
|
|
context.cli_context_manager = ContextManager(context.cli_context_name, context.temp_dir)
|
|
context.cli_context_manager.add_message("user", context.cli_prompt)
|
|
context.cli_context_manager.add_message("assistant", "Test response")
|
|
context.cli_context_manager.save()
|
|
|
|
|
|
@then("the conversation should be saved to the context")
|
|
def step_conversation_saved_to_context(context: Context) -> None:
|
|
"""Verify conversation is saved."""
|
|
assert len(context.cli_context_manager.messages) == 2
|
|
assert context.cli_context_manager.messages[0]["content"] == context.cli_prompt
|
|
|
|
|
|
@then("the global context should be persisted")
|
|
def step_global_context_persisted(context: Context) -> None:
|
|
"""Verify global context is persisted."""
|
|
context.cli_context_manager.save_global_context({"test": "global"})
|
|
|
|
# Reload and verify
|
|
new_manager = ContextManager(context.cli_context_name, context.temp_dir)
|
|
assert new_manager.global_context.get("test") == "global"
|
|
|
|
|
|
@given("I have an existing context with conversation history")
|
|
def step_existing_context_with_history(context: Context) -> None:
|
|
"""Create existing context with history."""
|
|
import tempfile
|
|
|
|
context.temp_dir = Path(tempfile.mkdtemp())
|
|
context.existing_context_name = "existing_context"
|
|
|
|
manager = ContextManager(context.existing_context_name, context.temp_dir)
|
|
manager.add_message("user", "Previous question")
|
|
manager.add_message("assistant", "Previous answer")
|
|
manager.save_global_context({"state": "previous"})
|
|
manager.save()
|
|
|
|
|
|
@when("I run the CLI with the same context name")
|
|
def step_run_cli_same_context(context: Context) -> None:
|
|
"""Run CLI with same context name."""
|
|
context.reloaded_manager = ContextManager(context.existing_context_name, context.temp_dir)
|
|
|
|
|
|
@then("the previous global context should be restored")
|
|
def step_previous_global_context_restored(context: Context) -> None:
|
|
"""Verify previous global context is restored."""
|
|
assert context.reloaded_manager.global_context.get("state") == "previous"
|
|
|
|
|
|
@then("the conversation should continue from the previous state")
|
|
def step_conversation_continues(context: Context) -> None:
|
|
"""Verify conversation continues from previous state."""
|
|
assert len(context.reloaded_manager.messages) == 2
|
|
assert context.reloaded_manager.messages[0]["content"] == "Previous question"
|
|
|
|
|
|
@given("I start an interactive session with a context manager")
|
|
def step_start_interactive_with_context(context: Context) -> None:
|
|
"""Start interactive session with context manager."""
|
|
import tempfile
|
|
|
|
context.temp_dir = Path(tempfile.mkdtemp())
|
|
context.interactive_context = ContextManager("interactive", context.temp_dir)
|
|
|
|
|
|
@when("I send messages and receive responses")
|
|
def step_send_receive_messages(context: Context) -> None:
|
|
"""Simulate sending and receiving messages."""
|
|
context.interactive_context.add_message("user", "Hello")
|
|
context.interactive_context.add_message("assistant", "Hi there!")
|
|
context.interactive_context.add_message("user", "How are you?")
|
|
context.interactive_context.add_message("assistant", "I'm doing well!")
|
|
|
|
|
|
@then("each exchange should be saved to the context")
|
|
def step_exchanges_saved(context: Context) -> None:
|
|
"""Verify exchanges are saved."""
|
|
assert len(context.interactive_context.messages) == 4
|
|
|
|
|
|
@then("the conversation history should be preserved")
|
|
def step_history_preserved(context: Context) -> None:
|
|
"""Verify conversation history is preserved."""
|
|
context.interactive_context.save()
|
|
|
|
# Reload and verify
|
|
new_manager = ContextManager("interactive", context.temp_dir)
|
|
assert len(new_manager.messages) == 4
|
|
|
|
|
|
@given("I have multiple agents updating context simultaneously")
|
|
def step_multiple_agents_concurrent(context: Context) -> None:
|
|
"""Set up multiple agents for concurrent updates."""
|
|
context.concurrent_contexts = []
|
|
for i in range(5):
|
|
ctx = {"agent_id": f"agent_{i}"}
|
|
context.concurrent_contexts.append(ctx)
|
|
|
|
|
|
@when("they all complete their updates")
|
|
def step_all_complete_updates(context: Context) -> None:
|
|
"""Simulate all agents completing updates."""
|
|
context.all_updates = {}
|
|
for i, ctx in enumerate(context.concurrent_contexts):
|
|
ctx[f"update_{i}"] = f"value_{i}"
|
|
context.all_updates.update(ctx)
|
|
|
|
|
|
@then("all updates should be captured without data loss")
|
|
def step_all_updates_captured(context: Context) -> None:
|
|
"""Verify all updates are captured."""
|
|
# We should have the last agent_id value (they overwrite each other)
|
|
assert "agent_id" in context.all_updates
|
|
# But we should have all the individual updates
|
|
for i in range(5):
|
|
assert f"update_{i}" in context.all_updates
|
|
assert context.all_updates[f"update_{i}"] == f"value_{i}"
|
|
|
|
|
|
@then("the final context should contain all changes")
|
|
def step_final_context_has_all_changes(context: Context) -> None:
|
|
"""Verify final context has all changes."""
|
|
# Should have agent_id + 5 update fields
|
|
assert len(context.all_updates) >= 6 # 1 agent_id + 5 updates
|
|
|
|
|
|
@given("I have a tool agent with code that modifies context in place")
|
|
def step_tool_agent_modifies_in_place(context: Context) -> None:
|
|
"""Create tool that modifies context in place."""
|
|
from cleveragents.templates.renderer import TemplateRenderer
|
|
|
|
config = {
|
|
"tools": [
|
|
{
|
|
"name": "in_place",
|
|
"code": """
|
|
context["modified"] = True
|
|
context["list"].append(4)
|
|
result = "Modified in place"
|
|
""",
|
|
}
|
|
]
|
|
}
|
|
template_renderer = TemplateRenderer()
|
|
context.in_place_tool = ToolAgent(name="in_place", config=config, template_renderer=template_renderer)
|
|
|
|
|
|
@when("the code executes with exec()")
|
|
def step_code_executes_with_exec(context: Context) -> None:
|
|
"""Execute code with exec."""
|
|
context.exec_context = {"list": [1, 2, 3], "original": True}
|
|
|
|
async def run():
|
|
return await context.in_place_tool.process_message(message="test", context=context.exec_context)
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
@then("the original context object should be modified")
|
|
def step_original_context_modified(context: Context) -> None:
|
|
"""Verify original context is modified."""
|
|
assert context.exec_context["modified"] is True
|
|
assert context.exec_context["list"] == [1, 2, 3, 4]
|
|
assert context.exec_context["original"] is True
|
|
|
|
|
|
@then("no deep copying should occur")
|
|
def step_no_deep_copying(context: Context) -> None:
|
|
"""Verify no deep copying occurred."""
|
|
# The list should have been modified in place
|
|
assert len(context.exec_context["list"]) == 4
|
|
|
|
|
|
@given("I have agents that may or may not update context")
|
|
def step_agents_optional_updates(context: Context) -> None:
|
|
"""Create agents with optional context updates."""
|
|
context.optional_updates = [
|
|
{"agent": "agent1", "update": {"key1": "value1"}},
|
|
{"agent": "agent2", "update": {}}, # Empty update
|
|
{"agent": "agent3", "update": {"key3": "value3"}},
|
|
{"agent": "agent4", "update": None}, # No update
|
|
{"agent": "agent5", "update": {"key5": "value5"}},
|
|
]
|
|
|
|
|
|
@when("some agents return empty context updates")
|
|
def step_some_agents_empty_updates(context: Context) -> None:
|
|
"""Process updates including empty ones."""
|
|
context.processed_updates = {}
|
|
for item in context.optional_updates:
|
|
update = item.get("update")
|
|
if update and isinstance(update, dict) and update:
|
|
context.processed_updates.update(update)
|
|
|
|
|
|
@then("only non-empty updates should be processed")
|
|
def step_only_non_empty_processed(context: Context) -> None:
|
|
"""Verify only non-empty updates are processed."""
|
|
assert "key1" in context.processed_updates
|
|
assert "key3" in context.processed_updates
|
|
assert "key5" in context.processed_updates
|
|
assert len(context.processed_updates) == 3
|
|
|
|
|
|
@then("the application should not crash")
|
|
def step_application_not_crash(context: Context) -> None:
|
|
"""Verify application handles empty updates gracefully."""
|
|
# The processing completed without errors
|
|
assert context.processed_updates is not None
|
|
|
|
|
|
@given("I have input, processing, and output streams")
|
|
def step_multiple_stream_types(context: Context) -> None:
|
|
"""Create multiple stream types."""
|
|
context.multi_router = ReactiveStreamRouter()
|
|
context.multi_router.create_stream("input")
|
|
context.multi_router.create_stream("processing")
|
|
context.multi_router.create_stream("output")
|
|
context.stream_contexts = {}
|
|
|
|
|
|
@when("each stream type updates context")
|
|
def step_each_stream_updates(context: Context) -> None:
|
|
"""Each stream updates context."""
|
|
context.stream_contexts["input"] = {"source": "input"}
|
|
context.stream_contexts["processing"] = {"stage": "processing"}
|
|
context.stream_contexts["output"] = {"result": "output"}
|
|
|
|
|
|
@then("updates from all stream types should be collected")
|
|
def step_updates_from_all_streams(context: Context) -> None:
|
|
"""Verify updates from all streams are collected."""
|
|
assert len(context.stream_contexts) == 3
|
|
assert "input" in context.stream_contexts
|
|
assert "processing" in context.stream_contexts
|
|
assert "output" in context.stream_contexts
|
|
|
|
|
|
@then("no updates should be lost")
|
|
def step_no_updates_lost(context: Context) -> None:
|
|
"""Verify no updates are lost."""
|
|
assert context.stream_contexts["input"]["source"] == "input"
|
|
assert context.stream_contexts["processing"]["stage"] == "processing"
|
|
assert context.stream_contexts["output"]["result"] == "output"
|
|
|
|
|
|
@given("I specify a custom context directory")
|
|
def step_specify_custom_directory(context: Context) -> None:
|
|
"""Specify custom context directory."""
|
|
import tempfile
|
|
|
|
context.custom_dir = Path(tempfile.mkdtemp()) / "custom_contexts"
|
|
context.custom_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
@when("I use context management commands")
|
|
def step_use_context_commands(context: Context) -> None:
|
|
"""Use context management commands with custom directory."""
|
|
context.custom_manager = ContextManager("custom", context.custom_dir)
|
|
context.custom_manager.add_message("user", "Custom directory test")
|
|
context.custom_manager.save()
|
|
|
|
|
|
@then("all operations should use the custom directory")
|
|
def step_operations_use_custom_dir(context: Context) -> None:
|
|
"""Verify operations use custom directory."""
|
|
assert context.custom_manager.context_dir.parent == context.custom_dir
|
|
|
|
|
|
@then("contexts should be isolated from default location")
|
|
def step_contexts_isolated(context: Context) -> None:
|
|
"""Verify contexts are isolated from default location."""
|
|
# Default location should not contain this context
|
|
default_dir = Path.home() / ".cleveragents" / "context"
|
|
if default_dir.exists():
|
|
assert "custom" not in [d.name for d in default_dir.iterdir()]
|