Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions python/packages/core/agent_framework/_compaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ def _has_content_type(message: Message, content_type: str) -> bool:
return any(content.type == content_type for content in message.contents)


def _has_function_call(message: Message) -> bool:
return _has_content_type(message, "function_call")
def _has_tool_call(message: Message) -> bool:
return any(content.type in {"function_call", "mcp_server_tool_call"} for content in message.contents)


def _has_reasoning(message: Message) -> bool:
return _has_content_type(message, "text_reasoning")


def _is_tool_call_assistant(message: Message) -> bool:
return message.role == "assistant" and _has_function_call(message)
return message.role == "assistant" and _has_tool_call(message)


def _is_reasoning_only_assistant(message: Message) -> bool:
Expand Down
31 changes: 31 additions & 0 deletions python/packages/core/tests/core/test_compaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ def _assistant_function_call(call_id: str) -> Message:
)


def _assistant_mcp_call(call_id: str) -> Message:
return Message(
role="assistant",
contents=[
Content.from_mcp_server_tool_call(
call_id=call_id,
tool_name="search",
server_name="test_server",
arguments='{"query":"x"}',
)
],
)


def _assistant_reasoning_and_function_calls(*call_ids: str) -> Message:
contents: list[Content] = [Content.from_text_reasoning(text="thinking")]
for call_id in call_ids:
Expand Down Expand Up @@ -154,6 +168,23 @@ def test_group_annotations_handle_same_message_reasoning_and_function_calls() ->
assert _group_has_reasoning(messages[1]) is True


async def test_sliding_window_keeps_reasoning_and_mcp_call_atomic() -> None:
messages = [
Message(role="system", contents=["system"]),
Message(role="assistant", contents=[Content.from_text_reasoning(id="rs_1", text="thinking")]),
_assistant_mcp_call("mcp_1"),
Message(role="assistant", contents=["answer"]),
Message(role="user", contents=["follow up"]),
]
annotate_message_groups(messages)

await SlidingWindowStrategy(keep_last_groups=3)(messages)

assert messages[1].additional_properties[EXCLUDED_KEY] is False
assert messages[2].additional_properties[EXCLUDED_KEY] is False
assert _group_id(messages[1]) == _group_id(messages[2])


def test_annotate_message_groups_with_tokenizer_adds_token_counts() -> None:
messages = [
Message(role="user", contents=["hello"]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ async def _item_to_message(item: Item, *, approval_storage: ApprovalStorage | No
reason_contents: list[Content] = []
if reasoning.summary:
for summary in reasoning.summary:
reason_contents.append(Content.from_text(summary.text))
reason_contents.append(Content.from_text_reasoning(id=reasoning.id, text=summary.text))
return Message(role="assistant", contents=reason_contents)

if item.type == "mcp_call":
Expand Down Expand Up @@ -1383,7 +1383,7 @@ async def _output_item_to_message(item: OutputItem, *, approval_storage: Approva
contents: list[Content] = []
if reasoning.summary:
for summary in reasoning.summary:
contents.append(Content.from_text(summary.text))
contents.append(Content.from_text_reasoning(id=reasoning.id, text=summary.text))
return Message(role="assistant", contents=contents)

if item.type == "mcp_call":
Expand Down
4 changes: 4 additions & 0 deletions python/packages/foundry_hosting/tests/test_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,8 @@ async def test_reasoning(self) -> None:
msg = await _output_item_to_message(item)
assert msg.role == "assistant"
assert len(msg.contents) == 1
assert msg.contents[0].type == "text_reasoning"
assert msg.contents[0].id == "r-1"
assert msg.contents[0].text == "thinking hard"

async def test_reasoning_no_summary(self) -> None:
Expand Down Expand Up @@ -1298,6 +1300,8 @@ async def test_reasoning_with_summary(self) -> None:
assert msg is not None
assert msg.role == "assistant"
assert len(msg.contents) == 1
assert msg.contents[0].type == "text_reasoning"
assert msg.contents[0].id == "r-1"
assert msg.contents[0].text == "thinking hard"

async def test_reasoning_no_summary(self) -> None:
Expand Down