Skip to content

Fix duplicate rehydrate during reasoning; centralize rehydrate and preserve cancel metadata#8171

Merged
mrubens merged 6 commits intomainfrom
fix/reasoning-cancel-centralized-rehydrate
Sep 20, 2025
Merged

Fix duplicate rehydrate during reasoning; centralize rehydrate and preserve cancel metadata#8171
mrubens merged 6 commits intomainfrom
fix/reasoning-cancel-centralized-rehydrate

Conversation

@hannesrudolph
Copy link
Copy Markdown
Collaborator

@hannesrudolph hannesrudolph commented Sep 18, 2025

Closes #8153

Before:

FocuSee.Project.2025-09-19.18-07-19.mp4

AFTER

FocuSee.Project.2025-09-19.18-12-22.mp4

Problem

  • Users occasionally saw a duplicate/overlaid task after pressing “Cancel” or after a mid-stream network failure—most visibly during “reasoning” streaming.
  • Root cause: two independent rehydration paths racing:
  • This race was easier to hit during reasoning because reasoning chunks are UI-only (persisted to clineMessages) and not added to apiConversationHistory mid-stream, so the Task catch reached rehydrate faster.

Changes

  1. Centralize rehydration in the Provider

    • Removed Task-side rehydrate in the streaming error/cancel catch; the Task now:
      • Persists an interruption marker first
      • Sets an explicit abortReason
      • Calls abortTask() and emits TaskAborted
      • Does not call createTaskWithHistoryItem
    • Provider listens for TaskAborted and rehydrates only for streaming failures (not user-cancels)
      Task.recursivelyMakeClineRequests()
      ClineProvider.onTaskAborted
  2. Prevent double-create by marking “abandoned” earlier on user-cancel

    • Set task.abortReason = "user_cancelled" and mark the current Task instance abandoned immediately after abortTask(), before waiting for the stream to drain
      ClineProvider.cancelTask()
    • This ensures the Task catch never tries to rehydrate.
  3. Provider-side cancel bookkeeping to mirror abortStream for user cancels

    • Because setting abandoned early can skip abortStream on user-cancel, the Provider now fills the same persistence gaps:
    • This preserves UI/API consistency and cancellation telemetry without reintroducing the race.
  4. Resume reconciliation for UI-only reasoning

    • On resuming from history, remove trailing reasoning-only UI rows that never entered apiConversationHistory (orphan partials)
      Task.resumeTaskFromHistory()
  5. Defensive safeguards to avoid rehydrate after rehydrate

Why this approach

  • Eliminates the duplicate/overlay by making the Provider the single source of rehydration truth.
  • Maintains a coherent timeline when cancelling mid-reasoning by explicitly persisting:
    • cancelReason into the last api_req_started row
    • an assistant “interrupted by user” entry into API history
  • Keeps normal success flows unchanged and produces a clean resume prompt consistently.

Behavioral impact

  • Cancel during reasoning: one rehydrate, no duplicates; cancelReason and interruption marker preserved.
  • Network failure mid-stream: Task emits TaskAborted with abortReason="streaming_failed"; Provider rehydrates once.
  • Cancel during text streaming: one rehydrate; no duplicates.
  • didFinishAbortingStream may not set on user-cancel (due to early abandoned), but Provider waits on other safe conditions and applies the same persistence updates Provider-side.

Key references


Important

Centralizes task rehydration in ClineProvider.ts to prevent duplicate rehydration during reasoning and updates localization for interruption messages.

  • Behavior:
    • Centralizes rehydration in ClineProvider.ts, removing task-side rehydration in Task.ts.
    • ClineProvider.ts now handles rehydration only for streaming failures, not user cancels.
    • Marks tasks as "abandoned" earlier on user-cancel to prevent double rehydration.
    • Updates UI/API consistency by appending interruption markers to apiConversationHistory.
  • Files:
    • Task.ts: Removes task-side rehydration logic, adds abortReason property.
    • ClineProvider.ts: Implements centralized rehydration logic, updates cancel bookkeeping.
    • Localization files: Adds interruption messages for user and API error interruptions.
  • Misc:
    • Ensures no rehydration occurs if the task instance has already changed.
    • Improves handling of reasoning-only UI rows during task resumption.

This description was created by Ellipsis for b1958e8. You can customize this summary. It will automatically update as commits are pushed.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer PR - Needs Review size:L This PR changes 100-499 lines, ignoring generated files.

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

[BUG] Cancel during response can blank conversation history (chat locks)

4 participants