fix(responses): patch custom_tool_call_output in place on guardrail write-back

This commit is contained in:
Tejas Chopra 2026-09-16 21:33:26 -07:00
parent 5ef40a630b
commit 067514bc76
2 changed files with 51 additions and 1 deletions

View file

@ -209,7 +209,7 @@ _TOOL_CALL_PAYLOAD_EVENT_TYPES: Final = _TOOL_CALL_PAYLOAD_DELTA_EVENT_TYPES | f
)
_OUTPUT_ITEM_EVENT_TYPES: Final = frozenset({"response.output_item.added", "response.output_item.done"})
_PATCHABLE_ITEM_FIELDS: Final[Mapping[str, str]] = MappingProxyType(
{"function_call_output": "output", "message": "content"}
{"function_call_output": "output", "custom_tool_call_output": "output", "message": "content"}
)
_EMPTY_RESPONSES_REQUEST: Final[ResponsesAPIOptionalRequestParams] = {}

View file

@ -2223,6 +2223,56 @@ class TestStructuredMessagesWriteBack:
}
assert result["input"][3] == {"role": "user", "content": "What is the codename?"}
@pytest.mark.asyncio
async def test_codex_custom_tool_items_survive_tool_output_compression(self):
handler = OpenAIResponsesHandler()
additional_tools_item = {
"type": "additional_tools",
"tools": [{"type": "custom", "name": "exec", "description": "Run a JavaScript snippet"}],
}
reasoning_item = {
"id": "rs_456",
"type": "reasoning",
"summary": [],
"encrypted_content": "gAAAAA-signed-reasoning",
}
custom_tool_call_item = {
"id": "ctc_456",
"type": "custom_tool_call",
"call_id": "call_exec",
"name": "exec",
"input": 'const r = await tools.exec_command({"cmd": "cat memo.txt"});\ntext(r.output);',
"status": "completed",
}
data = {
"model": "gpt-5.6",
"input": [
additional_tools_item,
{"role": "user", "content": "What is the codename?"},
reasoning_item,
custom_tool_call_item,
{
"type": "custom_tool_call_output",
"call_id": "call_exec",
"output": [
{"type": "input_text", "text": "Script completed\nOutput:\n"},
{"type": "input_text", "text": "memo " * 400},
],
},
],
}
result = await handler.process_input_messages(data, ToolOutputRewriteGuardrail())
assert result["input"][0] is additional_tools_item
assert result["input"][1] == {"role": "user", "content": "What is the codename?"}
assert result["input"][2] is reasoning_item
assert result["input"][3] is custom_tool_call_item
assert result["input"][4]["type"] == "custom_tool_call_output"
assert result["input"][4]["call_id"] == "call_exec"
assert COMPRESSED_MARKER in str(result["input"][4]["output"])
assert len(result["input"]) == 5
@pytest.mark.asyncio
async def test_web_search_call_item_preserved_verbatim(self):
handler = OpenAIResponsesHandler()