diff --git a/litellm/litellm_core_utils/redact_messages.py b/litellm/litellm_core_utils/redact_messages.py index 1f9464a2a26..b409b181a79 100644 --- a/litellm/litellm_core_utils/redact_messages.py +++ b/litellm/litellm_core_utils/redact_messages.py @@ -128,6 +128,8 @@ def _redact_responses_api_output(output_items): for content_part in output_item.content: if getattr(content_part, "text", None) is not None: content_part.text = REDACTED_BY_LITELLM + if getattr(content_part, "refusal", None) is not None: + content_part.refusal = REDACTED_BY_LITELLM # Redact reasoning items in output array if hasattr(output_item, "type") and output_item.type == "reasoning": @@ -155,6 +157,8 @@ def _redact_responses_api_output_dict(output_items, redacted_str: str): for content_item in output_item["content"]: if isinstance(content_item, dict) and content_item.get("text") is not None: content_item["text"] = redacted_str + if isinstance(content_item, dict) and content_item.get("refusal") is not None: + content_item["refusal"] = redacted_str if output_item.get("type") == "reasoning" and isinstance(output_item.get("summary"), list): for summary_item in output_item["summary"]: diff --git a/tests/test_litellm/litellm_core_utils/test_redact_messages.py b/tests/test_litellm/litellm_core_utils/test_redact_messages.py index c6c9a9dd2b7..276a67e0bd4 100644 --- a/tests/test_litellm/litellm_core_utils/test_redact_messages.py +++ b/tests/test_litellm/litellm_core_utils/test_redact_messages.py @@ -507,6 +507,26 @@ class TestPerformRedaction: assert redacted["output"][0]["name"] == "grep" assert redacted["output"][1]["input"] == "not-a-custom-input" + def test_redacts_responses_api_refusal_parts_dict(self): + result = { + "output": [ + { + "type": "message", + "role": "assistant", + "content": [ + {"type": "refusal", "refusal": "I cannot share the secret"}, + {"type": "output_text", "text": "ok"}, + ], + } + ] + } + + redacted = perform_redaction({}, result) + + assert redacted["output"][0]["content"][0]["refusal"] == "redacted-by-litellm" + assert redacted["output"][0]["content"][0]["type"] == "refusal" + assert redacted["output"][0]["content"][1]["text"] == "redacted-by-litellm" + def test_redacts_every_tool_call_in_multi_element_list(self): result = litellm.ModelResponse( id="resp-multi", @@ -585,6 +605,15 @@ class TestPerformRedaction: assert output_item.input == "redacted-by-litellm" assert output_item.name == "grep" + def test_redacts_responses_api_refusal_parts_object(self): + refusal = SimpleNamespace(type="refusal", refusal="I cannot share the secret") + output_item = SimpleNamespace(type="message", role="assistant", content=[refusal]) + + _redact_responses_api_output([output_item]) + + assert refusal.refusal == "redacted-by-litellm" + assert refusal.type == "refusal" + def test_redacts_response_output_objects_with_top_level_text(self): output_items = [ SimpleNamespace(text="top-level output"),