fix: preserve seller reasoning profiles across API adaptation - #976
Open
alexanderludwig wants to merge 4 commits into
Open
fix: preserve seller reasoning profiles across API adaptation#976alexanderludwig wants to merge 4 commits into
alexanderludwig wants to merge 4 commits into
Conversation
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.
Summary
response.completed.response.outputRoot cause
This investigation found two separate defects at different layers.
1. Request profile loss — buyer protocol adapter
The buyer sent
reasoning_effort: "none", but the canonical request representation did not carry reasoning effort. During Chat Completions → Responses adaptation, the field was silently discarded and the seller therefore received no equivalentreasoningobject.Historical authenticated audit evidence showed this consistently across the affected CatGPT run: the buyer request contained
reasoning_effort: "none", while the adapted seller request omittedreasoningand CatGPT reported its default effort instead.2. Blank response — seller Responses SSE collapse
After the request mapping was fixed, a real CatGPT smoke request proved that CatGPT honored
reasoning: { effort: "none" }and generated the requested text. However, CatGPT's stream ended with this event pattern:The OpenAI Responses seller ignored
response.output_item.doneand collapsed the stream using only the terminalresponse.completed.response. That discarded the valid output item and returned a blank non-stream response, which caused verifier batches to remainUNDETERMINED.Fix
Reasoning profile preservation
The canonical adapter now carries reasoning effort losslessly:
The canonical value remains model-agnostic rather than using a global hard-coded allowlist. The adapter preserves the requested profile; the selected upstream model remains responsible for accepting or rejecting it.
Specification-aligned output preservation
For forced-stream requests serving non-stream clients, the seller now collects complete
response.output_item.doneitems byoutput_index. If the terminal response already contains output, it is returned unchanged. If the terminal response has an empty or missingoutput, the seller restores the completed streamed items.This keeps the upstream item IDs, types, statuses, content, tool calls, refusals, and ordering intact. It does not synthesize message IDs or add the SDK-only top-level
output_textconvenience field.OpenAI API references
reasoning_efforton Chat Completions requests.reasoningconfiguration, includingreasoning.effort.response.output_item.doneas carrying the completed outputitemtogether with itsoutput_index, which is why the seller preserves those events when reconstructing a non-stream response.These references support both sides of the fix: preserve the client's reasoning setting while adapting request protocols, and preserve completed standard output items while collapsing a Responses stream. The final terminal response remains authoritative whenever it already contains output; reconstruction is only the compatibility fallback for CatGPT's observed empty terminal
output.Scope
This PR contains:
It does not change routing, verifier classification, or audit thresholds. It also does not claim to fix unrelated malformed responses such as refusals, non-numeric prose, or failures from other seller implementations.
Verification
Local validation:
pnpm --filter @antseed/api-adapter test— 120 tests passedpnpm --filter @antseed/provider-openai-responses test— 29 tests passedpnpm --filter @antseed/api-adapter typecheckpnpm --filter @antseed/provider-openai-responses typecheckpnpm --filter @antseed/api-adapter buildpnpm --filter @antseed/provider-openai-responses buildReal CatGPT smoke verification on September 1, 2026:
{ "statusCode": 200, "reasoningEffort": "none", "reasoningTokens": 0, "outputCount": 1, "outputItemType": "message", "outputItemStatus": "completed", "contentType": "output_text", "contentText": "42", "hasTopLevelOutputText": false }This was a minimal funded smoke test, not a full-network verification audit. A separate funded audit is still required to measure the reduction in
UNDETERMINEDresults across the network.