mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] Simplify API: ChatAgent -> Agent, ChatMessage -> Message (#3747)
* [BREAKING] Rename ChatAgent -> Agent, ChatMessage -> Message, ChatClientProtocol -> SupportsChatGetResponse Simplify the public API by removing redundant 'Chat' prefix from core types: - ChatAgent -> Agent - RawChatAgent -> RawAgent - ChatMessage -> Message - ChatClientProtocol -> SupportsChatGetResponse Also renamed internal WorkflowMessage (was Message in _runner_context) to avoid collision. No backward compatibility aliases - this is a clean breaking change. * [BREAKING] Rename Agent chat_client parameter to client * Fix rebase issues: WorkflowMessage references and broken markdown links * Fix formatting and lint issues from code quality checks * Fix import ordering in workflow sample files * fixed rebase * Fix test failures: use WorkflowMessage and A2AMessage after ChatMessage→Message rename - Replace Message(data=..., source_id=...) with WorkflowMessage(...) in workflow tests - Fix isinstance check in A2A agent to use A2AMessage instead of Message - Fix import in test_workflow_observability.py (Message→WorkflowMessage) * Fix lint, fmt, and sample errors after ChatMessage→Message rename - Auto-fix 70+ ruff lint issues across samples (ChatMessage→Message refs) - Fix HostedVectorStoreContent→Content.from_hosted_vector_store in file search sample - Fix _normalize_messages→normalize_messages in custom agent sample - Fix context.terminate→raise MiddlewareTermination in middleware samples - Fix with_update_hook→with_transform_hook in override middleware sample - Add TOptions_co import back to custom_chat_client sample - Add noqa for FastAPI File() default in chatkit sample - Fix B023 loop variable capture in weather agent sample * fix: update Agent constructor calls from chat_client to client in declaration-only tool tests * fix: add register_cleanup to devui lazy-loading proxy and type stub * fixed tests and updated new pieces * fix agui typevar * fix merge errors * fix merge conflicts * fiux merge * Remove unused links --------- Co-authored-by: Evan Mattson <evan.mattson@microsoft.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
a4c9e43afb
commit
0521f5bed8
@@ -13,13 +13,13 @@ from agent_framework import (
|
||||
AgentResponseUpdate,
|
||||
AgentThread,
|
||||
BaseChatClient,
|
||||
ChatClientProtocol,
|
||||
ChatMessage,
|
||||
ChatOptions,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
Message,
|
||||
SupportsAgentRun,
|
||||
SupportsChatGetResponse,
|
||||
)
|
||||
from agent_framework._clients import OptionsCoT
|
||||
from agent_framework._middleware import ChatMiddlewareLayer
|
||||
@@ -43,7 +43,7 @@ class StreamingChatClientStub(
|
||||
BaseChatClient[OptionsCoT],
|
||||
Generic[OptionsCoT],
|
||||
):
|
||||
"""Typed streaming stub that satisfies ChatClientProtocol."""
|
||||
"""Typed streaming stub that satisfies SupportsChatGetResponse."""
|
||||
|
||||
def __init__(self, stream_fn: StreamFn, response_fn: ResponseFn | None = None) -> None:
|
||||
super().__init__(function_middleware=[])
|
||||
@@ -55,7 +55,7 @@ class StreamingChatClientStub(
|
||||
@overload
|
||||
def get_response(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage],
|
||||
messages: str | Message | Sequence[str | Message],
|
||||
*,
|
||||
stream: Literal[False] = ...,
|
||||
options: ChatOptions[Any],
|
||||
@@ -65,7 +65,7 @@ class StreamingChatClientStub(
|
||||
@overload
|
||||
def get_response(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage],
|
||||
messages: str | Message | Sequence[str | Message],
|
||||
*,
|
||||
stream: Literal[False] = ...,
|
||||
options: OptionsCoT | ChatOptions[None] | None = ...,
|
||||
@@ -75,7 +75,7 @@ class StreamingChatClientStub(
|
||||
@overload
|
||||
def get_response(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage],
|
||||
messages: str | Message | Sequence[str | Message],
|
||||
*,
|
||||
stream: Literal[True],
|
||||
options: OptionsCoT | ChatOptions[Any] | None = ...,
|
||||
@@ -84,7 +84,7 @@ class StreamingChatClientStub(
|
||||
|
||||
def get_response(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage],
|
||||
messages: str | Message | Sequence[str | Message],
|
||||
*,
|
||||
stream: bool = False,
|
||||
options: OptionsCoT | ChatOptions[Any] | None = None,
|
||||
@@ -106,7 +106,7 @@ class StreamingChatClientStub(
|
||||
def _inner_get_response(
|
||||
self,
|
||||
*,
|
||||
messages: Sequence[ChatMessage],
|
||||
messages: Sequence[Message],
|
||||
stream: bool = False,
|
||||
options: Mapping[str, Any],
|
||||
**kwargs: Any,
|
||||
@@ -121,7 +121,7 @@ class StreamingChatClientStub(
|
||||
return self._get_response_impl(messages, options, **kwargs)
|
||||
|
||||
async def _get_response_impl(
|
||||
self, messages: Sequence[ChatMessage], options: Mapping[str, Any], **kwargs: Any
|
||||
self, messages: Sequence[Message], options: Mapping[str, Any], **kwargs: Any
|
||||
) -> ChatResponse:
|
||||
"""Non-streaming implementation."""
|
||||
if self._response_fn is not None:
|
||||
@@ -132,7 +132,7 @@ class StreamingChatClientStub(
|
||||
contents.extend(update.contents)
|
||||
|
||||
return ChatResponse(
|
||||
messages=[ChatMessage(role="assistant", contents=contents)],
|
||||
messages=[Message(role="assistant", contents=contents)],
|
||||
response_id="stub-response",
|
||||
)
|
||||
|
||||
@@ -141,7 +141,7 @@ def stream_from_updates(updates: list[ChatResponseUpdate]) -> StreamFn:
|
||||
"""Create a stream function that yields from a static list of updates."""
|
||||
|
||||
async def _stream(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
for update in updates:
|
||||
yield update
|
||||
@@ -159,7 +159,7 @@ class StubAgent(SupportsAgentRun):
|
||||
agent_id: str = "stub-agent",
|
||||
agent_name: str | None = "stub-agent",
|
||||
default_options: Any | None = None,
|
||||
chat_client: Any | None = None,
|
||||
client: Any | None = None,
|
||||
) -> None:
|
||||
self.id = agent_id
|
||||
self.name = agent_name
|
||||
@@ -168,14 +168,14 @@ class StubAgent(SupportsAgentRun):
|
||||
self.default_options: dict[str, Any] = (
|
||||
default_options if isinstance(default_options, dict) else {"tools": None, "response_format": None}
|
||||
)
|
||||
self.chat_client = chat_client or SimpleNamespace(function_invocation_configuration=None)
|
||||
self.client = client or SimpleNamespace(function_invocation_configuration=None)
|
||||
self.messages_received: list[Any] = []
|
||||
self.tools_received: list[Any] | None = None
|
||||
|
||||
@overload
|
||||
def run(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
|
||||
messages: str | Message | Sequence[str | Message] | None = None,
|
||||
*,
|
||||
stream: Literal[False] = ...,
|
||||
thread: AgentThread | None = None,
|
||||
@@ -185,7 +185,7 @@ class StubAgent(SupportsAgentRun):
|
||||
@overload
|
||||
def run(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
|
||||
messages: str | Message | Sequence[str | Message] | None = None,
|
||||
*,
|
||||
stream: Literal[True],
|
||||
thread: AgentThread | None = None,
|
||||
@@ -194,7 +194,7 @@ class StubAgent(SupportsAgentRun):
|
||||
|
||||
def run(
|
||||
self,
|
||||
messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None,
|
||||
messages: str | Message | Sequence[str | Message] | None = None,
|
||||
*,
|
||||
stream: bool = False,
|
||||
thread: AgentThread | None = None,
|
||||
@@ -226,7 +226,7 @@ class StubAgent(SupportsAgentRun):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def streaming_chat_client_stub() -> type[ChatClientProtocol]:
|
||||
def streaming_chat_client_stub() -> type[SupportsChatGetResponse]:
|
||||
"""Return the StreamingChatClientStub class for creating test instances."""
|
||||
return StreamingChatClientStub # type: ignore[return-value]
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ from collections.abc import AsyncGenerator, Awaitable, MutableSequence
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import (
|
||||
ChatMessage,
|
||||
ChatOptions,
|
||||
ChatResponse,
|
||||
ChatResponseUpdate,
|
||||
Content,
|
||||
Message,
|
||||
ResponseStream,
|
||||
tool,
|
||||
)
|
||||
@@ -29,13 +29,11 @@ class TestableAGUIChatClient(AGUIChatClient):
|
||||
"""Expose http service for monkeypatching."""
|
||||
return self._http_service
|
||||
|
||||
def extract_state_from_messages(
|
||||
self, messages: list[ChatMessage]
|
||||
) -> tuple[list[ChatMessage], dict[str, Any] | None]:
|
||||
def extract_state_from_messages(self, messages: list[Message]) -> tuple[list[Message], dict[str, Any] | None]:
|
||||
"""Expose state extraction helper."""
|
||||
return self._extract_state_from_messages(messages)
|
||||
|
||||
def convert_messages_to_agui_format(self, messages: list[ChatMessage]) -> list[dict[str, Any]]:
|
||||
def convert_messages_to_agui_format(self, messages: list[Message]) -> list[dict[str, Any]]:
|
||||
"""Expose message conversion helper."""
|
||||
return self._convert_messages_to_agui_format(messages)
|
||||
|
||||
@@ -44,7 +42,7 @@ class TestableAGUIChatClient(AGUIChatClient):
|
||||
return self._get_thread_id(options)
|
||||
|
||||
def inner_get_response(
|
||||
self, *, messages: MutableSequence[ChatMessage], options: dict[str, Any], stream: bool = False
|
||||
self, *, messages: MutableSequence[Message], options: dict[str, Any], stream: bool = False
|
||||
) -> Awaitable[ChatResponse] | ResponseStream[ChatResponseUpdate, ChatResponse]:
|
||||
"""Proxy to protected response call."""
|
||||
return self._inner_get_response(messages=messages, options=options, stream=stream)
|
||||
@@ -69,8 +67,8 @@ class TestAGUIChatClient:
|
||||
"""Test state extraction when no state is present."""
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
messages = [
|
||||
ChatMessage(role="user", text="Hello"),
|
||||
ChatMessage(role="assistant", text="Hi there"),
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Hi there"),
|
||||
]
|
||||
|
||||
result_messages, state = client.extract_state_from_messages(messages)
|
||||
@@ -89,8 +87,8 @@ class TestAGUIChatClient:
|
||||
state_b64 = base64.b64encode(state_json.encode("utf-8")).decode("utf-8")
|
||||
|
||||
messages = [
|
||||
ChatMessage(role="user", text="Hello"),
|
||||
ChatMessage(
|
||||
Message(role="user", text="Hello"),
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
|
||||
),
|
||||
@@ -112,7 +110,7 @@ class TestAGUIChatClient:
|
||||
state_b64 = base64.b64encode(invalid_json.encode("utf-8")).decode("utf-8")
|
||||
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
|
||||
),
|
||||
@@ -127,8 +125,8 @@ class TestAGUIChatClient:
|
||||
"""Test message conversion to AG-UI format."""
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
messages = [
|
||||
ChatMessage(role="user", text="What is the weather?"),
|
||||
ChatMessage(role="assistant", text="Let me check.", message_id="msg_123"),
|
||||
Message(role="user", text="What is the weather?"),
|
||||
Message(role="assistant", text="Let me check.", message_id="msg_123"),
|
||||
]
|
||||
|
||||
agui_messages = client.convert_messages_to_agui_format(messages)
|
||||
@@ -175,7 +173,7 @@ class TestAGUIChatClient:
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
|
||||
|
||||
messages = [ChatMessage(role="user", text="Test message")]
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
chat_options = ChatOptions()
|
||||
|
||||
updates: list[ChatResponseUpdate] = []
|
||||
@@ -208,7 +206,7 @@ class TestAGUIChatClient:
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
|
||||
|
||||
messages = [ChatMessage(role="user", text="Test message")]
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
chat_options = {}
|
||||
|
||||
response = await client.inner_get_response(messages=messages, options=chat_options)
|
||||
@@ -251,7 +249,7 @@ class TestAGUIChatClient:
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
|
||||
|
||||
messages = [ChatMessage(role="user", text="Test with tools")]
|
||||
messages = [Message(role="user", text="Test with tools")]
|
||||
chat_options = ChatOptions(tools=[test_tool])
|
||||
|
||||
response = await client.inner_get_response(messages=messages, options=chat_options)
|
||||
@@ -275,7 +273,7 @@ class TestAGUIChatClient:
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
|
||||
|
||||
messages = [ChatMessage(role="user", text="Test server tool execution")]
|
||||
messages = [Message(role="user", text="Test server tool execution")]
|
||||
|
||||
updates: list[ChatResponseUpdate] = []
|
||||
async for update in client.get_response(messages, stream=True):
|
||||
@@ -317,7 +315,7 @@ class TestAGUIChatClient:
|
||||
client = TestableAGUIChatClient(endpoint="http://localhost:8888/")
|
||||
monkeypatch.setattr(client.http_service, "post_run", mock_post_run)
|
||||
|
||||
messages = [ChatMessage(role="user", text="Test server tool execution")]
|
||||
messages = [Message(role="user", text="Test server tool execution")]
|
||||
|
||||
async for _ in client.get_response(
|
||||
messages, stream=True, options={"tool_choice": "auto", "tools": [client_tool]}
|
||||
@@ -333,8 +331,8 @@ class TestAGUIChatClient:
|
||||
state_b64 = base64.b64encode(state_json.encode("utf-8")).decode("utf-8")
|
||||
|
||||
messages = [
|
||||
ChatMessage(role="user", text="Hello"),
|
||||
ChatMessage(
|
||||
Message(role="user", text="Hello"),
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_uri(uri=f"data:application/json;base64,{state_b64}")],
|
||||
),
|
||||
|
||||
@@ -7,7 +7,7 @@ from collections.abc import AsyncIterator, MutableSequence
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from agent_framework import ChatAgent, ChatMessage, ChatOptions, ChatResponseUpdate, Content
|
||||
from agent_framework import Agent, ChatOptions, ChatResponseUpdate, Content, Message
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ async def test_agent_initialization_basic(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent[ChatOptions](
|
||||
chat_client=streaming_chat_client_stub(stream_fn),
|
||||
agent = Agent[ChatOptions](
|
||||
client=streaming_chat_client_stub(stream_fn),
|
||||
name="test_agent",
|
||||
instructions="Test",
|
||||
)
|
||||
@@ -38,11 +38,11 @@ async def test_agent_initialization_with_state_schema(streaming_chat_client_stub
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
state_schema: dict[str, dict[str, Any]] = {"document": {"type": "string"}}
|
||||
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
|
||||
|
||||
@@ -54,11 +54,11 @@ async def test_agent_initialization_with_predict_state_config(streaming_chat_cli
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
predict_config = {"document": {"tool": "write_doc", "tool_argument": "content"}}
|
||||
wrapper = AgentFrameworkAgent(agent=agent, predict_state_config=predict_config)
|
||||
|
||||
@@ -70,7 +70,7 @@ async def test_agent_initialization_with_pydantic_state_schema(streaming_chat_cl
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
@@ -78,7 +78,7 @@ async def test_agent_initialization_with_pydantic_state_schema(streaming_chat_cl
|
||||
document: str
|
||||
tags: list[str] = []
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
|
||||
wrapper_class_schema = AgentFrameworkAgent(agent=agent, state_schema=MyState)
|
||||
wrapper_instance_schema = AgentFrameworkAgent(agent=agent, state_schema=MyState(document="hi"))
|
||||
@@ -93,11 +93,11 @@ async def test_run_started_event_emission(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data = {"messages": [{"role": "user", "content": "Hi"}]}
|
||||
@@ -117,11 +117,11 @@ async def test_predict_state_custom_event_emission(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
predict_config = {
|
||||
"document": {"tool": "write_doc", "tool_argument": "content"},
|
||||
"summary": {"tool": "summarize", "tool_argument": "text"},
|
||||
@@ -149,11 +149,11 @@ async def test_initial_state_snapshot_with_schema(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
state_schema = {"document": {"type": "string"}}
|
||||
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
|
||||
|
||||
@@ -179,11 +179,11 @@ async def test_state_initialization_object_type(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
state_schema: dict[str, dict[str, Any]] = {"recipe": {"type": "object", "properties": {}}}
|
||||
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
|
||||
|
||||
@@ -206,11 +206,11 @@ async def test_state_initialization_array_type(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
state_schema: dict[str, dict[str, Any]] = {"steps": {"type": "array", "items": {}}}
|
||||
wrapper = AgentFrameworkAgent(agent=agent, state_schema=state_schema)
|
||||
|
||||
@@ -233,11 +233,11 @@ async def test_run_finished_event_emission(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data = {"messages": [{"role": "user", "content": "Hi"}]}
|
||||
@@ -255,11 +255,11 @@ async def test_tool_result_confirm_changes_accepted(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Document updated")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(
|
||||
agent=agent,
|
||||
state_schema={"document": {"type": "string"}},
|
||||
@@ -302,11 +302,11 @@ async def test_tool_result_confirm_changes_rejected(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
# Simulate tool result message with rejection
|
||||
@@ -336,11 +336,11 @@ async def test_tool_result_function_approval_accepted(streaming_chat_client_stub
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
# Simulate tool result with multiple steps
|
||||
@@ -382,11 +382,11 @@ async def test_tool_result_function_approval_rejected(streaming_chat_client_stub
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="OK")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
# Simulate tool result rejection with steps
|
||||
@@ -425,13 +425,13 @@ async def test_thread_metadata_tracking(streaming_chat_client_stub):
|
||||
captured_options: dict[str, Any] = {}
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
# Capture options to verify internal keys are NOT passed to chat client
|
||||
captured_options.update(options)
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data = {
|
||||
@@ -445,7 +445,7 @@ async def test_thread_metadata_tracking(streaming_chat_client_stub):
|
||||
events.append(event)
|
||||
|
||||
# AG-UI internal metadata should be stored in thread.metadata
|
||||
thread = agent.chat_client.last_thread
|
||||
thread = agent.client.last_thread
|
||||
thread_metadata = thread.metadata if thread and hasattr(thread, "metadata") else {}
|
||||
assert thread_metadata.get("ag_ui_thread_id") == "test_thread_123"
|
||||
assert thread_metadata.get("ag_ui_run_id") == "test_run_456"
|
||||
@@ -467,13 +467,13 @@ async def test_state_context_injection(streaming_chat_client_stub):
|
||||
captured_options: dict[str, Any] = {}
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
# Capture options to verify internal keys are NOT passed to chat client
|
||||
captured_options.update(options)
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(
|
||||
agent=agent,
|
||||
state_schema={"document": {"type": "string"}},
|
||||
@@ -489,7 +489,7 @@ async def test_state_context_injection(streaming_chat_client_stub):
|
||||
events.append(event)
|
||||
|
||||
# Current state should be stored in thread.metadata
|
||||
thread = agent.chat_client.last_thread
|
||||
thread = agent.client.last_thread
|
||||
thread_metadata = thread.metadata if thread and hasattr(thread, "metadata") else {}
|
||||
current_state = thread_metadata.get("current_state")
|
||||
if isinstance(current_state, str):
|
||||
@@ -506,11 +506,11 @@ async def test_no_messages_provided(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data: dict[str, Any] = {"messages": []}
|
||||
@@ -530,11 +530,11 @@ async def test_message_end_event_emission(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Hello world")])
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data: dict[str, Any] = {"messages": [{"role": "user", "content": "Hi"}]}
|
||||
@@ -558,13 +558,13 @@ async def test_error_handling_with_exception(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
if False:
|
||||
yield ChatResponseUpdate(contents=[])
|
||||
raise RuntimeError("Simulated failure")
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
input_data: dict[str, Any] = {"messages": [{"role": "user", "content": "Hi"}]}
|
||||
@@ -579,13 +579,13 @@ async def test_json_decode_error_in_tool_result(streaming_chat_client_stub):
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: dict[str, Any], **kwargs: Any
|
||||
messages: MutableSequence[Message], options: dict[str, Any], **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
if False:
|
||||
yield ChatResponseUpdate(contents=[])
|
||||
raise AssertionError("ChatClient should not be called with orphaned tool result")
|
||||
|
||||
agent = ChatAgent(name="test_agent", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test_agent", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
# Send invalid JSON as tool result without preceding tool call
|
||||
@@ -618,13 +618,13 @@ async def test_agent_with_use_service_thread_is_false(streaming_chat_client_stub
|
||||
request_service_thread_id: str | None = None
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], chat_options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], chat_options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(
|
||||
contents=[Content.from_text(text="Response")], response_id="resp_67890", conversation_id="conv_12345"
|
||||
)
|
||||
|
||||
agent = ChatAgent(chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent, use_service_thread=False)
|
||||
|
||||
input_data = {"messages": [{"role": "user", "content": "Hi"}], "thread_id": "conv_123456"}
|
||||
@@ -642,7 +642,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
|
||||
request_service_thread_id: str | None = None
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], chat_options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], chat_options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
nonlocal request_service_thread_id
|
||||
thread = kwargs.get("thread")
|
||||
@@ -651,7 +651,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
|
||||
contents=[Content.from_text(text="Response")], response_id="resp_67890", conversation_id="conv_12345"
|
||||
)
|
||||
|
||||
agent = ChatAgent(chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(client=streaming_chat_client_stub(stream_fn))
|
||||
wrapper = AgentFrameworkAgent(agent=agent, use_service_thread=True)
|
||||
|
||||
input_data = {"messages": [{"role": "user", "content": "Hi"}], "thread_id": "conv_123456"}
|
||||
@@ -659,7 +659,7 @@ async def test_agent_with_use_service_thread_is_true(streaming_chat_client_stub)
|
||||
events: list[Any] = []
|
||||
async for event in wrapper.run_agent(input_data):
|
||||
events.append(event)
|
||||
request_service_thread_id = agent.chat_client.last_service_thread_id
|
||||
request_service_thread_id = agent.client.last_service_thread_id
|
||||
assert request_service_thread_id == "conv_123456" # type: ignore[attr-defined] (service_thread_id should be set)
|
||||
|
||||
|
||||
@@ -679,15 +679,15 @@ async def test_function_approval_mode_executes_tool(streaming_chat_client_stub):
|
||||
return "2025/12/01 12:00:00"
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
# Capture the messages received by the chat client
|
||||
messages_received.clear()
|
||||
messages_received.extend(messages)
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Processing completed")])
|
||||
|
||||
agent = ChatAgent(
|
||||
chat_client=streaming_chat_client_stub(stream_fn),
|
||||
agent = Agent(
|
||||
client=streaming_chat_client_stub(stream_fn),
|
||||
name="test_agent",
|
||||
instructions="Test",
|
||||
tools=[get_datetime],
|
||||
@@ -770,17 +770,17 @@ async def test_function_approval_mode_rejection(streaming_chat_client_stub):
|
||||
return "All data deleted"
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
# Capture the messages received by the chat client
|
||||
messages_received.clear()
|
||||
messages_received.extend(messages)
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text="Operation cancelled")])
|
||||
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="test_agent",
|
||||
instructions="Test",
|
||||
chat_client=streaming_chat_client_stub(stream_fn),
|
||||
client=streaming_chat_client_stub(stream_fn),
|
||||
tools=[delete_all_data],
|
||||
)
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from agent_framework import ChatAgent, ChatResponseUpdate, Content
|
||||
from agent_framework import Agent, ChatResponseUpdate, Content
|
||||
from fastapi import FastAPI, Header, HTTPException
|
||||
from fastapi.params import Depends
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -28,7 +28,7 @@ def build_chat_client(streaming_chat_client_stub, stream_from_updates_fixture):
|
||||
async def test_add_endpoint_with_agent_protocol(build_chat_client):
|
||||
"""Test adding endpoint with raw SupportsAgentRun."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/test-agent")
|
||||
|
||||
@@ -42,7 +42,7 @@ async def test_add_endpoint_with_agent_protocol(build_chat_client):
|
||||
async def test_add_endpoint_with_wrapped_agent(build_chat_client):
|
||||
"""Test adding endpoint with pre-wrapped AgentFrameworkAgent."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
wrapped_agent = AgentFrameworkAgent(agent=agent, name="wrapped")
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, wrapped_agent, path="/wrapped-agent")
|
||||
@@ -57,7 +57,7 @@ async def test_add_endpoint_with_wrapped_agent(build_chat_client):
|
||||
async def test_endpoint_with_state_schema(build_chat_client):
|
||||
"""Test endpoint with state_schema parameter."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
state_schema = {"document": {"type": "string"}}
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/stateful", state_schema=state_schema)
|
||||
@@ -73,7 +73,7 @@ async def test_endpoint_with_state_schema(build_chat_client):
|
||||
async def test_endpoint_with_default_state_seed(build_chat_client):
|
||||
"""Test endpoint seeds default state when client omits it."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
state_schema = {"proverbs": {"type": "array"}}
|
||||
default_state = {"proverbs": ["Keep the original."]}
|
||||
|
||||
@@ -100,7 +100,7 @@ async def test_endpoint_with_default_state_seed(build_chat_client):
|
||||
async def test_endpoint_with_predict_state_config(build_chat_client):
|
||||
"""Test endpoint with predict_state_config parameter."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
predict_config = {"document": {"tool": "write_doc", "tool_argument": "content"}}
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/predictive", predict_state_config=predict_config)
|
||||
@@ -114,7 +114,7 @@ async def test_endpoint_with_predict_state_config(build_chat_client):
|
||||
async def test_endpoint_request_logging(build_chat_client):
|
||||
"""Test that endpoint logs request details."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/logged")
|
||||
|
||||
@@ -134,7 +134,7 @@ async def test_endpoint_request_logging(build_chat_client):
|
||||
async def test_endpoint_event_streaming(build_chat_client):
|
||||
"""Test that endpoint streams events correctly."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client("Streamed response"))
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client("Streamed response"))
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/stream")
|
||||
|
||||
@@ -168,7 +168,7 @@ async def test_endpoint_event_streaming(build_chat_client):
|
||||
async def test_endpoint_error_handling(build_chat_client):
|
||||
"""Test endpoint error handling during request parsing."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/failing")
|
||||
|
||||
@@ -184,8 +184,8 @@ async def test_endpoint_error_handling(build_chat_client):
|
||||
async def test_endpoint_multiple_paths(build_chat_client):
|
||||
"""Test adding multiple endpoints with different paths."""
|
||||
app = FastAPI()
|
||||
agent1 = ChatAgent(name="agent1", instructions="First agent", chat_client=build_chat_client("Response 1"))
|
||||
agent2 = ChatAgent(name="agent2", instructions="Second agent", chat_client=build_chat_client("Response 2"))
|
||||
agent1 = Agent(name="agent1", instructions="First agent", client=build_chat_client("Response 1"))
|
||||
agent2 = Agent(name="agent2", instructions="Second agent", client=build_chat_client("Response 2"))
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent1, path="/agent1")
|
||||
add_agent_framework_fastapi_endpoint(app, agent2, path="/agent2")
|
||||
@@ -202,7 +202,7 @@ async def test_endpoint_multiple_paths(build_chat_client):
|
||||
async def test_endpoint_default_path(build_chat_client):
|
||||
"""Test endpoint with default path."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent)
|
||||
|
||||
@@ -215,7 +215,7 @@ async def test_endpoint_default_path(build_chat_client):
|
||||
async def test_endpoint_response_headers(build_chat_client):
|
||||
"""Test that endpoint sets correct response headers."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/headers")
|
||||
|
||||
@@ -231,7 +231,7 @@ async def test_endpoint_response_headers(build_chat_client):
|
||||
async def test_endpoint_empty_messages(build_chat_client):
|
||||
"""Test endpoint with empty messages list."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/empty")
|
||||
|
||||
@@ -244,7 +244,7 @@ async def test_endpoint_empty_messages(build_chat_client):
|
||||
async def test_endpoint_complex_input(build_chat_client):
|
||||
"""Test endpoint with complex input data."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/complex")
|
||||
|
||||
@@ -269,7 +269,7 @@ async def test_endpoint_complex_input(build_chat_client):
|
||||
async def test_endpoint_openapi_schema(build_chat_client):
|
||||
"""Test that endpoint generates proper OpenAPI schema with request model."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/schema-test")
|
||||
|
||||
@@ -313,7 +313,7 @@ async def test_endpoint_openapi_schema(build_chat_client):
|
||||
async def test_endpoint_default_tags(build_chat_client):
|
||||
"""Test that endpoint uses default 'AG-UI' tag."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/default-tags")
|
||||
|
||||
@@ -331,7 +331,7 @@ async def test_endpoint_default_tags(build_chat_client):
|
||||
async def test_endpoint_custom_tags(build_chat_client):
|
||||
"""Test that endpoint accepts custom tags."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/custom-tags", tags=["Custom", "Agent"])
|
||||
|
||||
@@ -349,7 +349,7 @@ async def test_endpoint_custom_tags(build_chat_client):
|
||||
async def test_endpoint_missing_required_field(build_chat_client):
|
||||
"""Test that endpoint validates required fields with Pydantic."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/validation")
|
||||
|
||||
@@ -368,7 +368,7 @@ async def test_endpoint_internal_error_handling(build_chat_client):
|
||||
from unittest.mock import patch
|
||||
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
# Use default_state to trigger the code path that can raise an exception
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/error-test", default_state={"key": "value"})
|
||||
@@ -387,7 +387,7 @@ async def test_endpoint_internal_error_handling(build_chat_client):
|
||||
async def test_endpoint_with_dependencies_blocks_unauthorized(build_chat_client):
|
||||
"""Test that endpoint blocks requests when authentication dependency fails."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
async def require_api_key(x_api_key: str | None = Header(None)):
|
||||
if x_api_key != "secret-key":
|
||||
@@ -406,7 +406,7 @@ async def test_endpoint_with_dependencies_blocks_unauthorized(build_chat_client)
|
||||
async def test_endpoint_with_dependencies_allows_authorized(build_chat_client):
|
||||
"""Test that endpoint allows requests when authentication dependency passes."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
async def require_api_key(x_api_key: str | None = Header(None)):
|
||||
if x_api_key != "secret-key":
|
||||
@@ -429,7 +429,7 @@ async def test_endpoint_with_dependencies_allows_authorized(build_chat_client):
|
||||
async def test_endpoint_with_multiple_dependencies(build_chat_client):
|
||||
"""Test that endpoint supports multiple dependencies."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -457,7 +457,7 @@ async def test_endpoint_with_multiple_dependencies(build_chat_client):
|
||||
async def test_endpoint_without_dependencies_is_accessible(build_chat_client):
|
||||
"""Test that endpoint without dependencies remains accessible (backward compatibility)."""
|
||||
app = FastAPI()
|
||||
agent = ChatAgent(name="test", instructions="Test agent", chat_client=build_chat_client())
|
||||
agent = Agent(name="test", instructions="Test agent", client=build_chat_client())
|
||||
|
||||
# No dependencies parameter - should be accessible without auth
|
||||
add_agent_framework_fastapi_endpoint(app, agent, path="/open")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
"""Tests for orchestration helper functions."""
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
|
||||
from agent_framework_ag_ui._orchestration._helpers import (
|
||||
approval_steps,
|
||||
@@ -29,8 +29,8 @@ class TestPendingToolCallIds:
|
||||
def test_no_tool_calls(self):
|
||||
"""Returns empty set when no tool calls in messages."""
|
||||
messages = [
|
||||
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
|
||||
ChatMessage(role="assistant", contents=[Content.from_text("Hi there")]),
|
||||
Message(role="user", contents=[Content.from_text("Hello")]),
|
||||
Message(role="assistant", contents=[Content.from_text("Hi there")]),
|
||||
]
|
||||
result = pending_tool_call_ids(messages)
|
||||
assert result == set()
|
||||
@@ -38,7 +38,7 @@ class TestPendingToolCallIds:
|
||||
def test_pending_tool_call(self):
|
||||
"""Returns pending tool call ID when no result exists."""
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_function_call(call_id="call_123", name="get_weather", arguments="{}")],
|
||||
),
|
||||
@@ -49,11 +49,11 @@ class TestPendingToolCallIds:
|
||||
def test_resolved_tool_call(self):
|
||||
"""Returns empty set when tool call has result."""
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_function_call(call_id="call_123", name="get_weather", arguments="{}")],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call_123", result="sunny")],
|
||||
),
|
||||
@@ -64,7 +64,7 @@ class TestPendingToolCallIds:
|
||||
def test_multiple_tool_calls_some_resolved(self):
|
||||
"""Returns only unresolved tool call IDs."""
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(call_id="call_1", name="tool_a", arguments="{}"),
|
||||
@@ -72,11 +72,11 @@ class TestPendingToolCallIds:
|
||||
Content.from_function_call(call_id="call_3", name="tool_c", arguments="{}"),
|
||||
],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call_1", result="result_a")],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call_3", result="result_c")],
|
||||
),
|
||||
@@ -90,7 +90,7 @@ class TestIsStateContextMessage:
|
||||
|
||||
def test_state_context_message(self):
|
||||
"""Returns True for state context message."""
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="system",
|
||||
contents=[Content.from_text("Current state of the application: {}")],
|
||||
)
|
||||
@@ -98,7 +98,7 @@ class TestIsStateContextMessage:
|
||||
|
||||
def test_non_system_message(self):
|
||||
"""Returns False for non-system message."""
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="user",
|
||||
contents=[Content.from_text("Current state of the application: {}")],
|
||||
)
|
||||
@@ -106,7 +106,7 @@ class TestIsStateContextMessage:
|
||||
|
||||
def test_system_message_without_state_prefix(self):
|
||||
"""Returns False for system message without state prefix."""
|
||||
message = ChatMessage(
|
||||
message = Message(
|
||||
role="system",
|
||||
contents=[Content.from_text("You are a helpful assistant.")],
|
||||
)
|
||||
@@ -114,7 +114,7 @@ class TestIsStateContextMessage:
|
||||
|
||||
def test_empty_contents(self):
|
||||
"""Returns False for message with empty contents."""
|
||||
message = ChatMessage(role="system", contents=[])
|
||||
message = Message(role="system", contents=[])
|
||||
assert is_state_context_message(message) is False
|
||||
|
||||
|
||||
@@ -342,7 +342,7 @@ class TestLatestApprovalResponse:
|
||||
def test_no_approval_response(self):
|
||||
"""Returns None when no approval response in last message."""
|
||||
messages = [
|
||||
ChatMessage(role="assistant", contents=[Content.from_text("Hello")]),
|
||||
Message(role="assistant", contents=[Content.from_text("Hello")]),
|
||||
]
|
||||
result = latest_approval_response(messages)
|
||||
assert result is None
|
||||
@@ -357,7 +357,7 @@ class TestLatestApprovalResponse:
|
||||
function_call=fc,
|
||||
)
|
||||
messages = [
|
||||
ChatMessage(role="user", contents=[approval_content]),
|
||||
Message(role="user", contents=[approval_content]),
|
||||
]
|
||||
result = latest_approval_response(messages)
|
||||
assert result is approval_content
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
|
||||
from agent_framework_ag_ui._message_adapters import (
|
||||
agent_framework_messages_to_agui,
|
||||
@@ -24,7 +24,7 @@ def sample_agui_message():
|
||||
@pytest.fixture
|
||||
def sample_agent_framework_message():
|
||||
"""Create a sample Agent Framework message."""
|
||||
return ChatMessage(role="user", contents=[Content.from_text(text="Hello")], message_id="msg-123")
|
||||
return Message(role="user", contents=[Content.from_text(text="Hello")], message_id="msg-123")
|
||||
|
||||
|
||||
def test_agui_to_agent_framework_basic(sample_agui_message):
|
||||
@@ -100,7 +100,7 @@ def test_agui_tool_result_to_agent_framework():
|
||||
def test_agui_tool_approval_updates_tool_call_arguments():
|
||||
"""Tool approval updates matching tool call arguments for snapshots and agent context.
|
||||
|
||||
The LLM context (ChatMessage) should contain only enabled steps, so the LLM
|
||||
The LLM context (Message) should contain only enabled steps, so the LLM
|
||||
generates responses based on what was actually approved/executed.
|
||||
|
||||
The raw messages (for MESSAGES_SNAPSHOT) should contain all steps with status,
|
||||
@@ -446,7 +446,7 @@ def test_agui_with_tool_calls_to_agent_framework():
|
||||
|
||||
def test_agent_framework_to_agui_with_tool_calls():
|
||||
"""Test converting Agent Framework message with tool calls to AG-UI."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_text(text="Calling tool"),
|
||||
@@ -471,7 +471,7 @@ def test_agent_framework_to_agui_with_tool_calls():
|
||||
|
||||
def test_agent_framework_to_agui_multiple_text_contents():
|
||||
"""Test concatenating multiple text contents."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_text(text="Part 1 "), Content.from_text(text="Part 2")],
|
||||
)
|
||||
@@ -484,7 +484,7 @@ def test_agent_framework_to_agui_multiple_text_contents():
|
||||
|
||||
def test_agent_framework_to_agui_no_message_id():
|
||||
"""Test message without message_id - should auto-generate ID."""
|
||||
msg = ChatMessage(role="user", contents=[Content.from_text(text="Hello")])
|
||||
msg = Message(role="user", contents=[Content.from_text(text="Hello")])
|
||||
|
||||
messages = agent_framework_messages_to_agui([msg])
|
||||
|
||||
@@ -496,7 +496,7 @@ def test_agent_framework_to_agui_no_message_id():
|
||||
|
||||
def test_agent_framework_to_agui_system_role():
|
||||
"""Test system role conversion."""
|
||||
msg = ChatMessage(role="system", contents=[Content.from_text(text="System")])
|
||||
msg = Message(role="system", contents=[Content.from_text(text="System")])
|
||||
|
||||
messages = agent_framework_messages_to_agui([msg])
|
||||
|
||||
@@ -541,7 +541,7 @@ def test_extract_text_from_custom_contents():
|
||||
|
||||
def test_agent_framework_to_agui_function_result_dict():
|
||||
"""Test converting FunctionResultContent with dict result to AG-UI."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call-123", result={"key": "value", "count": 42})],
|
||||
message_id="msg-789",
|
||||
@@ -558,7 +558,7 @@ def test_agent_framework_to_agui_function_result_dict():
|
||||
|
||||
def test_agent_framework_to_agui_function_result_none():
|
||||
"""Test converting FunctionResultContent with None result to AG-UI."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call-123", result=None)],
|
||||
message_id="msg-789",
|
||||
@@ -574,7 +574,7 @@ def test_agent_framework_to_agui_function_result_none():
|
||||
|
||||
def test_agent_framework_to_agui_function_result_string():
|
||||
"""Test converting FunctionResultContent with string result to AG-UI."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call-123", result="plain text result")],
|
||||
message_id="msg-789",
|
||||
@@ -589,7 +589,7 @@ def test_agent_framework_to_agui_function_result_string():
|
||||
|
||||
def test_agent_framework_to_agui_function_result_empty_list():
|
||||
"""Test converting FunctionResultContent with empty list result to AG-UI."""
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call-123", result=[])],
|
||||
message_id="msg-789",
|
||||
@@ -611,7 +611,7 @@ def test_agent_framework_to_agui_function_result_single_text_content():
|
||||
class MockTextContent:
|
||||
text: str
|
||||
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call-123", result=[MockTextContent("Hello from MCP!")])],
|
||||
message_id="msg-789",
|
||||
@@ -633,7 +633,7 @@ def test_agent_framework_to_agui_function_result_multiple_text_contents():
|
||||
class MockTextContent:
|
||||
text: str
|
||||
|
||||
msg = ChatMessage(
|
||||
msg = Message(
|
||||
role="tool",
|
||||
contents=[
|
||||
Content.from_function_result(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
|
||||
from agent_framework_ag_ui._message_adapters import _deduplicate_messages, _sanitize_tool_history
|
||||
|
||||
@@ -13,7 +13,7 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
|
||||
tool for the approval UI flow that shouldn't be sent to the LLM.
|
||||
"""
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(
|
||||
@@ -23,7 +23,7 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
|
||||
)
|
||||
],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_text(text='{"accepted": true}')],
|
||||
),
|
||||
@@ -44,11 +44,11 @@ def test_sanitize_tool_history_filters_out_confirm_changes_only_message() -> Non
|
||||
|
||||
def test_deduplicate_messages_prefers_non_empty_tool_results() -> None:
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call1", result="")],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call1", result="result data")],
|
||||
),
|
||||
@@ -71,13 +71,13 @@ def test_convert_approval_results_to_tool_messages() -> None:
|
||||
# Simulate what happens after _resolve_approval_responses:
|
||||
# A user message contains function_result content (the executed tool result)
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(call_id="call_123", name="my_mcp_tool", arguments="{}"),
|
||||
],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_function_result(call_id="call_123", result="tool execution result"),
|
||||
@@ -109,13 +109,13 @@ def test_convert_approval_results_preserves_other_user_content() -> None:
|
||||
from agent_framework_ag_ui._run import _convert_approval_results_to_tool_messages
|
||||
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(call_id="call_123", name="my_tool", arguments="{}"),
|
||||
],
|
||||
),
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_text(text="User also said something"),
|
||||
@@ -152,12 +152,12 @@ def test_sanitize_tool_history_filters_confirm_changes_keeps_other_tools() -> No
|
||||
"""
|
||||
messages = [
|
||||
# User asks something
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_text(text="What time is it?")],
|
||||
),
|
||||
# Assistant calls MCP tool + confirm_changes
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(call_id="call_1", name="get_datetime", arguments="{}"),
|
||||
@@ -165,12 +165,12 @@ def test_sanitize_tool_history_filters_confirm_changes_keeps_other_tools() -> No
|
||||
],
|
||||
),
|
||||
# Tool result for the actual MCP tool
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="tool",
|
||||
contents=[Content.from_function_result(call_id="call_1", result="2024-01-01 12:00:00")],
|
||||
),
|
||||
# User asks something else
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_text(text="What's the date?")],
|
||||
),
|
||||
@@ -204,12 +204,12 @@ def test_sanitize_tool_history_filters_confirm_changes_from_assistant_messages()
|
||||
respond with "Here's your 5-step plan" instead of "Here's your 2-step plan".
|
||||
"""
|
||||
messages = [
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[Content.from_text(text="Build a robot")],
|
||||
),
|
||||
# Assistant message with both generate_task_steps and confirm_changes
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
Content.from_function_call(
|
||||
@@ -225,7 +225,7 @@ def test_sanitize_tool_history_filters_confirm_changes_from_assistant_messages()
|
||||
],
|
||||
),
|
||||
# Approval response
|
||||
ChatMessage(
|
||||
Message(
|
||||
role="user",
|
||||
contents=[
|
||||
Content.from_function_approval_response(
|
||||
|
||||
@@ -6,7 +6,7 @@ from ag_ui.core import (
|
||||
TextMessageEndEvent,
|
||||
TextMessageStartEvent,
|
||||
)
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
|
||||
from agent_framework_ag_ui._run import (
|
||||
FlowState,
|
||||
@@ -212,7 +212,7 @@ class TestInjectStateContext:
|
||||
|
||||
def test_no_state_message(self):
|
||||
"""Returns original messages when no state context needed."""
|
||||
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
|
||||
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
|
||||
result = _inject_state_context(messages, {}, {})
|
||||
assert result == messages
|
||||
|
||||
@@ -224,8 +224,8 @@ class TestInjectStateContext:
|
||||
def test_last_message_not_user(self):
|
||||
"""Returns original messages when last message is not from user."""
|
||||
messages = [
|
||||
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
|
||||
ChatMessage(role="assistant", contents=[Content.from_text("Hi")]),
|
||||
Message(role="user", contents=[Content.from_text("Hello")]),
|
||||
Message(role="assistant", contents=[Content.from_text("Hi")]),
|
||||
]
|
||||
state = {"key": "value"}
|
||||
schema = {"properties": {"key": {"type": "string"}}}
|
||||
@@ -237,8 +237,8 @@ class TestInjectStateContext:
|
||||
"""Injects state context before last user message."""
|
||||
|
||||
messages = [
|
||||
ChatMessage(role="system", contents=[Content.from_text("You are helpful")]),
|
||||
ChatMessage(role="user", contents=[Content.from_text("Hello")]),
|
||||
Message(role="system", contents=[Content.from_text("You are helpful")]),
|
||||
Message(role="user", contents=[Content.from_text("Hello")]),
|
||||
]
|
||||
state = {"document": "content"}
|
||||
schema = {"properties": {"document": {"type": "string"}}}
|
||||
@@ -405,7 +405,7 @@ def test_extract_approved_state_updates_no_handler():
|
||||
"""Test _extract_approved_state_updates returns empty with no handler."""
|
||||
from agent_framework_ag_ui._run import _extract_approved_state_updates
|
||||
|
||||
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
|
||||
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
|
||||
result = _extract_approved_state_updates(messages, None)
|
||||
assert result == {}
|
||||
|
||||
@@ -416,7 +416,7 @@ def test_extract_approved_state_updates_no_approval():
|
||||
from agent_framework_ag_ui._run import _extract_approved_state_updates
|
||||
|
||||
handler = PredictiveStateHandler(predict_state_config={"doc": {"tool": "write", "tool_argument": "content"}})
|
||||
messages = [ChatMessage(role="user", contents=[Content.from_text("Hello")])]
|
||||
messages = [Message(role="user", contents=[Content.from_text("Hello")])]
|
||||
result = _extract_approved_state_updates(messages, handler)
|
||||
assert result == {}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import json
|
||||
from collections.abc import AsyncIterator, MutableSequence
|
||||
from typing import Any
|
||||
|
||||
from agent_framework import ChatAgent, ChatMessage, ChatOptions, ChatResponseUpdate, Content
|
||||
from agent_framework import Agent, ChatOptions, ChatResponseUpdate, Content, Message
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@@ -35,13 +35,13 @@ async def test_structured_output_with_recipe(streaming_chat_client_stub, stream_
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(
|
||||
contents=[Content.from_text(text='{"recipe": {"name": "Pasta"}, "message": "Here is your recipe"}')]
|
||||
)
|
||||
|
||||
agent = ChatAgent(name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
agent.default_options = ChatOptions(response_format=RecipeOutput)
|
||||
|
||||
wrapper = AgentFrameworkAgent(
|
||||
@@ -73,7 +73,7 @@ async def test_structured_output_with_steps(streaming_chat_client_stub, stream_f
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
steps_data = {
|
||||
"steps": [
|
||||
@@ -83,7 +83,7 @@ async def test_structured_output_with_steps(streaming_chat_client_stub, stream_f
|
||||
}
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text=json.dumps(steps_data))])
|
||||
|
||||
agent = ChatAgent(name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
agent.default_options = ChatOptions(response_format=StepsOutput)
|
||||
|
||||
wrapper = AgentFrameworkAgent(
|
||||
@@ -116,8 +116,8 @@ async def test_structured_output_with_no_schema_match(streaming_chat_client_stub
|
||||
ChatResponseUpdate(contents=[Content.from_text(text='{"data": {"key": "value"}}')]),
|
||||
]
|
||||
|
||||
agent = ChatAgent(
|
||||
name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_from_updates_fixture(updates))
|
||||
agent = Agent(
|
||||
name="test", instructions="Test", client=streaming_chat_client_stub(stream_from_updates_fixture(updates))
|
||||
)
|
||||
agent.default_options = ChatOptions(response_format=GenericOutput)
|
||||
|
||||
@@ -149,11 +149,11 @@ async def test_structured_output_without_schema(streaming_chat_client_stub, stre
|
||||
info: str
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text='{"data": {"key": "value"}, "info": "processed"}')])
|
||||
|
||||
agent = ChatAgent(name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
agent.default_options = ChatOptions(response_format=DataOutput)
|
||||
|
||||
wrapper = AgentFrameworkAgent(
|
||||
@@ -182,10 +182,10 @@ async def test_no_structured_output_when_no_response_format(streaming_chat_clien
|
||||
|
||||
updates = [ChatResponseUpdate(contents=[Content.from_text(text="Regular text")])]
|
||||
|
||||
agent = ChatAgent(
|
||||
agent = Agent(
|
||||
name="test",
|
||||
instructions="Test",
|
||||
chat_client=streaming_chat_client_stub(stream_from_updates_fixture(updates)),
|
||||
client=streaming_chat_client_stub(stream_from_updates_fixture(updates)),
|
||||
)
|
||||
# No response_format set
|
||||
|
||||
@@ -208,12 +208,12 @@ async def test_structured_output_with_message_field(streaming_chat_client_stub,
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
output_data = {"recipe": {"name": "Salad"}, "message": "Fresh salad recipe ready"}
|
||||
yield ChatResponseUpdate(contents=[Content.from_text(text=json.dumps(output_data))])
|
||||
|
||||
agent = ChatAgent(name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
agent.default_options = ChatOptions(response_format=RecipeOutput)
|
||||
|
||||
wrapper = AgentFrameworkAgent(
|
||||
@@ -243,12 +243,12 @@ async def test_empty_updates_no_structured_processing(streaming_chat_client_stub
|
||||
from agent_framework.ag_ui import AgentFrameworkAgent
|
||||
|
||||
async def stream_fn(
|
||||
messages: MutableSequence[ChatMessage], options: ChatOptions, **kwargs: Any
|
||||
messages: MutableSequence[Message], options: ChatOptions, **kwargs: Any
|
||||
) -> AsyncIterator[ChatResponseUpdate]:
|
||||
if False:
|
||||
yield ChatResponseUpdate(contents=[])
|
||||
|
||||
agent = ChatAgent(name="test", instructions="Test", chat_client=streaming_chat_client_stub(stream_fn))
|
||||
agent = Agent(name="test", instructions="Test", client=streaming_chat_client_stub(stream_fn))
|
||||
agent.default_options = ChatOptions(response_format=RecipeOutput)
|
||||
|
||||
wrapper = AgentFrameworkAgent(agent=agent)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from agent_framework import ChatAgent, tool
|
||||
from agent_framework import Agent, tool
|
||||
|
||||
from agent_framework_ag_ui._orchestration._tooling import (
|
||||
collect_server_tools,
|
||||
@@ -31,14 +31,14 @@ def regular_tool() -> str:
|
||||
return "result"
|
||||
|
||||
|
||||
def _create_chat_agent_with_tool(tool_name: str = "regular_tool") -> ChatAgent:
|
||||
"""Create a ChatAgent with a mocked chat client and a simple tool.
|
||||
def _create_chat_agent_with_tool(tool_name: str = "regular_tool") -> Agent:
|
||||
"""Create a Agent with a mocked chat client and a simple tool.
|
||||
|
||||
Note: tool_name parameter is kept for API compatibility but the tool
|
||||
will always be named 'regular_tool' since tool uses the function name.
|
||||
"""
|
||||
mock_chat_client = MagicMock()
|
||||
return ChatAgent(chat_client=mock_chat_client, tools=[regular_tool])
|
||||
return Agent(client=mock_chat_client, tools=[regular_tool])
|
||||
|
||||
|
||||
def test_merge_tools_filters_duplicates() -> None:
|
||||
@@ -59,7 +59,7 @@ def test_register_additional_client_tools_assigns_when_configured() -> None:
|
||||
mock_chat_client = MagicMock(spec=BaseChatClient)
|
||||
mock_chat_client.function_invocation_configuration = normalize_function_invocation_configuration(None)
|
||||
|
||||
agent = ChatAgent(chat_client=mock_chat_client)
|
||||
agent = Agent(client=mock_chat_client)
|
||||
|
||||
tools = [DummyTool("x")]
|
||||
register_additional_client_tools(agent, tools)
|
||||
@@ -148,14 +148,14 @@ def test_collect_server_tools_no_default_options() -> None:
|
||||
def test_register_additional_client_tools_no_tools() -> None:
|
||||
"""register_additional_client_tools does nothing with None tools."""
|
||||
mock_chat_client = MagicMock()
|
||||
agent = ChatAgent(chat_client=mock_chat_client)
|
||||
agent = Agent(client=mock_chat_client)
|
||||
|
||||
# Should not raise
|
||||
register_additional_client_tools(agent, None)
|
||||
|
||||
|
||||
def test_register_additional_client_tools_no_chat_client() -> None:
|
||||
"""register_additional_client_tools does nothing when agent has no chat_client."""
|
||||
"""register_additional_client_tools does nothing when agent has no client."""
|
||||
from agent_framework_ag_ui._orchestration._tooling import register_additional_client_tools
|
||||
|
||||
class MockAgent:
|
||||
|
||||
@@ -404,11 +404,11 @@ def test_safe_json_parse_with_none():
|
||||
|
||||
def test_get_role_value_with_enum():
|
||||
"""Test get_role_value with enum role."""
|
||||
from agent_framework import ChatMessage, Content
|
||||
from agent_framework import Content, Message
|
||||
|
||||
from agent_framework_ag_ui._utils import get_role_value
|
||||
|
||||
message = ChatMessage(role="user", contents=[Content.from_text("test")])
|
||||
message = Message(role="user", contents=[Content.from_text("test")])
|
||||
result = get_role_value(message)
|
||||
assert result == "user"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user