fix(dashboard): test Responses nodes on /v1/responses, not chat completions (#13070) - #13087
Merged
diegosouzapw merged 2 commits intoSep 10, 2026
Conversation
…etions
detectTestKind mapped a provider node's apiType to audio, rerank and
embeddings only, so a text model on a node configured with
apiType: "responses" fell through to the chat branch and was probed with a
Chat Completions body on /v1/chat/completions. A Responses-native upstream
can answer 200 to that while carrying nothing a Chat Completions reader
recognises, so the dashboard marked the model unhealthy with "Provider
returned HTTP 200 but no text content" even though the same model answered
normally through /v1/responses.
detectTestKind now reports isResponses, last in the chain so that embedding,
rerank and audio models hosted on such a node keep the endpoints that were
already right for them. The probe sends { input, max_output_tokens } to
/v1/responses and is deliberately non-streaming: the existing reader
understands the output_text/output[] shapes but not Responses stream events,
so a streamed probe would read as empty -- the very failure being fixed.
Fixes diegosouzapw#13070
…upstream The first version of this test asserted on the request that reached globalThis.fetch. That proved nothing: for a node with apiType "responses" the router translates a Chat Completions body into Responses shape before it leaves, so the upstream body carries `input` either way and the test stayed green with the dispatch reverted. It now reads the call log, which records the internal endpoint path -- the same field the bug report used as evidence. Reverting the dispatch turns this test red and leaves the other five green.
diegosouzapw
merged commit Sep 10, 2026
f2d5728
into
diegosouzapw:release/v3.8.51
10 of 16 checks passed
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…etions (diegosouzapw#13070) (diegosouzapw#13087) Boarded with 13 sibling PRs into one worktree off release/v3.8.51 and validated as a set: 132 focused tests pass across all 15 test files in the batch, typecheck:core is clean, check-changelog-integrity reports no lost base bullets, and check-file-size is green. Your PR merged without conflict against its siblings. Thank you — the write-up made this reviewable: measuring the behaviour on the release tip and showing the before/after table meant the defect could be confirmed rather than taken on faith.
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.
Fixes #13070.
The defect
detectTestKind()reads the provider node'sapiType, but only maps it to audio, rerank and embeddings. There is no Responses branch, so every text model on a node configured withapiType: "responses"falls through to:which is hardcoded to
${INTERNAL_ORIGIN}/v1/chat/completions.A Responses-native upstream can answer 200 to that while carrying nothing a Chat Completions reader recognises, so the dashboard marks the model red with
Provider returned HTTP 200 but no text content— while the same model answers normally through/v1/responses.What changed
detectTestKind()now also reportsisResponses. It is last in the chain, after audio / rerank / embeddings: a Responses-typed node can still host an embedding or rerank model, and those endpoints were already right for it. Losing that ordering would break working setups instead of fixing a broken one.buildInternalResponsesRequest(), carrying the same health-check bypass headers as the chat and rerank builders.{ model, input, max_output_tokens }. Responses ignoresmax_tokens, which would let a reasoning model spend the whole default budget before emitting visible text.extractComboTestStreamResult()understands Chat Completions deltas and theoutput_text/output[]shapes, but not Responses stream events (response.output_text.delta), so a streamed probe would read as empty — the very failure being fixed. The reader is passed!isResponses && streamChatso it takes the JSON path.No reader change was needed:
extractComboTestResponseText()already handlesoutput_textandoutput[]. Only the request side was ever wrong.Evidence
Six new tests in
tests/unit/responses-node-model-test-13070.test.ts, plus the four existingdetectTestKinddeep-equal assertions extended with the new field.The wiring is pinned, not just the classification. My first version of the last test asserted on the request that reached
globalThis.fetch, and it was worthless: for a Responses node the router translates a Chat Completions body into Responses shape before it leaves, so the upstream body carriesinputeither way. That test stayed green with the dispatch reverted. It now reads the call log, which records the internal endpoint path — the same field the report used as evidence.Two-way mutation, run locally:
model-test-runner.test.ts32 / 32if (isResponses)dispatch, keepdetectTestKinddetectTestKindalways returnsisResponses: falseNot covered
The Responses streaming path. The probe avoids it rather than teaching
extractComboTestStreamResult()the Responses event shape; that is a larger change and a separate one. If you would rather the probe stream, say so and I will send the reader work instead.