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.
This commit is contained in:
Bossiara13 2026-05-15 17:28:22 +03:00
parent c7ab751e39
commit c22a24ccd8
11 changed files with 998 additions and 167 deletions

View file

@ -107,6 +107,21 @@ fn main() {
tauri_commands::set_tts_backend,
tauri_commands::llm_reset_context,
tauri_commands::llm_get_last_reply,
// Voice macros
tauri_commands::macros_list,
tauri_commands::macros_replay,
tauri_commands::macros_delete,
tauri_commands::macros_is_recording,
tauri_commands::macros_recording_name,
tauri_commands::macros_start_recording,
tauri_commands::macros_save_recording,
tauri_commands::macros_cancel_recording,
// Scheduler tasks
tauri_commands::scheduler_list,
tauri_commands::scheduler_remove,
tauri_commands::scheduler_clear,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

View file

@ -41,4 +41,12 @@ pub use voices::*;
// LLM/TTS backend introspection + hot-swap
mod backends;
pub use backends::*;
pub use backends::*;
// Voice macros
mod macros;
pub use macros::*;
// Scheduler tasks
mod scheduler;
pub use scheduler::*;

View file

@ -0,0 +1,58 @@
//! Tauri commands for the voice-macros system.
use serde::Serialize;
#[derive(Serialize)]
pub struct MacroInfo {
pub name: String,
pub steps_count: usize,
pub steps: Vec<String>,
pub created_at: i64,
pub last_run: Option<i64>,
}
#[tauri::command]
pub fn macros_list() -> Vec<MacroInfo> {
jarvis_core::macros::list().into_iter().map(|m| MacroInfo {
name: m.name,
steps_count: m.steps.len(),
steps: m.steps,
created_at: m.created_at,
last_run: m.last_run,
}).collect()
}
#[tauri::command]
pub fn macros_replay(name: String) -> Result<usize, String> {
jarvis_core::macros::replay(&name)
}
#[tauri::command]
pub fn macros_delete(name: String) -> bool {
jarvis_core::macros::delete(&name)
}
#[tauri::command]
pub fn macros_is_recording() -> bool {
jarvis_core::macros::is_recording()
}
#[tauri::command]
pub fn macros_recording_name() -> Option<String> {
jarvis_core::macros::recording_name()
}
#[tauri::command]
pub fn macros_start_recording(name: String) -> Result<(), String> {
jarvis_core::macros::start_recording(&name)
}
#[tauri::command]
pub fn macros_save_recording() -> Result<usize, String> {
jarvis_core::macros::save_recording()
}
#[tauri::command]
pub fn macros_cancel_recording() -> bool {
jarvis_core::macros::cancel_recording()
}

View file

@ -0,0 +1,59 @@
//! Tauri commands for the proactive scheduler.
use serde::Serialize;
#[derive(Serialize)]
pub struct ScheduledTaskInfo {
pub id: String,
pub name: String,
pub schedule_human: String,
pub action_kind: String,
pub action_text: Option<String>,
pub last_fired: Option<i64>,
pub enabled: bool,
pub created_at: i64,
}
fn schedule_human(s: &jarvis_core::scheduler::Schedule) -> String {
use jarvis_core::scheduler::Schedule;
match s {
Schedule::Daily { hour, minute } => format!("каждый день в {:02}:{:02}", hour, minute),
Schedule::Interval { seconds } => {
if *seconds % 3600 == 0 { format!("каждые {} ч", seconds / 3600) }
else if *seconds % 60 == 0 { format!("каждые {} мин", seconds / 60) }
else { format!("каждые {} сек", seconds) }
}
Schedule::Once { at } => format!("один раз @ {}", at),
}
}
#[tauri::command]
pub fn scheduler_list() -> Vec<ScheduledTaskInfo> {
use jarvis_core::scheduler::Action;
jarvis_core::scheduler::list().into_iter().map(|t| {
let (action_kind, action_text) = match &t.action {
Action::Speak { text } => ("speak".to_string(), Some(text.clone())),
Action::Lua { script_path } => ("lua".to_string(), Some(script_path.clone())),
};
ScheduledTaskInfo {
id: t.id,
name: t.name,
schedule_human: schedule_human(&t.schedule),
action_kind,
action_text,
last_fired: t.last_fired,
enabled: t.enabled,
created_at: t.created_at,
}
}).collect()
}
#[tauri::command]
pub fn scheduler_remove(id: String) -> bool {
jarvis_core::scheduler::remove(&id)
}
#[tauri::command]
pub fn scheduler_clear() -> usize {
jarvis_core::scheduler::clear()
}