fix(responses): default text.format for openai-compatible responses providers (#2093) - #2112
Open
StevanusPangau wants to merge 1 commit into
Open
StevanusPangau wants to merge 1 commit into
StevanusPangau wants to merge 1 commit into
Conversation
diegosouzapw
added a commit
to diegosouzapw/OmniRoute
that referenced
this pull request
Jun 26, 2026
…roviders
Some Responses-compatible upstreams (e.g. LM Studio) reject a `text` object
missing `text.format` with a 400 missing_required_parameter. DefaultExecutor
now fills the Responses-API default { type: "text" } before forwarding, guarded
to openai-compatible-*responses* providers and never overwriting an existing
format. Port of decolua/9router#2112.
Includes the file-size rebaseline for default.ts (859->876) covering this growth.
Co-authored-by: StevanusPangau <StevanusPangau@users.noreply.github.com>
afandiaziz
pushed a commit
to afandiaziz/9router
that referenced
this pull request
Aug 9, 2026
29 PR upstream di-cherry-pick (semua masih open upstream per 2026-08-09). Rincian lengkap + link per PR ada di FORK-CHANGES.md. P1 skala 2475 koneksi : decolua#2798 decolua#410 decolua#2879 decolua#879 decolua#2997 P2 akurasi token/usage: decolua#2422 decolua#2658 decolua#2762 decolua#2453 decolua#2668 decolua#2361 P3 provider & combo : decolua#2526 decolua#3125 decolua#1434 decolua#2689 decolua#2439 decolua#2724 decolua#2647 decolua#1805 decolua#2909 decolua#2853 decolua#2508 decolua#2928 decolua#2345 decolua#2112 decolua#2786 P4 keamanan : decolua#1666 decolua#2776 Revert decolua#664: menambah transformRequest kedua di DefaultExecutor sehingga menimpa yang pertama dan mematikan stream_options/text.format/ injectReasoningContent/stripUnsupportedParams — termasuk PR decolua#3081 yang sudah dipakai produksi. Test: 88 gagal / 1783 lulus — nol regresi vs baseline v0.5.50 (88/1656).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When using a custom OpenAI-compatible provider configured with API Type
responses, 9Router forwards a request body whosetextis an object missingtext.format. Some Responses-compatible upstreams (e.g. LM Studio) reject this with:{ "error": { "message": "Required", "type": "invalid_request_error", "param": "text.format", "code": "missing_required_parameter" } }This happens because a client calling
/v1/responses(source formatopenai-responses) routed to an openai-compatibleresponsesprovider (target formatopenai-responses) hits the translator passthrough path —source === target, so translation is skipped and the client'stextobject is forwarded verbatim, without a defaulttext.format.Fix
Default
text.formatto{ type: "text" }(the Responses API default for that field) in the executor before forwarding upstream, scoped to openai-compatibleresponsesproviders:openai-compatible-*and includesresponses.body.textis a plain object without aformat.textobject instead of mutating the caller's, and never overwrites an existingformat.Why this is safe
textis absent, non-object, or already hasformat.{ type: "text" }is the documented Responses API default, so it does not change behavior for upstreams that were already accepting the request.Tests
Adds
tests/unit/openai-compat-responses-text-format.test.js:text.formatto{ type: "text" }whentextis an object withoutformat.text.format.text.textvalue.npm exec -- vitest run tests/unit/openai-compat-responses-text-format.test.js --config tests/vitest.config.js npm run buildAll pass; related executor unit suites stay green (no regressions).
Fixes #2093