fix(codex): route commentary-phase preamble text to reasoning channel (fixes #41293)

GPT-5.x models on the Codex Responses API emit short pre-tool-call
"preamble" text as message items with phase="commentary". Previously,
_normalize_codex_response() added ALL message items to content_parts
regardless of phase, causing commentary text to leak as visible
assistant content on chat gateways.

Fix: when normalized_phase is "commentary" or "analysis", route the
message text to reasoning_parts instead of content_parts. This keeps
preamble/internal planning in the reasoning channel where it belongs.

Fixes NousResearch/hermes-agent#41293
This commit is contained in:
annguyenNous 2026-06-07 21:50:35 +07:00 committed by Teknium
parent ea125dd62e
commit 538173f679

View file

@ -1176,12 +1176,17 @@ def _normalize_codex_response(
saw_final_answer_phase = True
message_text = _extract_responses_message_text(item)
if message_text:
# Responses ``commentary``/``analysis`` phase text is scratch/tool
# preamble for the model/provider protocol, not user-visible final
# answer text. Preserve the exact message item for replay/cache
# continuity, but do not expose it as assistant content where the
# gateway/CLI/interim callbacks can leak it to the user.
if not is_commentary_phase:
# Responses ``commentary``/``analysis`` phase text is mid-turn
# preamble/progress narration, never the turn's final answer
# (Codex CLI excludes it from last-message extraction; issues
# #24933 / #41293). Keep it out of assistant content so it
# can't be concatenated into — or leak as — the final response,
# but surface it through the reasoning channel so the CLI/
# gateway display it like thinking text. The exact message
# item is still preserved below for replay/cache continuity.
if is_commentary_phase:
reasoning_parts.append(message_text)
else:
content_parts.append(message_text)
raw_message_item: Dict[str, Any] = {
"type": "message",