Skip to content

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Nov 2, 2025

Problem

Clicking Terminate during streaming caused several issues:

  • Entire chat view would blink/flicker
  • Task would close, pushing user to home, then back into the task
  • Cancel → Resume flow would grey the Resume button but not restart the loop
  • Input would become disabled and messages couldn't be sent

Root Causes

  1. Hard abort (abandoned=true) was disposing the task instance immediately
  2. Provider was rehydrating a new task instance from disk after abort
  3. Abort flags stayed set (abort=true) preventing loop resumption
  4. No deterministic spinner stopping on cancellation
  5. Streaming state wasn't reset on resume

Solution

Soft-Interrupt Pattern

  • Cancel now uses abortTask(false) to keep instance alive
  • Provider skips task recreation for user_cancelled aborts
  • Added presentResumableAsk() for in-place resume flow

State Management

  • Reset abort flags and streaming state before resuming
  • Inject cancelReason into last api_req_started for deterministic spinner stop
  • Transactional UI updates during checkpoint operations

Changes

Core Logic

  • Task.presentResumableAsk(): New method for soft-interrupt resume
  • Task.resumeTaskFromHistory(): Reset abort/streaming state after user confirms
  • Task.abortTask(): Distinguish soft (keep alive) vs hard abort (dispose)
  • ClineProvider.cancelTask(): Soft abort + schedule presentResumableAsk()
  • ClineProvider.onTaskAborted: Skip rehydration for user_cancelled

UI

  • ChatView: Handle cancelReason for deterministic streaming state

Tests

  • ✅ Task.presentResumableAsk.abort-reset.spec.ts: Verify abort flag reset on resume
  • ✅ ClineProvider.cancelTask.present-ask.spec.ts: Verify soft-interrupt flow
  • ✅ Task.spec.ts: Updated abort semantics (soft vs hard)
  • ✅ All existing tests pass (310 files, 0 failures)

Result

  • ✅ No UI flicker or navigation on Cancel
  • ✅ Resume button successfully restarts the agent loop
  • ✅ Input remains enabled throughout cancel/resume cycle
  • ✅ Spinner stops deterministically on cancellation
  • ✅ Task history stable, no duplicate entries

Testing Steps

  1. Start a task with streaming response
  2. Click Cancel button during streaming
  3. Verify Resume/Terminate dialog appears (no flicker)
  4. Click Resume
  5. Verify streaming continues and input is enabled

Related Issues

Fixes the UI blink issue when terminating tasks during streaming.


Important

Implements soft-interrupt pattern and state management improvements to prevent UI flicker and enable task resumption after cancellation.

  • Behavior:
    • Implements soft-interrupt pattern using abortTask(false) to prevent task instance disposal on cancel.
    • Introduces presentResumableAsk() in Task.ts for in-place resume flow.
    • Resets abort flags and streaming state before resuming tasks.
    • Injects cancelReason into api_req_started for deterministic spinner stop.
  • Core Logic:
    • Adds Task.presentResumableAsk() and Task.resumeTaskFromHistory() for task resumption.
    • Modifies Task.abortTask() to distinguish between soft and hard aborts.
    • Updates ClineProvider.cancelTask() to handle soft aborts and schedule presentResumableAsk().
  • UI:
    • Updates ChatView.tsx to handle cancelReason for streaming state management.
  • Tests:
    • Adds Task.presentResumableAsk.abort-reset.spec.ts to verify abort flag reset.
    • Adds ClineProvider.cancelTask.present-ask.spec.ts to verify soft-interrupt flow.
    • Updates Task.spec.ts for new abort semantics.
  • Result:
    • Eliminates UI flicker and navigation on task cancel.
    • Ensures resume button restarts the agent loop and input remains enabled.

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

Problem:
- Clicking Terminate during streaming caused the entire chat view to blink
- Task would close, user pushed to home, then back into the task
- Cancel → Resume flow would grey the Resume button but not restart the loop
- Input would become disabled and messages couldn't be sent

