microsoft / microsoft/copilot-for-eclipse

Stale chat progress can finish a newer active turn

Open
#417 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Java
Stars
126
Forks
60
Avg merge
2d 6h
Merged PRs (30d)
5

Description

Context

Discovered while reviewing #378, which fixes the confirmed #99 path where rebuilding the action buttons renders a disabled Send button during an active turn.

This issue tracks a separate turn-lifecycle race that can produce a similar symptom. It is not currently established as a root cause of #99.

Related review thread: https://github.com/microsoft/copilot-for-eclipse/pull/378#discussion_r3681652089

Problem

Each chat request is sent with a unique workDoneToken, and ProgressParamsAdapter parses the token returned on $/progress. However, CopilotLanguageClient.notifyProgress() forwards only ChatProgressValue, so the request identity is unavailable to ChatView.

ChatView currently associates top-level progress primarily by conversationId. Consecutive turns in one conversation share that ID, and any accepted top-level end event calls actionBar.markTurnFinished(). Asynchronous request errors also finish the action bar without checking whether the failed request is still active.

A possible sequence is:

  1. Turn A is running.
  2. The user cancels A; the UI immediately allows another send.
  3. Turn B starts in the same conversation.
  4. A delayed end(A) or error callback from A arrives.
  5. B is incorrectly marked finished and its Cancel button becomes Send.
  6. Subsequent progress for B may be ignored because onChatProgress() gates processing on actionBar.isTurnRunning().

A real log attached to #99 confirms that the language server can send a cancellation end after $/cancelRequest (about 15 ms later in that trace). That trace did not overlap the cancellation end with the next turn, so it demonstrates the event shape but not this race itself.

Expected behavior

A terminal progress event or asynchronous callback must only finish the top-level request to which it belongs. Events from an older request must not change the lifecycle or action-button state of a newer active turn.

Acceptance criteria

  • start A -> cancel A -> start B -> end A leaves B running with Cancel available.
  • A delayed error callback from A cannot finish B.
  • The matching end B still finishes B normally.
  • Request identity is preserved sufficiently to distinguish consecutive turns in the same conversation.
  • The lifecycle behavior is covered by automated tests.
  • Detailed handling of stale events, persistence, conversation metadata, and subagent progress is decided during implementation design rather than assumed by this issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace request identity through ProgressParamsAdapter and CopilotLanguageClient.notifyProgress() into ChatView, including actionBar lifecycle handling and asynchronous errors. Define the stale-event behavior during implementation, then add automated coverage for start A, cancel A, start B, delayed end or error from A, and the matching end B; done means B remains cancellable until its own completion.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.