OpenRouter and the Nous Portal replay reasoning_details for multi-turn reasoning continuity; every other OpenAI-compatible route either ignores the field or, when its schema is strict (Groq, Mistral, Cerebras, opencode relays), rejects the whole request with 400/422 once an earlier reasoning turn is in history — wedging the session after an in-session model switch (#70233). Strip the field from the wire copy in ChatCompletionsTransport.convert_messages (keyed on the target base_url), mirror it in the auxiliary wire boundary and the iteration-summary path; state.db history keeps the field so switching back to OpenRouter/Nous replays it again.
21 lines
883 B
Python
21 lines
883 B
Python
"""Message hygiene at the resolved auxiliary client boundary."""
|
|
|
|
from openai import AsyncOpenAI, OpenAI
|
|
|
|
from agent.transports.chat_completions import ChatCompletionsTransport
|
|
|
|
|
|
def prepare_chat_messages(client, kwargs: dict) -> dict:
|
|
"""Sanitize actual Chat Completions SDK requests, not native adapter replay.
|
|
|
|
Auxiliary and MoA callers can retain a prepared request before the virtual
|
|
transport sanitizes its copy. The resolved SDK client identifies the wire;
|
|
native Messages/Responses adapters must retain their reasoning sidecars.
|
|
"""
|
|
if not isinstance(client, (OpenAI, AsyncOpenAI)) or "messages" not in kwargs:
|
|
return kwargs
|
|
messages = ChatCompletionsTransport().convert_messages(
|
|
kwargs["messages"], model=kwargs.get("model"), base_url=str(getattr(client, "base_url", "") or ""),
|
|
)
|
|
return {**kwargs, "messages": messages}
|