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

Code before:
    # auto mode falls back to tags. We'll test this by creating a full message exchange.
    from pydantic_ai.messages import ModelRequest, ModelResponse, ThinkingPart, UserPromptPart

    # Create a model with auto mode
    c1 = completion_message(
        ChatCompletionMessage.model_construct(content='<think>fallback reasoning</think>response2', role='assistant')
    )
    m = OpenAIChatModel(
        'foobar',
        provider=OpenAIProvider(openai_client=MockOpenAI.create_mock(c1)),
        profile=OpenAIModelProfile(
            openai_chat_thinking_field='reasoning_content',
            openai_chat_send_back_thinking_parts='auto',
        ),
    )

    # Create a history with thinking from a different provider
    messages = [
        ModelRequest(parts=[UserPromptPart(content='question')]),
        ModelResponse(
            parts=[
                ThinkingPart(
                    content='reasoning from different provider',
                    id='reasoning_content',
                    provider_name='different-provider',
                ),
            ]
        ),
    ]

    # Make a request - the thinking should be sent back in tags since provider doesn't match
    settings = ModelSettings()
    params = ModelRequestParameters()
    await m.request(messages=messages, model_settings=settings, model_request_parameters=params)

    # The test passes if no exception is raised and the mock receives the correct format
    # (with tags, not in reasoning_content field)


async def test_openai_auto_mode_tags_sends_back_in_tags(allow_model_requests: None):
    """Test that auto mode detects reasoning from tags and sends back in tags."""
    c = completion_message(
        ChatCompletionMessage.model_construct(content='<think>reasoning</think>response', role='assistant')
    )
    m = OpenAIChatModel(
        'foobar',
        provider=OpenAIProvider(openai_client=MockOpenAI.create_mock(c)),
        profile=OpenAIModelProfile(openai_chat_send_back_thinking_parts='auto'),  # Auto mode, no thinking_field set
    )
    settings = ModelSettings()
    params = ModelRequestParameters()

Review comment (suggestion):
We should test what happens if:
- the mode is set to auto, but `thinking_field` is not set
- the field is set to `reasoning_content` and the mode is set to `auto`, but the reasoning actually comes in e.g `reasoning` (which is checked by default)

Code after:
    resp = await m.request(messages=[], model_settings=settings, model_request_parameters=params)
    assert m._map_model_response(resp) == snapshot(  # type: ignore[reportPrivateUsage]
        {
            'role': 'assistant',
            'content': """\
<think>
reasoning
</think>

response\
""",
        }
    )


async def test_openai_auto_mode_reasoning_field_sends_back_in_field(allow_model_requests: None):
    """Test that auto mode detects reasoning from field and sends back in field."""
    c = completion_message(
        ChatCompletionMessage.model_construct(content='response', reasoning_content='reasoning', role='assistant')
    )
    m = OpenAIChatModel(
        'foobar',
        provider=OpenAIProvider(openai_client=MockOpenAI.create_mock(c)),
        profile=OpenAIModelProfile(
            openai_chat_thinking_field='reasoning_content',
            openai_chat_send_back_thinking_parts='auto',  # Auto mode
        ),
    )
    settings = ModelSettings()
    params = ModelRequestParameters()
    resp = await m.request(messages=[], model_settings=settings, model_request_parameters=params)
    # Auto mode should detect thinking came from 'reasoning_content' field and send back in same field
    assert m._map_model_response(resp) == snapshot(  # type: ignore[reportPrivateUsage]
        {'role': 'assistant', 'reasoning_content': 'reasoning', 'content': 'response'}
    )


async def test_openai_auto_mode_reasoning_field_different_provider_uses_tags(allow_model_requests: None):
    """Test that auto mode falls back to tags when provider_name doesn't match."""
    # This test verifies behavior by checking that when thinking comes from a different provider, auto mode falls back to tags.
    c1 = completion_message(ChatCompletionMessage.model_construct(content='response2', role='assistant'))
    m = OpenAIChatModel(
        'foobar',
        provider=OpenAIProvider(openai_client=MockOpenAI.create_mock(c1)),
        profile=OpenAIModelProfile(
            openai_chat_thinking_field='reasoning_content',
            openai_chat_send_back_thinking_parts='auto',
        ),
    )

    messages = [