Repository navigation
Conversation
|
Hi @wxhking, this is your 5th Pull Request. 🙌 Join Developer CommunityThanks so much for your contribution! We'd love to invite you to join the official QwenPaw developer group! You can find the Discord and DingTalk group links under the "Developer Community" section on our docs page: We truly appreciate your enthusiasm—and look forward to your future contributions! 😊 We'll review your PR soon. |
|
+1 for surfacing truncation info in response metadata. This is the same observability gap I described in #8103 (daemon silent fallback). Users have no way to know:
Both cases leave users confused about what actually happened. Adding metadata like: {
"metadata": {
"finish_reason": "length",
"truncated": true,
"model_used": "actual-model-id",
"model_requested": "requested-model-id"
}
}...would make debugging much easier and build user trust. Related: #8103 (fallback notification), #7738 (kwargs filtering — different issue but same "silent failure" pattern). |


Description
When a generation is cut off by the output cap, the provider reports
finish_reason="length"on the terminal chunk, but the base stream parsernever reads it — the stop reason is silently dropped, and a truncated answer
is indistinguishable from a complete one (issue #8085).
This change surfaces the provider
finish_reasonas truncation metadata onthe final
ChatResponsefor both paths of the OpenAI-compatible providerlayer:
_SanitizedStreamrecords the last non-emptyfinish_reasonseen on theraw chunks. The terminal choice chunk usually produces no yielded delta,
so the value is kept on the stream wrapper and read once the final
accumulated response arrives — the same delta-only sidecar pattern the
relay already uses for tool-call extras.
_relay_stream_tool_call_extraswritesmetadata["finish_reason"]andemits one warning line when the captured value is
length._parse_completion_responsedoes the same for the non-streaming path.Behavior is unchanged for
stop,tool_calls, and every other stop reason.One boundary, consistent with the staged proposal in #8085: the pinned
AgentScope release drops
ChatResponse.metadatawhen converting modeloutput into agent events (the reason
FallbackChatModelpublishes routingtransparency through an out-of-band sink). In this first stage the metadata
is therefore observable by direct consumers of the provider layer, and the
warning log line is the signal visible everywhere. Propagating the flag
through the agent loop (e.g. reusing the fallback-notice sink pattern) and
rendering a channel notice are left as the follow-up stage for maintainers
to decide.
Related Issue: Fixes #8085
Security Considerations: None — the change only adds a diagnostic
metadata entry and one warning log line; no auth, config, or environment
handling is touched.
Type of Change
Component(s) Affected
Checklist
pre-commit run --all-fileslocally and it passes(all hooks pass on the two touched files; the
--all-filesrun reports3 pre-existing mypy errors in
src/qwenpaw/cli/shutdown_cmd.pyandpre-existing pylint W0613/E0611 findings in
tests/unit/loop/,tests/unit/plugins/computer_use/,tests/unit/sandbox/, andtests/unit/services/— none touch this change)pytestor as relevant) and they passTesting
uv run python -m pytest tests/unit/providers -qNew tests in
tests/unit/providers/test_openai_stream_toolcall_compat.py:finish_reason="length"→ final response metadata{"finish_reason": "length"}+ warning log linefinish_reason="stop"/"tool_calls"→ metadata untouched(controls)
finish_reason="length"/"stop"via the public modelcall path
Evidence
$ uv run python -m pytest tests/unit/providers -q 893 passed, 1 skipped, 2 warnings in 47.40s $ uvx pre-commit run --files src/qwenpaw/providers/openai_chat_model_compat.py tests/unit/providers/test_openai_stream_toolcall_compat.py check python ast / docstring / encoding pragma / private key / trailing whitespace / trailing commas: Passed mypy / black / flake8 / pylint: Passed