|
3 | 3 | import copy |
4 | 4 | import dataclasses |
5 | 5 | import json |
| 6 | +import logging |
6 | 7 | import time |
7 | 8 | from collections.abc import Callable |
8 | 9 | from typing import Any, cast |
|
11 | 12 | from pydantic import BaseModel |
12 | 13 | from typing_extensions import TypedDict |
13 | 14 |
|
| 15 | +import agents._debug as _debug |
14 | 16 | import agents.tool as tool_module |
15 | 17 | from agents import ( |
16 | 18 | Agent, |
@@ -780,6 +782,68 @@ def echo(value: str) -> str: |
780 | 782 | ) |
781 | 783 |
|
782 | 784 |
|
| 785 | +@pytest.mark.asyncio |
| 786 | +async def test_function_tool_bad_json_redacts_payload_when_dont_log_tool_data( |
| 787 | + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture |
| 788 | +) -> None: |
| 789 | + caplog.set_level(logging.DEBUG) |
| 790 | + monkeypatch.setattr(_debug, "DONT_LOG_TOOL_DATA", True) |
| 791 | + |
| 792 | + def echo(value: str) -> str: |
| 793 | + return value |
| 794 | + |
| 795 | + tool = function_tool(echo, name_override="echo_tool", failure_error_function=None) |
| 796 | + bad_json = '{"secret":"SECRET_TOKEN_123"' |
| 797 | + |
| 798 | + with pytest.raises(ModelBehaviorError) as exc_info: |
| 799 | + await tool.on_invoke_tool( |
| 800 | + ToolContext( |
| 801 | + None, |
| 802 | + tool_name="echo_tool", |
| 803 | + tool_call_id="1", |
| 804 | + tool_arguments=bad_json, |
| 805 | + ), |
| 806 | + bad_json, |
| 807 | + ) |
| 808 | + |
| 809 | + assert str(exc_info.value) == "Invalid JSON input for tool echo_tool" |
| 810 | + assert exc_info.value.__cause__ is None |
| 811 | + assert exc_info.value.__context__ is None |
| 812 | + assert "SECRET_TOKEN_123" not in str(exc_info.value) |
| 813 | + assert "SECRET_TOKEN_123" not in caplog.text |
| 814 | + |
| 815 | + |
| 816 | +@pytest.mark.asyncio |
| 817 | +async def test_function_tool_bad_json_includes_payload_when_tool_logging_enabled( |
| 818 | + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture |
| 819 | +) -> None: |
| 820 | + caplog.set_level(logging.DEBUG) |
| 821 | + monkeypatch.setattr(_debug, "DONT_LOG_TOOL_DATA", False) |
| 822 | + |
| 823 | + def echo(value: str) -> str: |
| 824 | + return value |
| 825 | + |
| 826 | + tool = function_tool(echo, name_override="echo_tool", failure_error_function=None) |
| 827 | + bad_json = '{"secret":"SECRET_TOKEN_123"' |
| 828 | + |
| 829 | + with pytest.raises(ModelBehaviorError) as exc_info: |
| 830 | + await tool.on_invoke_tool( |
| 831 | + ToolContext( |
| 832 | + None, |
| 833 | + tool_name="echo_tool", |
| 834 | + tool_call_id="1", |
| 835 | + tool_arguments=bad_json, |
| 836 | + ), |
| 837 | + bad_json, |
| 838 | + ) |
| 839 | + |
| 840 | + assert str(exc_info.value) == f"Invalid JSON input for tool echo_tool: {bad_json}" |
| 841 | + assert isinstance(exc_info.value.__cause__, json.JSONDecodeError) |
| 842 | + assert exc_info.value.__cause__.doc == bad_json |
| 843 | + assert "SECRET_TOKEN_123" in str(exc_info.value) |
| 844 | + assert "SECRET_TOKEN_123" in caplog.text |
| 845 | + |
| 846 | + |
783 | 847 | @pytest.mark.asyncio |
784 | 848 | async def test_default_failure_error_function_survives_deepcopy() -> None: |
785 | 849 | def boom() -> None: |
|
0 commit comments