# tests/models/syndarix/test_agent_instance.py """ Unit tests for the AgentInstance model. """ import uuid from datetime import UTC, datetime from decimal import Decimal from app.models.syndarix import ( AgentInstance, AgentStatus, AgentType, Project, ) class TestAgentInstanceModel: """Tests for AgentInstance model creation and fields.""" def test_create_agent_instance_with_required_fields(self, db_session): """Test creating an agent instance with only required fields.""" # First create dependencies project = Project( id=uuid.uuid4(), name="Test Project", slug="test-project-instance", ) db_session.add(project) agent_type = AgentType( id=uuid.uuid4(), name="Test Agent", slug="test-agent-instance", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(agent_type) db_session.commit() # Create agent instance instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Alice", ) db_session.add(instance) db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(project_id=project.id).first() assert retrieved is not None assert retrieved.agent_type_id == agent_type.id assert retrieved.project_id == project.id assert retrieved.status == AgentStatus.IDLE # Default assert retrieved.current_task is None assert retrieved.short_term_memory == {} assert retrieved.long_term_memory_ref is None assert retrieved.session_id is None assert retrieved.tasks_completed == 0 assert retrieved.tokens_used == 0 assert retrieved.cost_incurred == Decimal("0") def test_create_agent_instance_with_all_fields(self, db_session): """Test creating an agent instance with all optional fields.""" # First create dependencies project = Project( id=uuid.uuid4(), name="Full Project", slug="full-project-instance", ) db_session.add(project) agent_type = AgentType( id=uuid.uuid4(), name="Full Agent", slug="full-agent-instance", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(agent_type) db_session.commit() instance_id = uuid.uuid4() now = datetime.now(UTC) instance = AgentInstance( id=instance_id, agent_type_id=agent_type.id, project_id=project.id, name="Bob", status=AgentStatus.WORKING, current_task="Implementing user authentication", short_term_memory={"context": "Working on auth", "recent_files": ["auth.py"]}, long_term_memory_ref="project-123/agent-456", session_id="session-abc-123", last_activity_at=now, tasks_completed=5, tokens_used=10000, cost_incurred=Decimal("0.5000"), ) db_session.add(instance) db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance_id).first() assert retrieved.status == AgentStatus.WORKING assert retrieved.current_task == "Implementing user authentication" assert retrieved.short_term_memory == {"context": "Working on auth", "recent_files": ["auth.py"]} assert retrieved.long_term_memory_ref == "project-123/agent-456" assert retrieved.session_id == "session-abc-123" assert retrieved.tasks_completed == 5 assert retrieved.tokens_used == 10000 assert retrieved.cost_incurred == Decimal("0.5000") def test_agent_instance_timestamps(self, db_session): """Test that timestamps are automatically set.""" project = Project(id=uuid.uuid4(), name="Timestamp Project", slug="timestamp-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Timestamp Agent", slug="timestamp-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Charlie", ) db_session.add(instance) db_session.commit() assert isinstance(instance.created_at, datetime) assert isinstance(instance.updated_at, datetime) def test_agent_instance_string_representation(self, db_session): """Test the string representation of an agent instance.""" project = Project(id=uuid.uuid4(), name="Repr Project", slug="repr-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Repr Agent", slug="repr-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance_id = uuid.uuid4() instance = AgentInstance( id=instance_id, agent_type_id=agent_type.id, project_id=project.id, name="Dave", status=AgentStatus.IDLE, ) repr_str = repr(instance) assert "Dave" in repr_str assert str(instance_id) in repr_str assert str(agent_type.id) in repr_str assert str(project.id) in repr_str assert "idle" in repr_str class TestAgentInstanceStatus: """Tests for AgentInstance status transitions.""" def test_all_agent_statuses(self, db_session): """Test that all agent statuses can be stored.""" project = Project(id=uuid.uuid4(), name="Status Project", slug="status-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Status Agent", slug="status-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() for idx, status in enumerate(AgentStatus): instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name=f"Agent-{idx}", status=status, ) db_session.add(instance) db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.status == status def test_status_update(self, db_session): """Test updating agent instance status.""" project = Project(id=uuid.uuid4(), name="Update Status Project", slug="update-status-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Update Status Agent", slug="update-status-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Eve", status=AgentStatus.IDLE, ) db_session.add(instance) db_session.commit() # Update to WORKING instance.status = AgentStatus.WORKING instance.current_task = "Processing feature request" db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.status == AgentStatus.WORKING assert retrieved.current_task == "Processing feature request" def test_terminate_agent_instance(self, db_session): """Test terminating an agent instance.""" project = Project(id=uuid.uuid4(), name="Terminate Project", slug="terminate-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Terminate Agent", slug="terminate-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Frank", status=AgentStatus.WORKING, current_task="Working on something", session_id="active-session", ) db_session.add(instance) db_session.commit() # Terminate now = datetime.now(UTC) instance.status = AgentStatus.TERMINATED instance.terminated_at = now instance.current_task = None instance.session_id = None db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.status == AgentStatus.TERMINATED assert retrieved.terminated_at is not None assert retrieved.current_task is None assert retrieved.session_id is None class TestAgentInstanceMetrics: """Tests for AgentInstance usage metrics.""" def test_increment_metrics(self, db_session): """Test incrementing usage metrics.""" project = Project(id=uuid.uuid4(), name="Metrics Project", slug="metrics-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Metrics Agent", slug="metrics-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Grace", ) db_session.add(instance) db_session.commit() # Record task completion instance.tasks_completed += 1 instance.tokens_used += 1500 instance.cost_incurred += Decimal("0.0150") db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.tasks_completed == 1 assert retrieved.tokens_used == 1500 assert retrieved.cost_incurred == Decimal("0.0150") # Record another task retrieved.tasks_completed += 1 retrieved.tokens_used += 2500 retrieved.cost_incurred += Decimal("0.0250") db_session.commit() updated = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert updated.tasks_completed == 2 assert updated.tokens_used == 4000 assert updated.cost_incurred == Decimal("0.0400") def test_large_token_count(self, db_session): """Test handling large token counts.""" project = Project(id=uuid.uuid4(), name="Large Tokens Project", slug="large-tokens-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Large Tokens Agent", slug="large-tokens-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Henry", tokens_used=10_000_000_000, # 10 billion tokens cost_incurred=Decimal("100000.0000"), # $100,000 ) db_session.add(instance) db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.tokens_used == 10_000_000_000 assert retrieved.cost_incurred == Decimal("100000.0000") class TestAgentInstanceShortTermMemory: """Tests for AgentInstance short-term memory JSON field.""" def test_store_complex_memory(self, db_session): """Test storing complex short-term memory.""" project = Project(id=uuid.uuid4(), name="Memory Project", slug="memory-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Memory Agent", slug="memory-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() memory = { "conversation_history": [ {"role": "user", "content": "Implement feature X"}, {"role": "assistant", "content": "I'll start by..."}, ], "recent_files": ["auth.py", "models.py", "test_auth.py"], "decisions": { "architecture": "Use repository pattern", "testing": "TDD approach", }, "blockers": [], "context_tokens": 2048, } instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Ivy", short_term_memory=memory, ) db_session.add(instance) db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert retrieved.short_term_memory == memory assert len(retrieved.short_term_memory["conversation_history"]) == 2 assert "auth.py" in retrieved.short_term_memory["recent_files"] def test_update_memory(self, db_session): """Test updating short-term memory.""" project = Project(id=uuid.uuid4(), name="Update Memory Project", slug="update-memory-project-ai") agent_type = AgentType( id=uuid.uuid4(), name="Update Memory Agent", slug="update-memory-agent-ai", personality_prompt="Test", primary_model="claude-opus-4-5-20251101", ) db_session.add(project) db_session.add(agent_type) db_session.commit() instance = AgentInstance( id=uuid.uuid4(), agent_type_id=agent_type.id, project_id=project.id, name="Jack", short_term_memory={"initial": "state"}, ) db_session.add(instance) db_session.commit() # Update memory instance.short_term_memory = {"updated": "state", "new_key": "new_value"} db_session.commit() retrieved = db_session.query(AgentInstance).filter_by(id=instance.id).first() assert "initial" not in retrieved.short_term_memory assert retrieved.short_term_memory["updated"] == "state" assert retrieved.short_term_memory["new_key"] == "new_value"