Files
suno-mcp-server/NexusAI/AGENTS.md
T

17 KiB
Raw Blame History

AGENTS.md — NexusAI

Карта проекта для ИИ-агентов и разработчиков. Читай этот файл первым, чтобы не перечитывать весь код. Обновляй раздел «Последние изменения» и карту при значимых правках.


1. Что это

NexusAI — универсальный MCP-сервис для агентов. Даёт один набор инструментов для:

  • TTS (text-to-speech), STT (speech-to-text, локально),
  • генерации изображений / видео / музыки,
  • веб-поиска (search-augmented модели),
  • vision (описание изображения chat-моделью),
  • служебных операций: список моделей, оценка стоимости, загрузка файла, статистика.

Плюс веб-админка (Fastify) для галереи контента, учёта трат и управления провайдерами/ключами.

Первый и основной провайдер — NordRouter (https://nordrouter.com, OpenAI-совместимый). Архитектура провайдер-агностична: адаптеры добавляются в registry, слой инструментов не меняется.


2. Технологии

  • TypeScript, monorepo через npm workspaces (CommonJS, tsc).
  • MCP: @modelcontextprotocol/sdk (stdio-транспорт).
  • HTTP: undici (fetch + ProxyAgent + FormData).
  • БД: better-sqlite3 (журнал + провайдеры).
  • Админка: fastify + @fastify/static, фронт — ванильный HTML/CSS/JS (без сборки).
  • Схемы: zod (+ zod-to-json-schema для MCP inputSchema).
  • STT: Python sidecar faster-whisper, запускается через uv.

3. Карта проекта

NexusAI/
├── AGENTS.md                   # ← этот файл
├── README.md                   # пользовательская документация
├── TEST_RESUME.md              # лог ручных тестов (search/STT/TTS/image/video/vision)
├── .env.example                # все переменные окружения с описанием
├── package.json                # workspaces + скрипты build/start/admin
├── sidecar/
│   └── stt_server.py           # faster-whisper sidecar (JSON in argv → JSON stdout)
└── packages/
    ├── core/                   # @nexusai/core — общая логика, БД, провайдеры
    ├── mcp-server/             # @nexusai/mcp-server — MCP stdio-сервер (инструменты)
    └── admin/                  # @nexusai/admin — веб-дашборд

3.1 packages/core (@nexusai/core)

Файл Назначение
src/config.ts loadConfig() — читает все NEXUS_* / NORDROUTER_* env → NexusConfig.
src/index.ts Реэкспорт всего публичного API core.
src/db/journal.ts Journal — SQLite журнал генераций: record/getById/list/deleteById/stats.
src/db/providers-store.ts ProvidersStore — провайдеры + зашифрованные ключи (AES-256-GCM). Отдаёт ProviderView с маской.
src/security/crypto.ts KeyCipher (шифрование ключей), maskSecret. enabled = задан ли мастер-ключ.
src/security/resolver.ts KeyResolver — эффективные настройки провайдера. Приоритет ключа: ENV > DB. Грациозный фолбэк, если DB-ключ нечитаем.
src/media/storage.ts MediaStorage — скачивание URL/base64 на диск, mimeToExt/extToMime, cleanup(ttlDays).
src/media/content.ts buildEmbeddedContent() — упаковка файла в MCP-контент (image/audio) с лимитом.
src/providers/types.ts Базовые типы: Capability, MediaProvider, SearchProvider, SttProvider, ModelInfo и пр.
src/providers/registry.ts ProviderRegistry — карта name+capability → адаптер.
src/providers/model-catalog.ts ModelCatalog — фоновая синхронизация каталога моделей + fuzzy-подбор модели (LCS + токены, дешёвая при равенстве), ModelResolutionError со списком моделей.
src/providers/nordrouter/client.ts NordRouterClient — низкоуровневый HTTP (Bearer, rate-limit).
src/providers/nordrouter/media.ts NordRouterMediaProvider/media/generate + polling, estimate, upload (data-URL, MIME по расширению), listModels, checkKey. Capabilities: tts,image,video,music.
src/providers/nordrouter/search.ts NordRouterSearchProvider — веб-поиск через /v1/chat/completions (perplexity/sonar-pro), citations из annotations.
src/providers/nordrouter/index.ts createNordRouterProviders() — фабрика media+search.
src/providers/local-stt/whisper.ts LocalWhisperProvider — спавнит sidecar, materialize аудио (path/url/base64).
src/shared/http.ts HttpClient (retry, rate-limit, proxy, FormData), RateLimiter.
src/shared/errors.ts NexusError + codeFromHttpStatus.
src/shared/logger.ts createLoggerпишет только в stderr (stdout занят MCP).
src/shared/polling.ts pollUntilDone, sleep.

3.2 packages/mcp-server (@nexusai/mcp-server)

Файл Назначение
src/index.ts Точка входа: поднимает MCP Server на stdio, регистрирует ListTools/CallTool.
src/context.ts buildContext() — собирает AppContext: registry, storage, journal, providersStore, catalogs (Map<provider, ModelCatalog> с авто-синком), defaultProvider.
src/schemas.ts Zod-схемы входа для всех инструментов.
src/tools.ts TOOLS[] — описания + JSON Schema (генерится из zod).
src/handlers.ts Handlers — реализация всех инструментов, запись в журнал, резолв модели через catalog, запись STT-транскрипта в .md.

3.3 packages/admin (@nexusai/admin)

Файл Назначение
src/server.ts Fastify: раздаёт /media/:file (с корректным Content-Type, incl. text/markdown), статику public/, API.
src/context.ts buildAdminContext() — journal + providersStore + cipher (без registry).
src/routes.ts REST API (см. §6). KNOWN_TYPES = ['nordrouter','openai'].
public/index.html UI: вкладки, темы, галерея, модалка, автообновление. Ванильный CSS через --vars.
public/app.js Логика UI: fetch API, рендер плиток, модалка, аудиоплеер, авто-refresh.

4. MCP-инструменты (11)

Инструмент Что делает Ключевые аргументы
nexus_tts Синтез речи model (default audio/elevenlabs-tts), input.text/voice/...
nexus_image Генерация/редактирование картинок model (default image/nano-banana-2), input.prompt/image/...
nexus_video t2v / i2v (может занять минуты) model (default video/kling-2.6-t2v), input.prompt/image/...
nexus_music Генерация музыки model (default music/suno-v5), input...
nexus_stt Распознавание речи (локально) input.audioPath/audioUrl/audioBase64/language/model
nexus_web_search Веб-поиск с источниками query, recency, maxResults, model
nexus_vision Описание изображения chat-моделью image (url/path/base64), prompt, model (default google/gemini-3.1-flash-lite)
nexus_media_models Список моделей провайдера type, search
nexus_media_estimate Оценка стоимости до генерации model, input
nexus_media_upload Загрузка файла к провайдеру → URL path, name, mimeType
nexus_usage_stats Статистика из журнала sinceDays, list, limit

Медиа-пайплайн (Handlers.media): резолв модели через ModelCatalogprovider.generate (polling) → скачивание файла в media-dir → запись в журнал → возврат JSON (+ note при подмене модели).

Fuzzy-резолв модели: кривое имя → ближайшая (при равенстве — дешевле); нет совпадений → BAD_REQUEST с available (список категории, дешёвые первыми) и подсказкой попросить пользователя уточнить.


5. Возможности (capabilities)

Capability = 'tts' | 'stt' | 'image' | 'video' | 'music' | 'search' (в журнале также встречается vision).

Маппинг NordRouter type → capability (в model-catalog.ts): audio→tts, image→image, video→video, music→music.


6. Admin REST API

Метод Путь Назначение
GET /api/providers Список провайдеров (маска ключа), knownTypes, cryptoEnabled.
POST /api/providers Upsert провайдера (ключ шифруется).
POST /api/providers/:name/enabled Вкл/выкл.
POST /api/providers/:name/default Сделать default.
DELETE /api/providers/:name Удалить.
POST /api/providers/:name/check Проверка ключа реальным вызовом.
GET /api/stats?sinceDays= Статистика трат.
GET /api/generations?limit=&offset=&capability= Галерея (добавляет mediaUrl).
GET /api/generations/:id Одна запись.
DELETE /api/generations/:id Удалить запись + файл (только внутри media-dir).
GET /media/:file Раздача файла (Content-Type по расширению).

7. Переменные окружения (главное)

# NordRouter
NORDROUTER_API_KEY=sk-...
NORDROUTER_BASE_URL=https://nordrouter.com
# Общие
NEXUS_DEFAULT_PROVIDER=nordrouter
NEXUS_MEDIA_DIR=./media-output          # медиа + SQLite
NEXUS_DB_PATH=<media>/nexus.sqlite      # опц.
NEXUS_MASTER_KEY=<hex32|passphrase>     # шифрование ключей в БД (иначе только ENV-ключи)
NEXUS_EMBED_MAX_BYTES=10485760
NEXUS_LOG_LEVEL=info                    # логи → stderr
# STT
NEXUS_STT_PYTHON=uv
NEXUS_STT_MODEL=small                   # tiny|base|small|medium|large-v3 ИЛИ путь к CT2-модели
NEXUS_STT_DEVICE=auto ; NEXUS_STT_COMPUTE=auto
NEXUS_STT_LOCAL_ONLY=1                  # оффлайн (без скачивания)
HF_ENDPOINT=https://hf-mirror.com       # зеркало HF в закрытых сетях
# Admin
NEXUS_ADMIN_HOST=127.0.0.1 ; NEXUS_ADMIN_PORT=4123
# Proxy (опц.)
NEXUS_HTTP_PROXY=http://proxy:8080

Приоритет ключа: <NAME>_API_KEY (env) > зашифрованная запись в БД.


8. Команды

npm install
npm run build            # core → mcp-server → admin (по отдельности: build:core|build:mcp|build:admin)
npm run start            # запустить MCP-сервер (stdio)
npm run admin            # запустить админку (http://127.0.0.1:4123)

MCP работает по stdio → никогда не писать в stdout кроме протокола; все логи идут в stderr.

Локальный запуск админки в этой среде (фоновые процессы реапятся)

tmux new-session -d -s nexusadmin -c /home/user/moder/mcp/NexusAI \
  "export NEXUS_MEDIA_DIR=/tmp/opencode/nexus-media NEXUS_MASTER_KEY=... NEXUS_ADMIN_PORT=4123; \
   exec node packages/admin/dist/server.js >/tmp/opencode/admin_live.log 2>&1"

Тестирование инструментов без полного MCP-хендшейка

Импортировать buildContext + Handlers из dist/ и звать handlers.handle('nexus_*', args). ⚠️ Скрипт должен лежать внутри packages/mcp-server/ (иначе не резолвятся node_modules workspace). Env для теста: NEXUS_MEDIA_DIR, NEXUS_MASTER_KEY (тот же, что при сохранении ключа), STT-переменные.


9. Важные особенности / подводные камни

  • stdout только для MCP. Логи — в stderr (createLogger).
  • Ключ мастер-шифрования обязателен для чтения ключей из БД; иначе только ENV-ключи. Без ключа сервис не падает (грациозный фолбэк).
  • NordRouter upload ждёт data:<mime>;base64,... в поле data. MIME определяется по расширению — иначе HTTP 415.
  • Kling i2v не принимает прямую ссылку на сгенерированный контент — нужен URL из nexus_media_upload (?raw=1).
  • Видео-модели часто требуют полный набор полей (duration, aspect_ratio, resolution, ...), иначе HTTP 400.
  • STT не качает модель в закрытой сети (HF недоступен). Варианты: HF_ENDPOINT, локальная модель + NEXUS_STT_LOCAL_ONLY=1 (модель faster-whisper-* можно взять с ModelScope).
  • STT-транскрипт сохраняется как .md в media-dir и виден в галерее/модалке (не путать с исходным аудио).
  • Стоимость видео может превышать estUsd (например, Kling 2.6 i2v: est $0.34 → факт $0.69).
  • Некоторые модели бывают временно недоступны («Генерация временно недоступна — средства возвращены»).
  • ID моделей NordRouter для chat/vision: google/gemini-3.1-flash-lite, openai/gpt-5.x (НЕ gpt-4o).

10. Последние изменения

Свежие сверху. Держи актуальным.

  • 8bd2e89 — STT пишет транскрипт в .md (виден в галерее/модалке); ModelCatalog (фоновый синк + fuzzy-резолв с дешёвым фолбэком и подсказками); UI: аудиоплеер (кнопка в карточке + плеер в модалке), просмотр текстовых .md, автообновление активной вкладки без перезагрузки; /media отдаёт корректный Content-Type.
  • b2f57cc — новый инструмент nexus_vision; фикс nexus_media_upload (MIME по расширению, чинит 415); HttpClient поддерживает FormData.
  • c65f910 — STT больше не пишет путь исходного аудио как filePath (убрана битая ссылка в галерее).
  • 1bc3746 — Admin UX: светлая/тёмная тема, пагинация галереи, модалка + удаление, тип провайдера openai.
  • 6ff2b27 — фикс краша MCP при наличии ключа в БД без NEXUS_MASTER_KEY.
  • 679e564 — Admin (Phase 2): дашборд трат, галерея, управление провайдерами.

11. Куда добавлять новое

  • Новый провайдер → адаптер в core/src/providers/<name>/, регистрация в mcp-server/src/context.ts, тип в admin KNOWN_TYPES при необходимости.
  • Новый инструмент → схема в schemas.ts, ветка в Handlers.handle, описание в tools.ts.
  • Новое поле журнала → миграция в Journal.init, обновить GenerationRecord и SELECT-колонки в getById/list.
  • UIpublic/index.html (разметка/CSS) + public/app.js (логика). Сборки нет — правки применяются сразу.