# Архитектура микросервисов GooSeek

Документ описывает план разбиения монолитного приложения GooSeek на микросервисы.

---

## 1. Текущая архитектура (монолит)

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                         Next.js Application (monolith)                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  API Routes          │  Agents/Search         │  Models/Providers   │  Data  │
│  /api/chat           │  classifier            │  OpenAI, Anthropic  │  SQLite│
│  /api/search         │  researcher            │  Ollama, Groq...    │  config│
│  /api/images         │  widgets               │  registry           │  uploads│
│  /api/videos         │  writer                │                     │        │
│  /api/uploads        │  media (image/video)   │                     │        │
│  /api/chats          │                        │                     │        │
│  /api/providers      │                        │                     │        │
│  /api/config         │                        │                     │        │
│  /api/suggestions    │                        │                     │        │
│  /api/weather        │                        │                     │        │
│  /api/discover       │                        │                     │        │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│  External: SearXNG │ Yahoo Finance │ Open-Meteo │ LLM APIs (OpenAI, etc.)   │
└─────────────────────────────────────────────────────────────────────────────┘
```

---

## 2. Предлагаемые микросервисы

### 2.1 Общая схема

```
┌──────────────┐     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   Frontend   │────▶│   Gateway    │────▶│    Chat      │────▶│   Research   │
│  (Next.js)  │     │  (BFF/API)   │     │   Service    │     │   Service    │
└──────────────┘     └──────────────┘     └──────┬───────┘     └──────┬───────┘
       │                     │                   │                    │
       │                     │                   │                    │
       │                     ▼                   ▼                    ▼
       │             ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
       │             │  Config/Chats │     │  LLM Proxy   │     │  Search      │
       └────────────▶│   Service     │     │   Service    │     │  Service     │
                     └──────────────┘     └──────────────┘     └──────┬───────┘
                              │                   │                    │
                              │                   │                    │
                              ▼                   ▼                    ▼
                     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
                     │  Storage     │     │  Providers   │     │   Uploads    │
                     │  Service     │     │  (external)  │     │   Service    │
                     └──────────────┘     └──────────────┘     └──────────────┘
