Dealing with bot failures
This commit is contained in:
@@ -210,6 +210,17 @@ pub(in crate::chat::transport::matrix::bot) async fn handle_message(
|
||||
|
||||
// Persist to disk so history survives server restarts.
|
||||
save_history(&ctx.services.project_root, &guard);
|
||||
} else {
|
||||
// Clear session_id on error so a poisoned session (e.g. pending
|
||||
// tool call with no response) doesn't cause a crash loop on resume.
|
||||
let mut guard = ctx.history.lock().await;
|
||||
if let Some(conv) = guard.get_mut(&room_id)
|
||||
&& conv.session_id.is_some()
|
||||
{
|
||||
slog!("[matrix-bot] clearing session_id after error to prevent crash loop");
|
||||
conv.session_id = None;
|
||||
save_history(&ctx.services.project_root, &guard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -371,23 +371,38 @@ fn run_pty_session(
|
||||
// Wait briefly for Claude Code to flush its session transcript to disk.
|
||||
// The `result` event means the API response is done, but the process
|
||||
// still needs to write the conversation to the JSONL session file.
|
||||
match child.try_wait() {
|
||||
Ok(Some(_)) => {} // Already exited
|
||||
let exit_status = match child.try_wait() {
|
||||
Ok(Some(status)) => Some(status),
|
||||
_ => {
|
||||
// Give it up to 2 seconds to exit cleanly
|
||||
let mut status = None;
|
||||
for _ in 0..20 {
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
if let Ok(Some(_)) = child.try_wait() {
|
||||
if let Ok(Some(s)) = child.try_wait() {
|
||||
status = Some(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If still running after 2s, kill it
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
if status.is_none() {
|
||||
let _ = child.kill();
|
||||
status = child.wait().ok();
|
||||
}
|
||||
status
|
||||
}
|
||||
}
|
||||
};
|
||||
// Wait for the reader thread to release the cloned PTY master fd.
|
||||
let _ = reader_handle.join();
|
||||
|
||||
// Non-zero exit without a result event means Claude Code crashed
|
||||
// (e.g. MCP server not yet connected). Propagate as an error so
|
||||
// the caller can clear the session_id instead of persisting it.
|
||||
if !got_result
|
||||
&& let Some(ref status) = exit_status
|
||||
&& !status.success()
|
||||
{
|
||||
slog!("[pty-debug] Claude Code exited with non-zero status: {status}");
|
||||
return Err(format!("Claude Code crashed (exit status: {status})"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user