Skip to content

fix(server): honor missing-reasoning reject mode#34

Merged
yxlao merged 7 commits into
mainfrom
mipselqq/merge-fork
May 1, 2026
Merged

fix(server): honor missing-reasoning reject mode#34
yxlao merged 7 commits into
mainfrom
mipselqq/merge-fork

Conversation

@yxlao
Copy link
Copy Markdown
Owner

@yxlao yxlao commented May 1, 2026

Summary

This PR fixes the missing-reasoning rejection path so the proxy only returns its synthetic 409 missing_reasoning_content response when missing_reasoning_strategy == "reject".

In recover mode, if the proxy cannot drop any messages during recovery, it now forwards the request upstream and relays the provider response instead of short-circuiting with 409.

Fork Attribution

The core server-side guard:

if (
    prepared.missing_reasoning_messages
    and self.config.missing_reasoning_strategy == "reject"
):

is adapted from mipselqq/deepseek-cursor-proxy commit 96057fe, which changed the strict missing-reasoning 409 path so it only fires when the configured strategy is explicitly reject.

Changes

Validation

uv run python -m unittest tests.test_trace
uv run python -m unittest discover -s tests

yxlao added 7 commits May 1, 2026 14:41
The unconditional 409 short-circuit fired for any payload where
`missing_reasoning_messages > 0`, even in `recover` mode. The recovery
loop in `transform.py` cannot always drive missing indexes to empty —
e.g. when the request has no user message — so users who explicitly
opted into `recover` were getting 409s the proxy reserves for `reject`.

Add the strategy guard. Adds a regression test in `test_protocol.py`
exercising the no-user-message case in recover mode and asserting the
proxy forwards to upstream (which 400s) instead of pre-empting with 409.
Add the deeper observation: even with proper auth, the fork's passthrough
has no valid destination. Cursor's internal non-DeepSeek calls
(/summarize, GPT-4o, Composer) normally route to api.cursor.com, gated
by Cursor's own session auth that we don't have. OpenAI is a wrong
default; we can't replicate Cursor's routing.

Also note that real proxy logs from this user's setup show only
deepseek-v4-pro traffic — Cursor appears to keep non-DeepSeek calls on
its own backend in current versions, so the problem the fork was
solving may not be observable in practice. Hold off until we see real
traffic show up.
PR #33's test refactor trimmed test_transform.py from 1489 to 321 lines
and accidentally dropped five regression tests that locked in PR #28's
cross-mode/model context-preservation mechanisms (Pro/Flash family
normalization, portable turn-scoped keys, recovery-boundary
continuation). The production code is intact, but coverage was gone.

Restore the originals verbatim from commit 5f14da3 as a new
CrossModeAndModelTests class:

- test_deepseek_pro_and_flash_share_reasoning_namespace
- test_strict_hit_backfills_portable_cache_for_mode_switch
- test_portable_turn_cache_restores_final_assistant_after_tool_result
- test_portable_turn_cache_isolated_for_reused_tool_call_id
- test_recovered_response_is_recorded_under_pre_recovery_scope

Adjusted only the imports and the namespace/scope helpers to fit the
post-PR-#33 layout. All 87 tests pass.
@yxlao yxlao changed the title wip: mipselqq/merge fork fix(server): 409 only in reject mode; trace bodies May 1, 2026
@yxlao yxlao changed the title fix(server): 409 only in reject mode; trace bodies fix(server): honor missing-reasoning reject mode May 1, 2026
@yxlao yxlao merged commit 7bdf177 into main May 1, 2026
6 checks passed
@yxlao yxlao deleted the mipselqq/merge-fork branch May 1, 2026 14:32
maThiaslI152 added a commit to maThiaslI152/deepseek-cursor-proxy that referenced this pull request May 6, 2026
Merges 6 upstream commits from yxlao/deepseek-cursor-proxy:
- feat(streaming): add collapsible reasoning display (yxlao#32)
- refactor(proxy): audit thinking-mode protocol and refactor test suite (yxlao#33)
- fix(server): honor missing-reasoning reject mode (yxlao#34)
- fix: prevent recovery cascade and improve Stop-scenario reasoning lookup (yxlao#25)
- feat(config): default reasoning effort to max (yxlao#36)
- refactor(logging): simplified prints and add spinner (yxlao#37)

Combines both branches' changes:
- Concurrent request deduplication (ours) + dual-scope recording (upstream)
- Broad namespace cache keys (ours) + portable tool_name keys (upstream)
- Spinner, build_arg_parser, main() function (upstream)
- Metrics tracking, schema migration, graceful shutdown (ours)

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant