fix: persist LLM config to prefs store so Settings survive restarts

set_llm_config only mutated an in-memory Mutex; lib.rs always started
from LlmConfig::default(). Config now round-trips through the same
dm-pal-prefs.json store as dataDir, with a defaults fallback so a
future shape change can't brick startup. Prefs consts now live in
lib.rs (pub) instead of being mirrored per-module.
This commit is contained in:
itsamejms
2026-09-06 23:22:34 +01:00
parent 3eb0a2da2e
commit 03a634fdd0
3 changed files with 30 additions and 11 deletions
+2 -5
View File
@@ -3,11 +3,8 @@ use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use tauri::Manager;
use tauri_plugin_store::StoreExt;
// ponytail: the data-dir pref store + key are defined in lib.rs; mirror them
// here so this module is self-contained for reads/writes.
const PREFS_STORE: &str = "dm-pal-prefs.json";
const DATA_DIR_KEY: &str = "dataDir";
use crate::{DATA_DIR_KEY, PREFS_STORE};
// PREFS_STORE / DATA_DIR_KEY live in lib.rs (pub) — single source of truth.
#[derive(Debug, Serialize)]
pub struct DataDirInfo {
+13 -3
View File
@@ -3,6 +3,7 @@ use crate::llm::{self, AppState, ChatMessage, ChatResponse, GenerateRequest, Llm
use serde_json::json;
use tauri::ipc::Channel;
use tauri::AppHandle;
use tauri_plugin_store::StoreExt;
// ─── Simple (non-streaming) generate ─────────────────────────
@@ -95,9 +96,18 @@ pub fn get_llm_config(state: tauri::State<'_, AppState>) -> Result<crate::llm::L
}
#[tauri::command]
pub fn set_llm_config(state: tauri::State<'_, AppState>, config: crate::llm::LlmConfig) -> Result<(), String> {
let mut lock = state.config.lock().map_err(|e| e.to_string())?;
*lock = config;
pub fn set_llm_config(
app: AppHandle,
state: tauri::State<'_, AppState>,
config: crate::llm::LlmConfig,
) -> Result<(), String> {
let stored = serde_json::to_value(&config).map_err(|e| e.to_string())?;
*state.config.lock().map_err(|e| e.to_string())? = config;
// Persist so Settings survive restart. Same prefs store as dataDir;
// load_llm_config in lib.rs falls back to defaults if this ever unparses.
let store = app.store(crate::PREFS_STORE).map_err(|e| e.to_string())?;
store.set(crate::CONFIG_KEY, stored);
store.save().map_err(|e| e.to_string())?;
Ok(())
}
+15 -3
View File
@@ -12,8 +12,11 @@ use tauri_plugin_store::StoreExt;
// ponytail: the data-dir preference lives in a tiny store at the OS default
// app_data_dir so it's always discoverable at startup, even before we know the
// custom location. Key: `dataDir` (absolute path). Empty/missing → default.
const PREFS_STORE: &str = "dm-pal-prefs.json";
const DATA_DIR_KEY: &str = "dataDir";
// The persisted LLM config lives here too (key `llmConfig`) so Settings
// survive restarts. pub: commands modules read/write through crate::.
pub const PREFS_STORE: &str = "dm-pal-prefs.json";
pub const DATA_DIR_KEY: &str = "dataDir";
pub const CONFIG_KEY: &str = "llmConfig";
/// Resolve the data dir: the configured one if set and usable, else the
/// default `$APPDATA/dm-toolkit`.
@@ -34,6 +37,15 @@ fn resolve_data_dir(app: &tauri::AppHandle) -> std::path::PathBuf {
default
}
/// Load the persisted LLM config (Settings). Falls back to defaults when
/// missing or unparsable — a future config-shape change never bricks startup;
/// the DM just re-enters Settings once.
fn load_llm_config(app: &tauri::AppHandle) -> llm::LlmConfig {
let Ok(store) = app.store(PREFS_STORE) else { return llm::LlmConfig::default() };
let Some(v) = store.get(CONFIG_KEY) else { return llm::LlmConfig::default() };
serde_json::from_value(v).unwrap_or_default()
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
@@ -48,7 +60,7 @@ pub fn run() {
let gen = generations::GenerationStore::open(&data_dir)
.expect("open generations db");
app.manage(AppState {
config: Mutex::new(llm::LlmConfig::default()),
config: Mutex::new(load_llm_config(&app.handle())),
rag,
gen,
data_dir,