Skip to content

fix(responses): warn once when a custom provider drops replayed plaintext reasoning - #6882

Merged
lidge-jun merged 2 commits into
devfrom
codex/6675-plaintext-reasoning-notice
Oct 10, 2026
Merged

lidge-jun merged 2 commits into
devfrom
codex/6675-plaintext-reasoning-notice

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

A hand-configured openai-responses provider (for example Kimi K3 on vLLM, #6675) silently sends replayed plaintext reasoning as content: [] unless it sets preserveResponsesReasoningContent: true. That default is intentional and stays: the ChatGPT backend rejects echoed raw reasoning, and #2229 / #2258 recorded the token and privacy cost of forwarding it. What was missing is any sign that it happened, and the similarly named preserveReasoningContentModels looks like the right switch but only affects the Chat wire.

The serializer now reports when it blanks nonempty reasoning_text, and the passthrough adapter logs one warning per destination host the first time that happens for a custom provider:

[opencodex] Replayed plaintext reasoning was dropped for the custom Responses provider at gpu-box.local:8000. If that endpoint accepts reasoning_text replay, set "preserveResponsesReasoningContent": true on the provider; "preserveReasoningContentModels" applies only to the Chat wire.

The warning names only the host and option names, never request content. It is skipped for registry presets (matched by endpoint on either OpenAI wire, and by host pattern for the templated Azure preset), Azure OpenAI / AI Foundry per-resource hosts, OAuth and forward rows, Chat-wire rows, and OpenAI-operated destinations, where the blanking is a curated decision. Remembered hosts are capped at 64. The request body is unchanged in every case. The provider configuration reference now mentions the warning, the Kimi/vLLM case, and that the Chat-wire option does not apply.

This addresses the "warn when reasoning is discarded" follow-up on #6675. Surfacing the option in the custom-provider setup UI is left out, so the issue should stay open for that part.

Refs #6675

Verification

  • bun test tests/providers/deepseek-reasoning-replay.test.ts: 23 pass. New cases: the sanitizer reports only nonempty plaintext blanking (not preserved, empty, or empty-text items); a custom destination warns once with no request content; OpenAI, a registry preset routed to Responses (OpenGateway), forward, OAuth, Chat-wire rows and hand-configured Azure hosts (*.openai.azure.com, *.services.ai.azure.com, *.cognitiveservices.azure.com) stay silent, while a lookalike host outside Azure still warns; the passthrough serializer still blanks and emits exactly one notice, and a preserving provider keeps the text without a notice.
  • bun test on the five other suites that exercise reasoning replay through passthrough (openai-responses-passthrough, chat-inbound-reasoning-replay, claude-native-reasoning-continuity, anthropic-thinking-signature, alibaba-token-plan-wire-defaults): 265 pass.
  • bun x tsc --noEmit: exit 0.
  • Full suite not run locally; coverage left to hosted CI.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features
    • Custom Responses providers may now receive a one-time warning when nonempty plaintext reasoning is removed from a request, with guidance on preserving reasoning when supported. The warning excludes built-in and OpenAI-operated destinations, does not include request content, and appears only when reasoning is actually removed.
  • Documentation
    • Added a self-hosted Kimi deployment on vLLM as an example of a provider that accepts reasoning replay.

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 10, 2026 09:12
@lidge-jun lidge-jun added the bug Something isn't working label Oct 10, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-10T09:15:59.647214Z 6300750 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: ac941fb2-8460-4cf6-938b-ad9cacea78db


📥 Commits

Reviewing files that changed from the base of the PR and between 6300750 and bd04112.



📒 Files selected for processing (2)
  • src/adapters/openai-responses/plaintext-reasoning-notice.ts
  • tests/providers/deepseek-reasoning-replay.test.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.




📝 Walkthrough
📝 Walkthrough

Walkthrough

The Responses reasoning sanitizer now reports when it blanks non-empty plaintext reasoning. The passthrough adapter uses that signal to issue a bounded, once-per-host warning for eligible custom Responses providers. Tests cover eligibility and preservation settings. Provider documentation adds self-hosted Kimi on vLLM as an example.

Changes

Plaintext reasoning notices

Layer / File(s) Summary
Report blanked plaintext reasoning
src/adapters/openai-responses/reasoning.ts
sanitizeReasoningInputContent accepts an optional callback. It invokes the callback once if it blanks non-empty reasoning_text.
Filter and issue provider notices
src/adapters/openai-responses/plaintext-reasoning-notice.ts, src/adapters/openai-responses/passthrough.ts, tests/providers/deepseek-reasoning-replay.test.ts, docs-site/src/content/docs/reference/configuration/providers.md
The passthrough adapter connects the callback to a notice function. The function filters providers, warns once per host, and caps recorded hosts at 64. Tests cover the filters and preservation settings. The provider documentation adds self-hosted Kimi on vLLM as an example.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Sanitizer as sanitizeReasoningInputContent
  participant Adapter as OpenAI Responses passthrough
  participant Notice as notePlaintextReasoningDropped
  participant Console as console.warn
  Sanitizer->>Adapter: callback when non-empty reasoning_text is blanked
  Adapter->>Notice: provider configuration
  Notice->>Console: warning for an eligible, not-yet-noticed host
Loading


Merge Risk: ⚪ Minimal · up to bd041

This adds a one-time warning when a custom Responses provider drops replayed plaintext reasoning. Request behavior is unchanged, and no merge-blocking risk was found.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: warning once when a custom Responses provider drops replayed plaintext reasoning.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR





🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR



  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6300750e5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +32 to +34
return PROVIDER_REGISTRY.some(entry =>
normalizedProviderEndpoint(entry.baseUrl) === endpoint
|| (entry.destinationAliases ?? []).some(alias => normalizedProviderEndpoint(alias.baseUrl) === endpoint));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Warn custom providers on vLLM's default URL

When a hand-configured openai-responses provider uses vLLM's standard http://localhost:8000/v1 endpoint, this URL-only scan matches the unrelated, chat-only, overrideable vllm registry row in src/providers/registry/entries-core.ts:1201; isCustomResponsesProvider therefore returns false even while the serializer blanks nonempty reasoning content. This suppresses the newly documented warning for one of the feature's primary self-hosted scenarios, so the exemption should be restricted to registry entries with a curated Responses contract rather than every registry row sharing the URL.

Useful? React with 👍 / 👎.

stripEncryptedContent: threadServingIdentityChanged || requiresPlaintextReasoningReplay(provider),
dropForeignItemId: parsed._dropForeignReasoningItemIds === true,
requirePlaintextReasoning: requiresPlaintextReasoningReplay(provider),
onPlaintextReasoningBlanked: () => notePlaintextReasoningDropped(provider),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the owned structure contract for the warning

This callback adds new process-wide, user-visible adapter behavior and provider-classification rules, but the commit updates no mapped structure/ document; for example, structure/providers/chat-compat.md already describes the reasoning-input sanitization contract and now omits its warning and exemption behavior. Update the adapter area's owned structure documentation in the same change so the maintainer contract remains synchronized.

AGENTS.md reference: src/AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@lidge-jun
lidge-jun merged commit 3354119 into dev Oct 10, 2026
35 of 42 checks passed
@lidge-jun
lidge-jun deleted the codex/6675-plaintext-reasoning-notice branch October 10, 2026 10:31
@lidge-jun lidge-jun mentioned this pull request Oct 10, 2026
3 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant