[appimage] Technische Schulden: Cargo Warnings + Bridge Error-Handling + Chat-Layout
All checks were successful
Build AppImage / build (push) Successful in 9m13s

- Cargo Warnings: 0 (dead_code allow für load_sessions, invalidate_expired)
- Bridge: uncaughtException + unhandledRejection Handler, Ollama .catch()
- Rust: Parse-Fehler bei Bridge-Nachrichten werden geloggt statt verschluckt
- Chat-Panel: Detach-Layout Fix bereits enthalten (flex-shrink, min-height)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eddy 2026-04-21 14:40:38 +02:00
parent 97488ded61
commit f69f566b00
5 changed files with 31 additions and 14 deletions

View file

@ -105,9 +105,9 @@ Alles aus Phase 1-16 ist implementiert und funktionsfaehig:
|-----|-----------| |-----|-----------|
| TypeScript strict mode | Niedrig | | TypeScript strict mode | Niedrig |
| E2E Tests (Playwright) | Mittel | | E2E Tests (Playwright) | Mittel |
| Cargo warnings eliminieren | Niedrig | | ✅ Cargo warnings eliminieren | Erledigt — 0 Warnings |
| Dead Code in alten Panels | Niedrig | | Dead Code in alten Panels | Niedrig |
| Bridge Error-Handling verbessern | Mittel | | ✅ Bridge Error-Handling verbessern | Erledigt — Global Handler, Parse-Logging, .catch() |
--- ---

View file

@ -875,18 +875,18 @@ function handleCommand(msg) {
case 'check-ollama': { case 'check-ollama': {
// Ollama-Verfügbarkeit prüfen // Ollama-Verfügbarkeit prüfen
checkOllamaAvailability().then(status => { checkOllamaAvailability()
sendResponse(msg.id, status); .then(status => sendResponse(msg.id, status))
}); .catch(err => sendError(msg.id, `Ollama-Check fehlgeschlagen: ${err.message}`));
break; break;
} }
case 'set-ollama-config': { case 'set-ollama-config': {
if (msg.endpoint) ollamaEndpoint = msg.endpoint; if (msg.endpoint) ollamaEndpoint = msg.endpoint;
if (msg.model) ollamaModel = msg.model; if (msg.model) ollamaModel = msg.model;
checkOllamaAvailability().then(status => { checkOllamaAvailability()
sendResponse(msg.id, { ...status, endpoint: ollamaEndpoint, model: ollamaModel }); .then(status => sendResponse(msg.id, { ...status, endpoint: ollamaEndpoint, model: ollamaModel }))
}); .catch(err => sendError(msg.id, `Ollama-Config fehlgeschlagen: ${err.message}`));
break; break;
} }
@ -997,7 +997,7 @@ checkOllamaAvailability().then(status => {
if (status.available) { if (status.available) {
process.stderr.write(`🧠 Ollama verfügbar: ${status.models.length} Modelle (${ollamaEndpoint})\n`); process.stderr.write(`🧠 Ollama verfügbar: ${status.models.length} Modelle (${ollamaEndpoint})\n`);
} }
}); }).catch(() => { /* Ollama nicht erreichbar — kein Problem */ });
// ============ Main ============ // ============ Main ============
@ -1088,6 +1088,19 @@ process.on('SIGTERM', () => { clearInterval(keepAlive); cleanupDaemon(); process
process.on('SIGINT', () => { clearInterval(keepAlive); cleanupDaemon(); process.exit(0); }); process.on('SIGINT', () => { clearInterval(keepAlive); cleanupDaemon(); process.exit(0); });
process.on('exit', () => { cleanupDaemon(); }); process.on('exit', () => { cleanupDaemon(); });
// Globale Fehler-Handler — Bridge darf nicht still abstürzen
process.on('uncaughtException', (err) => {
process.stderr.write(`❌ Unbehandelter Fehler: ${err.message}\n${err.stack}\n`);
sendEvent('bridge-error', { type: 'uncaughtException', message: err.message, stack: err.stack });
sendMonitorEvent('error', `Bridge Crash: ${err.message}`, { stack: err.stack });
});
process.on('unhandledRejection', (reason) => {
const msg = reason instanceof Error ? reason.message : String(reason);
process.stderr.write(`❌ Unhandled Promise Rejection: ${msg}\n`);
sendEvent('bridge-error', { type: 'unhandledRejection', message: msg });
sendMonitorEvent('error', `Unhandled Rejection: ${msg}`, {});
});
// Bereit-Signal (im stdio-Modus sofort senden, im Daemon-Modus pro Client bei Connect) // Bereit-Signal (im stdio-Modus sofort senden, im Daemon-Modus pro Client bei Connect)
if (!IS_DAEMON) { if (!IS_DAEMON) {
sendEvent('ready', { version: '1.2.0', pid: process.pid, model: currentModel, availableModels: AVAILABLE_MODELS }); sendEvent('ready', { version: '1.2.0', pid: process.pid, model: currentModel, availableModels: AVAILABLE_MODELS });

View file

@ -234,8 +234,9 @@ fn connect_uds(app: &AppHandle, daemon_pid: Option<u32>) -> Result<(), String> {
std::thread::spawn(move || { std::thread::spawn(move || {
let reader = BufReader::new(reader_stream); let reader = BufReader::new(reader_stream);
for line in reader.lines().map_while(Result::ok) { for line in reader.lines().map_while(Result::ok) {
if let Ok(msg) = serde_json::from_str::<BridgeMessage>(&line) { match serde_json::from_str::<BridgeMessage>(&line) {
handle_bridge_message(&app_handle, msg); Ok(msg) => handle_bridge_message(&app_handle, msg),
Err(e) => println!("⚠️ Bridge-Nachricht nicht parsbar: {}{}", e, &line[..line.len().min(100)]),
} }
} }
println!("⚠️ UDS-Verbindung getrennt — versuche Reconnect..."); println!("⚠️ UDS-Verbindung getrennt — versuche Reconnect...");
@ -364,8 +365,9 @@ fn start_bridge_stdio(app: &AppHandle, script_path: &std::path::Path) -> Result<
std::thread::spawn(move || { std::thread::spawn(move || {
let reader = BufReader::new(stdout); let reader = BufReader::new(stdout);
for line in reader.lines().map_while(Result::ok) { for line in reader.lines().map_while(Result::ok) {
if let Ok(msg) = serde_json::from_str::<BridgeMessage>(&line) { match serde_json::from_str::<BridgeMessage>(&line) {
handle_bridge_message(&app_handle, msg); Ok(msg) => handle_bridge_message(&app_handle, msg),
Err(e) => println!("⚠️ Bridge-Nachricht nicht parsbar: {}{}", e, &line[..line.len().min(100)]),
} }
} }
println!("⚠️ Bridge stdout geschlossen"); println!("⚠️ Bridge stdout geschlossen");

View file

@ -517,7 +517,8 @@ impl Database {
Ok(()) Ok(())
} }
/// Lädt alle Sessions (neueste zuerst) /// Lädt alle Sessions (neueste zuerst) — Convenience-Wrapper
#[allow(dead_code)]
pub fn load_sessions(&self, limit: usize) -> SqlResult<Vec<Session>> { pub fn load_sessions(&self, limit: usize) -> SqlResult<Vec<Session>> {
self.load_sessions_filtered(limit, None) self.load_sessions_filtered(limit, None)
} }

View file

@ -60,6 +60,7 @@ impl KbCache {
} }
} }
#[allow(dead_code)]
fn invalidate_expired(&mut self) { fn invalidate_expired(&mut self) {
self.entries.retain(|_, v| v.created_at.elapsed() < self.ttl); self.entries.retain(|_, v| v.created_at.elapsed() < self.ttl);
} }