refactor: maintainability pass — dedup, central env config, cmd helpers, tests, ARCHITECTURE.md
User asked the code stays easy to fix/extend as the feature surface grows.
This commit refactors what was duplicated, centralises what was scattered,
adds tests where there were none, and writes the architecture doc that
contributors will need.
Deduplication
- tts::play_wav extracted to tts/mod.rs as pub(crate). Was identical in
piper.rs and silero.rs (~25 lines × 2). Both backends now call super::play_wav.
Centralised env config
- new crates/jarvis-core/src/runtime_config.rs — single doc-file for every
JARVIS_* / GROQ_* / OLLAMA_* env var. Includes:
- ENV_* constants with doc comments
- get(name) / get_bool(name, default) / get_parse(name, default) helpers
- feature-flag wrappers: llm_tts_enabled(), llm_router_enabled(),
llm_router_threshold()
- log_effective_config() prints active values on startup
- migrated llm_fallback (JARVIS_LLM_TTS), llm_router (JARVIS_LLM_ROUTER,
JARVIS_LLM_ROUTER_THRESHOLD) to use the new helpers. Pattern set for
future migrations.
Lua boilerplate killer
- new crates/jarvis-core/src/lua/api/cmd.rs exposing:
jarvis.cmd.ok(msg?) — play_ok + speak + {chain=false}
jarvis.cmd.chain_ok(msg?) — same but chain=true
jarvis.cmd.error(msg?) — play_error + speak + {chain=false}
jarvis.cmd.not_found(msg?) — play_not_found + speak + {chain=false}
jarvis.cmd.silent_ok / silent_error
- refactored 5 packs (daily_briefing/off, memory_pack/list, pomodoro/stop,
habit_nudge/stop_all, scheduler/clear) — each lost 3-4 lines of repetitive
play_*/speak/return boilerplate. Pattern for future packs documented in
ARCHITECTURE.md.
Tests (was 32, now 49)
- long_term_memory: 8 new tests for normalize_key, search_in (rank, limit,
empty), build_context_from (empty + populated), serde round-trips for
MemoryRecord and Store. Extracted pure logic (search_in, build_context_from)
into pub(crate) functions to enable testing without global state.
- profiles: 6 new tests for Profile::allows_command (empty/whitelist/blacklist/
deny-wins-over-allow), serde round-trip with all fields + minimal-fields
tolerance via #[serde(default)].
- runtime_config: 2 tests for get_bool / get_parse defaults.
- All 49 tests pass.
New mood/energy log pack
- resources/commands/mood_log/ with 2 commands:
mood.record "запиши настроение 7" / "сегодня мне грустно" → stores
timestamped entry via jarvis.memory.remember
mood.recap "как прошла неделя" → LLM summarises last 30 entries
- Showcase: composes memory + llm + cmd helpers in <30 lines per script.
ARCHITECTURE.md (new, 250 lines)
- Crate layout, data flow diagram (mic→action 10 steps), per-module
responsibility table, configuration layers, TTS pipeline diagram,
Lua sandbox details with API quick-ref, background-services overview,
"how to add a pack/feature/TTS backend" recipes, test coverage map,
build instructions with MSVC env, git workflow with Forgejo NO_PROXY trick.
- Aimed at someone who just cloned the repo and needs to fix a bug fast.
Build: cargo build --release -p jarvis-app -p jarvis-gui both green.
Tests: 49/49 jarvis-core unit tests pass.
This commit is contained in:
parent
45243c3e3c
commit
6225198821
22 changed files with 891 additions and 93 deletions
|
|
@ -137,7 +137,7 @@ pub fn handle(prompt: &str) {
|
|||
}
|
||||
|
||||
fn speak_reply(text: &str) {
|
||||
if std::env::var("JARVIS_LLM_TTS").as_deref() == Ok("false") {
|
||||
if !jarvis_core::runtime_config::llm_tts_enabled() {
|
||||
return;
|
||||
}
|
||||
tts::speak(text, &SpeakOpts::lang("ru"));
|
||||
|
|
|
|||
|
|
@ -60,19 +60,15 @@ fn build_state() -> Option<State> {
|
|||
return None;
|
||||
}
|
||||
};
|
||||
let threshold = std::env::var("JARVIS_LLM_ROUTER_THRESHOLD")
|
||||
.ok()
|
||||
.and_then(|v| v.parse::<f32>().ok())
|
||||
.unwrap_or(DEFAULT_THRESHOLD);
|
||||
let threshold = jarvis_core::runtime_config::llm_router_threshold();
|
||||
let _ = DEFAULT_THRESHOLD; // kept for backward visibility in source
|
||||
|
||||
info!("LLM router enabled (backend: {}, threshold {:.2}).", client.backend().name(), threshold);
|
||||
Some(State { client, threshold })
|
||||
}
|
||||
|
||||
fn router_enabled() -> bool {
|
||||
std::env::var("JARVIS_LLM_ROUTER")
|
||||
.map(|v| matches!(v.trim().to_lowercase().as_str(), "1" | "true" | "yes" | "on"))
|
||||
.unwrap_or(true) // default ON when GROQ_TOKEN is present
|
||||
jarvis_core::runtime_config::llm_router_enabled()
|
||||
&& config::LLM_DEFAULT_ENABLED
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ fn main() -> Result<(), String> {
|
|||
eprintln!("[jarvis-app] step: i18n::init");
|
||||
i18n::init(&settings.lock().language);
|
||||
|
||||
eprintln!("[jarvis-app] step: runtime_config::log_effective_config");
|
||||
jarvis_core::runtime_config::log_effective_config();
|
||||
|
||||
eprintln!("[jarvis-app] step: llm_fallback::init");
|
||||
llm_fallback::init();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue