fix(gateway): forward reasoning in chat completions (#37044) - #39006
fix(gateway): forward reasoning in chat completions (#37044)#39006rodboev wants to merge 1 commit into
Conversation
672f9d0 to
d6e24d6
Compare
teknium1
left a comment
There was a problem hiding this comment.
Thanks for covering the non-streaming response shape; current main still drops last_reasoning from /v1/chat/completions at gateway/platforms/api_server.py:2417-2420.
Problems
- The streaming branch added at
gateway/platforms/api_server.py:2027usestool_progress_callbackandreasoning.available. On current main, that event is derived from strippedassistant_message.contentand capped at 500 characters (agent/conversation_loop.py:4334-4350), not from provider reasoning. Native reasoning deltas usereasoning_callback(run_agent.py:4745-4752;agent/chat_completion_helpers.py:2057-2065). This can label answer text asdelta.reasoning_contentand misses structured/reasoning-only outputs. - The new streaming test manually fires
reasoning.available, so it does not cover the production reasoning callback chain.
Suggested changes
- Thread
reasoning_callbackthrough_run_agentand_create_agent, then queue and serialize its deltas asdelta.reasoning_content. - Update the stream test to invoke that callback and cover structured/reasoning-only output.
Automated hermes-sweeper review.
|
Good catch. The streaming path was treating I removed that source from the SSE path and threaded a dedicated The new regression enters |
d1945be to
680e88a
Compare
680e88a to
a2806be
Compare
|
Just want to comment here that this would be a much appreciated feature for my integration with OpenWebUI |
a2806be to
c290ec8
Compare
Summary
/v1/chat/completionsexposed assistant text but dropped reasoning generated by the provider. The streaming route had no path fromAIAgent.reasoning_callbackinto its SSE writer, and the non-streaming message discarded the completed turn'slast_reasoningvalue. Using the derivedreasoning.availabletool-progress event would have mislabeled final answer text and capped the output.This rebuild forwards the existing provider reasoning callback through the API adapter and emits its deltas as OpenAI-compatible
delta.reasoning_content. The callback uses current main'sThreadSafeAsyncQueueand shared_sse_frame()path. Non-streaming responses include the current turn'sreasoning_contentunder the samedisplay.show_reasoningpolicy. The display policy defaults to hidden and applies the existing API-server override precedence.Fixes #37044
Changes
gateway/platforms/api_server.py: pass provider reasoning through_run_agent()and_create_agent(), feed tagged deltas throughThreadSafeAsyncQueue, serialize them with_sse_frame(), and include non-emptylast_reasoningin non-streaming messages when display is enabled.tests/gateway/test_api_server.py: cover callback construction and forwarding, full reasoning payloads, reasoning-only output, empty and disabled reasoning, tool lifecycle coexistence, and non-streaming response shapes.Validation
delta.reasoning_content; assistant text remains indelta.content.reasoning_contentwhile answer, tool lifecycle, and completion output continue.message.reasoning_contentonly when non-empty and display is enabled./v1/responses,/v1/runs, session chat, messagingTest plan
bash scripts/run_tests.sh tests/gateway/test_api_server.py -k "reasoning or run_agent or stream_includes_tool_progress or stream_emits_tool_lifecycle or stream_tool_lifecycle" -v --timeout=0— 15 passed.bash scripts/run_tests.sh tests/gateway/test_api_server.py -k "stream_includes_tool_progress or stream_emits_tool_lifecycle or stream_tool_lifecycle_skips_internal or stream_cancelled_persists_incomplete_snapshot or stream_client_disconnect_persists_incomplete_snapshot" -v --timeout=0— 5 passed.ruff check gateway/platforms/api_server.py tests/gateway/test_api_server.py— passed.Not in scope
/v1/responses,/v1/runs, native session chat, and messaging platforms keep their established response formats and callback contracts.