Repository: pydantic/pydantic-ai
File: tests/test_agent.py (Python)

Code before:

class StringData(BaseModel):
    text: str

# This will have a name like "Result[StringData]" which needs sanitization
OutputType = [Result[StringData], Result[int]]
    '''

    mod = create_module(module_code)

    m = TestModel()
    agent = Agent(m, output_type=mod.OutputType)
    agent.run_sync('Hello')

    # The sanitizer should remove brackets from the generic type name
    assert m.last_model_request_parameters is not None
    assert m.last_model_request_parameters.output_tools is not None
    assert len(m.last_model_request_parameters.output_tools) == 2

    # Check that tool names don't contain brackets
    tool_names = [tool.name for tool in m.last_model_request_parameters.output_tools]
    for tool_name in tool_names:
        assert '[' not in tool_name, f"Tool name '{tool_name}' contains brackets"
        assert ']' not in tool_name, f"Tool name '{tool_name}' contains brackets"
        # Verify the name follows the pattern [a-zA-Z0-9_-]
        assert re.match(r'^[a-zA-Z0-9_-]+$', tool_name), f"Tool name '{tool_name}' contains invalid characters"


def test_output_type_with_two_descriptions():
    class MyOutput(BaseModel):
        """Description from docstring"""

        valid: bool

    m = TestModel()
    agent = Agent(m, output_type=ToolOutput(MyOutput, description='Description from ToolOutput'))
    result = agent.run_sync('Hello')
    assert result.output == snapshot(MyOutput(valid=False))
    assert m.last_model_request_parameters is not None
    assert m.last_model_request_parameters.output_tools == snapshot(
        [
            ToolDefinition(
                name='final_result',
                description='Description from ToolOutput. Description from docstring',
                parameters_json_schema={
                    'properties': {'valid': {'type': 'boolean'}},
                    'required': ['valid'],
                    'title': 'MyOutput',
                    'type': 'object',
                },
                kind='output',

Review comment (suggestion):
I'd like to add this (the snapshot will be filled in automatically when you run the test so that we see the names we ended up with.

```suggestion
    tool_names = [tool.name for tool in m.last_model_request_parameters.output_tools]
    assert tool_names == snapshot()
```

Code after:
    assert result.output == mod.Bar(b='b')
    assert got_tool_call_name == snapshot('final_result_Bar')


def test_output_type_generic_class_name_sanitization():
    """Test that generic class names with brackets are properly sanitized."""
    # This will have a name like "ResultGeneric[StringData]" which needs sanitization
    output_type = [ResultGeneric[StringData], ResultGeneric[int]]

    m = TestModel()
    agent = Agent(m, output_type=output_type)
    agent.run_sync('Hello')

    # The sanitizer should remove brackets from the generic type name
    assert m.last_model_request_parameters is not None
    assert m.last_model_request_parameters.output_tools is not None
    assert len(m.last_model_request_parameters.output_tools) == 2

    tool_names = [tool.name for tool in m.last_model_request_parameters.output_tools]
    assert tool_names == snapshot(['final_result_ResultGenericStringData', 'final_result_ResultGenericint'])


def test_output_type_with_two_descriptions():
    class MyOutput(BaseModel):
        """Description from docstring"""

        valid: bool

    m = TestModel()
    agent = Agent(m, output_type=ToolOutput(MyOutput, description='Description from ToolOutput'))
    result = agent.run_sync('Hello')
    assert result.output == snapshot(MyOutput(valid=False))
    assert m.last_model_request_parameters is not None
    assert m.last_model_request_parameters.output_tools == snapshot(
        [
            ToolDefinition(
                name='final_result',
                description='Description from ToolOutput. Description from docstring',
                parameters_json_schema={
                    'properties': {'valid': {'type': 'boolean'}},
                    'required': ['valid'],
                    'title': 'MyOutput',
                    'type': 'object',
                },
                kind='output',
            )
        ]
    )


def test_output_type_tool_output_union():