J.A.R.V.I.S-rust/README.md
Bossiara13 4e21024509 feat: Wave 3 — plugin system + custom wake-word trainer
#29 Plugin system:
- New jarvis-core::plugins module: discovers user packs in
  %APPDATA%\com.priler.jarvis\plugins\<name>\command.toml so authors can
  ship voice commands without rebuilding. Sandbox capped at "standard" —
  plugins cannot escalate to "full" (which would expose `os`). Disabled
  via a `disabled` flag file. Malformed packs warn and skip; never poison
  the rest of the list. 8 unit tests.
- commands::parse_commands() merges plugins into the loaded list.
- New /plugins GUI page with enable/disable switches, error reporting,
  "Open folder" button. Tauri commands plugins_list / plugins_set_enabled
  / plugins_open_folder. Header gets a "Плагины" button. i18n keys added
  for ru/en/ua.

#8 Custom wake-word trainer wizard:
- New jarvis-core::wake_trainer module: opens its own pv_recorder
  instance, records N short PCM clips, WAV-encodes them in memory, then
  calls rustpotter's WakewordRef::new_from_sample_buffers to train and
  persist a .rpw model under %APPDATA%/com.priler.jarvis/wake_words/.
  Keepsake WAVs are also dumped for retraining later. Sanitises names to
  block path traversal. 5 unit tests.
- Settings gain `custom_wake_word: String`; listener/rustpotter.rs now
  loads the user's selected model first and always falls back to the
  bundled default so the assistant keeps working even if the custom
  file is missing.
- New /wake-trainer GUI page: stepper UI for record-sample → train,
  shows recorded count, threshold slider, refuses to start while
  jarvis-app is running (mic exclusivity). Lists existing trained
  models with size + delete button.
- 8 Tauri commands wired through (status/defaults/start/record_sample/
  finish/cancel/list_models/delete_model).

Tests: 115 → 128 (+8 plugins +5 wake_trainer). Release builds green for
all three binaries (jarvis-app / jarvis-cli / jarvis-gui).
2026-05-16 13:26:42 +03:00