```

---

## 3. Описание сервисов

### 3.1 Frontend (Next.js UI)

**Назначение:** Только UI — страницы, компоненты, клиентский state.

**Содержимое:**
- `src/app/page.tsx`, `layout.tsx`, маршруты страниц
- `src/components/` — все UI компоненты
- `src/lib/hooks/` — клиентские хуки
- `src/lib/actions.ts` — вызовы к Gateway API

**Исключить:** Все API routes (`src/app/api/`), серверная логика агентов, прямые вызовы DB.

**API:** Вызывает только Gateway.

---

### 3.2 Gateway (Backend-for-Frontend / API Gateway)

**Назначение:** Единая точка входа для клиента, роутинг, валидация, агрегация.

**Реализация:** Отдельный Node.js сервис (Fastify/Express) или часть Next.js API routes, которая только проксирует.

**Маршруты:**
- `POST /api/chat` → Chat Service
- `POST /api/search` → Chat Service (API mode)
- `GET/POST /api/chats/*` → Storage Service
- `POST /api/uploads` → Uploads Service
- `GET/POST /api/providers/*` → Config + LLM Proxy
- `GET/POST /api/config/*` → Storage Service (config)
- `POST /api/suggestions` → Chat Service
- `POST /api/images` → Chat/Media Service
- `POST /api/videos` → Chat/Media Service
- `GET /api/weather` → Widgets Service (или inline)
- `POST /api/discover` → Search Service

**Зависимости:** Chat, Storage, Uploads, Search. Не содержит бизнес-логики.

---

### 3.3 Chat Service (Оркестратор)

**Назначение:** Главный оркестратор диалога: классификация, планирование, вызов research и writer.

**Исходники:**
- `src/lib/agents/search/index.ts` — SearchAgent
- `src/lib/agents/search/api.ts` — APISearchAgent
- `src/lib/agents/search/classifier.ts`
- `src/lib/agents/search/widgets/` — executor + виджеты (weather, stock, calc)
- `src/lib/prompts/search/` — classifier, writer, researcher prompts
- `src/lib/session.ts`

**API (внутренние):**
- `POST /classify` — классификация запроса
- `POST /search` — полный пайплайн (classify → research → widgets → write)
- `POST /suggestions` — генерация подсказок

**Вызывает:**
- Research Service — для поиска
- LLM Proxy — для LLM вызовов (classify, write, suggestions)
- Widgets (внешние API: Yahoo Finance, погода) — можно вынести в отдельный сервис

**Поток данных:**
1. Классификация (LLM)
2. Параллельно: Research Service + виджеты
3. Генерация ответа (LLM)
4. Сохранение в Storage (через Gateway или напрямую)

---

### 3.4 Research Service

**Назначение:** Выполнение исследовательского цикла — tools (web, academic, social, scrape, uploads).

**Исходники:**
- `src/lib/agents/search/researcher/` — Researcher, ActionRegistry
- `src/lib/agents/search/researcher/actions/` — webSearch, academicSearch, socialSearch, scrapeURL, uploadsSearch, plan, done
- `src/lib/prompts/search/researcher.ts`

**API:**
- `POST /research` — вход: classification, query, chatHistory, config → выход: searchFindings, findings

**Вызывает:**
- Search Service — SearXNG (web, academic, social)
- Uploads Service — семантический поиск по файлам
- LLM Proxy — для researcher agent (tool calls)
- Внешние URL — scrape

**Важно:** Researcher — это LLM-driven agent с tool calls. LLM решает, какой tool вызвать. Либо LLM живёт в Chat Service и вызывает tools по HTTP, либо Research Service сам держит копию researcher LLM — тогда нужно дублировать LLM-вызовы.

**Рекомендация:** Оставить researcher внутри Chat Service, а в Research Service вынести только **действия** (web search, scrape, uploads search) как отдельные HTTP endpoints. Chat Service вызывает Research Service по каждому tool call. Это уменьшает связанность, но увеличивает сетевые вызовы.

**Альтернатива:** Research как один сервис с LLM — получает query и classification, сам итерирует и возвращает готовые findings. Меньше round-trips, но дублирование LLM-инфраструктуры.

---

### 3.5 Search Service (SearXNG + обёртка)

**Назначение:** Обёртка над SearXNG для веб/академического/медиа поиска.

**Исходники:**
- `src/lib/searxng.ts`
- Вызовы: webSearch, academicSearch, socialSearch, image, video — все идут через `searchSearxng`

**API:**
- `GET /search?q=...&engines=...&categories=...`
- `GET /images?q=...`
- `GET /videos?q=...`

**Внешняя зависимость:** SearXNG (уже отдельный сервис/контейнер).

**Реализация:** Минимальный Node.js/Fastify сервис, который проксирует к SearXNG и добавляет логику (rate limiting, fallback, кэш).

---

### 3.6 Uploads Service

**Назначение:** Загрузка файлов, парсинг (PDF, DOCX, TXT), эмбеддинги, семантический поиск.

**Исходники:**
- `src/lib/uploads/manager.ts` — UploadManager
- `src/lib/uploads/store.ts` — UploadStore (поиск по эмбеддингам)
- `src/lib/utils/splitText.ts`, `computeSimilarity.ts`
- Зависимости: pdf-parse, officeparser

**API:**
- `POST /upload` — multipart, возвращает fileIds
- `POST /search` — query, fileIds → chunks (семантический поиск)
- `GET /files/:id` — метаданные файла

**Вызывает:** LLM Proxy — только для embedding модели (можно вынести в отдельный Embedding Service).

**Хранение:** Файлы на диске/volume, `uploaded_files.json`, `.content.json` с chunks.

---

### 3.7 Storage Service

**Назначение:** Централизованное хранилище: чаты, сообщения, конфигурация.

**Исходники:**
- `src/lib/db/` — schema, migrations, drizzle
- `src/lib/config/` — ConfigManager, modelProviders

**API:**
- `GET/POST/PUT/DELETE /chats`
- `GET/POST/PUT/DELETE /chats/:id`
- `GET/POST/PUT/DELETE /messages`
- `GET/POST /config`
- `GET/POST /config/providers`

**База:** SQLite (или PostgreSQL при масштабировании). config.json можно мигрировать в ту же БД или отдельную таблицу.

---

### 3.8 LLM Proxy Service (опционально)

**Назначение:** Единая точка для вызовов LLM и embedding — OpenAI, Anthropic, Ollama, Groq, Gemini и т.д.

**Исходники:**
- `src/lib/models/` — registry, providers, base LLM/Embedding

**API:**
- `POST /chat` — text generation (streaming)
- `POST /embed` — embedding
- `GET /providers` — список провайдеров и моделей

**Конфигурация:** Берёт из Storage Service (config/providers) или env.

**Альтернатива:** LLM Proxy можно не выделять в отдельный сервис — каждый сервис (Chat, Research, Uploads) сам подключается к провайдерам. Но тогда дублирование кода и конфигурации. Рекомендуется вынести в общую библиотеку или отдельный сервис.

---

### 3.9 Geo Device Service (реализован)

**Назначение:** Определение геопозиции пользователя, типа устройства, браузера и ОС.

**Расположение:** `apps/geo-device-service/`

**API:**
- `GET /api/context` — контекст по IP и заголовкам (User-Agent, Accept-Language)
- `POST /api/context` — контекст с дополнительными данными от клиента (screen, timezone, Geolocation API)

**Данные:**
- **geo** — latitude, longitude, city, country, timezone (geoip-lite по IP или из body)
- **device** — type (desktop/mobile/tablet), vendor, model
- **browser** — name, version (ua-parser-js)
- **os** — name, version
- **client** — screenWidth, viewportHeight, timezone, language, hardwareConcurrency, deviceMemory, doNotTrack (из POST body)

**Запуск:** `npm run dev:geo` или `PORT=4002 npm run start -w geo-device-service`

**Интеграция:** Frontend вызывает `/api/geo-context` (проксирует к сервису), клиент — `fetchContextWithClient()` из `@/lib/geoDevice`.

---

### 3.10 Localization Service (реализован)

**Назначение:** Локализация на основе геопозиции. Определяет locale (язык) пользователя по данным из Geo Device Service.

**Расположение:** `apps/localization-service/`

**Зависимость:** Geo Device Service (вызывает `/api/context` для получения countryCode, client.language, Accept-Language).

**API:**
- `GET /api/locale` — resolve locale по IP/заголовкам (гео через geo-device-service)
- `POST /api/locale` — resolve locale с client data (screen, language, geo)
- `GET /api/translations/:locale` — переводы для UI
- `GET /api/locales` — список поддерживаемых локалей

**Данные (LocalizationContext):**
- **locale** — BCP 47 language code (ru, en, de, ...)
- **source** — geo | accept-language | client | fallback

**Приоритет определения locale:**
1. client.language (браузер navigator.language)
2. Accept-Language заголовок
3. countryCode из геопозиции
4. fallback: en

**Запуск:** `npm run dev:locale` или `PORT=4003 npm run start -w localization-service`

**Конфигурация:** `GEO_DEVICE_SERVICE_URL` — URL geo-device-service (по умолчанию http://localhost:4002)

**Интеграция:** Frontend вызывает `/api/locale`, `/api/translations/[locale]` (проксирует к сервису), клиент — `fetchLocaleWithClient()`, `fetchTranslations()` из `@/lib/localization`.

---

## 4. Матрица зависимостей

| Сервис         | От кого получает вызовы          | Кого вызывает                    |
|----------------|----------------------------------|----------------------------------|
| Gateway        | Frontend                         | Chat, Storage, Uploads, Search   |
| Localization   | Frontend                         | Geo Device Service               |
| Geo Device     | Frontend, Localization           | —                                |
| Chat        | Gateway                          | Research, LLM Proxy, Storage     |
| Research    | Chat                             | Search, Uploads, LLM Proxy       |
| Search      | Research, Chat (media)           | SearXNG (внешний)                |
| Uploads     | Gateway, Research                | LLM Proxy (embedding)            |
| Storage     | Gateway, Chat                     | —                                |
| LLM Proxy   | Chat, Research, Uploads          | OpenAI, Anthropic, Ollama...     |

---

## 5. Разбиение по репозиториям/папкам

### Вариант A: Монорепо (рекомендуется для старта)

```
gooseek/
├── apps/
│   ├── frontend/          # Next.js UI
│   ├── gateway/           # BFF / API Gateway
│   ├── chat-service/      # SearchAgent, classifier, writer, widgets
│   ├── research-service/ # Researcher, actions
│   ├── search-service/   # SearXNG wrapper
│   ├── uploads-service/  # UploadManager, UploadStore
│   ├── storage-service/  # DB, config
│   ├── llm-proxy/        # Models registry, providers
│   ├── geo-device-service/   # Геопозиция, устройство, браузер
│   ├── localization-service/ # Локализация (зависит от geo-device)
│   ├── shared-types/     # Общие типы, DTO
│   └── shared-utils/     # formatHistory, splitText, computeSimilarity
├── docker-compose.yaml
└── package.json          # Turborepo/nx workspace
```

### Вариант B: polyrepo

Отдельные репозитории для каждого сервиса. Больше гибкости в деплое, но сложнее координация изменений.

---

## 6. Порядок миграции (фазы)

### Фаза 1: Выделение Search Service
- Обернуть SearXNG в отдельный сервис
- Chat/Research вызывают его по HTTP вместо прямого импорта `searchSearxng`
- **Риск:** Низкий. SearXNG уже внешний.

### Фаза 2: Выделение Storage Service
- Вынести DB + config в отдельный сервис
- Gateway и Chat переходят на HTTP к Storage
- **Риск:** Средний. Много точек входа в DB.

### Фаза 3: Выделение Uploads Service
- Вынести UploadManager + UploadStore
- Research (uploadsSearch action) и Gateway вызывают Uploads по HTTP
- **Риск:** Средний. Embedding модель — зависимость.

### Фаза 4: Выделение LLM Proxy
- Общая обёртка над провайдерами
- Chat, Research, Uploads вызывают LLM Proxy
- **Риск:** Высокий. Много мест используют LLM напрямую.

### Фаза 5: Выделение Research Service
- Researcher + actions в отдельный сервис
- Chat вызывает Research по одному endpoint «проведи исследование»
- **Риск:** Высокий. Тесная связь с Session, streaming.

### Фаза 6: Gateway + развязка Frontend
- Frontend только UI, все вызовы через Gateway
- Gateway — тонкий роутер без бизнес-логики
- **Риск:** Средний. Рефакторинг API routes.

---

## 7. Ключевые вызовы и риски

1. **Streaming:** Текущий chat stream идёт от SearchAgent до клиента. При разбиении нужно решить: стримить через Gateway (proxy) или от Chat Service напрямую (WebSocket/SSE через Gateway как туннель).

2. **Session/state:** SessionManager — in-memory. При масштабировании Chat Service нужен Redis или аналог для shared state.

3. **Латентность:** Каждый HTTP hop добавляет ~10–50ms. Research делает много итераций — если Research в отдельном сервисе, round-trips умножаются.

4. **Embedding в Uploads:** Uploads нужна embedding модель. Варианты: вызывать LLM Proxy, или держать тяжёлую модель (transformers) внутри Uploads.

5. **Конфигурация:** Сейчас config.json на диске. При микросервисах — централизованный config (env, vault, или Storage Service).

---

## 8. Минимальный MVP разбиения

Если цель — не полный microservices, а **модульность и возможность деплоить части отдельно**:

| Сервис        | Код                         | Отдельный процесс |
|---------------|-----------------------------|-------------------|
| **search-api**| `searxng.ts` + route        | Да (отдельный порт) |
| **uploads-api**| `uploads/` + route         | Да                |
| **chat**      | Всё остальное (agents, LLM, DB) | Один процесс   |
| **frontend**  | Next.js UI                  | Отдельно (static/SSR) |

Так получается 3–4 контейнера вместо 1, но без глубокой декомпозиции логики.

---

## 9. Следующие шаги

1. Определить: полное разбиение или MVP.
2. Выбрать стек для каждого сервиса (Node.js/Fastify, Next.js API routes, Go и т.д.).
3. Описать контракты API (OpenAPI/JSON Schema) для межсервисного взаимодействия.
4. Настроить docker-compose для локальной разработки.
5. Внедрить общие пакеты (shared-types, shared-utils) в монорепо.
6. Начать с Фазы 1 (Search Service) как пилот.
