mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Types API Review improvements (#3647)
* Replace Role and FinishReason classes with NewType + Literal
- Remove EnumLike metaclass from _types.py
- Replace Role class with NewType('Role', str) + RoleLiteral
- Replace FinishReason class with NewType('FinishReason', str) + FinishReasonLiteral
- Update all usages across codebase to use string literals
- Remove .value access patterns (direct string comparison now works)
- Add backward compatibility for legacy dict serialization format
- Update tests to reflect new string-based types
Addresses #3591, #3615
* Simplify ChatResponse and AgentResponse type hints (#3592)
- Remove overloads from ChatResponse.__init__
- Remove text parameter from ChatResponse.__init__
- Remove | dict[str, Any] from finish_reason and usage_details params
- Remove **kwargs from AgentResponse.__init__
- Both now accept ChatMessage | Sequence[ChatMessage] | None for messages
- Update docstrings and examples to reflect changes
- Fix tests that were using removed kwargs
- Fix Role type hint usage in ag-ui utils
* Remove text parameter from ChatResponseUpdate and AgentResponseUpdate (#3597)
- Remove text parameter from ChatResponseUpdate.__init__
- Remove text parameter from AgentResponseUpdate.__init__
- Remove **kwargs from both update classes
- Simplify contents parameter type to Sequence[Content] | None
- Update all usages to use contents=[Content.from_text(...)] pattern
- Fix imports in test files
- Update docstrings and examples
* Rename from_chat_response_updates to from_updates (#3593)
- ChatResponse.from_chat_response_updates → ChatResponse.from_updates
- ChatResponse.from_chat_response_generator → ChatResponse.from_update_generator
- AgentResponse.from_agent_run_response_updates → AgentResponse.from_updates
* Remove try_parse_value method from ChatResponse and AgentResponse (#3595)
- Remove try_parse_value method from ChatResponse
- Remove try_parse_value method from AgentResponse
- Remove try_parse_value calls from from_updates and from_update_generator methods
- Update samples to use try/except with response.value instead
- Update tests to use response.value pattern
- Users should now use response.value with try/except for safe parsing
* Add agent_id to AgentResponse and clarify author_name documentation (#3596)
- Add agent_id parameter to AgentResponse class
- Document that author_name is on ChatMessage objects, not responses
- Update ChatResponse docstring with author_name note
- Update AgentResponse docstring with author_name note
* Simplify ChatMessage.__init__ signature (#3618)
- Make contents a positional argument accepting Sequence[Content | str]
- Auto-convert strings in contents to TextContent
- Remove overloads, keep text kwarg for backward compatibility with serialization
- Update _parse_content_list to handle string items
- Update all usages across codebase to use new format: ChatMessage("role", ["text"])
* Allow Content as input on run and get_response
- Update prepare_messages and normalize_messages to accept Content
- Update type signatures in _agents.py and _clients.py
- Add tests for Content input handling
* Fix ChatMessage usage across packages and samples
Update all remaining ChatMessage(role=..., text=...) to use new
ChatMessage('role', ['text']) signature.
* Fix Role string usage and response format parsing
- Fix redis provider: remove .value access on string literals
- Fix durabletask ensure_response_format: set _response_format before accessing .value
* Fix ollama .value and ai_model_id issues, handle None in content list
- Fix ollama _chat_client: remove .value on string literals
- Fix ollama _chat_client: rename ai_model_id to model_id
- Fix _parse_content_list: skip None values gracefully
* Fix A2AAgent type signature to include Content
* Fix Role/FinishReason NewType dict annotations and improve test coverage to 95%
* Fix mypy errors for Role/FinishReason NewType usage
* Fix Role.TOOL and Role.ASSISTANT usage in _orchestrator_helpers.py
* Fix Role NewType usage in durabletask _models.py
This commit is contained in:
@@ -22,7 +22,6 @@ from agent_framework import (
|
||||
Content,
|
||||
HostedCodeInterpreterTool,
|
||||
HostedFileSearchTool,
|
||||
Role,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.exceptions import ServiceInitializationError
|
||||
@@ -405,7 +404,7 @@ async def test_process_stream_events_thread_run_created(mock_async_openai: Magic
|
||||
update = updates[0]
|
||||
assert isinstance(update, ChatResponseUpdate)
|
||||
assert update.conversation_id == thread_id
|
||||
assert update.role == Role.ASSISTANT
|
||||
assert update.role == "assistant"
|
||||
assert update.contents == []
|
||||
assert update.raw_representation == mock_response.data
|
||||
|
||||
@@ -449,7 +448,7 @@ async def test_process_stream_events_message_delta_text(mock_async_openai: Magic
|
||||
update = updates[0]
|
||||
assert isinstance(update, ChatResponseUpdate)
|
||||
assert update.conversation_id == thread_id
|
||||
assert update.role == Role.ASSISTANT
|
||||
assert update.role == "assistant"
|
||||
assert update.text == "Hello from assistant"
|
||||
assert update.raw_representation == mock_message_delta
|
||||
|
||||
@@ -488,7 +487,7 @@ async def test_process_stream_events_requires_action(mock_async_openai: MagicMoc
|
||||
update = updates[0]
|
||||
assert isinstance(update, ChatResponseUpdate)
|
||||
assert update.conversation_id == thread_id
|
||||
assert update.role == Role.ASSISTANT
|
||||
assert update.role == "assistant"
|
||||
assert len(update.contents) == 1
|
||||
assert update.contents[0] == test_function_content
|
||||
assert update.raw_representation == mock_run
|
||||
@@ -568,7 +567,7 @@ async def test_process_stream_events_run_completed_with_usage(
|
||||
update = updates[0]
|
||||
assert isinstance(update, ChatResponseUpdate)
|
||||
assert update.conversation_id == thread_id
|
||||
assert update.role == Role.ASSISTANT
|
||||
assert update.role == "assistant"
|
||||
assert len(update.contents) == 1
|
||||
|
||||
# Check the usage content
|
||||
@@ -696,7 +695,7 @@ def test_prepare_options_basic(mock_async_openai: MagicMock) -> None:
|
||||
"top_p": 0.9,
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -725,7 +724,7 @@ def test_prepare_options_with_tool_tool(mock_async_openai: MagicMock) -> None:
|
||||
"tool_choice": "auto",
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -750,7 +749,7 @@ def test_prepare_options_with_code_interpreter(mock_async_openai: MagicMock) ->
|
||||
"tool_choice": "auto",
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Calculate something")]
|
||||
messages = [ChatMessage("user", ["Calculate something"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -770,7 +769,7 @@ def test_prepare_options_tool_choice_none(mock_async_openai: MagicMock) -> None:
|
||||
"tool_choice": "none",
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -791,7 +790,7 @@ def test_prepare_options_required_function(mock_async_openai: MagicMock) -> None
|
||||
"tool_choice": tool_choice,
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -817,7 +816,7 @@ def test_prepare_options_with_file_search_tool(mock_async_openai: MagicMock) ->
|
||||
"tool_choice": "auto",
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Search for information")]
|
||||
messages = [ChatMessage("user", ["Search for information"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -842,7 +841,7 @@ def test_prepare_options_with_mapping_tool(mock_async_openai: MagicMock) -> None
|
||||
"tool_choice": "auto",
|
||||
}
|
||||
|
||||
messages = [ChatMessage(role=Role.USER, text="Use custom tool")]
|
||||
messages = [ChatMessage("user", ["Use custom tool"])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -864,7 +863,7 @@ def test_prepare_options_with_pydantic_response_format(mock_async_openai: MagicM
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
chat_client = create_test_openai_assistants_client(mock_async_openai)
|
||||
messages = [ChatMessage(role=Role.USER, text="Test")]
|
||||
messages = [ChatMessage("user", ["Test"])]
|
||||
options = {"response_format": TestResponse}
|
||||
|
||||
run_options, _ = chat_client._prepare_options(messages, options) # type: ignore
|
||||
@@ -880,8 +879,8 @@ def test_prepare_options_with_system_message(mock_async_openai: MagicMock) -> No
|
||||
chat_client = create_test_openai_assistants_client(mock_async_openai)
|
||||
|
||||
messages = [
|
||||
ChatMessage(role=Role.SYSTEM, text="You are a helpful assistant."),
|
||||
ChatMessage(role=Role.USER, text="Hello"),
|
||||
ChatMessage("system", ["You are a helpful assistant."]),
|
||||
ChatMessage("user", ["Hello"]),
|
||||
]
|
||||
|
||||
# Call the method
|
||||
@@ -901,7 +900,7 @@ def test_prepare_options_with_image_content(mock_async_openai: MagicMock) -> Non
|
||||
|
||||
# Create message with image content
|
||||
image_content = Content.from_uri(uri="https://example.com/image.jpg", media_type="image/jpeg")
|
||||
messages = [ChatMessage(role=Role.USER, contents=[image_content])]
|
||||
messages = [ChatMessage("user", [image_content])]
|
||||
|
||||
# Call the method
|
||||
run_options, tool_results = chat_client._prepare_options(messages, {}) # type: ignore
|
||||
@@ -1021,7 +1020,7 @@ async def test_get_response() -> None:
|
||||
"It's a beautiful day for outdoor activities.",
|
||||
)
|
||||
)
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like today?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like today?"]))
|
||||
|
||||
# Test that the client can be used to get a response
|
||||
response = await openai_assistants_client.get_response(messages=messages)
|
||||
@@ -1039,7 +1038,7 @@ async def test_get_response_tools() -> None:
|
||||
assert isinstance(openai_assistants_client, ChatClientProtocol)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like in Seattle?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like in Seattle?"]))
|
||||
|
||||
# Test that the client can be used to get a response
|
||||
response = await openai_assistants_client.get_response(
|
||||
@@ -1067,7 +1066,7 @@ async def test_streaming() -> None:
|
||||
"It's a beautiful day for outdoor activities.",
|
||||
)
|
||||
)
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like today?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like today?"]))
|
||||
|
||||
# Test that the client can be used to get a response
|
||||
response = openai_assistants_client.get_streaming_response(messages=messages)
|
||||
@@ -1091,7 +1090,7 @@ async def test_streaming_tools() -> None:
|
||||
assert isinstance(openai_assistants_client, ChatClientProtocol)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like in Seattle?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like in Seattle?"]))
|
||||
|
||||
# Test that the client can be used to get a response
|
||||
response = openai_assistants_client.get_streaming_response(
|
||||
@@ -1119,7 +1118,7 @@ async def test_with_existing_assistant() -> None:
|
||||
# First create an assistant to use in the test
|
||||
async with OpenAIAssistantsClient(model_id=INTEGRATION_TEST_MODEL) as temp_client:
|
||||
# Get the assistant ID by triggering assistant creation
|
||||
messages = [ChatMessage(role="user", text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
await temp_client.get_response(messages=messages)
|
||||
assistant_id = temp_client.assistant_id
|
||||
|
||||
@@ -1130,7 +1129,7 @@ async def test_with_existing_assistant() -> None:
|
||||
assert isinstance(openai_assistants_client, ChatClientProtocol)
|
||||
assert openai_assistants_client.assistant_id == assistant_id
|
||||
|
||||
messages = [ChatMessage(role="user", text="What can you do?")]
|
||||
messages = [ChatMessage("user", ["What can you do?"])]
|
||||
|
||||
# Test that the client can be used to get a response
|
||||
response = await openai_assistants_client.get_response(messages=messages)
|
||||
@@ -1149,7 +1148,7 @@ async def test_file_search() -> None:
|
||||
assert isinstance(openai_assistants_client, ChatClientProtocol)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like today?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like today?"]))
|
||||
|
||||
file_id, vector_store = await create_vector_store(openai_assistants_client)
|
||||
response = await openai_assistants_client.get_response(
|
||||
@@ -1175,7 +1174,7 @@ async def test_file_search_streaming() -> None:
|
||||
assert isinstance(openai_assistants_client, ChatClientProtocol)
|
||||
|
||||
messages: list[ChatMessage] = []
|
||||
messages.append(ChatMessage(role="user", text="What's the weather like today?"))
|
||||
messages.append(ChatMessage("user", ["What's the weather like today?"]))
|
||||
|
||||
file_id, vector_store = await create_vector_store(openai_assistants_client)
|
||||
response = openai_assistants_client.get_streaming_response(
|
||||
|
||||
@@ -154,7 +154,7 @@ def test_serialize_with_org_id(openai_unit_test_env: dict[str, str]) -> None:
|
||||
async def test_content_filter_exception_handling(openai_unit_test_env: dict[str, str]) -> None:
|
||||
"""Test that content filter errors are properly handled."""
|
||||
client = OpenAIChatClient()
|
||||
messages = [ChatMessage(role="user", text="test message")]
|
||||
messages = [ChatMessage("user", ["test message"])]
|
||||
|
||||
# Create a mock BadRequestError with content_filter code
|
||||
mock_response = MagicMock()
|
||||
@@ -209,7 +209,7 @@ def get_weather(location: str) -> str:
|
||||
async def test_exception_message_includes_original_error_details() -> None:
|
||||
"""Test that exception messages include original error details in the new format."""
|
||||
client = OpenAIChatClient(model_id="test-model", api_key="test-key")
|
||||
messages = [ChatMessage(role="user", text="test message")]
|
||||
messages = [ChatMessage("user", ["test message"])]
|
||||
|
||||
mock_response = MagicMock()
|
||||
original_error_message = "Invalid API request format"
|
||||
@@ -652,12 +652,12 @@ def test_function_approval_content_is_skipped_in_preparation(openai_unit_test_en
|
||||
)
|
||||
|
||||
# Test that approval request is skipped
|
||||
message_with_request = ChatMessage(role="assistant", contents=[approval_request])
|
||||
message_with_request = ChatMessage("assistant", [approval_request])
|
||||
prepared_request = client._prepare_message_for_openai(message_with_request)
|
||||
assert len(prepared_request) == 0 # Should be empty - approval content is skipped
|
||||
|
||||
# Test that approval response is skipped
|
||||
message_with_response = ChatMessage(role="user", contents=[approval_response])
|
||||
message_with_response = ChatMessage("user", [approval_response])
|
||||
prepared_response = client._prepare_message_for_openai(message_with_response)
|
||||
assert len(prepared_response) == 0 # Should be empty - approval content is skipped
|
||||
|
||||
@@ -752,7 +752,7 @@ def test_prepare_options_without_model_id(openai_unit_test_env: dict[str, str])
|
||||
client = OpenAIChatClient()
|
||||
client.model_id = None # Remove model_id
|
||||
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
messages = [ChatMessage("user", ["test"])]
|
||||
|
||||
with pytest.raises(ValueError, match="model_id must be a non-empty string"):
|
||||
client._prepare_options(messages, {})
|
||||
@@ -786,7 +786,7 @@ def test_prepare_options_with_instructions(openai_unit_test_env: dict[str, str])
|
||||
"""Test that instructions are prepended as system message."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
messages = [ChatMessage(role="user", text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
options = {"instructions": "You are a helpful assistant."}
|
||||
|
||||
prepared_options = client._prepare_options(messages, options)
|
||||
@@ -836,7 +836,7 @@ def test_tool_choice_required_with_function_name(openai_unit_test_env: dict[str,
|
||||
"""Test that tool_choice with required mode and function name is correctly prepared."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
messages = [ChatMessage("user", ["test"])]
|
||||
options = {
|
||||
"tools": [get_weather],
|
||||
"tool_choice": {"mode": "required", "required_function_name": "get_weather"},
|
||||
@@ -854,7 +854,7 @@ def test_response_format_dict_passthrough(openai_unit_test_env: dict[str, str])
|
||||
"""Test that response_format as dict is passed through directly."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
messages = [ChatMessage("user", ["test"])]
|
||||
custom_format = {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"name": "Test", "schema": {"type": "object"}},
|
||||
@@ -894,7 +894,7 @@ def test_prepare_options_removes_parallel_tool_calls_when_no_tools(openai_unit_t
|
||||
"""Test that parallel_tool_calls is removed when no tools are present."""
|
||||
client = OpenAIChatClient()
|
||||
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
messages = [ChatMessage("user", ["test"])]
|
||||
options = {"allow_multiple_tool_calls": True}
|
||||
|
||||
prepared_options = client._prepare_options(messages, options)
|
||||
@@ -906,7 +906,7 @@ def test_prepare_options_removes_parallel_tool_calls_when_no_tools(openai_unit_t
|
||||
async def test_streaming_exception_handling(openai_unit_test_env: dict[str, str]) -> None:
|
||||
"""Test that streaming errors are properly handled."""
|
||||
client = OpenAIChatClient()
|
||||
messages = [ChatMessage(role="user", text="test")]
|
||||
messages = [ChatMessage("user", ["test"])]
|
||||
|
||||
# Create a mock error during streaming
|
||||
mock_error = Exception("Streaming error")
|
||||
@@ -1008,14 +1008,14 @@ async def test_integration_options(
|
||||
# Prepare test message
|
||||
if option_name.startswith("tools") or option_name.startswith("tool_choice"):
|
||||
# Use weather-related prompt for tool tests
|
||||
messages = [ChatMessage(role="user", text="What is the weather in Seattle?")]
|
||||
messages = [ChatMessage("user", ["What is the weather in Seattle?"])]
|
||||
elif option_name.startswith("response_format"):
|
||||
# Use prompt that works well with structured output
|
||||
messages = [ChatMessage(role="user", text="The weather in Seattle is sunny")]
|
||||
messages.append(ChatMessage(role="user", text="What is the weather in Seattle?"))
|
||||
messages = [ChatMessage("user", ["The weather in Seattle is sunny"])]
|
||||
messages.append(ChatMessage("user", ["What is the weather in Seattle?"]))
|
||||
else:
|
||||
# Generic prompt for simple options
|
||||
messages = [ChatMessage(role="user", text="Say 'Hello World' briefly.")]
|
||||
messages = [ChatMessage("user", ["Say 'Hello World' briefly."])]
|
||||
|
||||
# Build options dict
|
||||
options: dict[str, Any] = {option_name: option_value}
|
||||
@@ -1032,7 +1032,7 @@ async def test_integration_options(
|
||||
)
|
||||
|
||||
output_format = option_value if option_name.startswith("response_format") else None
|
||||
response = await ChatResponse.from_chat_response_generator(response_gen, output_format_type=output_format)
|
||||
response = await ChatResponse.from_update_generator(response_gen, output_format_type=output_format)
|
||||
else:
|
||||
# Test non-streaming mode
|
||||
response = await client.get_response(
|
||||
@@ -1080,7 +1080,7 @@ async def test_integration_web_search() -> None:
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
response = await ChatResponse.from_chat_response_generator(client.get_streaming_response(**content))
|
||||
response = await ChatResponse.from_update_generator(client.get_streaming_response(**content))
|
||||
else:
|
||||
response = await client.get_response(**content)
|
||||
|
||||
@@ -1105,7 +1105,7 @@ async def test_integration_web_search() -> None:
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
response = await ChatResponse.from_chat_response_generator(client.get_streaming_response(**content))
|
||||
response = await ChatResponse.from_update_generator(client.get_streaming_response(**content))
|
||||
else:
|
||||
response = await client.get_response(**content)
|
||||
assert response.text is not None
|
||||
|
||||
@@ -69,7 +69,7 @@ async def test_cmc(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
await openai_chat_completion.get_response(messages=chat_history)
|
||||
@@ -88,7 +88,7 @@ async def test_cmc_chat_options(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
await openai_chat_completion.get_response(
|
||||
@@ -109,7 +109,7 @@ async def test_cmc_no_fcc_in_response(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
orig_chat_history = deepcopy(chat_history)
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
@@ -131,7 +131,7 @@ async def test_cmc_structured_output_no_fcc(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
# Define a mock response format
|
||||
class Test(BaseModel):
|
||||
@@ -153,7 +153,7 @@ async def test_scmc_chat_options(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_streaming_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
async for msg in openai_chat_completion.get_streaming_response(
|
||||
@@ -178,7 +178,7 @@ async def test_cmc_general_exception(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
with pytest.raises(ServiceResponseException):
|
||||
@@ -195,7 +195,7 @@ async def test_cmc_additional_properties(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
await openai_chat_completion.get_response(messages=chat_history, options={"reasoning_effort": "low"})
|
||||
@@ -233,7 +233,7 @@ async def test_get_streaming(
|
||||
stream = MagicMock(spec=AsyncStream)
|
||||
stream.__aiter__.return_value = [content1, content2]
|
||||
mock_create.return_value = stream
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
orig_chat_history = deepcopy(chat_history)
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
@@ -272,7 +272,7 @@ async def test_get_streaming_singular(
|
||||
stream = MagicMock(spec=AsyncStream)
|
||||
stream.__aiter__.return_value = [content1, content2]
|
||||
mock_create.return_value = stream
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
orig_chat_history = deepcopy(chat_history)
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
@@ -311,7 +311,7 @@ async def test_get_streaming_structured_output_no_fcc(
|
||||
stream = MagicMock(spec=AsyncStream)
|
||||
stream.__aiter__.return_value = [content1, content2]
|
||||
mock_create.return_value = stream
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
# Define a mock response format
|
||||
class Test(BaseModel):
|
||||
@@ -334,7 +334,7 @@ async def test_get_streaming_no_fcc_in_response(
|
||||
openai_unit_test_env: dict[str, str],
|
||||
):
|
||||
mock_create.return_value = mock_streaming_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
orig_chat_history = deepcopy(chat_history)
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
@@ -360,7 +360,7 @@ async def test_get_streaming_no_stream(
|
||||
mock_chat_completion_response: ChatCompletion, # AsyncStream[ChatCompletionChunk]?
|
||||
):
|
||||
mock_create.return_value = mock_chat_completion_response
|
||||
chat_history.append(ChatMessage(role="user", text="hello world"))
|
||||
chat_history.append(ChatMessage("user", ["hello world"]))
|
||||
|
||||
openai_chat_completion = OpenAIChatClient()
|
||||
with pytest.raises(ServiceResponseException):
|
||||
|
||||
@@ -39,7 +39,6 @@ from agent_framework import (
|
||||
HostedImageGenerationTool,
|
||||
HostedMCPTool,
|
||||
HostedWebSearchTool,
|
||||
Role,
|
||||
tool,
|
||||
)
|
||||
from agent_framework.exceptions import (
|
||||
@@ -215,7 +214,7 @@ def test_get_response_with_all_parameters() -> None:
|
||||
with pytest.raises(ServiceResponseException):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Test message")],
|
||||
messages=[ChatMessage("user", ["Test message"])],
|
||||
options={
|
||||
"include": ["message.output_text.logprobs"],
|
||||
"instructions": "You are a helpful assistant",
|
||||
@@ -261,7 +260,7 @@ def test_web_search_tool_with_location() -> None:
|
||||
with pytest.raises(ServiceResponseException):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="What's the weather?")],
|
||||
messages=[ChatMessage("user", ["What's the weather?"])],
|
||||
options={"tools": [web_search_tool], "tool_choice": "auto"},
|
||||
)
|
||||
)
|
||||
@@ -278,7 +277,7 @@ def test_file_search_tool_with_invalid_inputs() -> None:
|
||||
with pytest.raises(ValueError, match="HostedFileSearchTool requires inputs to be of type"):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Search files")],
|
||||
messages=[ChatMessage("user", ["Search files"])],
|
||||
options={"tools": [file_search_tool]},
|
||||
)
|
||||
)
|
||||
@@ -294,7 +293,7 @@ def test_code_interpreter_tool_variations() -> None:
|
||||
with pytest.raises(ServiceResponseException):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Run some code")],
|
||||
messages=[ChatMessage("user", ["Run some code"])],
|
||||
options={"tools": [code_tool_empty]},
|
||||
)
|
||||
)
|
||||
@@ -307,7 +306,7 @@ def test_code_interpreter_tool_variations() -> None:
|
||||
with pytest.raises(ServiceResponseException):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Process these files")],
|
||||
messages=[ChatMessage("user", ["Process these files"])],
|
||||
options={"tools": [code_tool_with_files]},
|
||||
)
|
||||
)
|
||||
@@ -327,7 +326,7 @@ def test_content_filter_exception() -> None:
|
||||
|
||||
with patch.object(client.client.responses, "create", side_effect=mock_error):
|
||||
with pytest.raises(OpenAIContentFilterException) as exc_info:
|
||||
asyncio.run(client.get_response(messages=[ChatMessage(role="user", text="Test message")]))
|
||||
asyncio.run(client.get_response(messages=[ChatMessage("user", ["Test message"])]))
|
||||
|
||||
assert "content error" in str(exc_info.value)
|
||||
|
||||
@@ -343,7 +342,7 @@ def test_hosted_file_search_tool_validation() -> None:
|
||||
with pytest.raises((ValueError, ServiceInvalidRequestError)):
|
||||
asyncio.run(
|
||||
client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Test")],
|
||||
messages=[ChatMessage("user", ["Test"])],
|
||||
options={"tools": [empty_file_search_tool]},
|
||||
)
|
||||
)
|
||||
@@ -364,9 +363,9 @@ def test_chat_message_parsing_with_function_calls() -> None:
|
||||
function_result = Content.from_function_result(call_id="test-call-id", result="Function executed successfully")
|
||||
|
||||
messages = [
|
||||
ChatMessage(role="user", text="Call a function"),
|
||||
ChatMessage(role="assistant", contents=[function_call]),
|
||||
ChatMessage(role="tool", contents=[function_result]),
|
||||
ChatMessage("user", ["Call a function"]),
|
||||
ChatMessage("assistant", [function_call]),
|
||||
ChatMessage("tool", [function_result]),
|
||||
]
|
||||
|
||||
# This should exercise the message parsing logic - will fail due to invalid API key
|
||||
@@ -392,7 +391,7 @@ async def test_response_format_parse_path() -> None:
|
||||
|
||||
with patch.object(client.client.responses, "parse", return_value=mock_parsed_response):
|
||||
response = await client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Test message")],
|
||||
messages=[ChatMessage("user", ["Test message"])],
|
||||
options={"response_format": OutputStruct, "store": True},
|
||||
)
|
||||
assert response.response_id == "parsed_response_123"
|
||||
@@ -419,7 +418,7 @@ async def test_response_format_parse_path_with_conversation_id() -> None:
|
||||
|
||||
with patch.object(client.client.responses, "parse", return_value=mock_parsed_response):
|
||||
response = await client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Test message")],
|
||||
messages=[ChatMessage("user", ["Test message"])],
|
||||
options={"response_format": OutputStruct, "store": True},
|
||||
)
|
||||
assert response.response_id == "parsed_response_123"
|
||||
@@ -442,7 +441,7 @@ async def test_bad_request_error_non_content_filter() -> None:
|
||||
with patch.object(client.client.responses, "parse", side_effect=mock_error):
|
||||
with pytest.raises(ServiceResponseException) as exc_info:
|
||||
await client.get_response(
|
||||
messages=[ChatMessage(role="user", text="Test message")],
|
||||
messages=[ChatMessage("user", ["Test message"])],
|
||||
options={"response_format": OutputStruct},
|
||||
)
|
||||
|
||||
@@ -463,7 +462,7 @@ async def test_streaming_content_filter_exception_handling() -> None:
|
||||
mock_create.side_effect.code = "content_filter"
|
||||
|
||||
with pytest.raises(OpenAIContentFilterException, match="service encountered a content error"):
|
||||
response_stream = client.get_streaming_response(messages=[ChatMessage(role="user", text="Test")])
|
||||
response_stream = client.get_streaming_response(messages=[ChatMessage("user", ["Test"])])
|
||||
async for _ in response_stream:
|
||||
break
|
||||
|
||||
@@ -658,7 +657,7 @@ def test_prepare_content_for_opentool_approval_response() -> None:
|
||||
function_call=function_call,
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, approval_response, {})
|
||||
result = client._prepare_content_for_openai("assistant", approval_response, {})
|
||||
|
||||
assert result["type"] == "mcp_approval_response"
|
||||
assert result["approval_request_id"] == "approval_001"
|
||||
@@ -675,7 +674,7 @@ def test_prepare_content_for_openai_error_content() -> None:
|
||||
error_details="Invalid parameter",
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, error_content, {})
|
||||
result = client._prepare_content_for_openai("assistant", error_content, {})
|
||||
|
||||
# ErrorContent should return empty dict (logged but not sent)
|
||||
assert result == {}
|
||||
@@ -693,7 +692,7 @@ def test_prepare_content_for_openai_usage_content() -> None:
|
||||
}
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, usage_content, {})
|
||||
result = client._prepare_content_for_openai("assistant", usage_content, {})
|
||||
|
||||
# UsageContent should return empty dict (logged but not sent)
|
||||
assert result == {}
|
||||
@@ -707,7 +706,7 @@ def test_prepare_content_for_openai_hosted_vector_store_content() -> None:
|
||||
vector_store_id="vs_123",
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, vector_store_content, {})
|
||||
result = client._prepare_content_for_openai("assistant", vector_store_content, {})
|
||||
|
||||
# HostedVectorStoreContent should return empty dict (logged but not sent)
|
||||
assert result == {}
|
||||
@@ -807,7 +806,7 @@ def test_prepare_message_for_openai_with_function_approval_response() -> None:
|
||||
function_call=function_call,
|
||||
)
|
||||
|
||||
message = ChatMessage(role="user", contents=[approval_response])
|
||||
message = ChatMessage("user", [approval_response])
|
||||
call_id_to_id: dict[str, str] = {}
|
||||
|
||||
result = client._prepare_message_for_openai(message, call_id_to_id)
|
||||
@@ -829,7 +828,7 @@ def test_chat_message_with_error_content() -> None:
|
||||
error_code="TEST_ERR",
|
||||
)
|
||||
|
||||
message = ChatMessage(role="assistant", contents=[error_content])
|
||||
message = ChatMessage("assistant", [error_content])
|
||||
call_id_to_id: dict[str, str] = {}
|
||||
|
||||
result = client._prepare_message_for_openai(message, call_id_to_id)
|
||||
@@ -854,7 +853,7 @@ def test_chat_message_with_usage_content() -> None:
|
||||
}
|
||||
)
|
||||
|
||||
message = ChatMessage(role="assistant", contents=[usage_content])
|
||||
message = ChatMessage("assistant", [usage_content])
|
||||
call_id_to_id: dict[str, str] = {}
|
||||
|
||||
result = client._prepare_message_for_openai(message, call_id_to_id)
|
||||
@@ -877,7 +876,7 @@ def test_hosted_file_content_preparation() -> None:
|
||||
name="document.pdf",
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.USER, hosted_file, {})
|
||||
result = client._prepare_content_for_openai("user", hosted_file, {})
|
||||
|
||||
assert result["type"] == "input_file"
|
||||
assert result["file_id"] == "file_abc123"
|
||||
@@ -900,7 +899,7 @@ def test_function_approval_response_with_mcp_tool_call() -> None:
|
||||
function_call=mcp_call,
|
||||
)
|
||||
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, approval_response, {})
|
||||
result = client._prepare_content_for_openai("assistant", approval_response, {})
|
||||
|
||||
assert result["type"] == "mcp_approval_response"
|
||||
assert result["approval_request_id"] == "approval_mcp_001"
|
||||
@@ -1358,14 +1357,14 @@ async def test_end_to_end_mcp_approval_flow(span_exporter) -> None:
|
||||
# Patch the create call to return the two mocked responses in sequence
|
||||
with patch.object(client.client.responses, "create", side_effect=[mock_response1, mock_response2]) as mock_create:
|
||||
# First call: get the approval request
|
||||
response = await client.get_response(messages=[ChatMessage(role="user", text="Trigger approval")])
|
||||
response = await client.get_response(messages=[ChatMessage("user", ["Trigger approval"])])
|
||||
assert response.messages[0].contents[0].type == "function_approval_request"
|
||||
req = response.messages[0].contents[0]
|
||||
assert req.id == "approval-1"
|
||||
|
||||
# Build a user approval and send it (include required function_call)
|
||||
approval = Content.from_function_approval_response(approved=True, id=req.id, function_call=req.function_call)
|
||||
approval_message = ChatMessage(role="user", contents=[approval])
|
||||
approval_message = ChatMessage("user", [approval])
|
||||
_ = await client.get_response(messages=[approval_message])
|
||||
|
||||
# Ensure two calls were made and the second includes the mcp_approval_response
|
||||
@@ -1469,7 +1468,7 @@ def test_streaming_response_basic_structure() -> None:
|
||||
|
||||
# Should get a valid ChatResponseUpdate structure
|
||||
assert isinstance(response, ChatResponseUpdate)
|
||||
assert response.role == Role.ASSISTANT
|
||||
assert response.role == "assistant"
|
||||
assert response.model_id == "test-model"
|
||||
assert isinstance(response.contents, list)
|
||||
assert response.raw_representation is mock_event
|
||||
@@ -1620,7 +1619,7 @@ def test_streaming_annotation_added_with_unknown_type() -> None:
|
||||
def test_service_response_exception_includes_original_error_details() -> None:
|
||||
"""Test that ServiceResponseException messages include original error details in the new format."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
messages = [ChatMessage(role="user", text="test message")]
|
||||
messages = [ChatMessage("user", ["test message"])]
|
||||
|
||||
mock_response = MagicMock()
|
||||
original_error_message = "Request rate limit exceeded"
|
||||
@@ -1645,7 +1644,7 @@ def test_service_response_exception_includes_original_error_details() -> None:
|
||||
def test_get_streaming_response_with_response_format() -> None:
|
||||
"""Test get_streaming_response with response_format."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
messages = [ChatMessage(role="user", text="Test streaming with format")]
|
||||
messages = [ChatMessage("user", ["Test streaming with format"])]
|
||||
|
||||
# It will fail due to invalid API key, but exercises the code path
|
||||
with pytest.raises(ServiceResponseException):
|
||||
@@ -1667,7 +1666,7 @@ def test_prepare_content_for_openai_image_content() -> None:
|
||||
media_type="image/jpeg",
|
||||
additional_properties={"detail": "high", "file_id": "file_123"},
|
||||
)
|
||||
result = client._prepare_content_for_openai(Role.USER, image_content_with_detail, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", image_content_with_detail, {}) # type: ignore
|
||||
assert result["type"] == "input_image"
|
||||
assert result["image_url"] == "https://example.com/image.jpg"
|
||||
assert result["detail"] == "high"
|
||||
@@ -1675,7 +1674,7 @@ def test_prepare_content_for_openai_image_content() -> None:
|
||||
|
||||
# Test image content without additional properties (defaults)
|
||||
image_content_basic = Content.from_uri(uri="https://example.com/basic.png", media_type="image/png")
|
||||
result = client._prepare_content_for_openai(Role.USER, image_content_basic, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", image_content_basic, {}) # type: ignore
|
||||
assert result["type"] == "input_image"
|
||||
assert result["detail"] == "auto"
|
||||
assert result["file_id"] is None
|
||||
@@ -1687,14 +1686,14 @@ def test_prepare_content_for_openai_audio_content() -> None:
|
||||
|
||||
# Test WAV audio content
|
||||
wav_content = Content.from_uri(uri="data:audio/wav;base64,abc123", media_type="audio/wav")
|
||||
result = client._prepare_content_for_openai(Role.USER, wav_content, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", wav_content, {}) # type: ignore
|
||||
assert result["type"] == "input_audio"
|
||||
assert result["input_audio"]["data"] == "data:audio/wav;base64,abc123"
|
||||
assert result["input_audio"]["format"] == "wav"
|
||||
|
||||
# Test MP3 audio content
|
||||
mp3_content = Content.from_uri(uri="data:audio/mp3;base64,def456", media_type="audio/mp3")
|
||||
result = client._prepare_content_for_openai(Role.USER, mp3_content, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", mp3_content, {}) # type: ignore
|
||||
assert result["type"] == "input_audio"
|
||||
assert result["input_audio"]["format"] == "mp3"
|
||||
|
||||
@@ -1705,12 +1704,12 @@ def test_prepare_content_for_openai_unsupported_content() -> None:
|
||||
|
||||
# Test unsupported audio format
|
||||
unsupported_audio = Content.from_uri(uri="data:audio/ogg;base64,ghi789", media_type="audio/ogg")
|
||||
result = client._prepare_content_for_openai(Role.USER, unsupported_audio, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", unsupported_audio, {}) # type: ignore
|
||||
assert result == {}
|
||||
|
||||
# Test non-media content
|
||||
text_uri_content = Content.from_uri(uri="https://example.com/document.txt", media_type="text/plain")
|
||||
result = client._prepare_content_for_openai(Role.USER, text_uri_content, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("user", text_uri_content, {}) # type: ignore
|
||||
assert result == {}
|
||||
|
||||
|
||||
@@ -1775,7 +1774,7 @@ def test_prepare_content_for_openai_text_reasoning_comprehensive() -> None:
|
||||
"encrypted_content": "secure_data_456",
|
||||
},
|
||||
)
|
||||
result = client._prepare_content_for_openai(Role.ASSISTANT, comprehensive_reasoning, {}) # type: ignore
|
||||
result = client._prepare_content_for_openai("assistant", comprehensive_reasoning, {}) # type: ignore
|
||||
assert result["type"] == "reasoning"
|
||||
assert result["summary"]["text"] == "Comprehensive reasoning summary"
|
||||
assert result["status"] == "in_progress"
|
||||
@@ -2091,7 +2090,7 @@ def test_parse_response_from_openai_image_generation_fallback():
|
||||
|
||||
async def test_prepare_options_store_parameter_handling() -> None:
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
messages = [ChatMessage(role="user", text="Test message")]
|
||||
messages = [ChatMessage("user", ["Test message"])]
|
||||
|
||||
test_conversation_id = "test-conversation-123"
|
||||
chat_options = ChatOptions(store=True, conversation_id=test_conversation_id)
|
||||
@@ -2117,7 +2116,7 @@ async def test_prepare_options_store_parameter_handling() -> None:
|
||||
async def test_conversation_id_precedence_kwargs_over_options() -> None:
|
||||
"""When both kwargs and options contain conversation_id, kwargs wins."""
|
||||
client = OpenAIResponsesClient(model_id="test-model", api_key="test-key")
|
||||
messages = [ChatMessage(role="user", text="Hello")]
|
||||
messages = [ChatMessage("user", ["Hello"])]
|
||||
|
||||
# options has a stale response id, kwargs carries the freshest one
|
||||
opts = {"conversation_id": "resp_old_123"}
|
||||
@@ -2224,14 +2223,14 @@ async def test_integration_options(
|
||||
# Prepare test message
|
||||
if option_name.startswith("tools") or option_name.startswith("tool_choice"):
|
||||
# Use weather-related prompt for tool tests
|
||||
messages = [ChatMessage(role="user", text="What is the weather in Seattle?")]
|
||||
messages = [ChatMessage("user", ["What is the weather in Seattle?"])]
|
||||
elif option_name.startswith("response_format"):
|
||||
# Use prompt that works well with structured output
|
||||
messages = [ChatMessage(role="user", text="The weather in Seattle is sunny")]
|
||||
messages.append(ChatMessage(role="user", text="What is the weather in Seattle?"))
|
||||
messages = [ChatMessage("user", ["The weather in Seattle is sunny"])]
|
||||
messages.append(ChatMessage("user", ["What is the weather in Seattle?"]))
|
||||
else:
|
||||
# Generic prompt for simple options
|
||||
messages = [ChatMessage(role="user", text="Say 'Hello World' briefly.")]
|
||||
messages = [ChatMessage("user", ["Say 'Hello World' briefly."])]
|
||||
|
||||
# Build options dict
|
||||
options: dict[str, Any] = {option_name: option_value}
|
||||
@@ -2248,7 +2247,7 @@ async def test_integration_options(
|
||||
)
|
||||
|
||||
output_format = option_value if option_name.startswith("response_format") else None
|
||||
response = await ChatResponse.from_chat_response_generator(response_gen, output_format_type=output_format)
|
||||
response = await ChatResponse.from_update_generator(response_gen, output_format_type=output_format)
|
||||
else:
|
||||
# Test non-streaming mode
|
||||
response = await openai_responses_client.get_response(
|
||||
@@ -2296,7 +2295,7 @@ async def test_integration_web_search() -> None:
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
response = await ChatResponse.from_chat_response_generator(client.get_streaming_response(**content))
|
||||
response = await ChatResponse.from_update_generator(client.get_streaming_response(**content))
|
||||
else:
|
||||
response = await client.get_response(**content)
|
||||
|
||||
@@ -2321,7 +2320,7 @@ async def test_integration_web_search() -> None:
|
||||
},
|
||||
}
|
||||
if streaming:
|
||||
response = await ChatResponse.from_chat_response_generator(client.get_streaming_response(**content))
|
||||
response = await ChatResponse.from_update_generator(client.get_streaming_response(**content))
|
||||
else:
|
||||
response = await client.get_response(**content)
|
||||
assert response.text is not None
|
||||
|
||||
Reference in New Issue
Block a user