feat: complete phase 2 -- multi-agent routing, interrupt TTL, escalation, templates
- Intent classification with LLM structured output (single/multi/ambiguous) - Discount agent with apply_discount and generate_coupon tools - Interrupt manager with 30-min TTL auto-expiration and retry prompts - Webhook escalation module with exponential backoff retry (max 3) - Three vertical industry templates (e-commerce, SaaS, fintech) - Template loading in AgentRegistry - Enhanced supervisor prompt with dynamic agent descriptions - 153 tests passing, 90.18% coverage
This commit is contained in:
70
backend/tests/unit/test_templates.py
Normal file
70
backend/tests/unit/test_templates.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""Tests for template loading in app.registry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from app.registry import AgentRegistry
|
||||
|
||||
TEMPLATES_DIR = Path(__file__).parent.parent.parent / "templates"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestListTemplates:
|
||||
def test_lists_all_templates(self) -> None:
|
||||
templates = AgentRegistry.list_templates(TEMPLATES_DIR)
|
||||
assert "e-commerce" in templates
|
||||
assert "saas" in templates
|
||||
assert "fintech" in templates
|
||||
|
||||
def test_returns_sorted(self) -> None:
|
||||
templates = AgentRegistry.list_templates(TEMPLATES_DIR)
|
||||
assert templates == tuple(sorted(templates))
|
||||
|
||||
def test_empty_dir_returns_empty(self, tmp_path: Path) -> None:
|
||||
templates = AgentRegistry.list_templates(tmp_path)
|
||||
assert templates == ()
|
||||
|
||||
def test_nonexistent_dir_returns_empty(self) -> None:
|
||||
templates = AgentRegistry.list_templates("/nonexistent/path")
|
||||
assert templates == ()
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestLoadTemplate:
|
||||
def test_load_ecommerce(self) -> None:
|
||||
registry = AgentRegistry.load_template("e-commerce", TEMPLATES_DIR)
|
||||
assert len(registry) == 4
|
||||
agents = registry.list_agents()
|
||||
names = {a.name for a in agents}
|
||||
assert "order_lookup" in names
|
||||
assert "discount" in names
|
||||
assert "fallback" in names
|
||||
|
||||
def test_load_saas(self) -> None:
|
||||
registry = AgentRegistry.load_template("saas", TEMPLATES_DIR)
|
||||
assert len(registry) == 3
|
||||
agents = registry.list_agents()
|
||||
names = {a.name for a in agents}
|
||||
assert "account_lookup" in names
|
||||
assert "subscription_management" in names
|
||||
|
||||
def test_load_fintech(self) -> None:
|
||||
registry = AgentRegistry.load_template("fintech", TEMPLATES_DIR)
|
||||
assert len(registry) == 3
|
||||
agents = registry.list_agents()
|
||||
names = {a.name for a in agents}
|
||||
assert "transaction_lookup" in names
|
||||
assert "dispute_handler" in names
|
||||
|
||||
def test_nonexistent_template_raises(self) -> None:
|
||||
with pytest.raises(FileNotFoundError, match="not found"):
|
||||
AgentRegistry.load_template("nonexistent", TEMPLATES_DIR)
|
||||
|
||||
def test_error_message_lists_available(self) -> None:
|
||||
try:
|
||||
AgentRegistry.load_template("nonexistent", TEMPLATES_DIR)
|
||||
except FileNotFoundError as exc:
|
||||
assert "e-commerce" in str(exc)
|
||||
Reference in New Issue
Block a user