Repository navigation
fix: MiMo remove unsupported body fields and preserve reasoning content - #1253
Conversation
Stop the Gitlawb Opengateway preset from forcing synthetic empty reasoning_content onto prior assistant tool-call messages. MiMo rejects that shape after Agent/sub-agent tool calls with upstream Param Incorrect errors. Add an OpenAI shim regression test covering MiMo tool history through https://opengateway.gitlawb.com/v1 while preserving the separate OpenGateway Gemini signature replay behavior. Validation: bun test src/services/api/openaiShim.test.ts; bun run build
…reserve reasoning content
…rip unsupported options
There was a problem hiding this comment.
Pull request overview
Fixes MiMo (Xiaomi) API integration issues by (1) stripping unsupported store and stream_options fields from request bodies for both OpenGateway and direct Xiaomi paths, (2) removing the empty reasoning_content fallback so real reasoning content is preserved during conversation replay, and (3) preserving thinking blocks for mimo-v2* models when restoring conversations from logs.
Changes:
- Replace
reasoningContentFallback: ''withremoveBodyFields: ['store', 'stream_options']in both the OpenGateway and Xiaomi MiMo transport configs, and add the same fallback inference formimo-v2*models inruntimeMetadata.ts. - Add
shouldPreserveThinkingBlocksForProviderReplay()inconversationRecovery.tsto skip thinking-block stripping when the active model ismimo-v2*. - Add 4 new test cases in
openaiShim.test.tsand a MiMo-specific assertion block inconversationRecovery.hooks.test.ts.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/integrations/gateways/gitlawb-opengateway.ts | Drop reasoning-content fallback config; strip store/stream_options from request body. |
| src/integrations/vendors/xiaomi-mimo.ts | Same change for the direct Xiaomi MiMo vendor path. |
| src/integrations/runtimeMetadata.ts | Add mimo-v2* inference branch matching the gateway/vendor config. |
| src/utils/conversationRecovery.ts | Add helper to preserve thinking blocks for mimo-v2* models during replay. |
| src/utils/conversationRecovery.hooks.test.ts | Add MiMo replay assertions confirming thinking blocks are preserved. |
| src/services/api/openaiShim.test.ts | Add 4 tests covering OpenGateway/Xiaomi reasoning preservation and body-field stripping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
BlockersNone found. Non-Blocking
Looks Good
Verdict: Approve — clean MiMo compatibility fix. |
Vasanthdev2004
left a comment
There was a problem hiding this comment.
Clean MiMo compatibility fix.
kevincodex1
left a comment
There was a problem hiding this comment.
Awesome! Thanks for working on this.
…nt (Twigpine#1253) * Fix OpenGateway MiMo agent tool history Stop the Gitlawb Opengateway preset from forcing synthetic empty reasoning_content onto prior assistant tool-call messages. MiMo rejects that shape after Agent/sub-agent tool calls with upstream Param Incorrect errors. Add an OpenAI shim regression test covering MiMo tool history through https://opengateway.gitlawb.com/v1 while preserving the separate OpenGateway Gemini signature replay behavior. Validation: bun test src/services/api/openaiShim.test.ts; bun run build * fix(MiMo): update integration to remove unnecessary body fields and preserve reasoning content * test(MiMo): enhance tests to verify reasoning_content handling and strip unsupported options --------- Co-authored-by: jatmn <the@jat.mn>
…nt (Twigpine#1253) * Fix OpenGateway MiMo agent tool history Stop the Gitlawb Opengateway preset from forcing synthetic empty reasoning_content onto prior assistant tool-call messages. MiMo rejects that shape after Agent/sub-agent tool calls with upstream Param Incorrect errors. Add an OpenAI shim regression test covering MiMo tool history through https://opengateway.gitlawb.com/v1 while preserving the separate OpenGateway Gemini signature replay behavior. Validation: bun test src/services/api/openaiShim.test.ts; bun run build * fix(MiMo): update integration to remove unnecessary body fields and preserve reasoning content * test(MiMo): enhance tests to verify reasoning_content handling and strip unsupported options --------- Co-authored-by: jatmn <the@jat.mn>
…tinuity DeepSeek V4 / Moonshot providers reject multi-turn conversations where a redacted_thinking block is silently dropped from the assistant message. The shim only matched b.type === 'thinking' when selecting the source for reasoning_content and when filtering redacted content out of the visible text stream, so any Anthropic-side redacted_thinking block never made it onto the OpenAI-shaped outgoing message and the provider 400'd on the next turn. This patch widens the filter at openaiShim.ts:585 to also match redacted_thinking for both the reasoning_content source selection and the textContent exclusion, so the block is preserved in the chain-of-thought stream (it carries no visible text, but the signature is what the provider needs to validate continuity). Adds a focused test in openaiShim.test.ts covering the redacted_thinking path end-to-end: the assistant message that carries a tool_call now has reasoning_content: '' attached even when the only thinking-shaped block is redacted_thinking, which is the field DeepSeek/Kimi strict-validate. Rebased against current upstream/main (c634fd8 9e942da). Noting the rest of the original PR Twigpine#1228 patch series was already absorbed by other merged work and is intentionally not re-applied here, to avoid duplication: - stripThinkingBlocks provider-conditional gating: PR Twigpine#1248 (0d3c157, 2026-05-23) — fix(recovery): keep thinking blocks on resume for reasoning-echo providers. This covers the recovery-path half of the original 1d333b9 patch with a more accurate shouldPreserveThinkingBlocksForProviderReplay helper instead of unconditional inject. - reasoning_content injection gating: PR Twigpine#828 (67de6bd, 2026-04-22) — fix(openai-shim): echo reasoning_content on assistant tool-call messages for Moonshot. This threaded preserveReasoningContent through convertMessages and _doOpenAIRequest with isMoonshotBaseUrl gating, then extended by PR Twigpine#1253 (aab2fbc, 2026-05-19) — fix: MiMo remove unsupported body fields and preserve reasoning content — which split the reasoningContentFallback flag ('omit' for MiMo, '' for DeepSeek/Moonshot/Z.AI). That 3-flag scheme is what the test suite in upstream/main encodes and differs from the unconditional inject in the original 1d333b9 patch. - reasoning_content heuristic tightening: PR Twigpine#1201 (1fc5116, 2026-06-03) — fix(api): tighten reasoning_content heuristic to prevent false-positive provider configuration leaks. This replaced the loose includes() check with a segment-boundary-aware inference and added 10 regression tests in runtimeMetadata.test.ts. - Test coverage carried in the original 64ad59b (4 edge-case tests for DeepSeek V4 reasoning_content continuity): three of the four were not carried forward because their scenarios are already covered upstream: * 'array-content assistant without thinking block still gets reasoning_content: ""' — covered by the tool-call branch in openaiShim.test.ts merged via Twigpine#828. * 'string-content assistant message gets reasoning_content: ""' — covered by the same tool-call branch in Twigpine#828. * 'synthetic interruption assistant message carries reasoning_content: ""' — covered by the filterOrphanedThinkingOnlyMessages path tested in conversationRecovery.test.ts via Twigpine#1248. The fourth, 'redacted_thinking block preserves continuity with reasoning_content: ""', is the only scenario that exercises a code path this patch actually changes (the b.type === 'redacted_thinking' match), so it is retained as the targeted regression test for this commit. The README.md note about DeepSeek V4 thinking mode is not part of this commit — the wider rebase is in upstream and a documentation follow-up will be filed separately if needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#1228) * fix(openai-shim): preserve redacted_thinking blocks for reasoning continuity DeepSeek V4 / Moonshot providers reject multi-turn conversations where a redacted_thinking block is silently dropped from the assistant message. The shim only matched b.type === 'thinking' when selecting the source for reasoning_content and when filtering redacted content out of the visible text stream, so any Anthropic-side redacted_thinking block never made it onto the OpenAI-shaped outgoing message and the provider 400'd on the next turn. This patch widens the filter at openaiShim.ts:585 to also match redacted_thinking for both the reasoning_content source selection and the textContent exclusion, so the block is preserved in the chain-of-thought stream (it carries no visible text, but the signature is what the provider needs to validate continuity). Adds a focused test in openaiShim.test.ts covering the redacted_thinking path end-to-end: the assistant message that carries a tool_call now has reasoning_content: '' attached even when the only thinking-shaped block is redacted_thinking, which is the field DeepSeek/Kimi strict-validate. Rebased against current upstream/main (c634fd8 9e942da). Noting the rest of the original PR #1228 patch series was already absorbed by other merged work and is intentionally not re-applied here, to avoid duplication: - stripThinkingBlocks provider-conditional gating: PR #1248 (0d3c157, 2026-05-23) — fix(recovery): keep thinking blocks on resume for reasoning-echo providers. This covers the recovery-path half of the original 1d333b9 patch with a more accurate shouldPreserveThinkingBlocksForProviderReplay helper instead of unconditional inject. - reasoning_content injection gating: PR #828 (67de6bd, 2026-04-22) — fix(openai-shim): echo reasoning_content on assistant tool-call messages for Moonshot. This threaded preserveReasoningContent through convertMessages and _doOpenAIRequest with isMoonshotBaseUrl gating, then extended by PR #1253 (aab2fbc, 2026-05-19) — fix: MiMo remove unsupported body fields and preserve reasoning content — which split the reasoningContentFallback flag ('omit' for MiMo, '' for DeepSeek/Moonshot/Z.AI). That 3-flag scheme is what the test suite in upstream/main encodes and differs from the unconditional inject in the original 1d333b9 patch. - reasoning_content heuristic tightening: PR #1201 (1fc5116, 2026-06-03) — fix(api): tighten reasoning_content heuristic to prevent false-positive provider configuration leaks. This replaced the loose includes() check with a segment-boundary-aware inference and added 10 regression tests in runtimeMetadata.test.ts. - Test coverage carried in the original 64ad59b (4 edge-case tests for DeepSeek V4 reasoning_content continuity): three of the four were not carried forward because their scenarios are already covered upstream: * 'array-content assistant without thinking block still gets reasoning_content: ""' — covered by the tool-call branch in openaiShim.test.ts merged via #828. * 'string-content assistant message gets reasoning_content: ""' — covered by the same tool-call branch in #828. * 'synthetic interruption assistant message carries reasoning_content: ""' — covered by the filterOrphanedThinkingOnlyMessages path tested in conversationRecovery.test.ts via #1248. The fourth, 'redacted_thinking block preserves continuity with reasoning_content: ""', is the only scenario that exercises a code path this patch actually changes (the b.type === 'redacted_thinking' match), so it is retained as the targeted regression test for this commit. The README.md note about DeepSeek V4 thinking mode is not part of this commit — the wider rebase is in upstream and a documentation follow-up will be filed separately if needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(openai-shim): propagate redacted_thinking.data into reasoning_content --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Twigpine#1228) * fix(openai-shim): preserve redacted_thinking blocks for reasoning continuity DeepSeek V4 / Moonshot providers reject multi-turn conversations where a redacted_thinking block is silently dropped from the assistant message. The shim only matched b.type === 'thinking' when selecting the source for reasoning_content and when filtering redacted content out of the visible text stream, so any Anthropic-side redacted_thinking block never made it onto the OpenAI-shaped outgoing message and the provider 400'd on the next turn. This patch widens the filter at openaiShim.ts:585 to also match redacted_thinking for both the reasoning_content source selection and the textContent exclusion, so the block is preserved in the chain-of-thought stream (it carries no visible text, but the signature is what the provider needs to validate continuity). Adds a focused test in openaiShim.test.ts covering the redacted_thinking path end-to-end: the assistant message that carries a tool_call now has reasoning_content: '' attached even when the only thinking-shaped block is redacted_thinking, which is the field DeepSeek/Kimi strict-validate. Rebased against current upstream/main (c634fd8 9e942da). Noting the rest of the original PR Twigpine#1228 patch series was already absorbed by other merged work and is intentionally not re-applied here, to avoid duplication: - stripThinkingBlocks provider-conditional gating: PR Twigpine#1248 (0d3c157, 2026-05-23) — fix(recovery): keep thinking blocks on resume for reasoning-echo providers. This covers the recovery-path half of the original 1d333b9 patch with a more accurate shouldPreserveThinkingBlocksForProviderReplay helper instead of unconditional inject. - reasoning_content injection gating: PR Twigpine#828 (67de6bd, 2026-04-22) — fix(openai-shim): echo reasoning_content on assistant tool-call messages for Moonshot. This threaded preserveReasoningContent through convertMessages and _doOpenAIRequest with isMoonshotBaseUrl gating, then extended by PR Twigpine#1253 (aab2fbc, 2026-05-19) — fix: MiMo remove unsupported body fields and preserve reasoning content — which split the reasoningContentFallback flag ('omit' for MiMo, '' for DeepSeek/Moonshot/Z.AI). That 3-flag scheme is what the test suite in upstream/main encodes and differs from the unconditional inject in the original 1d333b9 patch. - reasoning_content heuristic tightening: PR Twigpine#1201 (1fc5116, 2026-06-03) — fix(api): tighten reasoning_content heuristic to prevent false-positive provider configuration leaks. This replaced the loose includes() check with a segment-boundary-aware inference and added 10 regression tests in runtimeMetadata.test.ts. - Test coverage carried in the original 64ad59b (4 edge-case tests for DeepSeek V4 reasoning_content continuity): three of the four were not carried forward because their scenarios are already covered upstream: * 'array-content assistant without thinking block still gets reasoning_content: ""' — covered by the tool-call branch in openaiShim.test.ts merged via Twigpine#828. * 'string-content assistant message gets reasoning_content: ""' — covered by the same tool-call branch in Twigpine#828. * 'synthetic interruption assistant message carries reasoning_content: ""' — covered by the filterOrphanedThinkingOnlyMessages path tested in conversationRecovery.test.ts via Twigpine#1248. The fourth, 'redacted_thinking block preserves continuity with reasoning_content: ""', is the only scenario that exercises a code path this patch actually changes (the b.type === 'redacted_thinking' match), so it is retained as the targeted regression test for this commit. The README.md note about DeepSeek V4 thinking mode is not part of this commit — the wider rebase is in upstream and a documentation follow-up will be filed separately if needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(openai-shim): propagate redacted_thinking.data into reasoning_content --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
easoning_content during conversation replay for MiMo models instead of injecting empty fallback
Changes
emoveBodyFields: ['store', 'stream_options'] to gateway config
easoningContentFallback: '' with
emoveBodyFields, stop synthesizing empty reasoning
untimeMetadata.ts** — add fallback inference for mimo-v2* models with correct shim settings
Test plan
easoning_content without empty fallback
easoning_content without empty fallback
easoning_content when missing