Root causes:
1. Hard abort (abandoned=true) was disposing the task instance immediately
2. Provider was rehydrating a new task instance from disk after abort
3. Abort flags stayed set (abort=true) preventing loop resumption
4. No deterministic spinner stopping on cancellation
5. Streaming state wasn't reset on resume

Solution:
- Soft-interrupt: Cancel now uses abortTask(false) to keep instance alive
- No rehydration: Provider skips task recreation for user_cancelled aborts
- Resume pipeline: Added presentResumableAsk() for in-place resume flow
- Abort state reset: Clear abort flags and streaming state before resuming
- Spinner determinism: Inject cancelReason into last api_req_started
- Transactional UI: Pause state updates during checkpoint operations

Changes:
- Task.presentResumableAsk(): New method for soft-interrupt resume
- Task.resumeTaskFromHistory(): Reset abort/streaming state after user confirms
- Task.abortTask(): Distinguish soft (keep alive) vs hard abort (dispose)
- ClineProvider.cancelTask(): Soft abort + schedule presentResumableAsk()
- ClineProvider.onTaskAborted: Skip rehydration for user_cancelled
- ChatView: Handle cancelReason for deterministic streaming state

Tests:
- Task.presentResumableAsk.abort-reset.spec.ts: Verify abort flag reset
- ClineProvider.cancelTask.present-ask.spec.ts: Verify soft-interrupt flow
- Task.spec.ts: Updated abort semantics (soft vs hard)

Result:
- No UI flicker or navigation on Cancel
- Resume button successfully restarts the agent loop
- Input remains enabled throughout cancel/resume cycle
- Spinner stops deterministically on cancellation
- Task history stable, no duplicate entries
@daniel-lxs daniel-lxs requested review from cte, jr and mrubens as code owners November 2, 2025 23:57
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. UI/UX UI/UX related or focused labels Nov 2, 2025
@roomote
Copy link
Contributor

roomote bot commented Nov 2, 2025

See this task on Roo Code Cloud

All previously identified issues have been resolved. No new issues found in the latest commit.

  • Fix inverted logic in isStreaming calculation: when cost is defined, streaming is complete (should return false), not still active
Previous Reviews

Mention @roomote in a comment to trigger your PR Fixer agent and make changes to this pull request.

@daniel-lxs daniel-lxs moved this from Triage to PR [Needs Prelim Review] in Roo Code Roadmap Nov 2, 2025
The logic was inverted - when cost is defined in api_req_started, it means the API request has finished (streaming is complete), so should return false, not true.
When api_req_started exists without cost or cancelReason fields, the API request is still in progress and should be treated as streaming. Only return false when cost (completed) or cancelReason (cancelled) are present.
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Nov 3, 2025
@daniel-lxs daniel-lxs force-pushed the fix/cancel-resume-no-blink branch from b8bafd1 to ac57bd0 Compare November 3, 2025 19:40
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Nov 3, 2025
@daniel-lxs daniel-lxs moved this from PR [Needs Prelim Review] to PR [Needs Review] in Roo Code Roadmap Nov 3, 2025
…SON parsing

- Extract duplicated abort/streaming state reset logic into private helper method resetAbortAndStreamingState()
- Update resumeTaskFromHistory() and presentResumableAsk() to use the helper method
- Replace unsafe JSON.parse() with safeJsonParse() in ClineProvider.ts for better error handling

Addresses review feedback from @mrubens on PR #8986
@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Nov 3, 2025
@mrubens mrubens merged commit 58edc71 into main Nov 3, 2025
12 checks passed
@mrubens mrubens deleted the fix/cancel-resume-no-blink branch November 3, 2025 20:40
@github-project-automation github-project-automation bot moved this from New to Done in Roo Code Roadmap Nov 3, 2025
@github-project-automation github-project-automation bot moved this from PR [Needs Review] to Done in Roo Code Roadmap Nov 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer PR - Needs Review size:L This PR changes 100-499 lines, ignoring generated files. UI/UX UI/UX related or focused

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants