127 lines
6.6 KiB
Python
127 lines
6.6 KiB
Python
"""Seed data for VoIdeaAI.
|
|
|
|
Called from app lifespan when DB tables are empty.
|
|
Creates default tariff plans and sets system owner by email.
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.core.config import get_settings
|
|
from app.models.agent import AgentConfig
|
|
from app.models.tariff import TariffPlan
|
|
from app.services.user_service import UserService
|
|
|
|
settings = get_settings()
|
|
|
|
_AGENT_VERSIONS_FILE = Path(__file__).resolve().parent.parent.parent / "AGENT_VERSIONS.json"
|
|
|
|
|
|
def _load_agent_versions() -> dict[str, str]:
|
|
try:
|
|
return json.loads(_AGENT_VERSIONS_FILE.read_text(encoding="utf-8"))
|
|
except (FileNotFoundError, json.JSONDecodeError, OSError):
|
|
return {}
|
|
|
|
|
|
AGENT_DESCRIPTIONS: dict[str, str] = {
|
|
"conductor": "Дирижёр — оркестратор, единственная точка входа. Маршрутизирует запросы к ролевым агентам, верифицирует ответы.",
|
|
"business_analyst": "Бизнес-аналитик — оценивает бизнес-метрики, ROI, конкурентную среду, окупаемость идеи.",
|
|
"task_organizer": "Организатор задач — разбивает идею на конкретные шаги реализации с оценкой сроков.",
|
|
"lawyer": "Юрист — проверяет идею на соответствие законодательству РФ (44-ФЗ, 152-ФЗ, 223-ФЗ).",
|
|
"financial_consultant": "Финансовый консультант — бюджет, прогноз выручки, точка безубыточности.",
|
|
"solution_architect": "Архитектор решений — предлагает 2 варианта архитектуры: монолит и микросервисы.",
|
|
"tester": "Тестировщик — описывает сценарии тестирования (позитивные и негативные кейсы).",
|
|
"ui_designer": "UI-дизайнер — предлагает 2 варианта визуального дизайна интерфейса.",
|
|
"smm_specialist": "SMM-специалист — разрабатывает контент-план для соцсетей.",
|
|
"life_coach": "Лайф-коуч — ставит SMART-цели, поквартальные вехи развития.",
|
|
"accessibility_expert": "Эксперт по доступности — проверяет на WCAG 2.1 AA соответствие.",
|
|
"critic": "Критик — конструктивная критика, поиск «слепых зон» идеи.",
|
|
"copywriter": "Копирайтер — упаковывает идею в продающий текст для разных аудиторий.",
|
|
"keeper": "Хранитель — сохраняет проработанную идею в базу данных.",
|
|
"doc_agent": "DocAgent — автоматическая генерация и обновление документации.",
|
|
"backlog_agent": "BacklogAgent — управление бэклогом, приоритизация задач.",
|
|
"spec_agent": "SpecAgent — написание формальных спецификаций и требований.",
|
|
"audit_agent": "AuditAgent — аудит кода, архитектуры, безопасности.",
|
|
"observer_agent": "ObserverAgent — мониторинг системы, сбор метрик, алерты.",
|
|
"evolution_agent": "EvolutionAgent — автоматическое улучшение кода, рефакторинг.",
|
|
"security_agent": "SecurityAgent — проверка безопасности, уязвимости, OWASP.",
|
|
"qa_tester_agent": "QATesterAgent — автоматизированное тестирование, регресс.",
|
|
"fix_agent": "FixAgent — автоматическое исправление ошибок на основе логов.",
|
|
"ui_test_agent": "UITestAgent — тестирование UI/UX, скриншотные тесты.",
|
|
"rollout_agent": "RolloutAgent — управление релизами, миграции, откаты.",
|
|
}
|
|
|
|
|
|
async def seed_database(db: AsyncSession) -> None:
|
|
"""Seed initial data if tables are empty."""
|
|
await _seed_tariff_plans(db)
|
|
await _seed_agent_descriptions(db)
|
|
await _seed_owner(db)
|
|
|
|
|
|
async def _seed_tariff_plans(db: AsyncSession) -> None:
|
|
"""Create default Free tariff plan if none exist."""
|
|
result = await db.execute(select(TariffPlan).limit(1))
|
|
if result.scalar_one_or_none():
|
|
return
|
|
|
|
free_plan = TariffPlan(
|
|
name="Бесплатно",
|
|
code="free",
|
|
description="Базовый доступ ко всем функциям. Сейчас всё бесплатно 🎉",
|
|
price_monthly=0,
|
|
features={
|
|
"limit_ideas": None,
|
|
"limit_sessions_per_day": None,
|
|
"limit_agents": None,
|
|
"limit_team_members": None,
|
|
"limit_storage_mb": 100,
|
|
"has_voice": True,
|
|
"has_voice_commands": True,
|
|
"has_drive": True,
|
|
"has_advanced_analytics": True,
|
|
"has_api_access": True,
|
|
"has_priority_support": True,
|
|
"has_custom_branding": True,
|
|
"_promo": True,
|
|
},
|
|
is_active=True,
|
|
sort_order=0,
|
|
)
|
|
db.add(free_plan)
|
|
await db.commit()
|
|
|
|
|
|
async def _seed_agent_descriptions(db: AsyncSession) -> None:
|
|
"""Fill empty agent descriptions and update versions from AGENT_VERSIONS.json."""
|
|
agent_versions = _load_agent_versions()
|
|
result = await db.execute(select(AgentConfig))
|
|
agents = result.scalars().all()
|
|
updated = False
|
|
for agent in agents:
|
|
name = agent.agent_name.lower()
|
|
if name in AGENT_DESCRIPTIONS and (not agent.description or agent.description == ""):
|
|
agent.description = AGENT_DESCRIPTIONS[name]
|
|
updated = True
|
|
|
|
name_lower = agent.agent_name.lower()
|
|
expected_version = agent_versions.get(name_lower) or agent_versions.get(agent.agent_name)
|
|
if expected_version and agent.version != expected_version:
|
|
agent.version = expected_version
|
|
updated = True
|
|
|
|
if updated:
|
|
await db.commit()
|
|
|
|
|
|
async def _seed_owner(db: AsyncSession) -> None:
|
|
"""Set system owner by SYSTEM_OWNER_EMAIL if configured."""
|
|
if not settings.system_owner_email:
|
|
return
|
|
svc = UserService(db)
|
|
await svc.set_owner_by_email(settings.system_owner_email)
|