Commit graph

17 commits

Author SHA1 Message Date
Bossiara13
73fc404ec7 feat: /history page (recognition log) + multi wake-word loading
Some checks are pending
Rust CI / cargo test (jarvis-core) (push) Waiting to run
Rust CI / cargo clippy (push) Waiting to run
Rust CI / cargo check (workspace) (push) Waiting to run
# Recognition history page

New /history route in the Tauri GUI. Every voice/text phrase that
reaches the dispatcher gets a row with: timestamp, the phrase, what
happened, command id + confidence (if matched), which matcher fired
(intent / fuzzy / LLM-router / LLM-fallback).

Color coding:
- Green: command matched AND executed successfully
- Red:   command matched but failed, OR dispatcher error
- Blue:  LLM fallback handled it (Jarvis spoke a free-form reply)
- Orange: no match at all ("Не понял")

Live updates: GUI polls every 2s from the on-disk log, so the page
shows daemon writes in near real time even though they're separate
processes. Filter box for searching by phrase or command id.

Architecture:
- New core module `recognition_log` with ring buffer (cap 500) +
  atomic JSON write-through to `<APP_CONFIG_DIR>/recognition_log.json`.
- `record(phrase, source, outcome)` is the single call-site from the
  daemon's `execute_command()` — hooked into the 4 outcome paths
  (matched-ok, matched-fail, not-found, llm-handled, error).
