Repository navigation
fix(cursor): recover restarted threads with older runs - #24540
juliusmarminge wants to merge 6 commits into
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cursor's local store lists runs oldest first, so `listRuns({ limit: 1 })`
returned the thread's first run. Once an earlier restart had cancelled one
run, the next recovery saw that cancelled run, skipped the cancel, and the
resumed send failed with "already has active run" on every retry. Recovery
now walks every page via `nextCursor` and cancels the newest running run.
Fixes #24498
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — The change searches all pages of local run history so resumed Cursor threads can recover when older runs precede the active run. It preserves the existing one-time, conflict-triggered cancellation and retry behavior. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
…dotgg#24540) Cherry-picked from pingdotgg#24540 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AI-assisted; verified with the tests and tools listed above.
|
The automated pipeline stopped on this pull request and will not merge it: someone else pushed to fix/issue-24498 (head is now 340cab4); the pipeline does not build on commits it did not review It stays open for a person to finish or close. |
Dismissing prior approval to re-evaluate dd882d9
Problem
After a server restart interrupts a Cursor turn, later sends can fail permanently with
already has active run. Reproduced on Linux with Cursor Auto by restarting twice duringsleep 90: the first recovery cancels its orphan, but the second reads that older cancelled run and misses the currently running one.Change
Follow the Cursor SDK run-list cursors and select the newest running run before the existing cancel-and-retry recovery. Keep the same resumed-session guard and single recovery attempt. The regression mock now models oldest-first pagination, with the abandoned run after 50 terminal runs.
Scope and approval
Fixes #24498
GitCafe: https://git.cafe/pingdotgg/t3code/issues/24498
Triaged bug via the automated issue flow. This changes only Cursor server recovery and its focused test; clients and wire contracts are unchanged. The reporter’s existing #24499 is left untouched.
Verification
CursorAgentSdkRunnerError: Cursor Agent SDK run.start failed, caused byalready has active run(one failed, one passed).vp test run src/server/CursorAgentSdk.test.tsinpackages/provider-cursor: 2 passed. The regression requires the active run on page two; a mock with no next cursor fails.tsc --noEmitpassed.Runtime proof used main
8176b58931before and1e2fe076dbafter. Final head merges current main; the two changed Cursor files are byte-identical to that tested after revision. The clean after run uses its own native agent, consistently across both recoveries and the follow-up. No render paths changed, so the visual matrix is empty. No platform-specific code changed; desktop/mobile shells were not separately exercised.Models and harnesses: Claude Opus 5.5 through the Claude harness (tests and implementation); GPT-6.1-Sol through Codex and Claude Opus 5.5 through Claude (reviews); GPT-6.1-Sol through Codex (issue lead and proof).