fix(chatgpt): omit replayed private response items

This commit is contained in:
Alexandr A. Alexandrov 2026-09-17 21:40:28 +00:00
parent 31fbe6fc33
commit f2dae20e49
2 changed files with 45 additions and 8 deletions

View file

@ -98,7 +98,7 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
if "reasoning.encrypted_content" not in include:
include.append("reasoning.encrypted_content")
request["include"] = include
request["input"] = self._normalize_function_call_item_ids(request.get("input"))
request["input"] = self._normalize_responses_input_for_chatgpt(request.get("input"))
allowed_keys: Final = {
"model",
@ -121,20 +121,25 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig):
return filtered
@classmethod
def _normalize_function_call_item_ids(cls, input_value: Any) -> Any:
def _normalize_responses_input_for_chatgpt(cls, input_value: Any) -> Any:
if not isinstance(input_value, list):
return input_value
normalized_input: list[Any] = []
changed = False
for item in input_value:
if isinstance(item, dict) and item.get("type") == "function_call":
current_id = item.get("id")
normalized_id = cls._normalize_function_call_item_id(current_id)
if normalized_id != current_id:
item = dict(item)
item["id"] = normalized_id
if isinstance(item, dict):
item_type = item.get("type")
if item_type in {"reasoning", "web_search_call"}:
changed = True
continue
if item_type == "function_call":
current_id = item.get("id")
normalized_id = cls._normalize_function_call_item_id(current_id)
if normalized_id != current_id:
item = dict(item)
item["id"] = normalized_id
changed = True
normalized_input.append(item)
return normalized_input if changed else input_value

View file

@ -219,6 +219,38 @@ class TestChatGPTResponsesAPITransformation:
}
]
def test_chatgpt_omits_replayed_private_output_items(self):
config = ChatGPTResponsesAPIConfig()
input_items = [
{"type": "reasoning", "id": "rs_fixture", "encrypted_content": "opaque"},
{
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "continue"}],
},
{"type": "web_search_call", "id": "ws_fixture", "status": "completed"},
{
"type": "function_call",
"id": "fc_fixture",
"call_id": "call_fixture",
"name": "read_file",
"arguments": '{"path":"README.md"}',
},
]
request = config.transform_responses_api_request(
model="chatgpt/gpt-5.6-sol",
input=input_items,
response_api_optional_request_params={},
litellm_params=GenericLiteLLMParams(),
headers={},
)
assert [item["type"] for item in request["input"]] == [
"message",
"function_call",
]
@pytest.mark.parametrize(
"model_name",
[