- `recent(limit)` reads the in-memory buffer (daemon's view).
- `recent_from_disk(limit)` re-reads the JSON file — GUI uses this
  since the GUI process has its own buffer that doesn't see the
  daemon's writes.
- 5 new unit tests covering ring buffer trimming, outcome serde
  roundtrip, missing/corrupt/oversized file recovery.

GUI:
- `crates/jarvis-gui/src/tauri_commands/history.rs`: history_recent,
  history_clear. Flattens the Outcome enum into a single struct that's
  easier for the Svelte template to render.
- `frontend/src/routes/history/index.svelte`: ~270 lines. Stats badges
  (✓ N matched / ✗ N misses / total), filter input, virtual list of
  entry cards with color-coded left border. Polls every 2s.
- Header gets a new "История" / "History" button (between Plugins and
  Settings). Russian + English locale entries added.

# Multi wake-word loading

Was: `init()` loaded the bundled `jarvis-default.rpw` + at most ONE
custom (from `settings.custom_wake_word`). User had to pick a single
trained model.

Now: loads the bundled default PLUS every .rpw in
`APP_CONFIG_DIR/wake_words/` simultaneously. Rustpotter natively
supports multiple wake-word triggers — each adds robustness for
different voice profiles. The legacy `custom_wake_word` field is
checked for back-compat but is a no-op if it points inside the
already-loaded directory.

User-facing impact: train the wake-word once via /wake-trainer →
restart daemon → detection improves automatically without picking a
single "active" model.

# Settings → "Обучить wake-word" button

Added a purple button on the settings page that links to
/wake-trainer. The trainer existed but had no in-GUI link, so users
couldn't find it without typing the URL. Now sits next to the
"Конструктор команд (Python)" button.

Tests: 140 → 145 rust core tests (+5 recognition_log). Frontend
rebuilds in 6.2s. Release builds of jarvis-app + jarvis-gui green.
Practical test: GUI launches (MainWindowTitle confirmed), seed log
file written + visible to the page.
2026-05-24 23:23:43 +03:00
Bossiara13
3f8300dc6f chore: CI workflows + drop Ukrainian (UA → just RU/EN)
CI (.github/workflows/ci.yml):
- Three parallel jobs on push & PR: cargo test (jarvis-core), cargo
  clippy (lint, warnings-as-errors), cargo check (workspace). Windows
  runner, stable toolchain, rust-cache for fast incremental builds.
- Deliberately skips release build of jarvis-gui — that needs Node+npm
  +Tauri bundler and would balloon CI to ~10min per push.

Drop Ukrainian:
- Delete ua.ftl, remove UA from SUPPORTED_LANGUAGES.
- config.rs: prune UA arms from get_wake_phrases / get_wake_grammar /
  get_phrases_to_remove / get_llm_trigger_phrases / get_llm_system_prompt.
- stt/vosk.rs: drop UA → uk language mapping.
- tray menu: drop "Українська" entry.
- frontend: drop UA from Header.svelte language list, settings page
  language map, i18n.ts fallback.
- 82 command.toml files stripped of every `ua = [...]` block (205
  blocks total). Handled via subagent — TOML still parses, all 6 command
  tests pass.

.gitignore: stop tracking dev.env / dll_probe*.py / imports_full.txt
which were sitting in working tree.

Tests: 128 pass (no regression). Workspace still compiles end-to-end.
2026-05-16 13:38:12 +03:00
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
Bossiara13
4efe306b3a feat(gui): profile switcher chip in header
Visible visual indicator of the active profile + click-to-swap dropdown.
Closes the last small UX gap pointed out in earlier sessions.

Tauri (crates/jarvis-gui/src/tauri_commands/profile.rs)
  - profile_list()   → Vec<String> of available profile names
  - profile_active() → {name, description, icon, greeting}
  - profile_set(name) → swaps active profile, returns new active

Frontend (frontend/src/components/Header.svelte)
  - Polls profile_active every 5 seconds.
  - Shows a coloured chip with icon+name when profile != "default"
    (orange tint, attention-grabbing). For "default" — muted star chip.
  - Click opens a dropdown listing all profile names; click one → swap.
  - Dropdown closes on outside-click (shared handler with lang dropdown).
  - SCSS styled to match existing aesthetic.

Build: cargo build --release -p jarvis-gui green (2m).

Now the user can see at a glance which profile is active (e.g. "💼 work")
without having to ask voice or open Settings.
2026-05-16 00:48:23 +03:00
Bossiara13
d3180b7d78 feat: GUI /memory page + disk/date_math/sleep_timer packs (10 new commands)
GUI: Memory management completes the management trio (/macros + /scheduler + /memory).

Tauri commands (crates/jarvis-gui/src/tauri_commands/memory.rs)
  - memory_list             → Vec<MemoryFact{key, value, created_at, last_used_at, use_count}>
  - memory_remember(k, v)   → persist new fact (or overwrite)
  - memory_forget(key)      → delete by exact key
  - memory_search(q, limit) → substring search

GUI /memory page (frontend/src/routes/memory/index.svelte)
  - Top: add-fact form (key + value inputs + "+Добавить" button)
  - Substring filter input for the list
  - Per-card: key + use_count badge + value (highlighted box) + timestamps +
    "Забыть" button with confirm() guard
  - Auto-sorted by recency (last_used_at desc)
  - Empty state shows voice-hint: 'скажи Jarvis-у "запомни что я люблю чай улун"'

Header (frontend/src/components/Header.svelte)
  - New "Память" button between /scheduler and /settings.
  - i18n: header-memory in ru/en/ua FTL files.

New voice packs

resources/commands/disk/ (2 cmds)
  - disk.free      "сколько свободно на диске" / "сколько места на диске C"
                   PowerShell Get-PSDrive → speaks "Свободно X ГБ из Y, это N%"
  - disk.list      "какие у меня диски" → "C 120 ГБ, D 300 ГБ, E 50 ГБ"

resources/commands/date_math/ (2 cmds)
  - date.days_until    "сколько дней до нового года" / "сколько до 8 марта" /
                       "сколько до 15 марта" — recognises Russian months,
                       holidays (Новый год, Рождество, 8 марта, 9 мая).
                       Auto-rolls to next year if target already passed.
                       Russian-grammar pluralisation (день/дня/дней).
  - date.day_of_week   "какой сегодня день недели" — Zeller's congruence,
                       maps to ru day name.

resources/commands/sleep_timer/ (3 cmds)
  - sleep_timer.pause_in    "выключи музыку через 30 минут"
                            → scheduler one-shot lua action that fires media
                            VK_MEDIA_PLAY_PAUSE via the existing media_keys helper.
                            (Auto-generates _fire_pause.lua wrapper if missing.)
  - sleep_timer.shutdown_in "выключи компьютер через 1 час"
                            → shutdown.exe /s /t <secs>. Caps at 24 hours.
                            Speaks "Скажите 'отмени таймер' чтобы передумать."
  - sleep_timer.cancel      "отмени таймер выключения" / "не выключай компьютер"
                            → shutdown /a + scheduler.remove("sleep_timer_pause"),
                            idempotent.

Pack count: 64 → 67. Tests: 112/112 pass.
Build: cargo build --release -p jarvis-gui green.
2026-05-15 23:35:23 +03:00
Bossiara13
a2dfadf5c1 feat(gui): wire Footer + Settings to daemon over IPC (closes the gap from a6a098d)
a6a098d added daemon-side IPC handlers (SwitchLlm, ReloadLlm, QueryHealth)
but the GUI was still talking only to its own process. This commit wires
the frontend to actually use those handlers.

frontend/src/lib/ipc.ts
  - New DaemonHealth interface + daemonHealth: writable<DaemonHealth | null>.
  - handleEvent: "health_snapshot" case fills daemonHealth from daemon's IpcEvent.
  - New senders:
      switchDaemonLlm(backend)  → action "switch_llm"
      reloadDaemonLlm()          → action "reload_llm"
      queryDaemonHealth()        → action "query_health"

frontend/src/stores.ts
  - Re-exports daemonHealth + the three new senders + DaemonHealth type.

frontend/src/components/Footer.svelte
  - Polls every 5s but PREFERS IPC: if daemon connected, calls queryDaemonHealth
    (snapshot arrives via daemonHealth store).
  - Falls back to invoke("get_active_backends") if daemon offline — shows
    GUI-process view in that case, with the chip tooltip distinguishing
    "daemon" vs "gui-process" source.

frontend/src/routes/settings/index.svelte (AI Backends tab)
  - applyLlmBackend now ALSO fires switchDaemonLlm so the running listener
    picks the new backend without restart.
  - "Auto" (empty) path calls reloadDaemonLlm so daemon re-reads DB.

End-to-end flow now:
  GUI dropdown → set_llm_backend (Tauri, persists DB + swaps GUI proc)
              ↘ switchDaemonLlm (IPC, swaps daemon proc too)
              ↘ daemon emits health_snapshot on next QueryHealth
              ↘ daemonHealth store updates
              ↘ Footer chips re-render with new state

Build: cargo build --release -p jarvis-gui green.
2026-05-15 17:42:40 +03:00
Bossiara13
c22a24ccd8 feat(gui): /macros + /scheduler pages + README rewrite
Surfaces voice macros and scheduled tasks in the GUI, so the user doesn't
have to remember voice commands or grep schedule.json by hand.

Tauri commands (crates/jarvis-gui/src/tauri_commands/)
  - macros.rs:    macros_list, macros_replay, macros_delete, macros_is_recording,
                  macros_recording_name, macros_start_recording, macros_save_recording,
                  macros_cancel_recording (8 commands).
  - scheduler.rs: scheduler_list, scheduler_remove, scheduler_clear (3 commands).
  - Both exposed in main.rs invoke_handler.

GUI pages (frontend/src/routes/)
  - macros/index.svelte:
    * Lists all macros with name, steps_count, first 5 step previews,
      created/last_run timestamps.
    * Top: TextInput + "Начать запись" button. While recording shows orange
      banner with "Сохранить"/"Отменить" buttons + polls is_recording every 2s.
    * Per-card: "Запустить" (with busy state for replay duration), "Удалить".
    * confirm() before delete.
  - scheduler/index.svelte:
    * Lists tasks with name, schedule_human (e.g. "каждые 2 ч"), action body,
      ID, timestamps, action_kind badge.
    * "Отменить" per task + "Очистить всё (N)" bottom button.
    * Auto-polls every 5s (so the list updates as scheduler ticks fire tasks).

Header (frontend/src/components/Header.svelte)
  - Two new buttons: "Макросы" → /macros, "Расписание" → /scheduler.
  - Beside existing /commands and /settings buttons.

i18n
  - ru/en/ua FTL: settings-ai-backends, settings-llm-*, settings-tts-*,
    settings-profile, header-macros, header-scheduler.
  - Re-applied AI Backends keys for ua.ftl (earlier edit hadn't taken).

README.md (full rewrite)
  - Old README was 178 lines mostly explaining LLM-trigger flow and VAD config.
  - New README is ~190 lines covering: features (LLM hot-swap, memory, profiles,
    vision, scheduler, macros, utilities table), quick start, env vars table,
    build steps with vcvars setup, test command, structure tree, voice workflow
    diagram, license, roadmap.
  - Up to date for 59 packs and all new infra.

Build: cargo build --release -p jarvis-gui green (2m). 55/55 tests pass.
2026-05-15 17:28:22 +03:00
Bossiara13
d63399f4c9 feat(gui): footer backend chips + Settings 'AI Backends' tab + i18n
Surfaces the LLM/TTS hot-swap UX in the GUI so the user doesn't need env vars
or voice commands. Tauri commands for this landed in b243e67; this commit
wires them to Svelte.

Footer (frontend/src/components/Footer.svelte)
  - Poll get_active_backends() every 5 s, show TTS / LLM / Profile chips.
  - Chips have border accents by kind (cyan = TTS, lime = LLM, orange = Profile).
  - Friendly title tooltips with full backend + model names.
  - Silent if jarvis-gui can't reach the command (e.g. cold start) — no UI flicker.

Settings — new "AI Backends" tab (frontend/src/routes/settings/index.svelte)
  - Status banner showing active LLM (with model name) + TTS + Profile.
  - LLM selector: Auto / Groq / Ollama → calls set_llm_backend on change
    (hot-swap, persisted to DB).
  - TTS selector: Auto / SAPI / Piper / Silero → calls set_tts_backend
    (persisted, effective on next jarvis-app restart).
  - "Reset context" button → llm_reset_context Tauri command.
  - Error toast for swap failures (e.g. Groq selected but no GROQ_TOKEN).
  - Tips alert: how to install Ollama / Piper / voice commands.
  - Loads prefs via db_read('llm_backend' / 'tts_backend') on mount.

i18n strings (ru/en/ua, .ftl files)
  - 14 new keys: settings-ai-backends, settings-ai-active, settings-ai-auto,
    settings-ai-applying, settings-ai-error, settings-ai-tips,
    settings-llm-backend{,-desc}, settings-tts-backend{,-desc},
    settings-llm-context{,-desc}, settings-llm-reset, settings-profile.

Build glue (crates/jarvis-gui/Cargo.toml)
  - jarvis-core dep now includes the `llm` feature so backends.rs can resolve
    `jarvis_core::llm::*` (was failing to compile after the global LLM module).

.gitignore
  - tools/piper/*.dll, piper.exe, voices/, espeak-ng-data/ — locally
    installed binaries from tools/piper/install.ps1, not committed.

Build: cargo build --release -p jarvis-gui green (4m, includes npm/Vite).
Test path: rebuild + launch jarvis-gui, /settings → "AI Backends" tab.
2026-05-15 17:06:46 +03:00
Bossiara13
ae279aeef7 feat(gui): footer badge "Rust" + one-click run.bat launcher
GUI: Footer.svelte gets a small inline "Rust" pill next to the
copyright line (red bg #b7411a, white 11px, rounded). Now obvious
at-a-glance which fork's UI you're looking at when both python and
rust are open side-by-side. Python edition mirrors with a console
banner.

Launcher: run.bat at the repo root loads dev.env (skipping #-comments
and blank lines), then `start ""` spawns target\release\jarvis-gui.exe.
The new Desktop shortcut "Jarvis (Rust).lnk" points at this batch
file with resources\icons\icon.ico as its icon. WindowStyle=7 means
the cmd host stays minimized — only the GUI window pops up.

If the user hasn't built yet, the bat prints the cargo build command
and pauses instead of silently doing nothing.
2026-05-15 12:12:11 +03:00
Bossiara13
24457ad6c9 chore(gui): rebrand — strip TG/Boosty/Patreon/feedback-bot, keep CC BY-NC-SA attribution
The previous feature/gui-rebrand-polish work only updated the appInfo store
keys; Footer.svelte, settings, and the commands page were still rendering
upstream's Telegram channel, Boosty/Patreon support links, feedback bot,
and the original author byline. This finishes the job.

Rust side (applies after `cargo build` — currently a no-op until MSVC Build
Tools are reinstalled):
- Cargo.toml: authors = ["Bossiara13"], repository = J.A.R.V.I.S-rust fork.
  Original attribution stays in LICENSE.txt per CC BY-NC-SA 4.0; the UI
  no longer renders an author byline.
- config.rs: dropped TG_OFFICIAL_LINK / FEEDBACK_LINK / SUPPORT_BOOSTY_LINK
  / SUPPORT_PATREON_LINK. Added UPSTREAM_REPOSITORY_LINK (Priler/jarvis for
  the licence attribution), ISSUES_LINK (this fork's GH issues), and
  PYTHON_FORK_LINK.
- tauri_commands/etc.rs: dropped get_tg_official_link/get_boosty_link/
  get_patreon_link/get_feedback_link. Added get_upstream_link, get_issues_link,
  get_python_fork_link. Tidied up the Option<&str> -> String boilerplate
  with unwrap_or.
- main.rs: invoke_handler updated to match.

Frontend side (visible only after Rust rebuild — Tauri bundles the dist into
the exe):
- stores.ts: appInfo shape reduced to repositoryLink / upstreamLink /
  issuesLink / pythonForkLink / logFilePath. loadAppInfo() uses fetchOr()
  with hardcoded fallbacks so the UI still populates correctly when run
  against an un-rebuilt binary; fetchRepoOr() additionally overrides
  CARGO_PKG_REPOSITORY if it still resolves to upstream's Priler/jarvis.
- Footer.svelte: rewritten — © year + "J.A.R.V.I.S." + repo link + issues
  link + small "fork of Priler/jarvis · CC BY-NC-SA 4.0" attribution line.
  No author byline (it's in LICENSE.txt).
- routes/settings/index.svelte: feedback link now points to GitHub Issues.
- routes/commands/index.svelte: TG-channel reference replaced with a link
  to the Python fork (where the command builder lives) plus a pointer to
  resources/commands/ in this repo. Bruh GIF removed.
- locales/{ru,en,ua}.ftl: removed footer-author / footer-telegram /
  footer-support, added footer-issues / footer-fork-of, rewrote
  commands-wip-* strings, retargeted settings-beta-bot to "GitHub Issues".

Bundle identifier (com.priler.jarvis) kept intact to avoid moving the app
data directory.
2026-05-15 01:09:14 +03:00
Priler
47b7e7a65d Tray options implementation + Voice system rewrite + build fixes 2026-01-07 23:29:46 +05:00
Priler
412acb7e2d Multilingual support via Fluent + Frontend improvements + Rewrite of ArcReactor 2026-01-07 05:04:04 +05:00
Priler
adec595cfa websockets based IPC added in order to bind GUI/app together 2026-01-07 00:15:36 +05:00
Priler
eb0d40bae6 noise suppression added via nnnoiseless + vad + gain-normalizer + few frontend changes 2026-01-06 23:32:58 +05:00
Priler
0c28304840 frontend cleanup 2026-01-04 22:50:34 +05:00
Priler
091a41ac33 frontend fixes & db rewrite with serde 2026-01-04 09:00:51 +05:00
Priler
09f72622bc project restructure with Rust workspaces 2026-01-04 05:19:47 +05:00