mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: [BREAKING] update to v1.0.0 (#5062)
* updates to final deprecated pieces and versions * fix mypy * fix readme links
This commit is contained in:
committed by
GitHub
Unverified
parent
5f06b68535
commit
3446eb8d5d
@@ -136,7 +136,7 @@ from agent_framework import BaseChatClient, ChatResponse, Message
|
||||
class MyClient(BaseChatClient):
|
||||
async def _inner_get_response(self, *, messages, options, **kwargs) -> ChatResponse:
|
||||
# Call your LLM here
|
||||
return ChatResponse(messages=[Message(role="assistant", text="Hi!")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["Hi!"])])
|
||||
|
||||
async def _inner_get_streaming_response(self, *, messages, options, **kwargs):
|
||||
yield ChatResponseUpdate(...)
|
||||
|
||||
@@ -13,11 +13,11 @@ Highlights
|
||||
## Quick Install
|
||||
|
||||
```bash
|
||||
pip install agent-framework-core --pre
|
||||
pip install agent-framework-core
|
||||
# Optional: Add Azure AI Foundry integration
|
||||
pip install agent-framework-foundry --pre
|
||||
pip install agent-framework-foundry
|
||||
# Optional: Add OpenAI integration
|
||||
pip install agent-framework-openai --pre
|
||||
pip install agent-framework-openai
|
||||
```
|
||||
|
||||
Supported Platforms:
|
||||
|
||||
@@ -102,8 +102,6 @@ from ._middleware import (
|
||||
)
|
||||
from ._sessions import (
|
||||
AgentSession,
|
||||
BaseContextProvider, # type: ignore[reportDeprecated]
|
||||
BaseHistoryProvider, # type: ignore[reportDeprecated]
|
||||
ContextProvider,
|
||||
HistoryProvider,
|
||||
InMemoryHistoryProvider,
|
||||
@@ -280,9 +278,7 @@ __all__ = [
|
||||
"Annotation",
|
||||
"BaseAgent",
|
||||
"BaseChatClient",
|
||||
"BaseContextProvider",
|
||||
"BaseEmbeddingClient",
|
||||
"BaseHistoryProvider",
|
||||
"Case",
|
||||
"CharacterEstimatorTokenizer",
|
||||
"ChatAndFunctionMiddlewareTypes",
|
||||
|
||||
@@ -253,7 +253,8 @@ class BaseChatClient(SerializationMixin, ABC, Generic[OptionsCoT]):
|
||||
else:
|
||||
# Non-streaming implementation
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text="Hello!")], response_id="custom-response"
|
||||
messages=[Message(role="assistant", contents=["Hello!"])],
|
||||
response_id="custom-response",
|
||||
)
|
||||
|
||||
|
||||
@@ -261,9 +262,9 @@ class BaseChatClient(SerializationMixin, ABC, Generic[OptionsCoT]):
|
||||
client = CustomChatClient()
|
||||
|
||||
# Use the client to get responses
|
||||
response = await client.get_response([Message(role="user", text="Hello, how are you?")])
|
||||
response = await client.get_response([Message(role="user", contents=["Hello, how are you?"])])
|
||||
# Or stream responses
|
||||
async for update in client.get_response([Message(role="user", text="Hello!")], stream=True):
|
||||
async for update in client.get_response([Message(role="user", contents=["Hello!"])], stream=True):
|
||||
print(update)
|
||||
"""
|
||||
|
||||
|
||||
@@ -877,7 +877,7 @@ class ToolResultCompactionStrategy:
|
||||
insertion_index = starts.get(group_id, 0)
|
||||
summary_message = Message(
|
||||
role="assistant",
|
||||
text=summary_text,
|
||||
contents=[summary_text],
|
||||
message_id=summary_id,
|
||||
additional_properties={
|
||||
GROUP_ANNOTATION_KEY: summary_annotation,
|
||||
@@ -1015,10 +1015,10 @@ class SummarizationStrategy:
|
||||
try:
|
||||
summary_response: ChatResponse[None] = await self.client.get_response(
|
||||
[
|
||||
Message(role="system", text=self.prompt),
|
||||
Message(role="system", contents=[self.prompt]),
|
||||
Message(
|
||||
role="user",
|
||||
text=_format_messages_for_summary(messages_to_summarize),
|
||||
contents=[_format_messages_for_summary(messages_to_summarize)],
|
||||
),
|
||||
],
|
||||
stream=False,
|
||||
@@ -1044,7 +1044,7 @@ class SummarizationStrategy:
|
||||
|
||||
summary_message = Message(
|
||||
role="assistant",
|
||||
text=summary_text,
|
||||
contents=[summary_text],
|
||||
message_id=summary_id,
|
||||
additional_properties={
|
||||
GROUP_ANNOTATION_KEY: summary_annotation,
|
||||
|
||||
@@ -502,7 +502,7 @@ class ChatMiddleware(ABC):
|
||||
# Add system prompt to messages
|
||||
from agent_framework import Message
|
||||
|
||||
context.messages.insert(0, Message(role="system", text=self.system_prompt))
|
||||
context.messages.insert(0, Message(role="system", contents=[self.system_prompt]))
|
||||
|
||||
# Continue execution
|
||||
await call_next()
|
||||
|
||||
@@ -40,7 +40,7 @@ class SerializationProtocol(Protocol):
|
||||
|
||||
|
||||
# Message implements SerializationProtocol via SerializationMixin
|
||||
user_msg = Message(role="user", text="What's the weather like today?")
|
||||
user_msg = Message(role="user", contents=["What's the weather like today?"])
|
||||
|
||||
# Serialize to dictionary - automatic type identification and nested serialization
|
||||
msg_dict = user_msg.to_dict()
|
||||
|
||||
@@ -13,17 +13,11 @@ This module provides the core types for the context provider pipeline:
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import sys
|
||||
import uuid
|
||||
from abc import abstractmethod
|
||||
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
||||
from typing import TYPE_CHECKING, Any, ClassVar, TypeGuard, cast
|
||||
|
||||
if sys.version_info >= (3, 13):
|
||||
from warnings import deprecated # type: ignore # pragma: no cover
|
||||
else:
|
||||
from typing_extensions import deprecated # type: ignore # pragma: no cover
|
||||
|
||||
from ._middleware import ChatContext, ChatMiddleware
|
||||
from ._types import AgentResponse, ChatResponse, Message, ResponseStream
|
||||
from .exceptions import ChatClientInvalidResponseException
|
||||
@@ -698,30 +692,6 @@ class PerServiceCallHistoryPersistingMiddleware(ChatMiddleware):
|
||||
)
|
||||
|
||||
|
||||
@deprecated(
|
||||
"BaseContextProvider is deprecated. Use ContextProvider instead.",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
class BaseContextProvider(ContextProvider):
|
||||
"""Deprecated alias for :class:`ContextProvider`.
|
||||
|
||||
.. deprecated::
|
||||
BaseContextProvider is deprecated. Use :class:`ContextProvider` instead.
|
||||
"""
|
||||
|
||||
|
||||
@deprecated(
|
||||
"BaseHistoryProvider is deprecated. Use HistoryProvider instead.",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
class BaseHistoryProvider(HistoryProvider):
|
||||
"""Deprecated alias for :class:`HistoryProvider`.
|
||||
|
||||
.. deprecated::
|
||||
BaseHistoryProvider is deprecated. Use :class:`HistoryProvider` instead.
|
||||
"""
|
||||
|
||||
|
||||
class AgentSession:
|
||||
"""A conversation session with an agent.
|
||||
|
||||
|
||||
@@ -1669,7 +1669,6 @@ class Message(SerializationMixin):
|
||||
role: RoleLiteral | str,
|
||||
contents: Sequence[Content | str | Mapping[str, Any]] | None = None,
|
||||
*,
|
||||
text: str | None = None,
|
||||
author_name: str | None = None,
|
||||
message_id: str | None = None,
|
||||
additional_properties: MutableMapping[str, Any] | None = None,
|
||||
@@ -1683,21 +1682,14 @@ class Message(SerializationMixin):
|
||||
to TextContent), or dicts (parsed via Content.from_dict). Defaults to empty list.
|
||||
|
||||
Keyword Args:
|
||||
text: Deprecated. Text content of the message. Use contents instead.
|
||||
This parameter is kept for backward compatibility with serialization.
|
||||
author_name: Optional name of the author of the message.
|
||||
message_id: Optional ID of the chat message.
|
||||
additional_properties: Optional additional properties associated with the chat message.
|
||||
Additional properties are used within Agent Framework, they are not sent to services.
|
||||
raw_representation: Optional raw representation of the chat message.
|
||||
"""
|
||||
# Handle contents conversion
|
||||
parsed_contents = [] if contents is None else _parse_content_list(contents)
|
||||
|
||||
# Handle text for backward compatibility (from serialization)
|
||||
if text is not None:
|
||||
parsed_contents.append(Content.from_text(text=text))
|
||||
|
||||
self.role: str = role
|
||||
self.contents = parsed_contents
|
||||
self.author_name = author_name
|
||||
|
||||
@@ -21,7 +21,7 @@ def normalize_messages_input(
|
||||
return []
|
||||
|
||||
if isinstance(messages, str):
|
||||
return [Message(role="user", text=messages)]
|
||||
return [Message(role="user", contents=[messages])]
|
||||
|
||||
if isinstance(messages, Content):
|
||||
return [Message(role="user", contents=[messages])]
|
||||
@@ -31,9 +31,7 @@ def normalize_messages_input(
|
||||
|
||||
normalized: list[Message] = []
|
||||
for item in messages:
|
||||
if isinstance(item, str):
|
||||
normalized.append(Message(role="user", text=item))
|
||||
elif isinstance(item, Content):
|
||||
if isinstance(item, (str, Content)):
|
||||
normalized.append(Message(role="user", contents=[item]))
|
||||
elif isinstance(item, Message):
|
||||
normalized.append(item)
|
||||
|
||||
@@ -4,7 +4,7 @@ description = "Microsoft Agent Framework for building AI Agents with Python. Thi
|
||||
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
version = "1.0.0rc6"
|
||||
version = "1.0.0"
|
||||
license-files = ["LICENSE"]
|
||||
urls.homepage = "https://aka.ms/agent-framework"
|
||||
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
|
||||
@@ -12,7 +12,7 @@ urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=ta
|
||||
urls.issues = "https://github.com/microsoft/agent-framework/issues"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Development Status :: 4 - Beta",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
|
||||
@@ -105,7 +105,7 @@ class MockChatClient:
|
||||
self.call_count += 1
|
||||
if self.responses:
|
||||
return self.responses.pop(0)
|
||||
return ChatResponse(messages=Message(role="assistant", text="test response"))
|
||||
return ChatResponse(messages=Message(role="assistant", contents=["test response"]))
|
||||
|
||||
return _get()
|
||||
|
||||
@@ -186,7 +186,7 @@ class MockBaseChatClient(
|
||||
logger.debug(f"Running base chat client inner, with: {messages=}, {options=}, {kwargs=}")
|
||||
self.call_count += 1
|
||||
if not self.run_responses:
|
||||
return ChatResponse(messages=Message(role="assistant", text=f"test response - {messages[-1].text}"))
|
||||
return ChatResponse(messages=Message(role="assistant", contents=[f"test response - {messages[-1].text}"]))
|
||||
|
||||
response = self.run_responses.pop(0)
|
||||
|
||||
@@ -194,7 +194,7 @@ class MockBaseChatClient(
|
||||
return ChatResponse(
|
||||
messages=Message(
|
||||
role="assistant",
|
||||
text="I broke out of the function invocation loop...",
|
||||
contents=["I broke out of the function invocation loop..."],
|
||||
),
|
||||
conversation_id=response.conversation_id,
|
||||
)
|
||||
|
||||
@@ -306,7 +306,7 @@ async def test_chat_client_agent_response_format_dict_from_default_options(
|
||||
) -> None:
|
||||
"""AgentResponse.value should parse JSON dicts from default_options response_format."""
|
||||
json_text = json.dumps({"greeting": "Hello"})
|
||||
client.responses.append(ChatResponse(messages=Message(role="assistant", text=json_text))) # type: ignore[attr-defined]
|
||||
client.responses.append(ChatResponse(messages=Message(role="assistant", contents=[json_text]))) # type: ignore[attr-defined]
|
||||
|
||||
agent = Agent(
|
||||
client=client,
|
||||
@@ -366,13 +366,13 @@ async def test_chat_client_agent_prepare_session_and_messages(
|
||||
from agent_framework._sessions import InMemoryHistoryProvider
|
||||
|
||||
agent = Agent(client=client, context_providers=[InMemoryHistoryProvider()])
|
||||
message = Message(role="user", text="Hello")
|
||||
message = Message(role="user", contents=["Hello"])
|
||||
session = AgentSession()
|
||||
session.state[InMemoryHistoryProvider.DEFAULT_SOURCE_ID] = {"messages": [message]}
|
||||
|
||||
session_context, _ = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=session,
|
||||
input_messages=[Message(role="user", text="Test")],
|
||||
input_messages=[Message(role="user", contents=["Test"])],
|
||||
)
|
||||
result_messages = session_context.get_messages(include_input=True)
|
||||
|
||||
@@ -393,7 +393,7 @@ async def test_prepare_session_does_not_mutate_agent_chat_options(
|
||||
|
||||
_, prepared_chat_options = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=session,
|
||||
input_messages=[Message(role="user", text="Test")],
|
||||
input_messages=[Message(role="user", contents=["Test"])],
|
||||
)
|
||||
|
||||
assert prepared_chat_options.get("tools") is not None
|
||||
@@ -444,8 +444,8 @@ async def test_chat_agent_persists_history_per_service_call(
|
||||
session = AgentSession()
|
||||
session.state[provider.source_id] = {
|
||||
"messages": [
|
||||
Message(role="user", text="Earlier question"),
|
||||
Message(role="assistant", text="Earlier answer"),
|
||||
Message(role="user", contents=["Earlier question"]),
|
||||
Message(role="assistant", contents=["Earlier answer"]),
|
||||
]
|
||||
}
|
||||
chat_client_base.run_responses = [
|
||||
@@ -462,7 +462,9 @@ async def test_chat_agent_persists_history_per_service_call(
|
||||
),
|
||||
response_id="resp_call_1",
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="It is sunny in Seattle."), response_id="resp_call_2"),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", contents=["It is sunny in Seattle."]), response_id="resp_call_2"
|
||||
),
|
||||
]
|
||||
|
||||
agent = Agent(
|
||||
@@ -498,8 +500,8 @@ async def test_chat_agent_persists_history_per_service_call_streaming(
|
||||
session = AgentSession()
|
||||
session.state[provider.source_id] = {
|
||||
"messages": [
|
||||
Message(role="user", text="Earlier question"),
|
||||
Message(role="assistant", text="Earlier answer"),
|
||||
Message(role="user", contents=["Earlier question"]),
|
||||
Message(role="assistant", contents=["Earlier answer"]),
|
||||
]
|
||||
}
|
||||
chat_client_base.streaming_responses = [
|
||||
@@ -634,7 +636,7 @@ async def test_per_service_call_persistence_uses_real_service_storage_when_clien
|
||||
response_id="resp_call_1",
|
||||
),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="It is sunny in Seattle."),
|
||||
messages=Message(role="assistant", contents=["It is sunny in Seattle."]),
|
||||
conversation_id="resp_service_managed",
|
||||
response_id="resp_call_2",
|
||||
),
|
||||
@@ -777,7 +779,7 @@ async def test_chat_agent_without_per_service_call_persistence_preserves_respons
|
||||
) -> None:
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="Hello"),
|
||||
messages=Message(role="assistant", contents=["Hello"]),
|
||||
response_id="resp_call_1",
|
||||
)
|
||||
]
|
||||
@@ -801,7 +803,7 @@ async def test_per_service_call_persistence_rejects_real_service_conversation_id
|
||||
session.state[provider.source_id] = {"messages": []}
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="Hello"),
|
||||
messages=Message(role="assistant", contents=["Hello"]),
|
||||
conversation_id="resp_service_managed",
|
||||
)
|
||||
]
|
||||
@@ -1138,7 +1140,7 @@ async def test_chat_agent_context_providers_model_before_run(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
"""Test that context providers' before_run is called during agent run."""
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", text="Test context instructions")])
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", contents=["Test context instructions"])])
|
||||
agent = Agent(client=client, context_providers=[mock_provider])
|
||||
|
||||
await agent.run("Hello")
|
||||
@@ -1185,7 +1187,7 @@ async def test_chat_agent_context_instructions_in_messages(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
"""Test that AI context instructions are included in messages."""
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", text="Context-specific instructions")])
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", contents=["Context-specific instructions"])])
|
||||
agent = Agent(
|
||||
client=client,
|
||||
instructions="Agent instructions",
|
||||
@@ -1194,7 +1196,7 @@ async def test_chat_agent_context_instructions_in_messages(
|
||||
|
||||
# We need to test the _prepare_session_and_messages method directly
|
||||
session_context, _ = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=None, input_messages=[Message(role="user", text="Hello")]
|
||||
session=None, input_messages=[Message(role="user", contents=["Hello"])]
|
||||
)
|
||||
messages = session_context.get_messages(include_input=True)
|
||||
|
||||
@@ -1219,7 +1221,7 @@ async def test_chat_agent_no_context_instructions(
|
||||
)
|
||||
|
||||
session_context, _ = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=None, input_messages=[Message(role="user", text="Hello")]
|
||||
session=None, input_messages=[Message(role="user", contents=["Hello"])]
|
||||
)
|
||||
messages = session_context.get_messages(include_input=True)
|
||||
|
||||
@@ -1233,7 +1235,7 @@ async def test_chat_agent_run_stream_context_providers(
|
||||
client: SupportsChatGetResponse,
|
||||
) -> None:
|
||||
"""Test that context providers work with run method."""
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", text="Stream context instructions")])
|
||||
mock_provider = MockContextProvider(messages=[Message(role="system", contents=["Stream context instructions"])])
|
||||
agent = Agent(client=client, context_providers=[mock_provider])
|
||||
|
||||
# Collect all stream updates and get final response
|
||||
@@ -1727,7 +1729,7 @@ async def test_agent_tool_without_context_does_not_receive_session(chat_client_b
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, tools=[echo_session_info])
|
||||
@@ -1766,7 +1768,7 @@ async def test_agent_tool_receives_explicit_session_via_function_invocation_cont
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, tools=[capture_session_context])
|
||||
@@ -1899,8 +1901,8 @@ async def test_chat_agent_compaction_overrides_client_defaults(chat_client_base:
|
||||
)
|
||||
|
||||
await agent.run([
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
])
|
||||
|
||||
assert captured_roles == [["user", "assistant"]]
|
||||
@@ -1924,8 +1926,8 @@ async def test_chat_agent_uses_client_compaction_defaults_when_agent_unset(chat_
|
||||
agent = Agent(client=chat_client_base)
|
||||
|
||||
await agent.run([
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
])
|
||||
|
||||
assert captured_roles == [["assistant"]]
|
||||
@@ -1957,8 +1959,8 @@ async def test_chat_agent_run_level_compaction_and_tokenizer_override_agent_defa
|
||||
|
||||
await agent.run(
|
||||
[
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
],
|
||||
compaction_strategy=TruncationStrategy(max_n=1, compact_to=1),
|
||||
tokenizer=_FixedTokenizer(23),
|
||||
@@ -2352,7 +2354,7 @@ async def test_chat_agent_context_provider_adds_tools_when_agent_has_none(
|
||||
|
||||
# Run the agent and verify context tools are added
|
||||
_, options = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=None, input_messages=[Message(role="user", text="Hello")]
|
||||
session=None, input_messages=[Message(role="user", contents=["Hello"])]
|
||||
)
|
||||
|
||||
# The context tools should now be in the options
|
||||
@@ -2381,7 +2383,7 @@ async def test_chat_agent_context_provider_adds_instructions_when_agent_has_none
|
||||
|
||||
# Run the agent and verify context instructions are available
|
||||
_, options = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=None, input_messages=[Message(role="user", text="Hello")]
|
||||
session=None, input_messages=[Message(role="user", contents=["Hello"])]
|
||||
)
|
||||
|
||||
# The context instructions should now be in the options
|
||||
@@ -2408,7 +2410,7 @@ async def test_chat_agent_context_provider_adds_middleware_when_agent_has_none(
|
||||
|
||||
session_context, _ = await agent._prepare_session_and_messages( # type: ignore[reportPrivateUsage]
|
||||
session=None,
|
||||
input_messages=[Message(role="user", text="Hello")],
|
||||
input_messages=[Message(role="user", contents=["Hello"])],
|
||||
)
|
||||
|
||||
assert session_context.middleware["middleware-context"] == [context_chat_middleware]
|
||||
|
||||
@@ -40,7 +40,7 @@ class TestAsToolKwargsPropagation:
|
||||
|
||||
# Setup mock response
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from sub-agent")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from sub-agent"])]),
|
||||
]
|
||||
|
||||
# Create sub-agent with middleware
|
||||
@@ -82,7 +82,7 @@ class TestAsToolKwargsPropagation:
|
||||
|
||||
# Setup mock response
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from sub-agent")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from sub-agent"])]),
|
||||
]
|
||||
|
||||
sub_agent = Agent(
|
||||
@@ -133,8 +133,8 @@ class TestAsToolKwargsPropagation:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from agent_c")]),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from agent_b")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from agent_c"])]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from agent_b"])]),
|
||||
]
|
||||
|
||||
# Create agent C (bottom level)
|
||||
@@ -219,7 +219,7 @@ class TestAsToolKwargsPropagation:
|
||||
"""Test that as_tool works correctly when no extra kwargs are provided."""
|
||||
# Setup mock response
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from agent")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from agent"])]),
|
||||
]
|
||||
|
||||
sub_agent = Agent(
|
||||
@@ -248,7 +248,7 @@ class TestAsToolKwargsPropagation:
|
||||
|
||||
# Setup mock response
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response with options")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response with options"])]),
|
||||
]
|
||||
|
||||
sub_agent = Agent(
|
||||
@@ -295,8 +295,8 @@ class TestAsToolKwargsPropagation:
|
||||
|
||||
# Setup mock responses for both calls
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="First response")]),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Second response")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["First response"])]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Second response"])]),
|
||||
]
|
||||
|
||||
sub_agent = Agent(
|
||||
@@ -342,7 +342,7 @@ class TestAsToolKwargsPropagation:
|
||||
|
||||
# Setup mock response
|
||||
client.responses = [
|
||||
ChatResponse(messages=[Message(role="assistant", text="Response from sub-agent")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Response from sub-agent"])]),
|
||||
]
|
||||
|
||||
sub_agent = Agent(
|
||||
|
||||
@@ -31,13 +31,13 @@ def test_chat_client_type(client: SupportsChatGetResponse):
|
||||
|
||||
|
||||
async def test_chat_client_get_response(client: SupportsChatGetResponse):
|
||||
response = await client.get_response([Message(role="user", text="Hello")])
|
||||
response = await client.get_response([Message(role="user", contents=["Hello"])])
|
||||
assert response.text == "test response"
|
||||
assert response.messages[0].role == "assistant"
|
||||
|
||||
|
||||
async def test_chat_client_get_response_streaming(client: SupportsChatGetResponse):
|
||||
async for update in client.get_response([Message(role="user", text="Hello")], stream=True):
|
||||
async for update in client.get_response([Message(role="user", contents=["Hello"])], stream=True):
|
||||
assert update.text == "test streaming response " or update.text == "another update"
|
||||
assert update.role == "assistant"
|
||||
|
||||
@@ -62,7 +62,7 @@ async def test_base_client_get_response_uses_explicit_client_kwargs(chat_client_
|
||||
async def fake_inner_get_response(**kwargs):
|
||||
assert kwargs["trace_id"] == "trace-123"
|
||||
assert "function_invocation_kwargs" not in kwargs
|
||||
return ChatResponse(messages=[Message(role="assistant", text="ok")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["ok"])])
|
||||
|
||||
with patch.object(
|
||||
chat_client_base,
|
||||
@@ -70,7 +70,7 @@ async def test_base_client_get_response_uses_explicit_client_kwargs(chat_client_
|
||||
side_effect=fake_inner_get_response,
|
||||
) as mock_inner_get_response:
|
||||
await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
function_invocation_kwargs={"tool_request_id": "tool-123"},
|
||||
client_kwargs={"trace_id": "trace-123"},
|
||||
)
|
||||
@@ -78,13 +78,13 @@ async def test_base_client_get_response_uses_explicit_client_kwargs(chat_client_
|
||||
|
||||
|
||||
async def test_base_client_get_response(chat_client_base: SupportsChatGetResponse):
|
||||
response = await chat_client_base.get_response([Message(role="user", text="Hello")])
|
||||
response = await chat_client_base.get_response([Message(role="user", contents=["Hello"])])
|
||||
assert response.messages[0].role == "assistant"
|
||||
assert response.messages[0].text == "test response - Hello"
|
||||
|
||||
|
||||
async def test_base_client_get_response_streaming(chat_client_base: SupportsChatGetResponse):
|
||||
async for update in chat_client_base.get_response([Message(role="user", text="Hello")], stream=True):
|
||||
async for update in chat_client_base.get_response([Message(role="user", contents=["Hello"])], stream=True):
|
||||
assert update.text == "update - Hello" or update.text == "another update"
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@ async def test_base_client_applies_compaction_before_non_streaming_inner_call(
|
||||
|
||||
chat_client_base._get_non_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
await chat_client_base.get_response([
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
])
|
||||
assert captured_roles == [["assistant"]]
|
||||
|
||||
@@ -133,8 +133,8 @@ async def test_base_client_applies_compaction_before_streaming_inner_call(
|
||||
chat_client_base._get_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
async for _ in chat_client_base.get_response(
|
||||
[
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
],
|
||||
stream=True,
|
||||
):
|
||||
@@ -161,8 +161,8 @@ async def test_base_client_per_call_compaction_override_applies_before_inner_cal
|
||||
chat_client_base._get_non_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
await chat_client_base.get_response(
|
||||
[
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
],
|
||||
compaction_strategy=TruncationStrategy(max_n=1, compact_to=1),
|
||||
)
|
||||
@@ -191,8 +191,8 @@ async def test_base_client_per_call_tokenizer_override_annotates_messages(
|
||||
chat_client_base._get_non_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
await chat_client_base.get_response(
|
||||
[
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
],
|
||||
compaction_strategy=SlidingWindowStrategy(keep_last_groups=2),
|
||||
tokenizer=_FixedTokenizer(17),
|
||||
@@ -222,8 +222,8 @@ async def test_base_client_per_call_tokenizer_override_without_strategy_annotate
|
||||
chat_client_base._get_non_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
await chat_client_base.get_response(
|
||||
[
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
],
|
||||
tokenizer=_FixedTokenizer(17),
|
||||
)
|
||||
@@ -252,8 +252,8 @@ async def test_base_client_default_tokenizer_without_strategy_annotates_messages
|
||||
|
||||
chat_client_base._get_non_streaming_response = _capture # type: ignore[attr-defined,method-assign]
|
||||
await chat_client_base.get_response([
|
||||
Message(role="user", text="Hello"),
|
||||
Message(role="assistant", text="Previous response"),
|
||||
Message(role="user", contents=["Hello"]),
|
||||
Message(role="assistant", contents=["Previous response"]),
|
||||
])
|
||||
assert captured_token_counts == [[19, 19]]
|
||||
|
||||
@@ -276,7 +276,7 @@ async def test_chat_client_instructions_handling(chat_client_base: SupportsChatG
|
||||
instructions = "You are a helpful assistant."
|
||||
|
||||
async def fake_inner_get_response(**kwargs):
|
||||
return ChatResponse(messages=[Message(role="assistant", text="ok")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["ok"])])
|
||||
|
||||
with patch.object(
|
||||
chat_client_base,
|
||||
@@ -284,7 +284,7 @@ async def test_chat_client_instructions_handling(chat_client_base: SupportsChatG
|
||||
side_effect=fake_inner_get_response,
|
||||
) as mock_inner_get_response:
|
||||
await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"instructions": instructions}
|
||||
[Message(role="user", contents=["hello"])], options={"instructions": instructions}
|
||||
)
|
||||
mock_inner_get_response.assert_called_once()
|
||||
_, kwargs = mock_inner_get_response.call_args
|
||||
@@ -296,7 +296,7 @@ async def test_chat_client_instructions_handling(chat_client_base: SupportsChatG
|
||||
from agent_framework._types import prepend_instructions_to_messages
|
||||
|
||||
appended_messages = prepend_instructions_to_messages(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
instructions,
|
||||
)
|
||||
assert len(appended_messages) == 2
|
||||
|
||||
@@ -105,10 +105,10 @@ def _group_unknown_value(message: Message, key: str) -> Any:
|
||||
|
||||
def test_group_annotations_keep_tool_call_and_tool_result_atomic() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="user", contents=["hello"]),
|
||||
_assistant_function_call("c1"),
|
||||
_tool_result("c1", "ok"),
|
||||
Message(role="assistant", text="final"),
|
||||
Message(role="assistant", contents=["final"]),
|
||||
]
|
||||
|
||||
annotate_message_groups(messages)
|
||||
@@ -136,11 +136,11 @@ def test_group_annotations_include_reasoning_in_tool_call_group() -> None:
|
||||
|
||||
def test_group_annotations_handle_same_message_reasoning_and_function_calls() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="user", contents=["hello"]),
|
||||
_assistant_reasoning_and_function_calls("c1", "c2"),
|
||||
_tool_result("c1", "ok1"),
|
||||
_tool_result("c2", "ok2"),
|
||||
Message(role="assistant", text="final"),
|
||||
Message(role="assistant", contents=["final"]),
|
||||
]
|
||||
|
||||
annotate_message_groups(messages)
|
||||
@@ -155,8 +155,8 @@ def test_group_annotations_handle_same_message_reasoning_and_function_calls() ->
|
||||
|
||||
def test_annotate_message_groups_with_tokenizer_adds_token_counts() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="assistant", text="world"),
|
||||
Message(role="user", contents=["hello"]),
|
||||
Message(role="assistant", contents=["world"]),
|
||||
]
|
||||
|
||||
annotate_message_groups(
|
||||
@@ -187,9 +187,9 @@ def test_extend_compaction_messages_preserves_existing_annotations_and_tokens()
|
||||
|
||||
|
||||
def test_append_compaction_message_annotates_new_message() -> None:
|
||||
messages = [Message(role="user", text="hello")]
|
||||
messages = [Message(role="user", contents=["hello"])]
|
||||
annotate_message_groups(messages)
|
||||
append_compaction_message(messages, Message(role="assistant", text="world"))
|
||||
append_compaction_message(messages, Message(role="assistant", contents=["world"]))
|
||||
|
||||
assert len(messages) == 2
|
||||
assert isinstance(_group_id(messages[1]), str)
|
||||
@@ -197,11 +197,11 @@ def test_append_compaction_message_annotates_new_message() -> None:
|
||||
|
||||
async def test_truncation_strategy_keeps_system_anchor() -> None:
|
||||
messages = [
|
||||
Message(role="system", text="you are helpful"),
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="system", contents=["you are helpful"]),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
]
|
||||
strategy = TruncationStrategy(max_n=3, compact_to=3, preserve_system=True)
|
||||
annotate_message_groups(messages)
|
||||
@@ -217,9 +217,9 @@ async def test_truncation_strategy_keeps_system_anchor() -> None:
|
||||
async def test_truncation_strategy_compacts_when_token_limit_exceeded() -> None:
|
||||
tokenizer = CharacterEstimatorTokenizer()
|
||||
messages = [
|
||||
Message(role="system", text="you are helpful"),
|
||||
Message(role="user", text="u1 " * 200),
|
||||
Message(role="assistant", text="a1 " * 200),
|
||||
Message(role="system", contents=["you are helpful"]),
|
||||
Message(role="user", contents=["u1 " * 200]),
|
||||
Message(role="assistant", contents=["a1 " * 200]),
|
||||
]
|
||||
strategy = TruncationStrategy(
|
||||
max_n=80,
|
||||
@@ -248,12 +248,12 @@ def test_truncation_strategy_validates_token_targets() -> None:
|
||||
|
||||
async def test_selective_tool_call_strategy_excludes_older_tool_groups() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
_assistant_function_call("call-2"),
|
||||
_tool_result("call-2", "r2"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=1)
|
||||
annotate_message_groups(messages)
|
||||
@@ -269,10 +269,10 @@ async def test_selective_tool_call_strategy_excludes_older_tool_groups() -> None
|
||||
|
||||
async def test_selective_tool_call_strategy_with_zero_removes_assistant_tool_pair() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = SelectiveToolCallCompactionStrategy(keep_last_tool_call_groups=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -304,7 +304,7 @@ class _FakeSummarizer:
|
||||
options: dict[str, Any] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> ChatResponse:
|
||||
return ChatResponse(messages=[Message(role="assistant", text="summarized context")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["summarized context"])])
|
||||
|
||||
|
||||
class _FailingSummarizer:
|
||||
@@ -328,17 +328,17 @@ class _EmptySummarizer:
|
||||
options: dict[str, Any] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> ChatResponse:
|
||||
return ChatResponse(messages=[Message(role="assistant", text=" ")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=[" "])])
|
||||
|
||||
|
||||
async def test_summarization_strategy_adds_bidirectional_trace_links() -> None:
|
||||
messages = [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", text="u3"),
|
||||
Message(role="assistant", text="a3"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
Message(role="user", contents=["u3"]),
|
||||
Message(role="assistant", contents=["a3"]),
|
||||
]
|
||||
strategy = SummarizationStrategy(client=_FakeSummarizer(), target_count=2, threshold=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -366,12 +366,12 @@ async def test_summarization_strategy_returns_false_when_summary_generation_fail
|
||||
caplog: Any,
|
||||
) -> None:
|
||||
messages = [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", text="u3"),
|
||||
Message(role="assistant", text="a3"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
Message(role="user", contents=["u3"]),
|
||||
Message(role="assistant", contents=["a3"]),
|
||||
]
|
||||
strategy = SummarizationStrategy(client=_FailingSummarizer(), target_count=2, threshold=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -388,12 +388,12 @@ async def test_summarization_strategy_returns_false_when_summary_is_empty(
|
||||
caplog: Any,
|
||||
) -> None:
|
||||
messages = [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", text="u3"),
|
||||
Message(role="assistant", text="a3"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
Message(role="user", contents=["u3"]),
|
||||
Message(role="assistant", contents=["a3"]),
|
||||
]
|
||||
strategy = SummarizationStrategy(client=_EmptySummarizer(), target_count=2, threshold=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -408,9 +408,9 @@ async def test_summarization_strategy_returns_false_when_summary_is_empty(
|
||||
|
||||
async def test_token_budget_composed_strategy_meets_budget_or_falls_back() -> None:
|
||||
messages = [
|
||||
Message(role="system", text="system"),
|
||||
Message(role="user", text="user " * 200),
|
||||
Message(role="assistant", text="assistant " * 200),
|
||||
Message(role="system", contents=["system"]),
|
||||
Message(role="user", contents=["user " * 200]),
|
||||
Message(role="assistant", contents=["assistant " * 200]),
|
||||
]
|
||||
strategy = TokenBudgetComposedStrategy(
|
||||
token_budget=20,
|
||||
@@ -445,9 +445,9 @@ class _ExcludeOldestNonSystem:
|
||||
|
||||
async def test_apply_compaction_projects_included_messages_only() -> None:
|
||||
messages = [
|
||||
Message(role="system", text="sys"),
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="assistant", text="world"),
|
||||
Message(role="system", contents=["sys"]),
|
||||
Message(role="user", contents=["hello"]),
|
||||
Message(role="assistant", contents=["world"]),
|
||||
]
|
||||
|
||||
projected = await apply_compaction(messages, strategy=_ExcludeOldestNonSystem())
|
||||
@@ -462,12 +462,12 @@ async def test_apply_compaction_projects_included_messages_only() -> None:
|
||||
async def test_tool_result_compaction_collapses_old_groups_into_summary() -> None:
|
||||
"""Old tool-call groups are collapsed into summary messages, newest kept."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
_assistant_function_call("call-2"),
|
||||
_tool_result("call-2", "r2"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
|
||||
annotate_message_groups(messages)
|
||||
@@ -486,12 +486,12 @@ async def test_tool_result_compaction_collapses_old_groups_into_summary() -> Non
|
||||
async def test_tool_result_compaction_zero_collapses_all() -> None:
|
||||
"""With keep=0, all tool-call groups are collapsed into summaries."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
_assistant_function_call("call-2"),
|
||||
_tool_result("call-2", "r2"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -508,7 +508,7 @@ async def test_tool_result_compaction_zero_collapses_all() -> None:
|
||||
async def test_tool_result_compaction_no_change_when_within_limit() -> None:
|
||||
"""No compaction when tool groups count does not exceed keep limit."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
]
|
||||
@@ -532,7 +532,7 @@ def test_tool_result_compaction_rejects_negative() -> None:
|
||||
async def test_tool_result_compaction_preserves_tool_results_in_summary() -> None:
|
||||
"""Summary text should include the tool results from the collapsed group."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[
|
||||
@@ -542,7 +542,7 @@ async def test_tool_result_compaction_preserves_tool_results_in_summary() -> Non
|
||||
),
|
||||
_tool_result("c1", "sunny"),
|
||||
_tool_result("c2", "found 3 docs"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -559,10 +559,10 @@ async def test_tool_result_compaction_preserves_tool_results_in_summary() -> Non
|
||||
async def test_tool_result_compaction_bidirectional_tracing() -> None:
|
||||
"""Summary and originals should link to each other like SummarizationStrategy does."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("call-1"),
|
||||
_tool_result("call-1", "r1"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -594,10 +594,10 @@ async def test_tool_result_compaction_bidirectional_tracing() -> None:
|
||||
async def test_tool_result_compaction_summary_has_full_annotations() -> None:
|
||||
"""Summary messages inserted by ToolResultCompactionStrategy must have all compaction annotations."""
|
||||
messages = [
|
||||
Message(role="user", text="u"),
|
||||
Message(role="user", contents=["u"]),
|
||||
_assistant_function_call("c1"),
|
||||
_tool_result("c1", "r1"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -617,12 +617,12 @@ async def test_tool_result_compaction_summary_has_full_annotations() -> None:
|
||||
async def test_summarization_strategy_summary_has_full_annotations() -> None:
|
||||
"""Summary messages inserted by SummarizationStrategy must have all compaction annotations."""
|
||||
messages = [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", text="u3"),
|
||||
Message(role="assistant", text="a3"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
Message(role="user", contents=["u3"]),
|
||||
Message(role="assistant", contents=["a3"]),
|
||||
]
|
||||
strategy = SummarizationStrategy(client=_FakeSummarizer(), target_count=2, threshold=0)
|
||||
annotate_message_groups(messages)
|
||||
@@ -647,14 +647,14 @@ async def test_tool_result_compaction_multiple_groups_combined() -> None:
|
||||
separate summary, group 3 stays verbatim.
|
||||
"""
|
||||
messages = [
|
||||
Message(role="user", text="Compare weather in London, Paris, and Tokyo"),
|
||||
Message(role="user", contents=["Compare weather in London, Paris, and Tokyo"]),
|
||||
# Group 1: get_weather for London
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_function_call(call_id="c1", name="get_weather", arguments='{"city":"London"}')],
|
||||
),
|
||||
_tool_result("c1", '{"temp":12,"condition":"cloudy","wind":"NW 15km/h"}'),
|
||||
Message(role="assistant", text="London is cloudy at 12°C."),
|
||||
Message(role="assistant", contents=["London is cloudy at 12°C."]),
|
||||
# Group 2: get_weather for Paris + search_hotels
|
||||
Message(
|
||||
role="assistant",
|
||||
@@ -665,14 +665,14 @@ async def test_tool_result_compaction_multiple_groups_combined() -> None:
|
||||
),
|
||||
_tool_result("c2", '{"temp":18,"condition":"sunny"}'),
|
||||
_tool_result("c3", "Grand Hotel (€120), Le Petit (€85)"),
|
||||
Message(role="assistant", text="Paris is sunny at 18°C. Found 2 hotels."),
|
||||
Message(role="assistant", contents=["Paris is sunny at 18°C. Found 2 hotels."]),
|
||||
# Group 3: get_weather for Tokyo (most recent — should be kept)
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_function_call(call_id="c4", name="get_weather", arguments='{"city":"Tokyo"}')],
|
||||
),
|
||||
_tool_result("c4", '{"temp":22,"condition":"rainy"}'),
|
||||
Message(role="assistant", text="Tokyo is rainy at 22°C."),
|
||||
Message(role="assistant", contents=["Tokyo is rainy at 22°C."]),
|
||||
]
|
||||
strategy = ToolResultCompactionStrategy(keep_last_tool_call_groups=1)
|
||||
annotate_message_groups(messages)
|
||||
@@ -758,13 +758,13 @@ async def test_compaction_provider_compacts_existing_context_messages() -> None:
|
||||
|
||||
context = _MockSessionContext()
|
||||
context.context_messages["history"] = [
|
||||
Message(role="system", text="sys"),
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", text="u3"),
|
||||
Message(role="assistant", text="a3"),
|
||||
Message(role="system", contents=["sys"]),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
Message(role="user", contents=["u3"]),
|
||||
Message(role="assistant", contents=["a3"]),
|
||||
]
|
||||
|
||||
await provider.before_run(agent=None, session=None, context=context, state={})
|
||||
@@ -796,13 +796,13 @@ async def test_compaction_provider_preserves_messages_from_multiple_sources() ->
|
||||
|
||||
context = _MockSessionContext()
|
||||
context.context_messages["history"] = [
|
||||
Message(role="system", text="sys"),
|
||||
Message(role="user", text="old_user"),
|
||||
Message(role="assistant", text="old_assistant"),
|
||||
Message(role="system", contents=["sys"]),
|
||||
Message(role="user", contents=["old_user"]),
|
||||
Message(role="assistant", contents=["old_assistant"]),
|
||||
]
|
||||
context.context_messages["rag"] = [
|
||||
Message(role="user", text="recent_rag_context"),
|
||||
Message(role="assistant", text="recent_rag_answer"),
|
||||
Message(role="user", contents=["recent_rag_context"]),
|
||||
Message(role="assistant", contents=["recent_rag_answer"]),
|
||||
]
|
||||
|
||||
await provider.before_run(agent=None, session=None, context=context, state={})
|
||||
@@ -829,11 +829,11 @@ async def test_compaction_provider_after_run_compacts_stored_history() -> None:
|
||||
session = _MockSession()
|
||||
session.state["in_memory_history"] = {
|
||||
"messages": [
|
||||
Message(role="user", text="old question"),
|
||||
Message(role="assistant", text="old answer"),
|
||||
Message(role="user", contents=["old question"]),
|
||||
Message(role="assistant", contents=["old answer"]),
|
||||
_assistant_function_call("c1"),
|
||||
_tool_result("c1", "result"),
|
||||
Message(role="assistant", text="final answer"),
|
||||
Message(role="assistant", contents=["final answer"]),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -873,11 +873,11 @@ async def test_compaction_provider_both_strategies() -> None:
|
||||
# before_run: compact loaded context
|
||||
context = _MockSessionContext()
|
||||
context.context_messages["history"] = [
|
||||
Message(role="system", text="sys"),
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1"),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="system", contents=["sys"]),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"]),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
]
|
||||
await provider.before_run(agent=None, session=None, context=context, state={})
|
||||
assert len(context.get_messages()) == 3
|
||||
@@ -886,10 +886,10 @@ async def test_compaction_provider_both_strategies() -> None:
|
||||
session = _MockSession()
|
||||
session.state["history"] = {
|
||||
"messages": [
|
||||
Message(role="user", text="q"),
|
||||
Message(role="user", contents=["q"]),
|
||||
_assistant_function_call("c1"),
|
||||
_tool_result("c1", "ok"),
|
||||
Message(role="assistant", text="done"),
|
||||
Message(role="assistant", contents=["done"]),
|
||||
]
|
||||
}
|
||||
await provider.after_run(agent=None, session=session, context=_MockSessionContext(), state={})
|
||||
@@ -904,8 +904,8 @@ async def test_compaction_provider_none_strategies_are_noop() -> None:
|
||||
|
||||
context = _MockSessionContext()
|
||||
context.context_messages["history"] = [
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="assistant", text="hi"),
|
||||
Message(role="user", contents=["hello"]),
|
||||
Message(role="assistant", contents=["hi"]),
|
||||
]
|
||||
|
||||
await provider.before_run(agent=None, session=None, context=context, state={})
|
||||
@@ -924,10 +924,10 @@ async def test_in_memory_history_provider_skip_excluded() -> None:
|
||||
provider = _InMemoryHistoryProvider(skip_excluded=True)
|
||||
state: dict[str, Any] = {
|
||||
"messages": [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1", additional_properties={EXCLUDED_KEY: True}),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="assistant", text="a2"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"], additional_properties={EXCLUDED_KEY: True}),
|
||||
Message(role="user", contents=["u2"]),
|
||||
Message(role="assistant", contents=["a2"]),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -944,9 +944,9 @@ async def test_in_memory_history_provider_default_loads_all() -> None:
|
||||
provider = _InMemoryHistoryProvider()
|
||||
state: dict[str, Any] = {
|
||||
"messages": [
|
||||
Message(role="user", text="u1"),
|
||||
Message(role="assistant", text="a1", additional_properties={EXCLUDED_KEY: True}),
|
||||
Message(role="user", text="u2"),
|
||||
Message(role="user", contents=["u1"]),
|
||||
Message(role="assistant", contents=["a1"], additional_properties={EXCLUDED_KEY: True}),
|
||||
Message(role="user", contents=["u2"]),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ async def test_base_client_with_function_calling(chat_client_base: SupportsChatG
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
)
|
||||
assert exec_counter == 1
|
||||
assert len(response.messages) == 3
|
||||
@@ -93,7 +93,7 @@ async def test_base_client_with_function_calling_string_input(chat_client_base:
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response("hello", options={"tool_choice": "auto", "tools": [ai_func]})
|
||||
@@ -132,10 +132,10 @@ async def test_base_client_with_function_calling_resets(chat_client_base: Suppor
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
)
|
||||
assert exec_counter == 2
|
||||
assert len(response.messages) == 5
|
||||
@@ -193,11 +193,11 @@ async def test_function_loop_applies_compaction_projection_each_model_call(chat_
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
)
|
||||
|
||||
assert len(captured_roles) >= 2
|
||||
@@ -256,11 +256,11 @@ async def test_function_loop_token_budget_strategy_caps_tokens_each_iteration(
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello " * 160)],
|
||||
[Message(role="user", contents=["hello " * 160])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func]},
|
||||
)
|
||||
|
||||
@@ -349,13 +349,13 @@ async def test_base_client_executes_function_calls_across_multiple_response_mess
|
||||
conversation_id="conv_after_first_call",
|
||||
),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="done"),
|
||||
messages=Message(role="assistant", contents=["done"]),
|
||||
conversation_id="conv_after_second_call",
|
||||
),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func], "conversation_id": "conv_initial"},
|
||||
)
|
||||
|
||||
@@ -392,7 +392,7 @@ async def test_function_invocation_inside_aiohttp_server(chat_client_base: Suppo
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, tools=[ai_func])
|
||||
@@ -449,7 +449,7 @@ async def test_function_invocation_in_threaded_aiohttp_app(chat_client_base: Sup
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, tools=[ai_func])
|
||||
@@ -569,7 +569,7 @@ async def test_function_invocation_scenarios(
|
||||
|
||||
# Single function call content
|
||||
func_call = Content.from_function_call(call_id="1", name=function_name, arguments='{"arg1": "value1"}')
|
||||
completion = Message(role="assistant", text="done")
|
||||
completion = Message(role="assistant", contents=["done"])
|
||||
|
||||
chat_client_base.run_responses = [ChatResponse(messages=Message(role="assistant", contents=[func_call]))] + (
|
||||
[] if approval_required else [ChatResponse(messages=completion)]
|
||||
@@ -618,12 +618,12 @@ async def test_function_invocation_scenarios(
|
||||
options["conversation_id"] = conversation_id
|
||||
|
||||
if not streaming:
|
||||
response = await chat_client_base.get_response([Message(role="user", text="hello")], options=options)
|
||||
response = await chat_client_base.get_response([Message(role="user", contents=["hello"])], options=options)
|
||||
messages = response.messages
|
||||
else:
|
||||
updates = []
|
||||
async for update in chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options=options, stream=True
|
||||
[Message(role="user", contents=["hello"])], options=options, stream=True
|
||||
):
|
||||
updates.append(update)
|
||||
messages = updates
|
||||
@@ -729,7 +729,7 @@ async def test_rejected_approval(chat_client_base: SupportsChatGetResponse):
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Get the response with approval requests
|
||||
@@ -850,7 +850,7 @@ async def test_persisted_approval_messages_replay_correctly(chat_client_base: Su
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Get approval request
|
||||
@@ -860,7 +860,7 @@ async def test_persisted_approval_messages_replay_correctly(chat_client_base: Su
|
||||
|
||||
# Store messages (like a thread would)
|
||||
persisted_messages = [
|
||||
Message(role="user", text="hello"),
|
||||
Message(role="user", contents=["hello"]),
|
||||
*response1.messages,
|
||||
]
|
||||
|
||||
@@ -899,7 +899,7 @@ async def test_no_duplicate_function_calls_after_approval_processing(chat_client
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response1 = await chat_client_base.get_response(
|
||||
@@ -943,7 +943,7 @@ async def test_rejection_result_uses_function_call_id(chat_client_base: Supports
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response1 = await chat_client_base.get_response(
|
||||
@@ -1000,14 +1000,14 @@ async def test_max_iterations_limit(chat_client_base: SupportsChatGetResponse):
|
||||
)
|
||||
),
|
||||
# Failsafe response when tool_choice is set to "none"
|
||||
ChatResponse(messages=Message(role="assistant", text="giving up on tools")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["giving up on tools"])),
|
||||
]
|
||||
|
||||
# Set max_iterations to 1 in additional_properties
|
||||
chat_client_base.function_invocation_configuration["max_iterations"] = 1
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
)
|
||||
|
||||
# With max_iterations=1, we should:
|
||||
@@ -1061,7 +1061,7 @@ async def test_max_iterations_no_orphaned_function_calls(chat_client_base: Suppo
|
||||
chat_client_base.function_invocation_configuration["max_iterations"] = 2
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func]},
|
||||
)
|
||||
|
||||
@@ -1111,13 +1111,13 @@ async def test_max_iterations_makes_final_toolchoice_none_call(chat_client_base:
|
||||
)
|
||||
),
|
||||
# This response should be reached via failsafe (tool_choice="none")
|
||||
ChatResponse(messages=Message(role="assistant", text="Final answer after giving up on tools.")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["Final answer after giving up on tools."])),
|
||||
]
|
||||
|
||||
chat_client_base.function_invocation_configuration["max_iterations"] = 1
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func]},
|
||||
)
|
||||
|
||||
@@ -1170,13 +1170,13 @@ async def test_max_iterations_preserves_all_fcc_messages(chat_client_base: Suppo
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="Done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["Done"])),
|
||||
]
|
||||
|
||||
chat_client_base.function_invocation_configuration["max_iterations"] = 2
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func]},
|
||||
)
|
||||
|
||||
@@ -1301,14 +1301,14 @@ async def test_max_function_calls_limits_parallel_invocations(chat_client_base:
|
||||
)
|
||||
),
|
||||
# Final response after tool_choice="none" is forced
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Allow many iterations but cap total function calls at 5
|
||||
chat_client_base.function_invocation_configuration["max_function_calls"] = 5
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="search")], options={"tool_choice": "auto", "tools": [search_func]}
|
||||
[Message(role="user", contents=["search"])], options={"tool_choice": "auto", "tools": [search_func]}
|
||||
)
|
||||
|
||||
# First iteration executes 3 calls (total=3, under limit).
|
||||
@@ -1355,13 +1355,13 @@ async def test_max_function_calls_single_calls_per_iteration(chat_client_base: S
|
||||
)
|
||||
),
|
||||
# After limit is reached
|
||||
ChatResponse(messages=Message(role="assistant", text="all done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["all done"])),
|
||||
]
|
||||
|
||||
chat_client_base.function_invocation_configuration["max_function_calls"] = 2
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="look up keys")], options={"tool_choice": "auto", "tools": [lookup_func]}
|
||||
[Message(role="user", contents=["look up keys"])], options={"tool_choice": "auto", "tools": [lookup_func]}
|
||||
)
|
||||
|
||||
# 2 single calls executed, then limit reached, tool_choice="none" forced
|
||||
@@ -1390,13 +1390,13 @@ async def test_max_function_calls_none_means_unlimited(chat_client_base: Support
|
||||
)
|
||||
)
|
||||
for i in range(5)
|
||||
] + [ChatResponse(messages=Message(role="assistant", text="finished"))]
|
||||
] + [ChatResponse(messages=Message(role="assistant", contents=["finished"]))]
|
||||
|
||||
# Explicitly set to None (default) — should not limit
|
||||
chat_client_base.function_invocation_configuration["max_function_calls"] = None
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="do things")], options={"tool_choice": "auto", "tools": [do_thing_func]}
|
||||
[Message(role="user", contents=["do things"])], options={"tool_choice": "auto", "tools": [do_thing_func]}
|
||||
)
|
||||
|
||||
assert exec_counter == 5
|
||||
@@ -1414,14 +1414,14 @@ async def test_function_invocation_config_enabled_false(chat_client_base: Suppor
|
||||
return f"Processed {arg1}"
|
||||
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(messages=Message(role="assistant", text="response without function calling")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["response without function calling"])),
|
||||
]
|
||||
|
||||
# Disable function invocation
|
||||
chat_client_base.function_invocation_configuration["enabled"] = False
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [ai_func]}
|
||||
)
|
||||
|
||||
# Function should not be executed - when enabled=False, the loop doesn't run
|
||||
@@ -1447,12 +1447,12 @@ async def test_function_invocation_config_enabled_false_preserves_invocation_kwa
|
||||
|
||||
chat_client_base.chat_middleware = [capture_middleware]
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(messages=Message(role="assistant", text="response without function calling")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["response without function calling"])),
|
||||
]
|
||||
chat_client_base.function_invocation_configuration["enabled"] = False
|
||||
|
||||
await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [ai_func]},
|
||||
function_invocation_kwargs={"tool_request_id": "tool-123"},
|
||||
)
|
||||
@@ -1502,14 +1502,14 @@ async def test_function_invocation_config_max_consecutive_errors(chat_client_bas
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="final response")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["final response"])),
|
||||
]
|
||||
|
||||
# Set max_consecutive_errors to 2
|
||||
chat_client_base.function_invocation_configuration["max_consecutive_errors_per_request"] = 2
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
)
|
||||
|
||||
# Should stop after 2 consecutive errors and force a non-tool response
|
||||
@@ -1552,7 +1552,7 @@ async def test_function_invocation_stop_clears_conversation_id_non_stream(chat_c
|
||||
session_stub = type("SessionStub", (), {"service_session_id": "resp_seed"})()
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
options={"tool_choice": "auto", "tools": [error_func]},
|
||||
client_kwargs={"session": session_stub},
|
||||
)
|
||||
@@ -1579,14 +1579,14 @@ async def test_function_invocation_config_terminate_on_unknown_calls_false(chat_
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set terminate_on_unknown_calls to False (default)
|
||||
chat_client_base.function_invocation_configuration["terminate_on_unknown_calls"] = False
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
)
|
||||
|
||||
# Should have a result message indicating the tool wasn't found
|
||||
@@ -1624,7 +1624,7 @@ async def test_function_invocation_config_terminate_on_unknown_calls_true(chat_c
|
||||
# Should raise an exception when encountering an unknown function
|
||||
with pytest.raises(KeyError, match='Error: Requested function "unknown_function" not found'):
|
||||
await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
)
|
||||
|
||||
assert exec_counter == 0
|
||||
@@ -1656,7 +1656,7 @@ async def test_function_invocation_config_additional_tools(chat_client_base: Sup
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Add hidden_func to additional_tools
|
||||
@@ -1664,7 +1664,7 @@ async def test_function_invocation_config_additional_tools(chat_client_base: Sup
|
||||
|
||||
# Only pass visible_func in the tools parameter
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [visible_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [visible_func]}
|
||||
)
|
||||
|
||||
# Additional tools are treated as declaration_only, so not executed
|
||||
@@ -1697,14 +1697,14 @@ async def test_function_invocation_config_include_detailed_errors_false(chat_cli
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to False (default)
|
||||
chat_client_base.function_invocation_configuration["include_detailed_errors"] = False
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
)
|
||||
|
||||
# Should have a generic error message
|
||||
@@ -1733,14 +1733,14 @@ async def test_function_invocation_config_include_detailed_errors_true(chat_clie
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to True
|
||||
chat_client_base.function_invocation_configuration["include_detailed_errors"] = True
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
)
|
||||
|
||||
# Should have detailed error message
|
||||
@@ -1832,14 +1832,14 @@ async def test_argument_validation_error_with_detailed_errors(chat_client_base:
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to True
|
||||
chat_client_base.function_invocation_configuration["include_detailed_errors"] = True
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
)
|
||||
|
||||
# Should have detailed validation error
|
||||
@@ -1868,14 +1868,14 @@ async def test_argument_validation_error_without_detailed_errors(chat_client_bas
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to False (default)
|
||||
chat_client_base.function_invocation_configuration["include_detailed_errors"] = False
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
)
|
||||
|
||||
# Should have generic validation error
|
||||
@@ -1906,7 +1906,7 @@ async def test_hosted_tool_approval_response(chat_client_base: SupportsChatGetRe
|
||||
)
|
||||
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Send the approval response
|
||||
@@ -1947,13 +1947,13 @@ async def test_hosted_mcp_approval_response_passthrough(chat_client_base: Suppor
|
||||
|
||||
# The second call (after approval) should return a final response
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(messages=Message(role="assistant", text="Here are the docs results.")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["Here are the docs results."])),
|
||||
]
|
||||
|
||||
# Build message list mimicking handle_approvals_without_session:
|
||||
# [original query, assistant with approval_request, user with approval_response]
|
||||
messages = [
|
||||
Message(role="user", text="Search docs for azure storage"),
|
||||
Message(role="user", contents=["Search docs for azure storage"]),
|
||||
Message(role="assistant", contents=[mcp_approval_request]),
|
||||
Message(role="user", contents=[mcp_approval_response]),
|
||||
]
|
||||
@@ -2034,7 +2034,7 @@ async def test_mixed_local_and_hosted_approval_flow(chat_client_base: SupportsCh
|
||||
chat_client_base.run_responses = [
|
||||
ChatResponse(messages=Message(role="assistant", contents=[local_fc])),
|
||||
# After local approval + hosted approval, the final response
|
||||
ChatResponse(messages=Message(role="assistant", text="Done with both tools.")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["Done with both tools."])),
|
||||
]
|
||||
|
||||
# User approves the local function call
|
||||
@@ -2045,7 +2045,7 @@ async def test_mixed_local_and_hosted_approval_flow(chat_client_base: SupportsCh
|
||||
mcp_approval_response = mcp_approval_request.to_function_approval_response(approved=True)
|
||||
|
||||
messages = [
|
||||
Message(role="user", text="Search docs and run local"),
|
||||
Message(role="user", contents=["Search docs and run local"]),
|
||||
Message(role="assistant", contents=[local_fc, mcp_approval_request]),
|
||||
Message(role="user", contents=[local_approval_response]),
|
||||
Message(role="user", contents=[mcp_approval_response]),
|
||||
@@ -2080,12 +2080,12 @@ async def test_unapproved_tool_execution_raises_exception(chat_client_base: Supp
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Get approval request
|
||||
response1 = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
)
|
||||
|
||||
approval_req = [c for c in response1.messages[0].contents if c.type == "function_approval_request"][0]
|
||||
@@ -2137,7 +2137,7 @@ async def test_approved_function_call_with_error_without_detailed_errors(chat_cl
|
||||
contents=[Content.from_function_call(call_id="1", name="error_func", arguments='{"arg1": "value1"}')],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to False (default)
|
||||
@@ -2145,7 +2145,7 @@ async def test_approved_function_call_with_error_without_detailed_errors(chat_cl
|
||||
|
||||
# Get approval request
|
||||
response1 = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
)
|
||||
|
||||
approval_req = [c for c in response1.messages[0].contents if c.type == "function_approval_request"][0]
|
||||
@@ -2202,7 +2202,7 @@ async def test_approved_function_call_with_error_with_detailed_errors(chat_clien
|
||||
contents=[Content.from_function_call(call_id="1", name="error_func", arguments='{"arg1": "value1"}')],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to True
|
||||
@@ -2210,7 +2210,7 @@ async def test_approved_function_call_with_error_with_detailed_errors(chat_clien
|
||||
|
||||
# Get approval request
|
||||
response1 = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [error_func]}
|
||||
)
|
||||
|
||||
approval_req = [c for c in response1.messages[0].contents if c.type == "function_approval_request"][0]
|
||||
@@ -2267,7 +2267,7 @@ async def test_approved_function_call_with_validation_error(chat_client_base: Su
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Set include_detailed_errors to True to see validation details
|
||||
@@ -2275,7 +2275,7 @@ async def test_approved_function_call_with_validation_error(chat_client_base: Su
|
||||
|
||||
# Get approval request
|
||||
response1 = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [typed_func]}
|
||||
)
|
||||
|
||||
approval_req = [c for c in response1.messages[0].contents if c.type == "function_approval_request"][0]
|
||||
@@ -2328,12 +2328,12 @@ async def test_approved_function_call_successful_execution(chat_client_base: Sup
|
||||
contents=[Content.from_function_call(call_id="1", name="success_func", arguments='{"arg1": "value1"}')],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Get approval request
|
||||
response1 = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [success_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [success_func]}
|
||||
)
|
||||
|
||||
approval_req = [c for c in response1.messages[0].contents if c.type == "function_approval_request"][0]
|
||||
@@ -2391,7 +2391,7 @@ async def test_declaration_only_tool(chat_client_base: SupportsChatGetResponse):
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
@@ -2447,11 +2447,11 @@ async def test_multiple_function_calls_parallel_execution(chat_client_base: Supp
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [func1, func2]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [func1, func2]}
|
||||
)
|
||||
|
||||
# Both functions should have been executed
|
||||
@@ -2485,12 +2485,12 @@ async def test_callable_function_converted_to_tool(chat_client_base: SupportsCha
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
# Pass plain function (will be auto-converted)
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [plain_function]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [plain_function]}
|
||||
)
|
||||
|
||||
# Function should be executed
|
||||
@@ -2518,13 +2518,13 @@ async def test_conversation_id_handling(chat_client_base: SupportsChatGetRespons
|
||||
conversation_id="conv_123", # Simulate service-side thread
|
||||
),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="done"),
|
||||
messages=Message(role="assistant", contents=["done"]),
|
||||
conversation_id="conv_123",
|
||||
),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
)
|
||||
|
||||
# Should have executed the function
|
||||
@@ -2549,11 +2549,11 @@ async def test_function_result_appended_to_existing_assistant_message(chat_clien
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [test_func]}
|
||||
)
|
||||
|
||||
# Should have messages with both function call and function result
|
||||
@@ -2596,11 +2596,11 @@ async def test_error_recovery_resets_counter(chat_client_base: SupportsChatGetRe
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [sometimes_fails]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [sometimes_fails]}
|
||||
)
|
||||
|
||||
# Should have both an error and a success
|
||||
@@ -2912,7 +2912,7 @@ async def test_streaming_function_invocation_config_terminate_on_unknown_calls_t
|
||||
# Should raise an exception when encountering an unknown function
|
||||
with pytest.raises(KeyError, match='Error: Requested function "unknown_function" not found'):
|
||||
async for _ in chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
[Message(role="user", contents=["hello"])], options={"tool_choice": "auto", "tools": [known_func]}
|
||||
):
|
||||
pass
|
||||
|
||||
@@ -3248,7 +3248,7 @@ async def test_terminate_loop_single_function_call(chat_client_base: SupportsCha
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
@@ -3314,7 +3314,7 @@ async def test_terminate_loop_multiple_function_calls_one_terminates(chat_client
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="done")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["done"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
@@ -3444,7 +3444,7 @@ async def test_conversation_id_updated_in_options_between_tool_iterations():
|
||||
async def _get() -> ChatResponse:
|
||||
self.call_count += 1
|
||||
if not self.run_responses:
|
||||
return ChatResponse(messages=Message(role="assistant", text="done"))
|
||||
return ChatResponse(messages=Message(role="assistant", contents=["done"]))
|
||||
return self.run_responses.pop(0)
|
||||
|
||||
return _get()
|
||||
@@ -3491,7 +3491,7 @@ async def test_conversation_id_updated_in_options_between_tool_iterations():
|
||||
conversation_id="conv_after_first_call",
|
||||
),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="done"),
|
||||
messages=Message(role="assistant", contents=["done"]),
|
||||
conversation_id="conv_after_second_call",
|
||||
),
|
||||
]
|
||||
@@ -3706,7 +3706,7 @@ async def test_user_input_request_propagates_through_as_tool(chat_client_base: S
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="delegate this")],
|
||||
[Message(role="user", contents=["delegate this"])],
|
||||
options={"tool_choice": "auto", "tools": [delegate_tool]},
|
||||
)
|
||||
|
||||
@@ -3755,7 +3755,7 @@ async def test_user_input_request_multiple_contents_propagate(chat_client_base:
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="do something")],
|
||||
[Message(role="user", contents=["do something"])],
|
||||
options={"tool_choice": "auto", "tools": [multi_request]},
|
||||
)
|
||||
|
||||
@@ -3792,11 +3792,11 @@ async def test_user_input_request_empty_contents_returns_fallback(chat_client_ba
|
||||
],
|
||||
)
|
||||
),
|
||||
ChatResponse(messages=Message(role="assistant", text="handled")),
|
||||
ChatResponse(messages=Message(role="assistant", contents=["handled"])),
|
||||
]
|
||||
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="do something")],
|
||||
[Message(role="user", contents=["do something"])],
|
||||
options={"tool_choice": "auto", "tools": [empty_request]},
|
||||
)
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class TestAgentContext:
|
||||
|
||||
def test_init_with_defaults(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test AgentContext initialization with default values."""
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
assert context.agent is mock_agent
|
||||
@@ -48,7 +48,7 @@ class TestAgentContext:
|
||||
|
||||
def test_init_with_custom_values(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test AgentContext initialization with custom values."""
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
metadata = {"key": "value"}
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True, metadata=metadata)
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestAgentContext:
|
||||
"""Test AgentContext initialization with session parameter."""
|
||||
from agent_framework import AgentSession
|
||||
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
session = AgentSession()
|
||||
context = AgentContext(agent=mock_agent, messages=messages, session=session)
|
||||
|
||||
@@ -100,7 +100,7 @@ class TestChatContext:
|
||||
|
||||
def test_init_with_defaults(self, mock_chat_client: Any) -> None:
|
||||
"""Test ChatContext initialization with default values."""
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
@@ -113,7 +113,7 @@ class TestChatContext:
|
||||
|
||||
def test_init_with_custom_values(self, mock_chat_client: Any) -> None:
|
||||
"""Test ChatContext initialization with custom values."""
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {"temperature": 0.5}
|
||||
metadata = {"key": "value"}
|
||||
|
||||
@@ -167,10 +167,10 @@ class TestAgentMiddlewarePipeline:
|
||||
async def test_execute_no_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline execution with no middleware."""
|
||||
pipeline = AgentMiddlewarePipeline()
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
return expected_response
|
||||
@@ -193,10 +193,10 @@ class TestAgentMiddlewarePipeline:
|
||||
|
||||
middleware = OrderTrackingMiddleware("test")
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
execution_order.append("handler")
|
||||
@@ -209,7 +209,7 @@ class TestAgentMiddlewarePipeline:
|
||||
async def test_execute_stream_no_middleware(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test pipeline streaming execution with no middleware."""
|
||||
pipeline = AgentMiddlewarePipeline()
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> ResponseStream[AgentResponseUpdate, AgentResponse]:
|
||||
@@ -244,7 +244,7 @@ class TestAgentMiddlewarePipeline:
|
||||
|
||||
middleware = StreamOrderTrackingMiddleware("test")
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> ResponseStream[AgentResponseUpdate, AgentResponse]:
|
||||
@@ -270,14 +270,14 @@ class TestAgentMiddlewarePipeline:
|
||||
"""Test pipeline execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
execution_order: list[str] = []
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
# Handler should not be executed when terminated before next()
|
||||
execution_order.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
response = await pipeline.execute(context, final_handler)
|
||||
assert response is None
|
||||
@@ -288,13 +288,13 @@ class TestAgentMiddlewarePipeline:
|
||||
"""Test pipeline execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
execution_order: list[str] = []
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
execution_order.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
response = await pipeline.execute(context, final_handler)
|
||||
assert response is not None
|
||||
@@ -306,7 +306,7 @@ class TestAgentMiddlewarePipeline:
|
||||
"""Test pipeline streaming execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -334,7 +334,7 @@ class TestAgentMiddlewarePipeline:
|
||||
"""Test pipeline streaming execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
execution_order: list[str] = []
|
||||
|
||||
@@ -371,11 +371,11 @@ class TestAgentMiddlewarePipeline:
|
||||
|
||||
middleware = SessionCapturingMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
session = AgentSession()
|
||||
context = AgentContext(agent=mock_agent, messages=messages, session=session)
|
||||
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
return expected_response
|
||||
@@ -396,10 +396,10 @@ class TestAgentMiddlewarePipeline:
|
||||
|
||||
middleware = SessionCapturingMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, session=None)
|
||||
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
return expected_response
|
||||
@@ -563,11 +563,11 @@ class TestChatMiddlewarePipeline:
|
||||
async def test_execute_no_middleware(self, mock_chat_client: Any) -> None:
|
||||
"""Test pipeline execution with no middleware."""
|
||||
pipeline = ChatMiddlewarePipeline()
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
expected_response = ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
return expected_response
|
||||
@@ -590,11 +590,11 @@ class TestChatMiddlewarePipeline:
|
||||
|
||||
middleware = OrderTrackingChatMiddleware("test")
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
expected_response = ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
expected_response = ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
execution_order.append("handler")
|
||||
@@ -607,7 +607,7 @@ class TestChatMiddlewarePipeline:
|
||||
async def test_execute_stream_no_middleware(self, mock_chat_client: Any) -> None:
|
||||
"""Test pipeline streaming execution with no middleware."""
|
||||
pipeline = ChatMiddlewarePipeline()
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
|
||||
@@ -642,7 +642,7 @@ class TestChatMiddlewarePipeline:
|
||||
|
||||
middleware = StreamOrderTrackingChatMiddleware("test")
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
|
||||
@@ -669,7 +669,7 @@ class TestChatMiddlewarePipeline:
|
||||
"""Test pipeline execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
execution_order: list[str] = []
|
||||
@@ -677,7 +677,7 @@ class TestChatMiddlewarePipeline:
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
# Handler should not be executed when terminated before next()
|
||||
execution_order.append("handler")
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
response = await pipeline.execute(context, final_handler)
|
||||
assert response is None
|
||||
@@ -688,14 +688,14 @@ class TestChatMiddlewarePipeline:
|
||||
"""Test pipeline execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
execution_order: list[str] = []
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
execution_order.append("handler")
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
response = await pipeline.execute(context, final_handler)
|
||||
assert response is not None
|
||||
@@ -707,7 +707,7 @@ class TestChatMiddlewarePipeline:
|
||||
"""Test pipeline streaming execution with termination before next()."""
|
||||
middleware = self.PreNextTerminateChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
execution_order: list[str] = []
|
||||
@@ -732,7 +732,7 @@ class TestChatMiddlewarePipeline:
|
||||
"""Test pipeline streaming execution with termination after next()."""
|
||||
middleware = self.PostNextTerminateChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
execution_order: list[str] = []
|
||||
@@ -774,12 +774,12 @@ class TestClassBasedMiddleware:
|
||||
|
||||
middleware = MetadataAgentMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
metadata_updates.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -835,12 +835,12 @@ class TestFunctionBasedMiddleware:
|
||||
execution_order.append("function_after")
|
||||
|
||||
pipeline = AgentMiddlewarePipeline(test_agent_middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
execution_order.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -894,12 +894,12 @@ class TestMixedMiddleware:
|
||||
execution_order.append("function_after")
|
||||
|
||||
pipeline = AgentMiddlewarePipeline(ClassMiddleware(), function_middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
execution_order.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -956,13 +956,13 @@ class TestMixedMiddleware:
|
||||
execution_order.append("function_after")
|
||||
|
||||
pipeline = ChatMiddlewarePipeline(ClassChatMiddleware(), function_chat_middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
execution_order.append("handler")
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -997,12 +997,12 @@ class TestMultipleMiddlewareOrdering:
|
||||
|
||||
middleware = [FirstMiddleware(), SecondMiddleware(), ThirdMiddleware()]
|
||||
pipeline = AgentMiddlewarePipeline(*middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
execution_order.append("handler")
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1081,13 +1081,13 @@ class TestMultipleMiddlewareOrdering:
|
||||
|
||||
middleware = [FirstChatMiddleware(), SecondChatMiddleware(), ThirdChatMiddleware()]
|
||||
pipeline = ChatMiddlewarePipeline(*middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
execution_order.append("handler")
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1133,13 +1133,13 @@ class TestContextContentValidation:
|
||||
|
||||
middleware = ContextValidationMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
# Verify metadata was set by middleware
|
||||
assert ctx.metadata.get("validated") is True
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
assert result is not None
|
||||
@@ -1212,14 +1212,14 @@ class TestContextContentValidation:
|
||||
|
||||
middleware = ChatContextValidationMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {"temperature": 0.5}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
# Verify metadata was set by middleware
|
||||
assert ctx.metadata.get("validated") is True
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
assert result is not None
|
||||
@@ -1239,14 +1239,14 @@ class TestStreamingScenarios:
|
||||
|
||||
middleware = StreamingFlagMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
|
||||
# Test non-streaming
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
streaming_flags.append(ctx.stream)
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1280,7 +1280,7 @@ class TestStreamingScenarios:
|
||||
|
||||
middleware = StreamProcessingMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
|
||||
async def final_stream_handler(ctx: AgentContext) -> ResponseStream[AgentResponseUpdate, AgentResponse]:
|
||||
@@ -1320,7 +1320,7 @@ class TestStreamingScenarios:
|
||||
|
||||
middleware = ChatStreamingFlagMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
|
||||
# Test non-streaming
|
||||
@@ -1328,7 +1328,7 @@ class TestStreamingScenarios:
|
||||
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
streaming_flags.append(ctx.stream)
|
||||
return ChatResponse(messages=[Message(role="assistant", text="response")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1362,7 +1362,7 @@ class TestStreamingScenarios:
|
||||
|
||||
middleware = ChatStreamProcessingMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
|
||||
@@ -1442,7 +1442,7 @@ class TestMiddlewareExecutionControl:
|
||||
|
||||
middleware = NoNextMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
handler_called = False
|
||||
@@ -1450,7 +1450,7 @@ class TestMiddlewareExecutionControl:
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return AgentResponse(messages=[Message(role="assistant", text="should not execute")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["should not execute"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1469,7 +1469,7 @@ class TestMiddlewareExecutionControl:
|
||||
|
||||
middleware = NoNextStreamingMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
|
||||
handler_called = False
|
||||
@@ -1539,7 +1539,7 @@ class TestMiddlewareExecutionControl:
|
||||
await call_next()
|
||||
|
||||
pipeline = AgentMiddlewarePipeline(FirstMiddleware(), SecondMiddleware())
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
handler_called = False
|
||||
@@ -1547,7 +1547,7 @@ class TestMiddlewareExecutionControl:
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return AgentResponse(messages=[Message(role="assistant", text="should not execute")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["should not execute"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1566,7 +1566,7 @@ class TestMiddlewareExecutionControl:
|
||||
|
||||
middleware = NoNextChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
@@ -1575,7 +1575,7 @@ class TestMiddlewareExecutionControl:
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return ChatResponse(messages=[Message(role="assistant", text="should not execute")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["should not execute"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -1594,7 +1594,7 @@ class TestMiddlewareExecutionControl:
|
||||
|
||||
middleware = NoNextStreamingChatMiddleware()
|
||||
pipeline = ChatMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options, stream=True)
|
||||
|
||||
@@ -1639,7 +1639,7 @@ class TestMiddlewareExecutionControl:
|
||||
await call_next()
|
||||
|
||||
pipeline = ChatMiddlewarePipeline(FirstChatMiddleware(), SecondChatMiddleware())
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
chat_options: dict[str, Any] = {}
|
||||
context = ChatContext(client=mock_chat_client, messages=messages, options=chat_options)
|
||||
|
||||
@@ -1648,7 +1648,7 @@ class TestMiddlewareExecutionControl:
|
||||
async def final_handler(ctx: ChatContext) -> ChatResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return ChatResponse(messages=[Message(role="assistant", text="should not execute")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["should not execute"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class TestResultOverrideMiddleware:
|
||||
|
||||
async def test_agent_middleware_response_override_non_streaming(self, mock_agent: SupportsAgentRun) -> None:
|
||||
"""Test that agent middleware can override response for non-streaming execution."""
|
||||
override_response = AgentResponse(messages=[Message(role="assistant", text="overridden response")])
|
||||
override_response = AgentResponse(messages=[Message(role="assistant", contents=["overridden response"])])
|
||||
|
||||
class ResponseOverrideMiddleware(AgentMiddleware):
|
||||
async def process(self, context: AgentContext, call_next: Callable[[], Awaitable[None]]) -> None:
|
||||
@@ -49,7 +49,7 @@ class TestResultOverrideMiddleware:
|
||||
|
||||
middleware = ResponseOverrideMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages)
|
||||
|
||||
handler_called = False
|
||||
@@ -57,7 +57,7 @@ class TestResultOverrideMiddleware:
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return AgentResponse(messages=[Message(role="assistant", text="original response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["original response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -83,7 +83,7 @@ class TestResultOverrideMiddleware:
|
||||
|
||||
middleware = StreamResponseOverrideMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=True)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> ResponseStream[AgentResponseUpdate, AgentResponse]:
|
||||
@@ -146,7 +146,7 @@ class TestResultOverrideMiddleware:
|
||||
# Then conditionally override based on content
|
||||
if any("special" in msg.text for msg in context.messages if msg.text):
|
||||
context.result = AgentResponse(
|
||||
messages=[Message(role="assistant", text="Special response from middleware!")]
|
||||
messages=[Message(role="assistant", contents=["Special response from middleware!"])]
|
||||
)
|
||||
|
||||
# Create Agent with override middleware
|
||||
@@ -154,14 +154,14 @@ class TestResultOverrideMiddleware:
|
||||
agent = Agent(client=mock_chat_client, middleware=[middleware])
|
||||
|
||||
# Test override case
|
||||
override_messages = [Message(role="user", text="Give me a special response")]
|
||||
override_messages = [Message(role="user", contents=["Give me a special response"])]
|
||||
override_response = await agent.run(override_messages)
|
||||
assert override_response.messages[0].text == "Special response from middleware!"
|
||||
# Verify chat client was called since middleware called next()
|
||||
assert mock_chat_client.call_count == 1
|
||||
|
||||
# Test normal case
|
||||
normal_messages = [Message(role="user", text="Normal request")]
|
||||
normal_messages = [Message(role="user", contents=["Normal request"])]
|
||||
normal_response = await agent.run(normal_messages)
|
||||
assert normal_response.messages[0].text == "test response"
|
||||
# Verify chat client was called for normal case
|
||||
@@ -190,7 +190,7 @@ class TestResultOverrideMiddleware:
|
||||
agent = Agent(client=mock_chat_client, middleware=[middleware])
|
||||
|
||||
# Test streaming override case
|
||||
override_messages = [Message(role="user", text="Give me a custom stream")]
|
||||
override_messages = [Message(role="user", contents=["Give me a custom stream"])]
|
||||
override_updates: list[AgentResponseUpdate] = []
|
||||
async for update in agent.run(override_messages, stream=True):
|
||||
override_updates.append(update)
|
||||
@@ -201,7 +201,7 @@ class TestResultOverrideMiddleware:
|
||||
assert override_updates[2].text == " response!"
|
||||
|
||||
# Test normal streaming case
|
||||
normal_messages = [Message(role="user", text="Normal streaming request")]
|
||||
normal_messages = [Message(role="user", contents=["Normal streaming request"])]
|
||||
normal_updates: list[AgentResponseUpdate] = []
|
||||
async for update in agent.run(normal_messages, stream=True):
|
||||
normal_updates.append(update)
|
||||
@@ -228,10 +228,10 @@ class TestResultOverrideMiddleware:
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
nonlocal handler_called
|
||||
handler_called = True
|
||||
return AgentResponse(messages=[Message(role="assistant", text="executed response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["executed response"])])
|
||||
|
||||
# Test case where next() is NOT called
|
||||
no_execute_messages = [Message(role="user", text="Don't run this")]
|
||||
no_execute_messages = [Message(role="user", contents=["Don't run this"])]
|
||||
no_execute_context = AgentContext(agent=mock_agent, messages=no_execute_messages, stream=False)
|
||||
no_execute_result = await pipeline.execute(no_execute_context, final_handler)
|
||||
|
||||
@@ -243,7 +243,7 @@ class TestResultOverrideMiddleware:
|
||||
handler_called = False
|
||||
|
||||
# Test case where next() IS called
|
||||
execute_messages = [Message(role="user", text="Please execute this")]
|
||||
execute_messages = [Message(role="user", contents=["Please execute this"])]
|
||||
execute_context = AgentContext(agent=mock_agent, messages=execute_messages, stream=False)
|
||||
execute_result = await pipeline.execute(execute_context, final_handler)
|
||||
|
||||
@@ -321,11 +321,11 @@ class TestResultObservability:
|
||||
|
||||
middleware = ObservabilityMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=False)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
return AgentResponse(messages=[Message(role="assistant", text="executed response")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["executed response"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
@@ -384,16 +384,16 @@ class TestResultObservability:
|
||||
if "modify" in context.result.messages[0].text:
|
||||
# Override after observing
|
||||
context.result = AgentResponse(
|
||||
messages=[Message(role="assistant", text="modified after execution")]
|
||||
messages=[Message(role="assistant", contents=["modified after execution"])]
|
||||
)
|
||||
|
||||
middleware = PostExecutionOverrideMiddleware()
|
||||
pipeline = AgentMiddlewarePipeline(middleware)
|
||||
messages = [Message(role="user", text="test")]
|
||||
messages = [Message(role="user", contents=["test"])]
|
||||
context = AgentContext(agent=mock_agent, messages=messages, stream=False)
|
||||
|
||||
async def final_handler(ctx: AgentContext) -> AgentResponse:
|
||||
return AgentResponse(messages=[Message(role="assistant", text="response to modify")])
|
||||
return AgentResponse(messages=[Message(role="assistant", contents=["response to modify"])])
|
||||
|
||||
result = await pipeline.execute(context, final_handler)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class TestChatAgentClassBasedMiddleware:
|
||||
agent = Agent(client=client, middleware=[middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -105,7 +105,7 @@ class TestChatAgentClassBasedMiddleware:
|
||||
middleware = TrackingFunctionMiddleware("function_middleware")
|
||||
agent = Agent(client=chat_client_base, middleware=[middleware])
|
||||
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
assert response is not None
|
||||
@@ -135,8 +135,8 @@ class TestChatAgentFunctionBasedMiddleware:
|
||||
|
||||
# Execute the agent with multiple messages
|
||||
messages = [
|
||||
Message(role="user", text="message1"),
|
||||
Message(role="user", text="message2"), # This should not be processed due to termination
|
||||
Message(role="user", contents=["message1"]),
|
||||
Message(role="user", contents=["message2"]), # This should not be processed due to termination
|
||||
]
|
||||
response = await agent.run(messages)
|
||||
|
||||
@@ -163,8 +163,8 @@ class TestChatAgentFunctionBasedMiddleware:
|
||||
|
||||
# Execute the agent with multiple messages
|
||||
messages = [
|
||||
Message(role="user", text="message1"),
|
||||
Message(role="user", text="message2"),
|
||||
Message(role="user", contents=["message1"]),
|
||||
Message(role="user", contents=["message2"]),
|
||||
]
|
||||
response = await agent.run(messages)
|
||||
|
||||
@@ -229,7 +229,7 @@ class TestChatAgentFunctionBasedMiddleware:
|
||||
agent = Agent(client=client, middleware=[tracking_agent_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -266,7 +266,7 @@ class TestChatAgentFunctionBasedMiddleware:
|
||||
execution_order.append("function_function_after")
|
||||
|
||||
agent = Agent(client=chat_client_base, middleware=[tracking_function_middleware])
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
assert response is not None
|
||||
@@ -303,7 +303,7 @@ class TestChatAgentStreamingMiddleware:
|
||||
]
|
||||
|
||||
# Execute streaming
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
updates: list[AgentResponseUpdate] = []
|
||||
async for update in agent.run(messages, stream=True):
|
||||
updates.append(update)
|
||||
@@ -333,7 +333,7 @@ class TestChatAgentStreamingMiddleware:
|
||||
# Create Agent with middleware
|
||||
middleware = FlagTrackingMiddleware()
|
||||
agent = Agent(client=client, middleware=[middleware])
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
|
||||
# Test non-streaming execution
|
||||
response = await agent.run(messages)
|
||||
@@ -372,7 +372,7 @@ class TestChatAgentMultipleMiddlewareOrdering:
|
||||
agent = Agent(client=client, middleware=[middleware1, middleware2, middleware3])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -424,7 +424,7 @@ class TestChatAgentMultipleMiddlewareOrdering:
|
||||
function_function_middleware,
|
||||
],
|
||||
)
|
||||
await agent.run([Message(role="user", text="test")])
|
||||
await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
async def test_mixed_middleware_types_with_supported_client(self, chat_client_base: "MockBaseChatClient") -> None:
|
||||
"""Test mixed class and function-based middleware with a full chat client."""
|
||||
@@ -457,7 +457,7 @@ class TestChatAgentMultipleMiddlewareOrdering:
|
||||
],
|
||||
)
|
||||
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
assert response is not None
|
||||
@@ -488,7 +488,7 @@ class TestChatAgentMultipleMiddlewareOrdering:
|
||||
MiddlewareException,
|
||||
match="Context providers may only add chat or function middleware",
|
||||
):
|
||||
await agent.run([Message(role="user", text="test message")])
|
||||
await agent.run([Message(role="user", contents=["test message"])])
|
||||
|
||||
|
||||
# region Tool Functions for Testing
|
||||
@@ -547,7 +547,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
|
||||
chat_client_base.run_responses = [function_call_response, final_response]
|
||||
|
||||
@@ -560,7 +560,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="Get weather for Seattle")]
|
||||
messages = [Message(role="user", contents=["Get weather for Seattle"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -609,7 +609,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
|
||||
chat_client_base.run_responses = [function_call_response, final_response]
|
||||
|
||||
@@ -621,7 +621,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="Get weather for San Francisco")]
|
||||
messages = [Message(role="user", contents=["Get weather for San Francisco"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -683,7 +683,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
|
||||
chat_client_base.run_responses = [function_call_response, final_response]
|
||||
|
||||
@@ -695,7 +695,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="Get weather for New York")]
|
||||
messages = [Message(role="user", contents=["Get weather for New York"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -795,7 +795,7 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
agent = Agent(client=chat_client_base, middleware=[kwargs_middleware], tools=[sample_tool_function])
|
||||
|
||||
# Execute the agent with custom parameters passed as kwargs
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages, options={"additional_function_arguments": {"custom_param": "test_value"}})
|
||||
|
||||
# Verify response
|
||||
@@ -841,14 +841,14 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Done!")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Done!"])]),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, middleware=[capture_middleware], tools=[sample_tool_function])
|
||||
|
||||
session_metadata = {"tenant": "acme-corp", "region": "us-west"}
|
||||
await agent.run(
|
||||
[Message(role="user", text="Get weather")],
|
||||
[Message(role="user", contents=["Get weather"])],
|
||||
function_invocation_kwargs={
|
||||
"user_id": "user-456",
|
||||
"session_metadata": session_metadata,
|
||||
@@ -885,13 +885,13 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Done!")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Done!"])]),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, middleware=[capture_middleware], tools=[sample_tool_function])
|
||||
|
||||
await agent.run(
|
||||
[Message(role="user", text="Get weather")],
|
||||
[Message(role="user", contents=["Get weather"])],
|
||||
function_invocation_kwargs={
|
||||
"user_id": "from-kwargs",
|
||||
"tenant_id": "from-kwargs",
|
||||
@@ -940,13 +940,13 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Done!")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Done!"])]),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, middleware=[capture_middleware], tools=[sample_tool_function])
|
||||
|
||||
await agent.run(
|
||||
[Message(role="user", text="Get weather for both cities")],
|
||||
[Message(role="user", contents=["Get weather for both cities"])],
|
||||
function_invocation_kwargs={
|
||||
"user_id": "user-456",
|
||||
"request_id": "req-001",
|
||||
@@ -984,12 +984,12 @@ class TestChatAgentFunctionMiddlewareWithTools:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Done!")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Done!"])]),
|
||||
]
|
||||
|
||||
agent = Agent(client=chat_client_base, middleware=[capture_middleware], tools=[sample_tool_function])
|
||||
|
||||
await agent.run([Message(role="user", text="Get weather")])
|
||||
await agent.run([Message(role="user", contents=["Get weather"])])
|
||||
|
||||
# No runtime kwargs should be present
|
||||
assert "user_id" not in captured_kwargs
|
||||
@@ -1355,7 +1355,7 @@ class TestRunLevelMiddleware:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
chat_client_base.run_responses = [function_call_response, final_response]
|
||||
|
||||
# Create agent with agent-level middleware
|
||||
@@ -1446,7 +1446,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
chat_client_base.responses = [function_call_response, final_response]
|
||||
|
||||
# Should work without errors
|
||||
@@ -1456,7 +1456,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
tools=[custom_tool_wrapped],
|
||||
)
|
||||
|
||||
response = await agent.run([Message(role="user", text="test")])
|
||||
response = await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
assert response is not None
|
||||
assert "decorator_type_match_agent" in execution_order
|
||||
@@ -1477,7 +1477,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
await call_next()
|
||||
|
||||
agent = Agent(client=client, middleware=[mismatched_middleware])
|
||||
await agent.run([Message(role="user", text="test")])
|
||||
await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
async def test_only_decorator_specified(self, chat_client_base: "MockBaseChatClient") -> None:
|
||||
"""Only decorator specified - rely on decorator."""
|
||||
@@ -1517,7 +1517,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
chat_client_base.responses = [function_call_response, final_response]
|
||||
|
||||
# Should work - relies on decorator
|
||||
@@ -1527,7 +1527,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
tools=[custom_tool_wrapped],
|
||||
)
|
||||
|
||||
response = await agent.run([Message(role="user", text="test")])
|
||||
response = await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
assert response is not None
|
||||
assert "decorator_only_agent" in execution_order
|
||||
@@ -1573,7 +1573,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
)
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", text="Final response")])
|
||||
final_response = ChatResponse(messages=[Message(role="assistant", contents=["Final response"])])
|
||||
chat_client_base.responses = [function_call_response, final_response]
|
||||
|
||||
# Should work - relies on type annotations
|
||||
@@ -1581,7 +1581,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
client=chat_client_base, middleware=[type_only_agent, type_only_function], tools=[custom_tool_wrapped]
|
||||
)
|
||||
|
||||
response = await agent.run([Message(role="user", text="test")])
|
||||
response = await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
assert response is not None
|
||||
assert "type_only_agent" in execution_order
|
||||
@@ -1596,7 +1596,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
# Should raise MiddlewareException
|
||||
with pytest.raises(MiddlewareException, match="Cannot determine middleware type"):
|
||||
agent = Agent(client=client, middleware=[no_info_middleware])
|
||||
await agent.run([Message(role="user", text="test")])
|
||||
await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
async def test_insufficient_parameters_error(self, client: Any) -> None:
|
||||
"""Test that middleware with insufficient parameters raises an error."""
|
||||
@@ -1610,7 +1610,7 @@ class TestMiddlewareDecoratorLogic:
|
||||
pass
|
||||
|
||||
agent = Agent(client=client, middleware=[insufficient_params_middleware])
|
||||
await agent.run([Message(role="user", text="test")])
|
||||
await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
async def test_decorator_markers_preserved(self) -> None:
|
||||
"""Test that decorator markers are properly set on functions."""
|
||||
@@ -1682,7 +1682,7 @@ class TestChatAgentSessionBehavior:
|
||||
session = agent.create_session()
|
||||
|
||||
# First run
|
||||
first_messages = [Message(role="user", text="first message")]
|
||||
first_messages = [Message(role="user", contents=["first message"])]
|
||||
first_response = await agent.run(first_messages, session=session)
|
||||
|
||||
# Verify first response
|
||||
@@ -1690,7 +1690,7 @@ class TestChatAgentSessionBehavior:
|
||||
assert len(first_response.messages) > 0
|
||||
|
||||
# Second run - use the same thread
|
||||
second_messages = [Message(role="user", text="second message")]
|
||||
second_messages = [Message(role="user", contents=["second message"])]
|
||||
second_response = await agent.run(second_messages, session=session)
|
||||
|
||||
# Verify second response
|
||||
@@ -1762,7 +1762,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -1789,7 +1789,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[tracking_chat_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -1813,7 +1813,7 @@ class TestChatAgentChatMiddleware:
|
||||
if msg.role == "system":
|
||||
continue
|
||||
original_text = msg.text or ""
|
||||
context.messages[idx] = Message(role=msg.role, text=f"MODIFIED: {original_text}")
|
||||
context.messages[idx] = Message(role=msg.role, contents=[f"MODIFIED: {original_text}"])
|
||||
break
|
||||
await call_next()
|
||||
|
||||
@@ -1822,7 +1822,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[message_modifier_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify that the message was modified (MockBaseChatClient echoes back the input)
|
||||
@@ -1836,7 +1836,7 @@ class TestChatAgentChatMiddleware:
|
||||
async def response_override_middleware(context: ChatContext, call_next: Callable[[], Awaitable[None]]) -> None:
|
||||
# Override the response without calling next()
|
||||
context.result = ChatResponse(
|
||||
messages=[Message(role="assistant", text="MiddlewareTypes overridden response")],
|
||||
messages=[Message(role="assistant", contents=["MiddlewareTypes overridden response"])],
|
||||
response_id="middleware-response-123",
|
||||
)
|
||||
context.terminate = True
|
||||
@@ -1846,7 +1846,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[response_override_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify that the response was overridden
|
||||
@@ -1876,7 +1876,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[first_middleware, second_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -1914,7 +1914,7 @@ class TestChatAgentChatMiddleware:
|
||||
]
|
||||
|
||||
# Execute streaming
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
updates: list[AgentResponseUpdate] = []
|
||||
async for update in agent.run(messages, stream=True):
|
||||
updates.append(update)
|
||||
@@ -1937,7 +1937,9 @@ class TestChatAgentChatMiddleware:
|
||||
async def process(self, context: ChatContext, call_next: Callable[[], Awaitable[None]]) -> None:
|
||||
execution_order.append("middleware_before")
|
||||
# Set a custom response since we're terminating
|
||||
context.result = ChatResponse(messages=[Message(role="assistant", text="Terminated by middleware")])
|
||||
context.result = ChatResponse(
|
||||
messages=[Message(role="assistant", contents=["Terminated by middleware"])]
|
||||
)
|
||||
raise MiddlewareTermination
|
||||
# We call next() but since terminate=True, execution should stop
|
||||
await call_next()
|
||||
@@ -1948,7 +1950,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[PreTerminationChatMiddleware()])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response was from middleware
|
||||
@@ -1973,7 +1975,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[PostTerminationChatMiddleware()])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response is from actual execution
|
||||
@@ -2012,7 +2014,7 @@ class TestChatAgentChatMiddleware:
|
||||
middleware=[chat_middleware, function_middleware, agent_middleware],
|
||||
tools=[sample_tool_function],
|
||||
)
|
||||
await agent.run([Message(role="user", text="test")])
|
||||
await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
assert execution_order == [
|
||||
"agent_middleware_before",
|
||||
@@ -2041,7 +2043,7 @@ class TestChatAgentChatMiddleware:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Final response")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Final response"])]),
|
||||
]
|
||||
|
||||
async def tracking_agent_middleware(
|
||||
@@ -2076,7 +2078,7 @@ class TestChatAgentChatMiddleware:
|
||||
tools=[sample_tool_function],
|
||||
)
|
||||
|
||||
response = await agent.run([Message(role="user", text="test")])
|
||||
response = await agent.run([Message(role="user", contents=["test"])])
|
||||
|
||||
assert response is not None
|
||||
assert client.call_count == 2
|
||||
@@ -2168,7 +2170,7 @@ class TestChatAgentChatMiddleware:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Final response")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Final response"])]),
|
||||
]
|
||||
|
||||
agent = Agent(
|
||||
@@ -2179,7 +2181,7 @@ class TestChatAgentChatMiddleware:
|
||||
)
|
||||
|
||||
response = await agent.run(
|
||||
[Message(role="user", text="Get weather for Seattle")],
|
||||
[Message(role="user", contents=["Get weather for Seattle"])],
|
||||
middleware=[run_chat_middleware, run_function_middleware],
|
||||
)
|
||||
|
||||
@@ -2230,7 +2232,7 @@ class TestChatAgentChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[kwargs_middleware])
|
||||
|
||||
# Execute the agent with runtime options
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(
|
||||
messages,
|
||||
options={"temperature": 0.7, "max_tokens": 100, "custom_param": "test_value"},
|
||||
@@ -2288,7 +2290,7 @@ class TestChatAgentChatMiddleware:
|
||||
# yield AgentResponseUpdate()
|
||||
|
||||
# return _stream()
|
||||
# return AgentResponse(messages=[Message(role="assistant", text="response")])
|
||||
# return AgentResponse(messages=[Message(role="assistant", contents=["response"])])
|
||||
|
||||
# def get_new_thread(self, **kwargs):
|
||||
# return None
|
||||
|
||||
@@ -43,7 +43,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [LoggingChatMiddleware()]
|
||||
|
||||
# Execute chat client directly
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -68,7 +68,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [logging_chat_middleware]
|
||||
|
||||
# Execute chat client directly
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -87,14 +87,14 @@ class TestChatMiddleware:
|
||||
# Modify the first message by adding a prefix
|
||||
if context.messages and len(context.messages) > 0:
|
||||
original_text = context.messages[0].text or ""
|
||||
context.messages[0] = Message(role=context.messages[0].role, text=f"MODIFIED: {original_text}")
|
||||
context.messages[0] = Message(role=context.messages[0].role, contents=[f"MODIFIED: {original_text}"])
|
||||
await call_next()
|
||||
|
||||
# Add middleware to chat client
|
||||
chat_client_base.chat_middleware = [message_modifier_middleware]
|
||||
|
||||
# Execute chat client
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(messages)
|
||||
|
||||
# Verify that the message was modified (MockChatClient echoes back the input)
|
||||
@@ -110,7 +110,7 @@ class TestChatMiddleware:
|
||||
async def response_override_middleware(context: ChatContext, call_next: Callable[[], Awaitable[None]]) -> None:
|
||||
# Override the response without calling next()
|
||||
context.result = ChatResponse(
|
||||
messages=[Message(role="assistant", text="MiddlewareTypes overridden response")],
|
||||
messages=[Message(role="assistant", contents=["MiddlewareTypes overridden response"])],
|
||||
response_id="middleware-response-123",
|
||||
)
|
||||
context.terminate = True
|
||||
@@ -119,7 +119,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [response_override_middleware]
|
||||
|
||||
# Execute chat client
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(messages)
|
||||
|
||||
# Verify that the response was overridden
|
||||
@@ -148,7 +148,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [first_middleware, second_middleware]
|
||||
|
||||
# Execute chat client
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -179,7 +179,7 @@ class TestChatMiddleware:
|
||||
agent = Agent(client=client, middleware=[agent_level_chat_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -213,7 +213,7 @@ class TestChatMiddleware:
|
||||
agent = Agent(client=chat_client_base, middleware=[first_middleware, second_middleware])
|
||||
|
||||
# Execute the agent
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await agent.run(messages)
|
||||
|
||||
# Verify response
|
||||
@@ -252,7 +252,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [streaming_middleware]
|
||||
|
||||
# Execute streaming response
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
updates: list[object] = []
|
||||
async for update in chat_client_base.get_response(messages, stream=True):
|
||||
updates.append(update)
|
||||
@@ -274,7 +274,7 @@ class TestChatMiddleware:
|
||||
await call_next()
|
||||
|
||||
# First call with run-level middleware
|
||||
messages = [Message(role="user", text="first message")]
|
||||
messages = [Message(role="user", contents=["first message"])]
|
||||
response1 = await chat_client_base.get_response(
|
||||
messages,
|
||||
client_kwargs={"middleware": [counting_middleware]},
|
||||
@@ -283,13 +283,13 @@ class TestChatMiddleware:
|
||||
assert execution_count["count"] == 1
|
||||
|
||||
# Second call WITHOUT run-level middleware - should not execute the middleware
|
||||
messages = [Message(role="user", text="second message")]
|
||||
messages = [Message(role="user", contents=["second message"])]
|
||||
response2 = await chat_client_base.get_response(messages)
|
||||
assert response2 is not None
|
||||
assert execution_count["count"] == 1 # Should still be 1, not 2
|
||||
|
||||
# Third call with run-level middleware again - should execute
|
||||
messages = [Message(role="user", text="third message")]
|
||||
messages = [Message(role="user", contents=["third message"])]
|
||||
response3 = await chat_client_base.get_response(
|
||||
messages,
|
||||
client_kwargs={"middleware": [counting_middleware]},
|
||||
@@ -310,7 +310,7 @@ class TestChatMiddleware:
|
||||
|
||||
async def fake_inner_get_response(**kwargs: Any) -> ChatResponse:
|
||||
assert "middleware" not in kwargs
|
||||
return ChatResponse(messages=[Message(role="assistant", text="ok")])
|
||||
return ChatResponse(messages=[Message(role="assistant", contents=["ok"])])
|
||||
|
||||
with patch.object(
|
||||
chat_client_base,
|
||||
@@ -318,7 +318,7 @@ class TestChatMiddleware:
|
||||
side_effect=fake_inner_get_response,
|
||||
) as mock_inner_get_response:
|
||||
response = await chat_client_base.get_response(
|
||||
[Message(role="user", text="hello")],
|
||||
[Message(role="user", contents=["hello"])],
|
||||
client_kwargs={"middleware": [inspecting_middleware], "trace_id": "trace-123"},
|
||||
)
|
||||
|
||||
@@ -350,7 +350,7 @@ class TestChatMiddleware:
|
||||
chat_client_base.chat_middleware = [kwargs_middleware]
|
||||
|
||||
# Execute chat client with runtime options
|
||||
messages = [Message(role="user", text="test message")]
|
||||
messages = [Message(role="user", contents=["test message"])]
|
||||
response = await chat_client_base.get_response(
|
||||
messages,
|
||||
options={"temperature": 0.7, "max_tokens": 100, "custom_param": "test_value"},
|
||||
@@ -493,12 +493,12 @@ class TestChatMiddleware:
|
||||
]
|
||||
)
|
||||
final_response = ChatResponse(
|
||||
messages=[Message(role="assistant", text="Based on the weather data, it's sunny!")]
|
||||
messages=[Message(role="assistant", contents=["Based on the weather data, it's sunny!"])]
|
||||
)
|
||||
|
||||
client.run_responses = [function_call_response, final_response]
|
||||
# Execute the chat client directly with tools - this should trigger function invocation and middleware
|
||||
messages = [Message(role="user", text="What's the weather in San Francisco?")]
|
||||
messages = [Message(role="user", contents=["What's the weather in San Francisco?"])]
|
||||
response = await client.get_response(messages, options={"tools": [sample_tool_wrapped]})
|
||||
|
||||
# Verify response
|
||||
@@ -557,7 +557,7 @@ class TestChatMiddleware:
|
||||
client.run_responses = [function_call_response]
|
||||
|
||||
# Execute the chat client directly with run-level middleware and tools
|
||||
messages = [Message(role="user", text="What's the weather in New York?")]
|
||||
messages = [Message(role="user", contents=["What's the weather in New York?"])]
|
||||
response = await client.get_response(
|
||||
messages,
|
||||
options={"tools": [sample_tool_wrapped]},
|
||||
@@ -627,11 +627,11 @@ class TestChatMiddleware:
|
||||
)
|
||||
]
|
||||
),
|
||||
ChatResponse(messages=[Message(role="assistant", text="Based on the weather data, it's sunny!")]),
|
||||
ChatResponse(messages=[Message(role="assistant", contents=["Based on the weather data, it's sunny!"])]),
|
||||
]
|
||||
|
||||
response = await client.get_response(
|
||||
[Message(role="user", text="What's the weather in Seattle?")],
|
||||
[Message(role="user", contents=["What's the weather in Seattle?"])],
|
||||
options={"tools": [sample_tool_wrapped]},
|
||||
client_kwargs={"middleware": [run_level_chat_middleware, run_level_function_middleware]},
|
||||
)
|
||||
@@ -710,7 +710,7 @@ class TestChatMiddleware:
|
||||
|
||||
updates: list[ChatResponseUpdate] = []
|
||||
async for update in client.get_response(
|
||||
[Message(role="user", text="What's the weather in Seattle?")],
|
||||
[Message(role="user", contents=["What's the weather in Seattle?"])],
|
||||
options={"tools": [sample_tool_wrapped]},
|
||||
client_kwargs={"middleware": [run_level_chat_middleware, run_level_function_middleware]},
|
||||
stream=True,
|
||||
|
||||
@@ -203,7 +203,7 @@ async def test_chat_client_observability(mock_chat_client, span_exporter: InMemo
|
||||
"""Test that when diagnostics are enabled, telemetry is applied."""
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options={"model": "Test"})
|
||||
assert response is not None
|
||||
@@ -227,7 +227,7 @@ async def test_chat_client_observability_accepts_model_option(
|
||||
"""Test that telemetry also captures the modern model option."""
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options={"model": "Test"})
|
||||
assert response is not None
|
||||
@@ -243,7 +243,7 @@ async def test_chat_client_streaming_observability(
|
||||
):
|
||||
"""Test streaming telemetry through the chat telemetry mixin."""
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
span_exporter.clear()
|
||||
# Collect all yielded updates
|
||||
updates = []
|
||||
@@ -274,7 +274,7 @@ async def test_chat_client_observability_with_instructions(
|
||||
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
options = {"model": "Test", "instructions": "You are a helpful assistant."}
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options=options)
|
||||
@@ -303,7 +303,7 @@ async def test_chat_client_streaming_observability_with_instructions(
|
||||
import json
|
||||
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
options = {"model": "Test", "instructions": "You are a helpful assistant."}
|
||||
span_exporter.clear()
|
||||
|
||||
@@ -332,7 +332,7 @@ async def test_chat_client_observability_without_instructions(
|
||||
"""Test that system_instructions attribute is not set when instructions are not provided."""
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
options = {"model": "Test"} # No instructions
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options=options)
|
||||
@@ -353,7 +353,7 @@ async def test_chat_client_observability_with_empty_instructions(
|
||||
"""Test that system_instructions attribute is not set when instructions is an empty string."""
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
options = {"model": "Test", "instructions": ""} # Empty string
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options=options)
|
||||
@@ -376,7 +376,7 @@ async def test_chat_client_observability_with_list_instructions(
|
||||
|
||||
client = mock_chat_client()
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
options = {"model": "Test", "instructions": ["Instruction 1", "Instruction 2"]}
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options=options)
|
||||
@@ -397,7 +397,7 @@ async def test_chat_client_observability_with_list_instructions(
|
||||
async def test_chat_client_without_model_observability(mock_chat_client, span_exporter: InMemorySpanExporter):
|
||||
"""Test telemetry shouldn't fail when the model is not provided for unknown reason."""
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages)
|
||||
|
||||
@@ -414,7 +414,7 @@ async def test_chat_client_without_model_observability(mock_chat_client, span_ex
|
||||
async def test_chat_client_streaming_without_model_observability(mock_chat_client, span_exporter: InMemorySpanExporter):
|
||||
"""Test streaming telemetry shouldn't fail when the model is not provided for unknown reason."""
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
span_exporter.clear()
|
||||
# Collect all yielded updates
|
||||
updates = []
|
||||
@@ -1549,7 +1549,7 @@ async def test_chat_client_observability_exception(mock_chat_client, span_export
|
||||
raise ValueError("Test error")
|
||||
|
||||
client = FailingChatClient()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
|
||||
span_exporter.clear()
|
||||
with pytest.raises(ValueError, match="Test error"):
|
||||
@@ -1579,7 +1579,7 @@ async def test_chat_client_streaming_observability_exception(mock_chat_client, s
|
||||
return ResponseStream(_stream(), finalizer=ChatResponse.from_updates)
|
||||
|
||||
client = FailingStreamingChatClient()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
|
||||
span_exporter.clear()
|
||||
with pytest.raises(ValueError, match="Streaming error"):
|
||||
@@ -2079,13 +2079,13 @@ async def test_capture_messages_with_finish_reason(mock_chat_client, span_export
|
||||
class ClientWithFinishReason(mock_chat_client):
|
||||
async def _inner_get_response(self, *, messages, options, **kwargs):
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text="Done")],
|
||||
messages=[Message(role="assistant", contents=["Done"])],
|
||||
usage_details=UsageDetails(input_token_count=5, output_token_count=10),
|
||||
finish_reason="stop",
|
||||
)
|
||||
|
||||
client = ClientWithFinishReason()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options={"model": "Test"})
|
||||
@@ -2175,7 +2175,7 @@ async def test_agent_streaming_exception(span_exporter: InMemorySpanExporter, en
|
||||
async def test_chat_client_when_disabled(mock_chat_client, span_exporter: InMemorySpanExporter):
|
||||
"""Test that no spans are created when instrumentation is disabled."""
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options={"model": "Test"})
|
||||
@@ -2190,7 +2190,7 @@ async def test_chat_client_when_disabled(mock_chat_client, span_exporter: InMemo
|
||||
async def test_chat_client_streaming_when_disabled(mock_chat_client, span_exporter: InMemorySpanExporter):
|
||||
"""Test streaming creates no spans when instrumentation is disabled."""
|
||||
client = mock_chat_client()
|
||||
messages = [Message(role="user", text="Test")]
|
||||
messages = [Message(role="user", contents=["Test"])]
|
||||
|
||||
span_exporter.clear()
|
||||
updates = []
|
||||
@@ -2540,7 +2540,7 @@ async def test_layer_ordering_span_sequence_with_function_calling(span_exporter:
|
||||
],
|
||||
)
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text="The weather in Seattle is sunny!")],
|
||||
messages=[Message(role="assistant", contents=["The weather in Seattle is sunny!"])],
|
||||
)
|
||||
|
||||
return _get()
|
||||
@@ -2549,7 +2549,7 @@ async def test_layer_ordering_span_sequence_with_function_calling(span_exporter:
|
||||
span_exporter.clear()
|
||||
|
||||
response = await client.get_response(
|
||||
messages=[Message(role="user", text="What's the weather in Seattle?")],
|
||||
messages=[Message(role="user", contents=["What's the weather in Seattle?"])],
|
||||
options={"tools": [get_weather], "tool_choice": "auto"},
|
||||
)
|
||||
|
||||
@@ -2598,7 +2598,7 @@ async def test_agent_and_chat_spans_do_not_duplicate_response_telemetry(
|
||||
|
||||
def _finalize(updates: Sequence[ChatResponseUpdate]) -> ChatResponse:
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text="Nested response")],
|
||||
messages=[Message(role="assistant", contents=["Nested response"])],
|
||||
response_id="nested_resp_123",
|
||||
usage_details=UsageDetails(input_token_count=11, output_token_count=22),
|
||||
finish_reason="stop",
|
||||
@@ -2608,7 +2608,7 @@ async def test_agent_and_chat_spans_do_not_duplicate_response_telemetry(
|
||||
|
||||
async def _get() -> ChatResponse:
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text="Nested response")],
|
||||
messages=[Message(role="assistant", contents=["Nested response"])],
|
||||
response_id="nested_resp_123",
|
||||
usage_details=UsageDetails(input_token_count=11, output_token_count=22),
|
||||
finish_reason="stop",
|
||||
@@ -2666,12 +2666,12 @@ async def test_capture_messages_preserves_non_ascii_characters(mock_chat_client,
|
||||
class ClientWithJapanese(mock_chat_client):
|
||||
async def _inner_get_response(self, *, messages, options, **kwargs):
|
||||
return ChatResponse(
|
||||
messages=[Message(role="assistant", text=japanese_text)],
|
||||
messages=[Message(role="assistant", contents=[japanese_text])],
|
||||
usage_details=UsageDetails(input_token_count=5, output_token_count=10),
|
||||
)
|
||||
|
||||
client = ClientWithJapanese()
|
||||
messages = [Message(role="user", text=japanese_text)]
|
||||
messages = [Message(role="user", contents=[japanese_text])]
|
||||
|
||||
span_exporter.clear()
|
||||
response = await client.get_response(messages=messages, options={"model": "Test"})
|
||||
@@ -2715,7 +2715,7 @@ async def test_system_instructions_preserves_non_ascii_characters(span_exporter:
|
||||
_capture_messages(
|
||||
span=span,
|
||||
provider_name="test_provider",
|
||||
messages=[Message(role="user", text="Test")],
|
||||
messages=[Message(role="user", contents=["Test"])],
|
||||
system_instructions=chinese_text,
|
||||
)
|
||||
|
||||
@@ -2840,7 +2840,7 @@ async def test_agent_instructions_from_default_options(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel", "instructions": "Default system instructions."}
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await agent.run(messages)
|
||||
|
||||
@@ -2866,7 +2866,7 @@ async def test_agent_instructions_from_options_override(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel"} # No default instructions
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await agent.run(messages, options={"instructions": "Override instructions."})
|
||||
|
||||
@@ -2891,7 +2891,7 @@ async def test_agent_instructions_merged_from_default_and_options(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel", "instructions": "Default instructions."}
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await agent.run(messages, options={"instructions": "Additional instructions."})
|
||||
|
||||
@@ -2918,7 +2918,7 @@ async def test_agent_streaming_instructions_from_default_options(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel", "instructions": "Default streaming instructions."}
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
updates = []
|
||||
stream = agent.run(messages, stream=True)
|
||||
@@ -2947,7 +2947,7 @@ async def test_agent_streaming_instructions_merged_from_default_and_options(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel", "instructions": "Default instructions."}
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
updates = []
|
||||
stream = agent.run(messages, stream=True, options={"instructions": "Stream override."})
|
||||
@@ -2975,7 +2975,7 @@ async def test_agent_no_instructions_in_default_or_options(
|
||||
agent = mock_chat_agent()
|
||||
agent.default_options = {"model": "TestModel"} # No instructions
|
||||
|
||||
messages = [Message(role="user", text="Test message")]
|
||||
messages = [Message(role="user", contents=["Test message"])]
|
||||
span_exporter.clear()
|
||||
response = await agent.run(messages)
|
||||
|
||||
@@ -3204,7 +3204,7 @@ async def test_agent_invoke_span_aggregates_usage_across_tool_calls(span_exporte
|
||||
usage_details=UsageDetails(input_token_count=2239, output_token_count=192),
|
||||
),
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="The weather in Seattle is sunny."),
|
||||
messages=Message(role="assistant", contents=["The weather in Seattle is sunny."]),
|
||||
usage_details=UsageDetails(input_token_count=2569, output_token_count=99),
|
||||
),
|
||||
]
|
||||
@@ -3248,7 +3248,7 @@ async def test_agent_invoke_span_usage_single_call(span_exporter: InMemorySpanEx
|
||||
client = MockBaseChatClient()
|
||||
client.run_responses = [
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="Hello!"),
|
||||
messages=Message(role="assistant", contents=["Hello!"]),
|
||||
usage_details=UsageDetails(input_token_count=100, output_token_count=50),
|
||||
),
|
||||
]
|
||||
@@ -3291,7 +3291,7 @@ async def test_agent_invoke_span_aggregates_usage_on_max_iterations_exhaustion(s
|
||||
),
|
||||
# Exhaustion path: consumed by tool_choice="none" final call (mock ignores usage)
|
||||
ChatResponse(
|
||||
messages=Message(role="assistant", text="placeholder"),
|
||||
messages=Message(role="assistant", contents=["placeholder"]),
|
||||
usage_details=UsageDetails(input_token_count=300, output_token_count=60),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -8,8 +8,6 @@ import pytest
|
||||
from agent_framework import (
|
||||
AgentContext,
|
||||
AgentSession,
|
||||
BaseContextProvider,
|
||||
BaseHistoryProvider,
|
||||
ChatContext,
|
||||
ContextProvider,
|
||||
HistoryProvider,
|
||||
@@ -237,23 +235,6 @@ class TestContextProvider:
|
||||
await provider.after_run(agent=None, session=session, context=ctx, state={}) # type: ignore[arg-type]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Deprecated provider alias tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TestDeprecatedProviderAliases:
|
||||
def test_base_context_provider_warns_and_is_compatible(self) -> None:
|
||||
with pytest.warns(DeprecationWarning, match="BaseContextProvider is deprecated. Use ContextProvider instead."):
|
||||
provider = BaseContextProvider(source_id="test")
|
||||
|
||||
assert isinstance(provider, ContextProvider)
|
||||
|
||||
def test_base_provider_aliases_preserve_subtyping(self) -> None:
|
||||
assert issubclass(BaseContextProvider, ContextProvider)
|
||||
assert issubclass(BaseHistoryProvider, HistoryProvider)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# HistoryProvider tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -699,7 +699,7 @@ def test_ai_content_serialization(args: dict):
|
||||
def test_chat_message_text():
|
||||
"""Test the Message class to ensure it initializes correctly with text content."""
|
||||
# Create a Message with a role and text content
|
||||
message = Message(role="user", text="Hello, how are you?")
|
||||
message = Message(role="user", contents=["Hello, how are you?"])
|
||||
|
||||
# Check the type and content
|
||||
assert message.role == "user"
|
||||
@@ -730,7 +730,7 @@ def test_chat_message_contents():
|
||||
|
||||
|
||||
def test_chat_message_with_chatrole_instance():
|
||||
m = Message(role="user", text="hi")
|
||||
m = Message(role="user", contents=["hi"])
|
||||
assert m.role == "user"
|
||||
assert m.text == "hi"
|
||||
|
||||
@@ -741,7 +741,7 @@ def test_chat_message_with_chatrole_instance():
|
||||
def test_chat_response():
|
||||
"""Test the ChatResponse class to ensure it initializes correctly with a message."""
|
||||
# Create a Message
|
||||
message = Message(role="assistant", text="I'm doing well, thank you!")
|
||||
message = Message(role="assistant", contents=["I'm doing well, thank you!"])
|
||||
|
||||
# Create a ChatResponse with the message
|
||||
response = ChatResponse(messages=message)
|
||||
@@ -756,7 +756,7 @@ def test_chat_response():
|
||||
|
||||
def test_chat_response_accepts_model_alias() -> None:
|
||||
"""Test ChatResponse accepts model and exposes it through model alias."""
|
||||
response = ChatResponse(messages=Message(role="assistant", text="Hello"), model="claude-test")
|
||||
response = ChatResponse(messages=Message(role="assistant", contents=["Hello"]), model="claude-test")
|
||||
|
||||
assert response.model == "claude-test"
|
||||
assert response.model == "claude-test"
|
||||
@@ -769,7 +769,7 @@ class OutputModel(BaseModel):
|
||||
def test_chat_response_with_format():
|
||||
"""Test the ChatResponse class to ensure it initializes correctly with a message."""
|
||||
# Create a Message
|
||||
message = Message(role="assistant", text='{"response": "Hello"}')
|
||||
message = Message(role="assistant", contents=['{"response": "Hello"}'])
|
||||
|
||||
# Create a ChatResponse with the message
|
||||
response = ChatResponse(messages=message, response_format=OutputModel)
|
||||
@@ -786,7 +786,7 @@ def test_chat_response_with_format():
|
||||
def test_chat_response_with_format_init():
|
||||
"""Test the ChatResponse class to ensure it initializes correctly with a message."""
|
||||
# Create a Message
|
||||
message = Message(role="assistant", text='{"response": "Hello"}')
|
||||
message = Message(role="assistant", contents=['{"response": "Hello"}'])
|
||||
|
||||
# Create a ChatResponse with the message
|
||||
response = ChatResponse(messages=message, response_format=OutputModel)
|
||||
@@ -802,7 +802,7 @@ def test_chat_response_with_format_init():
|
||||
|
||||
def test_chat_response_with_mapping_response_format() -> None:
|
||||
"""ChatResponse.value should parse JSON when response_format is a mapping."""
|
||||
message = Message(role="assistant", text='{"response": "Hello"}')
|
||||
message = Message(role="assistant", contents=['{"response": "Hello"}'])
|
||||
response = ChatResponse(
|
||||
messages=message,
|
||||
response_format={"type": "object", "properties": {"response": {"type": "string"}}},
|
||||
@@ -821,7 +821,7 @@ def test_chat_response_value_raises_on_invalid_schema():
|
||||
name: str = Field(min_length=10)
|
||||
score: int = Field(gt=0, le=100)
|
||||
|
||||
message = Message(role="assistant", text='{"id": 1, "name": "test", "score": -5}')
|
||||
message = Message(role="assistant", contents=['{"id": 1, "name": "test", "score": -5}'])
|
||||
response = ChatResponse(messages=message, response_format=StrictSchema)
|
||||
|
||||
with raises(ValidationError) as exc_info:
|
||||
@@ -842,7 +842,7 @@ def test_agent_response_value_raises_on_invalid_schema():
|
||||
name: str = Field(min_length=10)
|
||||
score: int = Field(gt=0, le=100)
|
||||
|
||||
message = Message(role="assistant", text='{"id": 1, "name": "test", "score": -5}')
|
||||
message = Message(role="assistant", contents=['{"id": 1, "name": "test", "score": -5}'])
|
||||
response = AgentResponse(messages=message, response_format=StrictSchema)
|
||||
|
||||
with raises(ValidationError) as exc_info:
|
||||
@@ -1185,7 +1185,7 @@ def test_chat_options_and_tool_choice_required_specific_function() -> None:
|
||||
|
||||
@fixture
|
||||
def chat_message() -> Message:
|
||||
return Message(role="user", text="Hello")
|
||||
return Message(role="user", contents=["Hello"])
|
||||
|
||||
|
||||
@fixture
|
||||
@@ -1302,7 +1302,7 @@ def test_agent_run_response_created_at() -> None:
|
||||
# Test with a properly formatted UTC timestamp
|
||||
utc_timestamp = "2024-12-01T00:31:30.000000Z"
|
||||
response = AgentResponse(
|
||||
messages=[Message(role="assistant", text="Hello")],
|
||||
messages=[Message(role="assistant", contents=["Hello"])],
|
||||
created_at=utc_timestamp,
|
||||
)
|
||||
assert response.created_at == utc_timestamp
|
||||
@@ -1312,7 +1312,7 @@ def test_agent_run_response_created_at() -> None:
|
||||
now_utc = datetime.now(tz=timezone.utc)
|
||||
formatted_utc = now_utc.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
response_with_now = AgentResponse(
|
||||
messages=[Message(role="assistant", text="Hello")],
|
||||
messages=[Message(role="assistant", contents=["Hello"])],
|
||||
created_at=formatted_utc,
|
||||
)
|
||||
assert response_with_now.created_at == formatted_utc
|
||||
@@ -1466,7 +1466,7 @@ def test_chat_tool_mode_eq_with_string():
|
||||
|
||||
@fixture
|
||||
def agent_run_response_async() -> AgentResponse:
|
||||
return AgentResponse(messages=[Message(role="user", text="Hello")])
|
||||
return AgentResponse(messages=[Message(role="user", contents=["Hello"])])
|
||||
|
||||
|
||||
async def test_agent_run_response_from_async_generator():
|
||||
|
||||
@@ -158,8 +158,8 @@ async def test_agent_executor_checkpoint_stores_and_restores_state() -> None:
|
||||
|
||||
# Add some initial messages to the session state to verify session state persistence
|
||||
initial_messages = [
|
||||
Message(role="user", text="Initial message 1"),
|
||||
Message(role="assistant", text="Initial response 1"),
|
||||
Message(role="user", contents=["Initial message 1"]),
|
||||
Message(role="assistant", contents=["Initial response 1"]),
|
||||
]
|
||||
initial_session.state["history"] = {"messages": initial_messages}
|
||||
|
||||
@@ -256,9 +256,9 @@ async def test_agent_executor_save_and_restore_state_directly() -> None:
|
||||
|
||||
# Add messages to session state
|
||||
session_messages = [
|
||||
Message(role="user", text="Message in session 1"),
|
||||
Message(role="assistant", text="Session response 1"),
|
||||
Message(role="user", text="Message in session 2"),
|
||||
Message(role="user", contents=["Message in session 1"]),
|
||||
Message(role="assistant", contents=["Session response 1"]),
|
||||
Message(role="user", contents=["Message in session 2"]),
|
||||
]
|
||||
session.state["history"] = {"messages": session_messages}
|
||||
|
||||
@@ -266,8 +266,8 @@ async def test_agent_executor_save_and_restore_state_directly() -> None:
|
||||
|
||||
# Add messages to executor cache
|
||||
cache_messages = [
|
||||
Message(role="user", text="Cached user message"),
|
||||
Message(role="assistant", text="Cached assistant response"),
|
||||
Message(role="user", contents=["Cached user message"]),
|
||||
Message(role="assistant", contents=["Cached assistant response"]),
|
||||
]
|
||||
executor._cache = list(cache_messages) # type: ignore[reportPrivateUsage]
|
||||
|
||||
@@ -562,7 +562,7 @@ async def test_checkpoint_restore_works_without_context_mode_in_state() -> None:
|
||||
|
||||
# Simulate a checkpoint state without context_mode (as saved by the new code)
|
||||
state: dict[str, Any] = {
|
||||
"cache": [Message(role="user", text="cached msg")],
|
||||
"cache": [Message(role="user", contents=["cached msg"])],
|
||||
"full_conversation": [],
|
||||
"agent_session": AgentSession().to_dict(),
|
||||
"pending_agent_requests": {},
|
||||
|
||||
@@ -8,7 +8,7 @@ from agent_framework._workflows._events import WorkflowEvent
|
||||
|
||||
def test_workflow_event_with_agent_response_data_type() -> None:
|
||||
"""Verify WorkflowEvent[AgentResponse].data is typed as AgentResponse."""
|
||||
response = AgentResponse(messages=[Message(role="assistant", text="Hello")])
|
||||
response = AgentResponse(messages=[Message(role="assistant", contents=["Hello"])])
|
||||
event: WorkflowEvent[AgentResponse] = WorkflowEvent.emit(executor_id="test", data=response)
|
||||
|
||||
# This assignment should pass type checking without a cast
|
||||
@@ -29,7 +29,7 @@ def test_workflow_event_with_agent_response_update_data_type() -> None:
|
||||
|
||||
def test_workflow_event_repr() -> None:
|
||||
"""Verify WorkflowEvent.__repr__ uses consistent format."""
|
||||
response = AgentResponse(messages=[Message(role="assistant", text="Hello")])
|
||||
response = AgentResponse(messages=[Message(role="assistant", contents=["Hello"])])
|
||||
event: WorkflowEvent[AgentResponse] = WorkflowEvent.emit(executor_id="test", data=response)
|
||||
|
||||
repr_str = repr(event)
|
||||
|
||||
@@ -540,7 +540,7 @@ async def test_executor_invoked_event_data_not_mutated_by_handler():
|
||||
async def mutator(messages: list[Message], ctx: WorkflowContext[list[Message]]) -> None:
|
||||
# The handler mutates the input list by appending new messages
|
||||
original_len = len(messages)
|
||||
messages.append(Message(role="assistant", text="Added by executor"))
|
||||
messages.append(Message(role="assistant", contents=["Added by executor"]))
|
||||
await ctx.send_message(messages)
|
||||
# Verify mutation happened
|
||||
assert len(messages) == original_len + 1
|
||||
@@ -548,7 +548,7 @@ async def test_executor_invoked_event_data_not_mutated_by_handler():
|
||||
workflow = WorkflowBuilder(start_executor=mutator).build()
|
||||
|
||||
# Run with a single user message
|
||||
input_messages = [Message(role="user", text="hello")]
|
||||
input_messages = [Message(role="user", contents=["hello"])]
|
||||
events = await workflow.run(input_messages)
|
||||
|
||||
# Find the invoked event for the Mutator executor
|
||||
|
||||
@@ -322,7 +322,7 @@ class _RoundTripCoordinator(Executor):
|
||||
assert response.full_conversation is not None
|
||||
await ctx.send_message(
|
||||
AgentExecutorRequest(
|
||||
messages=list(response.full_conversation) + [Message(role="user", text="apply feedback")],
|
||||
messages=list(response.full_conversation) + [Message(role="user", contents=["apply feedback"])],
|
||||
should_respond=True,
|
||||
),
|
||||
target_id=self._target_agent_id,
|
||||
@@ -418,7 +418,7 @@ class _FullHistoryReplayCoordinator(Executor):
|
||||
ctx: WorkflowContext[AgentExecutorRequest, Any],
|
||||
) -> None:
|
||||
full_conv = list(response.full_conversation or response.agent_response.messages)
|
||||
full_conv.append(Message(role="user", text="follow-up"))
|
||||
full_conv.append(Message(role="user", contents=["follow-up"]))
|
||||
# Simulate a prior run: the target executor has a stored previous_response_id.
|
||||
self._target_exec._session.service_session_id = "resp_PREVIOUS_RUN" # pyright: ignore[reportPrivateUsage]
|
||||
await ctx.send_message(
|
||||
|
||||
@@ -344,7 +344,7 @@ class TestWorkflowAgent:
|
||||
workflow = WorkflowBuilder(start_executor=yielding_executor).build()
|
||||
|
||||
# Run directly - should return output event (type='output') in result
|
||||
direct_result = await workflow.run([Message(role="user", text="hello")])
|
||||
direct_result = await workflow.run([Message(role="user", contents=["hello"])])
|
||||
direct_outputs = direct_result.get_outputs()
|
||||
assert len(direct_outputs) == 1
|
||||
assert direct_outputs[0] == "processed: hello"
|
||||
@@ -479,8 +479,8 @@ class TestWorkflowAgent:
|
||||
async def list_yielding_executor(messages: list[Message], ctx: WorkflowContext[Never, list[Message]]) -> None:
|
||||
# Yield a list of Messages (as SequentialBuilder does)
|
||||
msg_list = [
|
||||
Message(role="user", text="first message"),
|
||||
Message(role="assistant", text="second message"),
|
||||
Message(role="user", contents=["first message"]),
|
||||
Message(role="assistant", contents=["second message"]),
|
||||
Message(
|
||||
role="assistant",
|
||||
contents=[Content.from_text(text="third"), Content.from_text(text="fourth")],
|
||||
|
||||
@@ -65,7 +65,7 @@ class DummyAgent(BaseAgent):
|
||||
if isinstance(m, Message):
|
||||
norm.append(m)
|
||||
elif isinstance(m, str):
|
||||
norm.append(Message(role="user", text=m))
|
||||
norm.append(Message(role="user", contents=[m]))
|
||||
return AgentResponse(messages=norm)
|
||||
|
||||
async def _run_stream_impl(self) -> AsyncIterator[AgentResponseUpdate]:
|
||||
|
||||
@@ -469,10 +469,10 @@ async def test_magentic_kwargs_flow_to_agents() -> None:
|
||||
self.task_ledger = None
|
||||
|
||||
async def plan(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Plan: Test task", author_name="manager")
|
||||
return Message(role="assistant", contents=["Plan: Test task"], author_name="manager")
|
||||
|
||||
async def replan(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Replan: Test task", author_name="manager")
|
||||
return Message(role="assistant", contents=["Replan: Test task"], author_name="manager")
|
||||
|
||||
async def create_progress_ledger(self, magentic_context: MagenticContext) -> MagenticProgressLedger:
|
||||
# Return completed on first call
|
||||
@@ -485,7 +485,7 @@ async def test_magentic_kwargs_flow_to_agents() -> None:
|
||||
)
|
||||
|
||||
async def prepare_final_answer(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Final answer", author_name="manager")
|
||||
return Message(role="assistant", contents=["Final answer"], author_name="manager")
|
||||
|
||||
agent = _KwargsCapturingAgent(name="agent1")
|
||||
manager = _MockManager()
|
||||
@@ -520,10 +520,10 @@ async def test_magentic_kwargs_stored_in_state() -> None:
|
||||
self.task_ledger = None
|
||||
|
||||
async def plan(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Plan", author_name="manager")
|
||||
return Message(role="assistant", contents=["Plan"], author_name="manager")
|
||||
|
||||
async def replan(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Replan", author_name="manager")
|
||||
return Message(role="assistant", contents=["Replan"], author_name="manager")
|
||||
|
||||
async def create_progress_ledger(self, magentic_context: MagenticContext) -> MagenticProgressLedger:
|
||||
return MagenticProgressLedger(
|
||||
@@ -535,7 +535,7 @@ async def test_magentic_kwargs_stored_in_state() -> None:
|
||||
)
|
||||
|
||||
async def prepare_final_answer(self, magentic_context: MagenticContext) -> Message:
|
||||
return Message(role="assistant", text="Final", author_name="manager")
|
||||
return Message(role="assistant", contents=["Final"], author_name="manager")
|
||||
|
||||
agent = _KwargsCapturingAgent(name="agent1")
|
||||
manager = _MockManager()
|
||||
|
||||
Reference in New Issue
Block a user