Gemini text-turn thought signatures (native thoughtSignature on a text or trailing empty-text part; OpenAI-compat/Vertex message-level extra_content.google.thought_signature) were discarded at capture, and the Copilot /chat/completions reasoning_text / reasoning_opaque fields and the Gemini-3 function.thought_signature were never read. Replaying the Gemini text-turn signature makes the server rehydrate the turn's thoughts (live: 31 -> 237/250 prompt tokens). agent/reasoning_carriers.py captures them (stream + non-stream), stores them top-level on the live dict plus one private hermes.native_assistant reasoning_details record (persisted in the existing column, so resume/gateway replay keep them), and lifts each one onto the wire only for the route that reads it: extra_content on the same Gemini gate as tool-call extra_content, reasoning_opaque/text and function.thought_signature only to githubcopilot.com. The private record is never forwarded (no profile declares that type). Copilot reasoning_text is shown as the turn's reasoning.
25 lines
1.0 KiB
Python
25 lines
1.0 KiB
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
|
|
from agent.reasoning_carriers import shape_wire_carriers
|
|
|
|
base_url = str(getattr(client, "base_url", "") or "")
|
|
messages = ChatCompletionsTransport().convert_messages(
|
|
shape_wire_carriers(kwargs["messages"], model=kwargs.get("model"), base_url=base_url),
|
|
model=kwargs.get("model"), base_url=base_url,
|
|
)
|
|
return {**kwargs, "messages": messages}
|