Skip to content

Commit cdca327

Browse files
fab-uleuhclaude
andcommitted
fix(server): improve agent session state lifecycle
- Skip stale "done" state from file when detecting agent state, since the tmux window may have been reused for a new process - Ensure hook scripts exist on disk before injecting Claude Code hooks (guards against missing scripts if startup write failed) - Clean up session state directory when closing a session Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 661d6da commit cdca327

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

nomadflow-rs/crates/nomadflow-core/src/agent_state.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,9 @@ impl AgentStateService {
377377
self.read_state(&session.session_id).await
378378
} else {
379379
// Try hook-driven state file first (works when Claude Code runs
380-
// in a legacy 2-part tmux window with auto-discovered session ID)
380+
// in a legacy 2-part tmux window with auto-discovered session ID).
381+
// Ignore "done" state from file: the tmux window may have been reused
382+
// for a new process, so fall through to live process detection.
381383
if let Some(state) = self.read_state(&session.session_id).await {
382384
if state.state != AgentStateKind::Done {
383385
return Some(state);

nomadflow-rs/crates/nomadflow-server/src/routes/sessions.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ async fn create_session(
119119

120120
// Inject Claude Code hooks if agent type is claude-code (AC #2)
121121
if agent_type == "claude-code" {
122+
// Ensure hook script exists on disk (idempotent, guards against startup failure)
123+
let _ = state.agent_state.ensure_hook_scripts().await;
122124
let worktree_path = std::path::Path::new(&request.worktree_path);
123125
if let Err(e) = state
124126
.agent_state
@@ -239,6 +241,18 @@ async fn close_session(
239241
}
240242

241243
let closed = state.tmux.kill_window(&window_name).await;
244+
245+
// Clean up session state directory (agent-state.json, worktree-path)
246+
let session_state_dir = state.agent_state.sessions_dir().join(&request.session_id);
247+
if session_state_dir.is_dir() {
248+
if let Err(e) = tokio::fs::remove_dir_all(&session_state_dir).await {
249+
tracing::warn!(
250+
"Failed to clean up session state dir for {}: {e}",
251+
request.session_id
252+
);
253+
}
254+
}
255+
242256
Ok(Json(CloseSessionResponse { closed }))
243257
}
244258

0 commit comments

Comments
 (0)