mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Feat: Add finish_reason support to AgentResponse and AgentResponseUpdate (#5211)
* feat: add finish_reason support to AgentResponse and AgentResponseUpdate Add finish_reason field to AgentResponse and AgentResponseUpdate classes, propagate it through _process_update() and map_chat_to_agent_update(), and add comprehensive unit tests. Fixes #4622 * feat: add finish_reason to AgentResponse and AgentResponseUpdate * style: add copyright header to test_finish_reason.py * docs: add finish_reason to AgentResponse and AgentResponseUpdate docstrings * refactor: move finish_reason tests into test_types.py per review feedback Move all finish_reason test cases from the separate test_finish_reason.py file into test_types.py as requested by eavanvalkenburg. Tests are placed in a new '# region finish_reason' section at the end of the file. * fix: use model instead of model_id in _process_update Address PR review feedback from @eavanvalkenburg — ChatResponse and ChatResponseUpdate both use 'model', not 'model_id'. * fix: resolve SIM102 lint error in _process_update Combine nested if statements for AgentResponse finish_reason check to satisfy ruff SIM102 rule, with line wrapping to stay under 120 chars. * fix: resolve pyright reportArgumentType in map_chat_to_agent_update Add type: ignore[arg-type] for FinishReason NewType widening when passing ChatResponseUpdate.finish_reason to AgentResponseUpdate. Matches existing patterns in the codebase (40+ similar ignores).
This commit is contained in:
committed by
GitHub
Unverified
parent
90a633967c
commit
91e34358eb
@@ -40,8 +40,10 @@ from agent_framework._types import (
|
||||
_get_data_bytes_as_str,
|
||||
_parse_content_list,
|
||||
_parse_structured_response_value,
|
||||
_process_update,
|
||||
_validate_uri,
|
||||
add_usage_details,
|
||||
map_chat_to_agent_update,
|
||||
validate_tool_mode,
|
||||
)
|
||||
from agent_framework.exceptions import AdditionItemMismatch, ContentError
|
||||
@@ -4179,3 +4181,101 @@ def test_prepend_instructions_custom_role():
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
# region finish_reason
|
||||
|
||||
|
||||
def test_agent_response_init_with_finish_reason() -> None:
|
||||
"""Test that AgentResponse correctly initializes and stores finish_reason."""
|
||||
response = AgentResponse(
|
||||
messages=[Message("assistant", [Content.from_text("test")])],
|
||||
finish_reason="stop",
|
||||
)
|
||||
assert response.finish_reason == "stop"
|
||||
|
||||
|
||||
def test_agent_response_update_init_with_finish_reason() -> None:
|
||||
"""Test that AgentResponseUpdate correctly initializes and stores finish_reason."""
|
||||
update = AgentResponseUpdate(
|
||||
contents=[Content.from_text("test")],
|
||||
role="assistant",
|
||||
finish_reason="stop",
|
||||
)
|
||||
assert update.finish_reason == "stop"
|
||||
|
||||
|
||||
def test_map_chat_to_agent_update_forwards_finish_reason() -> None:
|
||||
"""Test that mapping a ChatResponseUpdate with finish_reason forwards it."""
|
||||
chat_update = ChatResponseUpdate(
|
||||
contents=[Content.from_text("test")],
|
||||
finish_reason="length",
|
||||
)
|
||||
agent_update = map_chat_to_agent_update(chat_update, agent_name="test_agent")
|
||||
|
||||
assert agent_update.finish_reason == "length"
|
||||
assert agent_update.author_name == "test_agent"
|
||||
|
||||
|
||||
def test_process_update_propagates_finish_reason_to_agent_response() -> None:
|
||||
"""Test that _process_update correctly updates an AgentResponse from an AgentResponseUpdate."""
|
||||
response = AgentResponse(messages=[Message("assistant", [Content.from_text("test")])])
|
||||
update = AgentResponseUpdate(
|
||||
contents=[Content.from_text("more text")],
|
||||
role="assistant",
|
||||
finish_reason="stop",
|
||||
)
|
||||
|
||||
# Process the update
|
||||
_process_update(response, update)
|
||||
|
||||
assert response.finish_reason == "stop"
|
||||
|
||||
|
||||
def test_process_update_does_not_overwrite_with_none() -> None:
|
||||
"""Test that _process_update does not overwrite an existing finish_reason with None."""
|
||||
response = AgentResponse(
|
||||
messages=[Message("assistant", [Content.from_text("test")])],
|
||||
finish_reason="length",
|
||||
)
|
||||
update = AgentResponseUpdate(
|
||||
contents=[Content.from_text("more text")],
|
||||
role="assistant",
|
||||
finish_reason=None,
|
||||
)
|
||||
|
||||
# Process the update
|
||||
_process_update(response, update)
|
||||
|
||||
assert response.finish_reason == "length"
|
||||
|
||||
|
||||
def test_agent_response_serialization_includes_finish_reason() -> None:
|
||||
"""Test that AgentResponse serializes correctly, including finish_reason."""
|
||||
response = AgentResponse(
|
||||
messages=[Message("assistant", [Content.from_text("test")])],
|
||||
response_id="test_123",
|
||||
finish_reason="stop",
|
||||
)
|
||||
|
||||
# Serialize using the framework's API and verify finish_reason is included.
|
||||
data = response.to_dict()
|
||||
assert "finish_reason" in data
|
||||
assert data["finish_reason"] == "stop"
|
||||
|
||||
|
||||
def test_agent_response_update_serialization_includes_finish_reason() -> None:
|
||||
"""Test that AgentResponseUpdate serializes correctly, including finish_reason."""
|
||||
update = AgentResponseUpdate(
|
||||
contents=[Content.from_text("test")],
|
||||
role="assistant",
|
||||
response_id="test_456",
|
||||
finish_reason="tool_calls",
|
||||
)
|
||||
|
||||
data = update.to_dict()
|
||||
assert "finish_reason" in data
|
||||
assert data["finish_reason"] == "tool_calls"
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user