Initial commit: VoIdeaAI - voice-first AI idea assistant

This commit is contained in:
2026-05-13 12:51:42 +03:00
commit 688d043dad
421 changed files with 47915 additions and 0 deletions
+316
View File
@@ -0,0 +1,316 @@
# Полная спецификация проекта для ИИ-ассистента
Этот файл — единственный источник истины для ИИ, работающего с проектом.
Прочитай его полностью перед началом любой работы. Если какой-то аспект не описан — спроси.
---
## 1. РОЛИ
- **Ты — ИИ-ассистент.** Твоя задача: писать код, соответствующий правилам проекта.
- **Пользователь — владелец проекта.** Он принимает все стратегические решения.
- **Агенты — автоматические участники.** Они следят за качеством, версиями и эволюцией.
---
## 2. СТРУКТУРА ПРОЕКТА (MUST FOLLOW)
```
project/
├── app/ # Backend (Python FastAPI)
│ ├── __init__.py
│ ├── main.py # FastAPI app, lifespan, middleware
│ ├── api/
│ │ └── v1/ # Версионированные роуты
│ │ ├── __init__.py # api_v1_router = APIRouter(prefix="/api/v1")
│ │ ├── auth.py # POST /login, /register, /refresh, /oauth
│ │ ├── users.py # GET/PATCH /me
│ │ ├── ideas.py # CRUD /ideas + POST /analyze
│ │ ├── agents.py # GET /agents + POST /run
│ │ ├── sync.py # POST /sync/pull, /sync/push
│ │ └── admin.py # GET /users, /health, /logs
│ ├── core/
│ │ ├── __init__.py
│ │ ├── config.py # Pydantic Settings из .env
│ │ ├── base.py # SQLBase, CoreModel, UUIDMixin, TimestampMixin
│ │ ├── database.py # Engine + async_session_maker + get_db
│ │ ├── security.py # JWT create/decode, password hash
│ │ ├── exceptions.py # HTTPException подклассы
│ │ ├── dependencies.py # get_db, get_current_user, require_admin
│ │ └── metrics.py # Middleware для сбора метрик
│ ├── models/ # SQLAlchemy модели
│ ├── schemas/ # Pydantic схемы (Request/Response)
│ ├── services/ # Бизнес-логика
│ ├── integrations/ # AI провайдеры, внешние API
│ ├── tasks/ # Celery задачи (или прямой вызов)
│ └── agents/ # Системные агенты
├── webui/ # Frontend (React + Vite + Tailwind)
│ ├── src/
│ │ ├── main.tsx
│ │ ├── App.tsx # BrowserRouter + Routes
│ │ ├── index.css # Tailwind directives
│ │ ├── api/ # HTTP-клиент, типы запросов
│ │ ├── auth/ # AuthContext, login/register
│ │ ├── components/ # Layout, ProtectedRoute
│ │ └── pages/ # Dashboard, IdeaView, Admin
│ └── vite.config.ts # Vite + React + PWA proxy
├── tests/ # pytest тесты
├── docs/ # Документация
├── CHANGELOG/ # Версионирование
├── migrations/ # Alembic миграции
├── .env.example
└── project.yaml
```
## 3. ПРАВИЛА КОДИРОВАНИЯ (MUST FOLLOW)
### 3.1 Python
- **Версия:** Python 3.12+
- **Типизация:** `from __future__ import annotations` во всех файлах, `X | None` вместо `Optional[X]`
- **Строки:** двойные кавычки `"` для строковых литералов, одинарные `'` для docstrings
- **Длина строки:** 88 символов (ruff format)
- **Импорты:** абсолютные, порядок: stdlib → third-party → local (алфавитный внутри групп)
- **Docstrings:** Google-style для всех публичных классов/функций/методов
- **Именование:** классы PascalCase, функции/переменные snake_case, константы UPPER_SNAKE
- **Линтер:** ruff (E, F, W, I, N, UP)
- **Форматтер:** ruff format
### 3.2 SQL
- **Ключевые слова:** UPPERCASE (SELECT, FROM, WHERE)
- **Таблицы/поля:** snake_case
- **Индексы:** `ix_tablename_column`
- **Уникальность:** `uq_tablename_column`
### 3.3 TypeScript/React
- **Форматтер:** Prettier (100 символов)
- **Типы:** strict TypeScript, `any` запрещён
- **Импорты:** абсолютные через `@/` alias
- **Стили:** Tailwind CSS, никаких CSS-in-JS
- **Асинхронность:** async/await, `.then()` запрещён
- **Состояние:** zustand или React Context
## 4. АРХИТЕКТУРА (MUST FOLLOW)
### 4.1 Слои (зависимости только внутрь)
```
API → Services → Integrations → Data → Core
```
- **API** не знает про БД. Не создаёт сессий. Только Depends(get_db).
- **Services** не знают про HTTP. Не импортируют FastAPI/fastapi. Работают с БД через сессию.
- **Integrations** не знают про бизнес-логику. Оборачивают внешние API.
- **Data** (models) — SQLAlchemy модели и репозитории.
- **Core** — конфиг, базовые классы, утилиты, безопасность.
### 4.2 Сервисы
Сервис — это класс, который принимает `db: AsyncSession` в конструкторе:
```python
class IdeaService:
def __init__(self, db: AsyncSession):
self.db = db
async def get_by_id(self, idea_id: str) -> Idea | None:
result = await self.db.execute(select(Idea).where(Idea.id == idea_id))
return result.scalar_one_or_none()
```
### 4.3 API
API-роуты — это функции, которые:
1. Принимают `Depends(get_db)` и `Depends(get_current_user)`
2. Создают сервис с сессией
3. Вызывают метод сервиса
4. Возвращают Pydantic response
```python
@router.get("/{idea_id}", response_model=IdeaResponse)
async def get_idea(
idea_id: str,
user: Annotated[User, Depends(get_current_user)],
db: AsyncSession = Depends(get_db),
):
service = IdeaService(db)
idea = await service.get_by_id(idea_id)
if not idea or str(idea.user_id) != str(user.id):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return _to_response(idea)
```
### 4.4 Зависимости (dependencies.py)
- `get_db()` — yield async_session_maker(), commit/rollback/close
- `get_current_user(credentials, db)` — decode JWT → find user in DB
- `require_admin(user)` — check is_superuser
ВАЖНО: `get_current_user` принимает `db = Depends(get_db)`, а не создаёт свою сессию.
### 4.5 Config
```python
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
server_host: str = "0.0.0.0"
server_port: int = 8020
database_url: str = "sqlite+aiosqlite:///./app.db"
jwt_secret_key: str = ""
log_level: str = "INFO"
@property
def is_sqlite(self) -> bool:
return "sqlite" in self.database_url
```
## 5. БАЗА ДАННЫХ
### 5.1 Поддержка SQLite и PostgreSQL
Для портабельности между SQLite (dev) и PostgreSQL (prod) используем:
- **UUID поля:** `String(36)` во всех моделях (храним UUID как строку)
- **JSON/Array:** `JSON` вместо `JSONB` и `ARRAY`
- **Автовыбор:** через `settings.database_url` и `settings.is_sqlite`
### 5.2 Модели
```python
class UUIDMixin:
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4()))
class TimestampMixin:
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
```
## 6. AI-ИНТЕГРАЦИЯ
### 6.1 Паттерн FallbackChain
```python
class AIProvider(ABC):
async def analyze(self, prompt: str, **kwargs) -> AIResult: ...
class FallbackChain:
def __init__(self, providers: list[AIProvider], max_retries: int = 2):
...
async def analyze(self, prompt: str, **kwargs) -> AIResult:
# Try each provider in order, max_retries per provider
# 1st retry after 2s, 2nd after 5s
# All fail → AIResult(success=False, error="All providers failed")
```
### 6.2 Где хранить промпты
- **YAML-файл** (`docs/agent_prompts.yaml`) для настроек (system_prompt, temperature, max_tokens, provider)
- **MD-файлы** (`docs/specs/agents/`) для детальных спецификаций
- Загрузка через `PromptLoader` (пытается YAML → falls back к MD)
## 7. АГЕНТЫ (IF APPLICABLE)
### 7.1 Ядро (4 агента, с первого коммита)
1. **DocAgent** — пишет документацию
2. **AuditAgent** — проверяет правила
3. **EvolutionAgent** — версионирует агентов
4. **SupervisorAgent** — следит за всеми агентами
### 7.2 Архитектура агента
```python
class BaseAgent(ABC):
name: str
version: str = "1.0.0"
description: str = ""
triggers: list[AgentTrigger]
async def run(self, context: dict | None = None) -> AgentResult: ...
async def health_check(self) -> bool: ...
def compute_checksum(self) -> str: ... # SHA256 от __file__
def bump_version(self, version_type: str = "patch") -> str: ...
```
### 7.3 Agent Versioning
- Каждый агент: независимое A.B.C
- SHA256 checksum файла агента сравнивается с хранимым
- Не совпал → авто-бамп patch + запись в `CHANGELOG/agents/<name>.md`
- EvolutionAgent бампает minor (новая capability) и major (breaking change)
- Формат changelog:
```markdown
# agent_name Changelog
<!-- checksum: sha256hash -->
## 1.0.1 (2026-05-10)
- Fixed: описание
## 1.0.0 (2026-05-09)
- Initial version
```
## 8. ФОНОВЫЕ ЗАДАЧИ
### 8.1 Celery (production) / Прямой вызов (dev)
```python
# tasks/analysis.py
@celery_app.task(bind=True, max_retries=2, name="analyze_idea")
def analyze_idea(self, idea_id: str, role: str) -> dict:
return asyncio.run(_analyze_idea_async(idea_id, role))
# services/analysis_service.py
class AnalysisService:
async def start_analysis(self, idea_id: str) -> dict:
if settings.celery_broker_url:
task = analyze_idea.delay(idea_id, role)
else:
task = await _analyze_local(idea_id, role)
...
```
## 9. ТЕСТИРОВАНИЕ
- **Фреймворк:** pytest с asyncio_mode=auto
- **Unit-тесты:** `tests/unit/` — изолированные, mocked зависимости
- **Integration-тесты:** `tests/integration/` — с БД, реальные запросы
- **Smoke-тесты:** `tests/smoke/` — минимум 1 на endpoint
- **Покрытие:** > 80% (критический код: auth, security, payments — 100%)
## 10. БЕЗОПАСНОСТЬ
- JWT: HS256, access_token 60min, refresh_token 30d
- Пароли: bcrypt (passlib)
- .env в .gitignore — всегда
- Pydantic валидация на всех входах
- RBAC: user, admin (is_superuser)
## 11. РЕШЕНИЯ (SHOULD ASK)
Перед каждым из этих выборов — остановись и спроси пользователя:
| Решение | Опции по умолчанию |
|---------|-------------------|
| База данных | SQLite (dev) → PostgreSQL (prod) |
| Фоновые задачи | Прямой вызов (dev) → Celery (prod) |
| AI провайдеры | FallbackChain с 2 провайдерами |
| Аутентификация | Email+password + JWT |
| Агенты | 4 ядерных + остальные по необходимости |
| Фронтенд | React + Vite + Tailwind + PWA |
| CI/CD | GitHub Actions |
## 12. ЧТО ДЕЛАТЬ ЕСЛИ НЕ ЗНАЕШЬ
1. Поищи в `docs/` — там описано 90% ситуаций
2. Если не нашёл — открой `notes/encountered-issues.md` — может это уже было
3. Если и там нет — посмотри на `notes/improvements.md` — может это запланированное улучшение
4. Если ничего не помогло — **спроси пользователя с рекомендацией**
---
*Этот файл сгенерирован на основе реального опыта. Обновляется при изменении проекта.*