fix: avoid restoring stale sessions with dangling tool calls#2364
fix: avoid restoring stale sessions with dangling tool calls#2364changeworldBT wants to merge 1 commit intosipeed:mainfrom
Conversation
| // (assistant tool calls plus later steering/user messages) as if it were valid | ||
| // history. We keep completed tool-call sequences intact and only trim the | ||
| // incomplete suffix. | ||
| func sanitizeRecoveredHistory(history []providers.Message) []providers.Message { |
There was a problem hiding this comment.
sanitizeRecoveredHistory not only removes the incomplete assistant/tool block: with return history[:i] it truncates the entire suffix starting with the assistant with ToolCalls. This means that any user/steering message persisted after that point is lost altogether on reboot. It is also in contrast to the sanitizer already used by the ContextBuilder, which discards the broken tool-call round but preserves subsequent non-tool messages. Here we risk permanent loss of real input instead of limiting the fix to only incomplete runtime state.
| session.Updated = time.Now() | ||
| } | ||
|
|
||
| func (sm *SessionManager) GetHistory(key string) []providers.Message { |
There was a problem hiding this comment.
The helper is called inside SessionManager.GetHistory, so it doesn't just apply to history retrieved from disk after a restart: it changes the meaning of each session read in memory. This also breaks the stated SessionStore contract (GetHistory returns the full message history) and causes runtime callers to see a filtered view instead of the actual persisted log. If recovery is the problem, sanitization should be applied in the session bootstrap/reopen or materialized once, not hidden behind each GetHistory.
Summary
Problem
If a session is persisted while an assistant tool-call turn is still unfinished, restarting picoclaw can restore that broken tail as valid history. New Telegram messages may then get redirected into the steering queue instead of starting a fresh turn, leaving the bot stuck in typing without a final reply.
Fix
Sanitize recovered session history before it is reused by the agent. If the history ends with an assistant message containing tool calls that do not have a complete set of matching tool results, trim that dangling suffix and keep only the safe, completed history.
Notes
This keeps completed tool-call sequences intact while preventing stale unfinished execution state from surviving process restart.