fix: Session-Filter vereinfacht + Piper/Whisper Modell-Pfade erweitert [appimage]
Some checks failed
Build AppImage / build (push) Failing after 3m9s

- db.rs: load_sessions_filtered() ohne shared row_mapper (Borrow-Probleme)
- voice.rs: Modell-Suche auch in ~/.local/share/claude-desktop/models/
  und ~/.claude-desktop/models/ (AppImage + Nix-Wrapper Kompatibilität)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eddy 2026-04-21 13:40:51 +02:00
parent c2db56f392
commit a3d1dadc46
2 changed files with 38 additions and 23 deletions

View file

@ -524,40 +524,39 @@ impl Database {
/// Sessions laden, optional gefiltert nach working_dir (Projekt-Bindung) /// Sessions laden, optional gefiltert nach working_dir (Projekt-Bindung)
pub fn load_sessions_filtered(&self, limit: usize, working_dir: Option<&str>) -> SqlResult<Vec<Session>> { pub fn load_sessions_filtered(&self, limit: usize, working_dir: Option<&str>) -> SqlResult<Vec<Session>> {
let row_mapper = |row: &rusqlite::Row| -> rusqlite::Result<Session> { if let Some(dir) = working_dir {
Ok(Session {
id: row.get(0)?,
claude_session_id: row.get(1)?,
title: row.get(2)?,
working_dir: row.get(3)?,
message_count: row.get(4)?,
token_input: row.get(5)?,
token_output: row.get(6)?,
cost_usd: row.get(7)?,
status: row.get(8)?,
created_at: row.get(9)?,
updated_at: row.get(10)?,
last_message: row.get(11)?,
})
};
let sessions = if let Some(dir) = working_dir {
let mut stmt = self.conn.prepare( let mut stmt = self.conn.prepare(
"SELECT id, claude_session_id, title, working_dir, message_count, "SELECT id, claude_session_id, title, working_dir, message_count,
token_input, token_output, cost_usd, status, created_at, updated_at, last_message token_input, token_output, cost_usd, status, created_at, updated_at, last_message
FROM sessions WHERE working_dir = ?1 ORDER BY updated_at DESC LIMIT ?2" FROM sessions WHERE working_dir = ?1 ORDER BY updated_at DESC LIMIT ?2"
)?; )?;
stmt.query_map(params![dir, limit as i64], row_mapper)?.collect::<SqlResult<Vec<_>>>()? stmt.query_map(params![dir, limit as i64], |row| {
Ok(Session {
id: row.get(0)?, claude_session_id: row.get(1)?, title: row.get(2)?,
working_dir: row.get(3)?, message_count: row.get(4)?,
token_input: row.get(5)?, token_output: row.get(6)?,
cost_usd: row.get(7)?, status: row.get(8)?,
created_at: row.get(9)?, updated_at: row.get(10)?,
last_message: row.get(11)?,
})
})?.collect()
} else { } else {
let mut stmt = self.conn.prepare( let mut stmt = self.conn.prepare(
"SELECT id, claude_session_id, title, working_dir, message_count, "SELECT id, claude_session_id, title, working_dir, message_count,
token_input, token_output, cost_usd, status, created_at, updated_at, last_message token_input, token_output, cost_usd, status, created_at, updated_at, last_message
FROM sessions ORDER BY updated_at DESC LIMIT ?1" FROM sessions ORDER BY updated_at DESC LIMIT ?1"
)?; )?;
stmt.query_map(params![limit as i64], row_mapper)?.collect::<SqlResult<Vec<_>>>()? stmt.query_map(params![limit as i64], |row| {
}; Ok(Session {
id: row.get(0)?, claude_session_id: row.get(1)?, title: row.get(2)?,
Ok(sessions) working_dir: row.get(3)?, message_count: row.get(4)?,
token_input: row.get(5)?, token_output: row.get(6)?,
cost_usd: row.get(7)?, status: row.get(8)?,
created_at: row.get(9)?, updated_at: row.get(10)?,
last_message: row.get(11)?,
})
})?.collect()
}
} }
/// Holt eine Session nach ID /// Holt eine Session nach ID

View file

@ -27,9 +27,17 @@ fn whisper_model_path() -> String {
.ok() .ok()
.and_then(|p| p.parent().map(|p| p.to_path_buf())); .and_then(|p| p.parent().map(|p| p.to_path_buf()));
let home_dir = std::env::var("HOME").ok()
.map(std::path::PathBuf::from);
let candidates = vec![ let candidates = vec![
// Relativ zum Binary (Dev-Modus)
exe_dir.as_ref().map(|d| d.join("../models/ggml-base.bin")), exe_dir.as_ref().map(|d| d.join("../models/ggml-base.bin")),
exe_dir.as_ref().map(|d| d.join("models/ggml-base.bin")), exe_dir.as_ref().map(|d| d.join("models/ggml-base.bin")),
// XDG Data Home / Home-Verzeichnis (AppImage + Nix-Wrapper)
home_dir.as_ref().map(|d| d.join(".local/share/claude-desktop/models/ggml-base.bin")),
home_dir.as_ref().map(|d| d.join(".claude-desktop/models/ggml-base.bin")),
// CWD Fallback
Some(std::path::PathBuf::from("models/ggml-base.bin")), Some(std::path::PathBuf::from("models/ggml-base.bin")),
]; ];
@ -48,9 +56,17 @@ fn piper_model_path() -> String {
.ok() .ok()
.and_then(|p| p.parent().map(|p| p.to_path_buf())); .and_then(|p| p.parent().map(|p| p.to_path_buf()));
let home_dir = std::env::var("HOME").ok()
.map(std::path::PathBuf::from);
let candidates = vec![ let candidates = vec![
// Relativ zum Binary (Dev-Modus)
exe_dir.as_ref().map(|d| d.join("../models/de_DE-thorsten-high.onnx")), exe_dir.as_ref().map(|d| d.join("../models/de_DE-thorsten-high.onnx")),
exe_dir.as_ref().map(|d| d.join("models/de_DE-thorsten-high.onnx")), exe_dir.as_ref().map(|d| d.join("models/de_DE-thorsten-high.onnx")),
// XDG Data Home / Home-Verzeichnis (AppImage + Nix-Wrapper)
home_dir.as_ref().map(|d| d.join(".local/share/claude-desktop/models/de_DE-thorsten-high.onnx")),
home_dir.as_ref().map(|d| d.join(".claude-desktop/models/de_DE-thorsten-high.onnx")),
// CWD Fallback
Some(std::path::PathBuf::from("models/de_DE-thorsten-high.onnx")), Some(std::path::PathBuf::from("models/de_DE-thorsten-high.onnx")),
]; ];