311 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# J.A.R.V.I.S. (Rust) — форк Bossiara13
Локальный голосовой ассистент для Windows. Форк Rust-переписки
[Priler/jarvis](https://github.com/Priler/jarvis). Сильно расширен в этом форке
(см. ниже). Может работать **полностью офлайн** через Ollama, или с облачным
LLM через Groq — выбор переключается **голосом** на лету.
Зеркала:
- GitHub: <https://github.com/DmitryBykov-ISPO/J.A.R.V.I.S-rust>
- Forgejo (self-hosted): `http://192.168.0.10:3000/bossiara13/J.A.R.V.I.S-rust`
(только в LAN; используй `NO_PROXY=192.168.0.10` если у тебя локальный прокси)
Для контрибьюторов: см. [ARCHITECTURE.md](ARCHITECTURE.md) — карта кода, data flow,
рецепты "как добавить пак / фичу / TTS backend".
## Что внутри
- **STT**: Vosk + webrtc-vad для умного завершения по тишине.
- **Wake-word**: Vosk / Rustpotter / Picovoice Porcupine (выбор в Settings).
- **TTS**: трёхбэкендовая абстракция — SAPI (стоковый), **Piper** (нейронный,
рекомендуется, ~90 МБ), Silero (PyTorch). Выбор через `JARVIS_TTS` или GUI.
- **LLM**: двухбэкендовая — **Groq** (облако, бесплатно) или **Ollama** (локально,
офлайн). Hot-swap через голос / GUI / `JARVIS_LLM`. Выбор сохраняется в БД.
- **Lua sandbox**: каждая команда — Lua-скрипт с тремя уровнями песочницы.
Полный API: `jarvis.speak/llm/http/fs/state/system/memory/profile/scheduler/
vision/macros/cmd/text/...` — см. ARCHITECTURE.md.
- **Tauri 2 GUI**: 4 страницы (главная, /commands список 59 паков, /settings,
футер с активными движками).
## Возможности (то, чего нет в апстриме)
### Управление LLM
- **Agentic LLM router (IMBA-1)**: если fuzzy/intent не нашёл команду, LLM
выбирает ближайшую из реестра по JSON-схеме. Алисе/Сири такое не снилось.
- **Hot-swap локального и облачного LLM**: "переключись на локальный" /
"переключись на облако". Выбор персистентен (Settings → AI Backends).
- **Reset/repeat контекст**: "сбрось контекст" / "повтори последнее".
- **Memory injection**: LLM автоматически получает релевантные факты из
долгосрочной памяти в system prompt.
### Долгосрочная память
- "Запомни что я люблю чай улун" → JSON-стор в `<APP_CONFIG_DIR>/long_term_memory.json`.
- "Что ты помнишь про чай" / "забудь про X" / "что ты знаешь обо мне".
- LLM-чат получает релевантные факты через substring search.
### Профили
- 5 предзаполненных: default ★, work 💼, game 🎮, sleep 🌙, driving 🚗.
- "Режим работа" / "режим игра" / "режим сон" / "режим за рулём" / "обычный режим".
- Каждый профиль может иметь allow/deny списки команд + personality для LLM.
### Vision (multimodal)
- "Что на экране" / "опиши экран" / "прочитай ошибку" → скриншот через
PowerShell → base64 → Groq vision (`llama-3.2-11b-vision-preview`) → голос.
- Требует `GROQ_TOKEN` (Ollama пока без vision в этой интеграции).
### Проактивный планировщик
- "Напомни через 5 минут выключить кофеварку" → one-shot.
- "Каждые 2 часа напоминай попить воды" → interval.
- "Каждый день в 9:00 делай брифинг" → daily.
- "Отмени напоминание про воду" / "очисти расписание" / "что у меня запланировано".
- Фоновый поток (тик каждые 30 сек). Сохраняется в `<APP_CONFIG_DIR>/schedule.json`.
### Voice macros (VoiceAttack-style)
- "Запиши макрос работа" → начинает запись.
- Любые следующие команды (открой браузер, режим работа, ...) копятся.
- "Сохрани макрос" → персистится.
- "Запусти макрос работа" → проигрывает каждый шаг с интервалом 800мс.
- Список / удаление / отмена.
### Утилиты
| Команда | Что делает |
|---|---|
| "Найди в гугле X" | DuckDuckGo Instant Answer + LLM-перессказ |
| "Википедия X" / "что такое X" | Wikipedia REST API (ru→en fallback) + LLM-перевод |
| "Сколько 1000 долларов в рублях" | CBR-XML курс + конвертация |
| "Сколько Сбер" | MOEX биржа, 22 тикера в карте |
| "Переведи буфер" | Clipboard → LLM → обратно в clipboard |
| "Напоминай мне пить воду" | Habit nudge: каждые 2 часа |
| "Напоминай размяться" | Каждые 50 минут |
| "Напоминай отдыхать глазам" | 20-20-20 rule, каждые 20 минут |
| "Запусти помодоро" | 25/5 циклы с голосовыми напоминаниями |
| "Запиши настроение 7" / "как прошла неделя" | Mood log + LLM-сводка |
| "Утренний брифинг" / "настрой утренний брифинг на 9:00" | Время+профиль+задачи+память+LLM-мотивашка |
| "Укажи проект C:\..." / "что делает функция X" | Codebase Q&A — LLM по локальной кодобазе |
| "Открытые пиары" / "разбери последний PR" | gh CLI + LLM-ревью |
| "Пауза" / "следующий трек" | Windows media keys (Spotify / YouTube / Foobar) |
| "Диагностика" / "доложи о себе" | Состояние всех бэкендов одной строкой |
Всего паков: **85** (`resources/commands/*/command.toml`) +
плагины пользователя из `%APPDATA%\com.priler.jarvis\plugins\`.
Полный список: GUI → /commands (с поиском и фильтрами).
### Плагины
Голосовые команды, которые лежат **вне** проекта. Каждый плагин —
папка с тем же `command.toml` + Lua-скриптами:
```
%APPDATA%\com.priler.jarvis\plugins\<имя>\
command.toml (тот же формат, что и встроенные паки)
*.lua (скрипты, на которые ссылается toml)
disabled (опционально — пустой файл, отключает плагин)
```
Подгружается при следующем старте `jarvis-app.exe`. Sandbox принудительно
понижается до `standard` — плагин не может попросить `full` (доступ к `os`).
GUI → /plugins показывает список, флажки enable/disable, кнопку «Открыть папку».
### Своё кодовое слово
GUI → /wake-trainer — мастер: запишите 530 примеров своего голоса,
обучите персональную `.rpw`-модель, выберите её в Настройках, перезапустите
ассистент. Файл — `%APPDATA%\com.priler.jarvis\wake_words\<имя>.rpw`.
## Быстрый старт
```powershell
# 1. Клонировать
git clone https://github.com/DmitryBykov-ISPO/J.A.R.V.I.S-rust.git C:\Jarvis\rust
cd C:\Jarvis\rust
# 2. Поставить нейронный TTS (один раз, ~90 МБ)
pwsh tools/piper/install.ps1
# 3a. Облачный LLM — получи токен на https://console.groq.com/keys
echo "GROQ_TOKEN=gsk_..." > dev.env
# 3b. ИЛИ локальный LLM
# Скачай https://ollama.com/download, выполни:
# ollama pull qwen2.5:3b
# (Jarvis сам подхватит, если GROQ_TOKEN отсутствует)
# 4. Сборка
cd frontend && npm install && npm run build && cd ..
cargo build --release -p jarvis-app -p jarvis-gui
# 5. Запуск
target\release\jarvis-app.exe # фоновый демон с микрофоном
target\release\jarvis-gui.exe # GUI для управления
```
Подробнее: см. секцию "Сборка" ниже.
## Конфигурация (env vars)
Все JARVIS_* / GROQ_* / OLLAMA_* переменные документированы в
`crates/jarvis-core/src/runtime_config.rs`. Ключевые:
| Переменная | По умолчанию | Назначение |
|---|---|---|
| `GROQ_TOKEN` | — | Токен для облачного LLM (без него — Ollama / выкл) |
| `GROQ_MODEL` | `llama-3.3-70b-versatile` | Groq-модель |
| `GROQ_VISION_MODEL` | `llama-3.2-11b-vision-preview` | Vision-модель для "что на экране" |
| `OLLAMA_BASE_URL` | `http://localhost:11434/v1` | Адрес Ollama |
| `OLLAMA_MODEL` | `qwen2.5:3b` | Локальная модель (любая через `ollama pull`) |
| `JARVIS_LLM` | auto | `groq` / `ollama` / пусто (auto-detect) |
| `JARVIS_TTS` | auto | `sapi` / `piper` / `silero` / пусто (auto) |
| `JARVIS_TTS_PIPER_BIN` | автопоиск | Путь к piper.exe |
| `JARVIS_TTS_PIPER_VOICE` | автопоиск | Путь к голосу .onnx |
| `JARVIS_LLM_ROUTER` | `1` | Включить agentic router |
| `JARVIS_LLM_ROUTER_THRESHOLD` | `0.55` | Confidence threshold |
| `JARVIS_LLM_TTS` | `true` | Озвучивать LLM-ответ |
Файл `dev.env` подхватывается автоматически (jarvis-app ищет от exe вверх по 5
уровням), так что переменные можно держать в одном месте.
Персистентные настройки (`voice`, `microphone`, `vosk_model`, `llm_backend`,
`tts_backend`, ...) хранятся в `<APP_CONFIG_DIR>/settings.json` и правятся
через GUI Settings или Lua `jarvis.settings.set(key, val)`.
## Сборка
Требования:
- Rust 1.93+ (stable MSVC).
- Node 20+ и npm для фронтенда.
- MSVC build tools (`vcvars64.bat`). VS 2022 / 2026 / 2026 — любая.
- Python 3 (только для `post_build.py`, опционально).
- Vosk/Porcupine/PvRecorder DLL'и в `lib/windows/amd64/` (уже в репо).
Команды:
```powershell
# Один раз: загрузить MSVC окружение
$vc = "C:\Program Files\Microsoft Visual Studio\18\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmd /c "`"$vc`" >NUL && set" | % {
if ($_ -match '^([^=]+)=(.*)$') {
[Environment]::SetEnvironmentVariable($matches[1], $matches[2], 'Process')
}
}
# Собрать фронтенд
cd frontend
npm install
npm run build
cd ..
# Workspace
cargo build --release -p jarvis-app -p jarvis-gui
```
Холодная сборка ~10 мин (ONNX runtime, aws-lc-rs, tauri). Инкремент ~30 сек.
`jarvis-gui/build.rs` сам зовёт `npm run build` если фронтенд устарел, так что
для итераций по UI достаточно `cargo build -p jarvis-gui`.
## Тесты
```powershell
cargo test -p jarvis-core --lib # все unit-тесты
cargo test -p jarvis-core --lib scheduler:: # фильтр по модулю
```
Текущее покрытие: **55 unit-тестов**, см. таблицу в ARCHITECTURE.md.
## Структура
```
crates/
jarvis-core library — STT, wake-word, TTS, LLM, intent, commands, IPC,
Lua sandbox, scheduler, memory, profiles, macros, vision
jarvis-app daemon бинарь — микрофон, listening loop, dispatcher, tray, IPC
jarvis-gui Tauri + Svelte GUI — settings, commands list, footer chips
jarvis-cli debug CLI (classify/execute/list)
frontend/ Vite + Svelte UI для jarvis-gui
resources/
commands/ 59 voice-command packs (Lua скрипты + TOML)
models/ ONNX (intent classifier, GLiNER) — Git LFS
vosk/ Vosk модели (small-ru, small-en, ...)
voices/ пресеты звуков реакций (greet/ok/error/...)
tools/
piper/ Piper TTS бинарник + голоса (.onnx) — устанавливаются install.ps1
silero/ Python helper для Silero TTS (опционально)
ARCHITECTURE.md — для контрибьюторов: data flow, рецепты, тесты.
```
## Голосовой workflow
Поднимаешь `jarvis-app.exe`, говоришь:
```
"Джарвис" ─ wake-word
↓ играет "reply" звук
"Какая сегодня погода?"
↓ STT (Vosk) распознаёт
↓ Intent classifier (MiniLM ONNX) пробует найти команду
↓ Levenshtein fallback
↓ Agentic LLM router (если включён)
↓ LLM fallback (chat)
↓ Озвучивает ответ
"Какая температура завтра?"
↓ 30-сек grace window — без повторного wake-word
↓ LLM помнит контекст разговора
```
После каждой команды есть 30-секундное окно для follow-up без повторного
"Джарвис" (`CONVERSATION_GRACE_MS`).
## Это форк
Оригинальный автор — Abraham Tugalov (Priler).
Апстрим: <https://github.com/Priler/jarvis>.
Лицензия сохранена: **CC BY-NC-SA 4.0** (см. `LICENSE.txt`).
В `Cargo.toml` декларирован `license = "GPL-3.0-only"` — это несоответствие
унаследовано от апстрима и не правилось, чтобы не расходиться с upstream-конфигом.
Приоритет имеет `LICENSE.txt`.
## Python-версия
Старая версия ассистента была на Python. Последний коммит с Python-кодом в
апстриме — [943efbf](https://github.com/Priler/jarvis/tree/943efbfbdb8aeb5889fa5e2dc7348ca4ea0b81df).
Параллельный Python-форк живёт в отдельном репо
([J.A.R.V.I.S-py](https://github.com/DmitryBykov-ISPO/J.A.R.V.I.S-py)) — там же,
но **17 новых паков из Rust-форка пока туда не зеркалированы** (TODO).
## Поддерживаемость
- `runtime_config.rs` — все env vars в одном файле с doc-комментами.
- `tts/` — trait-based, добавить новый бэкенд = реализовать `TtsBackend`.
- `llm/mod.rs` — shared global client, hot-swap через `swap_to(LlmBackend)`.
- `jarvis.cmd.{ok/error/not_found}` — boilerplate-killer для Lua-паков.
- 55 unit-тестов прикрывают всё, что не требует мика/динамика/сети.
- ARCHITECTURE.md содержит рецепты "как добавить X".
## Что в roadmap (что ещё хочется)
- **faster-whisper STT** рядом с Vosk для длинных LLM-фраз.
- **Реальные Win32 макросы** (keyboard + mouse hooks), не только voice replay.
- **Spotify Web API** через OAuth — "что играет", "сохрани в плейлист".
- **Outlook COM** — голосовая почта / календарь.
- **GUI /macros + /scheduler страницы** — управление без голоса.
- **Python parity** для 17 новых паков.
См. `~/.claude/projects/C--Jarvis/memory/project_jarvis_roadmap.md` (если ты
— Claude помогаешь автору) или открой issue.
## Лицензия
CC BY-NC-SA 4.0 — Creative Commons **Attribution-NonCommercial-ShareAlike**.
Полный текст: `LICENSE.txt`. Атрибуция Abraham Tugalov сохранена.