diff --git a/internal/agent/coordinator.go b/internal/agent/coordinator.go index 9822a7e494e3170b7712df7f0169260c37799ea1..99a9c4d0e62b5789549b4b9cfb5a23b179356634 100644 --- a/internal/agent/coordinator.go +++ b/internal/agent/coordinator.go @@ -841,7 +841,6 @@ func (c *coordinator) Summarize(ctx context.Context, sessionID string) error { } func (c *coordinator) RecoverSession(ctx context.Context, sessionID string) error { - // Skip recovery if session is currently active if c.currentAgent != nil && c.currentAgent.IsSessionBusy(sessionID) { return nil } @@ -856,42 +855,16 @@ func (c *coordinator) RecoverSession(ctx context.Context, sessionID string) erro continue } - // Handle incomplete summary messages - if msg.IsSummaryMessage { - msg.FinishThinking() - msg.AddFinish(message.FinishReasonError, "Summarization interrupted", "Session was interrupted during summarization") - if updateErr := c.messages.Update(ctx, msg); updateErr != nil { - slog.Error("Failed to recover summary message", "message_id", msg.ID, "error", updateErr) + for _, tc := range msg.ToolCalls() { + if !tc.Finished { + msg.FinishToolCall(tc.ID) } - continue - } - - // Handle incomplete assistant messages with tool calls - if msg.Role == message.Assistant && len(msg.ToolCalls()) > 0 { - // Mark any unfinished tool calls as finished - for _, tc := range msg.ToolCalls() { - if !tc.Finished { - msg.FinishToolCall(tc.ID) - } - } - // Batch all modifications before single update - msg.FinishThinking() - msg.AddFinish(message.FinishReasonError, "Response interrupted", "Session was interrupted during tool execution") - if updateErr := c.messages.Update(ctx, msg); updateErr != nil { - slog.Error("Failed to recover assistant message", "message_id", msg.ID, "error", updateErr) - } - continue } - // Handle incomplete assistant messages without tool calls - // (e.g., message content was partially generated but interrupted) - if msg.Role == message.Assistant && msg.Content().Text != "" { - msg.FinishThinking() - msg.AddFinish(message.FinishReasonError, "Response interrupted", "Session was interrupted during response generation") - if updateErr := c.messages.Update(ctx, msg); updateErr != nil { - slog.Error("Failed to recover assistant message", "message_id", msg.ID, "error", updateErr) - } - continue + msg.FinishThinking() + msg.AddFinish(message.FinishReasonError, "Session interrupted", "The session was previously interrupted") + if updateErr := c.messages.Update(ctx, msg); updateErr != nil { + slog.Error("Failed to recover message", "message_id", msg.ID, "error", updateErr) } } diff --git a/internal/ui/model/session.go b/internal/ui/model/session.go index 38fd718db9cf2b44eb48538a9debb25870b90a7d..fe8b7c64de56fb7368768ceafe31b3bb95a57c1c 100644 --- a/internal/ui/model/session.go +++ b/internal/ui/model/session.go @@ -3,6 +3,7 @@ package model import ( "context" "fmt" + "log/slog" "path/filepath" "slices" "strings" @@ -47,6 +48,10 @@ func (m *UI) loadSession(sessionID string) tea.Cmd { return uiutil.ReportError(err)() } + if recoverErr := m.com.App.AgentCoordinator.RecoverSession(context.Background(), session.ID); recoverErr != nil { + slog.Error("Failed to recover session", "session_id", session.ID, "error", recoverErr) + } + files, err := m.com.App.History.ListBySession(context.Background(), sessionID) if err != nil { // TODO: better error handling