Skip to content

fix: decode Composer Cursor thinking output - #1310

Merged
decolua merged 1 commit into
decolua:masterfrom
noestelar:fix/cursor-composer-thinking
May 21, 2026
Merged

decolua merged 1 commit into
decolua:masterfrom
noestelar:fix/cursor-composer-thinking

Conversation

@noestelar

@noestelar noestelar commented May 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Decode Cursor Composer visible output from the thinking field after the last </think> marker.
  • Keep hidden thinking private; only emit the visible suffix as assistant content.
  • Cover non-streaming, streaming, and non-Composer behavior with unit tests.

Test plan

  • cd tests && NODE_PATH=../node_modules ./node_modules/.bin/vitest run --reporter=verbose cursor-composer-thinking.test.js
  • npm run build

@decolua
decolua merged commit e3cab13 into decolua:master May 21, 2026
ysocrius pushed a commit to ysocrius/9router that referenced this pull request May 29, 2026
ysocrius pushed a commit to ysocrius/9router that referenced this pull request May 30, 2026
joefour pushed a commit to joefour/9router that referenced this pull request May 30, 2026
- Add composerToolCalls parser (full-width and ASCII markers)
- Wire non-streaming and streaming paths in cursor executor
- Unit tests for parse and streaming holdback/flush
- Builds on merged decolua#1310 and final-marker strip from prior work
ysocrius pushed a commit to ysocrius/9router that referenced this pull request Jun 5, 2026
bemodestdoteth pushed a commit to bemodestdoteth/9router that referenced this pull request Jun 10, 2026
ricatix pushed a commit to ricatix/9router that referenced this pull request Jun 15, 2026
diegosouzapw pushed a commit to cheaper-inference/OmniRoute that referenced this pull request Jun 21, 2026
The composer-* family on Cursor encodes its visible reply inside the
`thinking` protobuf field, separated from the (private) chain-of-thought
by a final `</think>` marker. OmniRoute was forwarding the whole thinking
payload as `reasoning_content` only, so OpenAI-compatible clients saw an
empty `message.content` and never displayed the reply.

The cursor executor now:
- detects Composer models (case-insensitive, tolerates vendor prefix);
- splits the thinking payload at the last `</think>` marker;
- streams the suffix as `content` deltas (mirrored into `totalText` so
  the non-streaming aggregator surfaces it as `message.content`);
- keeps only the pre-marker hidden reasoning in `reasoning_content`,
  with the visible portion stripped to avoid duplication.

Non-Composer models keep their existing reasoning_content contract.

Inspired-by: decolua/9router#1310
Co-authored-by: Noé Rivera <95829890+noestelar@users.noreply.github.com>
ibanunmangun pushed a commit to ibanunmangun/9router that referenced this pull request Jul 22, 2026
Shinzzyak pushed a commit to Shinzzyak/VansRouter that referenced this pull request Sep 11, 2026
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.

2 participants