fix: stale Claude-Session-ID automatisch resetten [appimage]
All checks were successful
Build AppImage / build (push) Successful in 6m20s
All checks were successful
Build AppImage / build (push) Successful in 6m20s
Wenn die in SQLite gespeicherte claude_session_id keine passende
Konversation mehr hat (neue Maschine, Cache geleert, frische Installation),
warf das SDK "No conversation found with session ID: <uuid>" und der
Chat blieb kaputt — der Retry in claude-bridge.js hat NIE gegriffen, weil
er auf queryOptions.sessionId geprueft hat waehrend wir queryOptions.resume
setzen.
Fix:
- claude-bridge.js: Retry-Guard auf queryOptions.resume umgezogen + Match
auf die konkrete Fehlermeldung ("No conversation found with session ID").
Bei stale ID: session-reset-Event an Rust senden, dann retry ohne resume.
- claude.rs: Neuer Handler fuer session-reset — loescht die stale
claude_session_id aus der aktiven Session in der DB, damit die App beim
naechsten Start nicht wieder in denselben Fehler laeuft.
Reproduziert auf VM + NixOS-Desktop nach frischer Installation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3913e1cce8
commit
2e473cde00
2 changed files with 33 additions and 6 deletions
|
|
@ -481,18 +481,26 @@ async function sendMessage(message, requestId, model = null, contextOverride = n
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hilfsfunktion: Iteration mit Fallback bei ungueltiger Session-ID
|
// Hilfsfunktion: Iteration mit Fallback bei ungueltiger Session-ID.
|
||||||
|
// Typischer Auslöser: "No conversation found with session ID: <uuid>"
|
||||||
|
// passiert wenn die in SQLite gespeicherte Claude-Session lokal fehlt
|
||||||
|
// (neue Maschine, Projekt-Cache geloescht, frische Installation, ...).
|
||||||
async function* iterateWithRetry() {
|
async function* iterateWithRetry() {
|
||||||
try {
|
try {
|
||||||
for await (const ev of conversation) yield ev;
|
for await (const ev of conversation) yield ev;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Wenn Resume-Session ungueltig → Retry ohne sessionId
|
const msg = err?.message || String(err);
|
||||||
if (queryOptions.sessionId) {
|
const isStaleSession = /no conversation found with session id/i.test(msg);
|
||||||
|
if (queryOptions.resume && isStaleSession) {
|
||||||
|
const staleId = queryOptions.resume;
|
||||||
|
// Rust-Seite informieren, damit die stale ID aus der DB geloescht
|
||||||
|
// wird — sonst probieren wir beim naechsten Start wieder dasselbe.
|
||||||
|
sendEvent('session-reset', { staleSessionId: staleId, reason: msg });
|
||||||
sendMonitorEvent('agent', 'Resume fehlgeschlagen, starte neue Session', {
|
sendMonitorEvent('agent', 'Resume fehlgeschlagen, starte neue Session', {
|
||||||
reason: err.message || String(err),
|
reason: msg,
|
||||||
oldSessionId: queryOptions.sessionId,
|
oldSessionId: staleId,
|
||||||
});
|
});
|
||||||
delete queryOptions.sessionId;
|
delete queryOptions.resume;
|
||||||
conversation = query({ prompt: fullPrompt, options: queryOptions });
|
conversation = query({ prompt: fullPrompt, options: queryOptions });
|
||||||
for await (const ev of conversation) yield ev;
|
for await (const ev of conversation) yield ev;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,25 @@ fn handle_bridge_message(app: &AppHandle, msg: BridgeMessage) {
|
||||||
}
|
}
|
||||||
let _ = app.emit("claude-result", &payload);
|
let _ = app.emit("claude-result", &payload);
|
||||||
}
|
}
|
||||||
|
"session-reset" => {
|
||||||
|
// Bridge meldet: resume-Session war ungueltig ("No conversation
|
||||||
|
// found with session ID"). Stale claude_session_id aus DB
|
||||||
|
// entfernen, sonst laeuft die App beim naechsten Start wieder
|
||||||
|
// in denselben Fehler.
|
||||||
|
if let Some(db_state) = app.try_state::<Arc<Mutex<db::Database>>>() {
|
||||||
|
let db_lock = db_state.lock().unwrap();
|
||||||
|
if let Ok(Some(active_id)) = db_lock.get_setting("active_session_id") {
|
||||||
|
if !active_id.is_empty() {
|
||||||
|
if let Ok(Some(mut session)) = db_lock.get_session(&active_id) {
|
||||||
|
let old = session.claude_session_id.take();
|
||||||
|
let _ = db_lock.update_session(&session);
|
||||||
|
println!("🧹 Stale claude_session_id geloescht: {:?}", old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = app.emit("session-reset", &payload);
|
||||||
|
}
|
||||||
"all-stopped" => {
|
"all-stopped" => {
|
||||||
println!("⏹️ Alle Agents gestoppt");
|
println!("⏹️ Alle Agents gestoppt");
|
||||||
let _ = app.emit("all-stopped", ());
|
let _ = app.emit("all-stopped", ());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue