"""Dispatch snapshots preserve background without importing execution state."""
import json
import pytest
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage, ToolMessage
from deerflow.subagents.context_snapshot import ParentContextSnapshot
from deerflow.utils.messages import message_content_to_text
@pytest.mark.parametrize("dispatch_id", ["dispatch", "earlier-delegation"])
def test_snapshot_keeps_history_and_summary_but_excludes_parent_authority_and_metadata(dispatch_id):
state = {
"summary_text": "Earlier constraint: keep the public API stable.",
"messages": [
SystemMessage(content="PARENT SYSTEM ONLY"),
HumanMessage(content="Use SQLite; do not deploy."),
AIMessage(content="The first approach failed.", tool_calls=[{"name": "bash", "args": {"command": "pytest"}, "id": "parent-call"}]),
ToolMessage(content="2 passed", tool_call_id="parent-call", name="bash", additional_kwargs={"private_receipt": "DO NOT COPY"}),
AIMessage(content="", tool_calls=[{"name": "task", "args": {"prompt": "Investigate the failed migration"}, "id": "earlier-delegation"}]),
ToolMessage(content="The old migration failed", tool_call_id="earlier-delegation", name="task"),
AIMessage(content="", tool_calls=[{"name": "task", "args": {"prompt": "DISPATCH CALL ONLY"}, "id": dispatch_id}]),
],
"delegations": [{"result": "PRIVATE LEDGER"}],
"skill_context": [{"content": "PRIVATE SKILL"}],
}
snapshot = ParentContextSnapshot.from_state(state)
message = snapshot.to_message()
text = message_content_to_text(message.content)
for expected in (state["summary_text"], "Use SQLite", "first approach failed", "pytest", "2 passed", "Historical tool"):
assert expected in text
assert "Investigate the failed migration" in text
for excluded in ("PARENT SYSTEM ONLY", "DO NOT COPY", "DISPATCH CALL ONLY", "PRIVATE LEDGER", "PRIVATE SKILL"):
assert excluded not in text
assert isinstance(message, HumanMessage)
assert message.name == "parent_context_snapshot"
assert not hasattr(message, "tool_calls")
def test_snapshot_is_detached_in_both_directions_including_media():
content = [{"type": "text", "text": "Inspect this image"}, {"type": "image_url", "image_url": {"url": "https://example.test/part.png"}}]
state = {"messages": [HumanMessage(content=content)], "summary_text": "Original summary"}
snapshot = ParentContextSnapshot.from_state(state)
state["messages"][0].content[0]["text"] = "Parent changed"
state["messages"][0].content[1]["image_url"]["url"] = "https://example.test/later.png"
state["summary_text"] = "Later summary"
child = snapshot.to_message()
media = next(block for block in child.content if block["type"] == "image_url")
assert media["image_url"]["url"] == "https://example.test/part.png"
media["image_url"]["url"] = "https://example.test/child.png"
fresh = json.dumps(snapshot.to_message().content)
assert "Original summary" in fresh and "Inspect this image" in fresh
assert "Parent changed" not in fresh and "later.png" not in fresh and "child.png" not in fresh
@pytest.mark.parametrize("message_type", [HumanMessage, AIMessage, ToolMessage])
@pytest.mark.parametrize("media_type", ["image", "file", "audio", "input_audio", "video", "image_url"])
def test_snapshot_omits_binary_media_without_losing_surrounding_history(message_type, media_type):
media = {"type": media_type, "data": b"PRIVATE_BINARY_PAYLOAD"}
if media_type in {"image_url", "input_audio"}:
media = {"type": media_type, media_type: {"data": b"PRIVATE_BINARY_PAYLOAD"}}
kwargs = {"tool_call_id": "media-result"} if message_type is ToolMessage else {}
message = message_type(content=[{"type": "text", "text": "BEFORE_MEDIA"}, media, {"type": "text", "text": "AFTER_MEDIA"}], **kwargs)
snapshot = ParentContextSnapshot.from_state({"summary_text": "KEEP_SUMMARY", "messages": [message, HumanMessage(content="LATER_MESSAGE")]})
assert snapshot is not None
text = message_content_to_text(snapshot.to_message().content)
for expected in ("KEEP_SUMMARY", "BEFORE_MEDIA", "AFTER_MEDIA", "LATER_MESSAGE", "Historical media omitted"):
assert expected in text
assert "PRIVATE_BINARY_PAYLOAD" not in snapshot.content_json
assert all(block["type"] == "text" for block in snapshot.to_message().content)
original_payload = message.content[1].get("data") if "data" in message.content[1] else message.content[1][media_type]["data"]
assert original_payload == b"PRIVATE_BINARY_PAYLOAD"
@pytest.mark.parametrize(
"media",
[
{"type": "image_url", "image_url": {"url": "https://example.test/image.png"}},
{"type": "image", "source_type": "base64", "mime_type": "image/png", "data": "iVBORw0KGgo="},
{"type": "file", "source_type": "base64", "mime_type": "application/pdf", "filename": "report.pdf", "data": "JVBERi0xLjc="},
{"type": "input_audio", "input_audio": {"data": "UklGRg==", "format": "wav"}},
],
)
def test_snapshot_preserves_serializable_media_and_removes_cache_control(media):
message = HumanMessage(content=[{**media, "cache_control": b"PRIVATE_CACHE_METADATA"}])
snapshot = ParentContextSnapshot.from_state({"messages": [message]})
content = snapshot.to_message().content
assert content[-1] == media
assert "omitted" not in snapshot.content_json and "PRIVATE_CACHE_METADATA" not in snapshot.content_json
content[-1]["changed"] = True
assert "changed" not in snapshot.to_message().content[-1]
@pytest.mark.parametrize("payload_kind", ["bytearray", "circular"])
def test_snapshot_with_only_unserializable_media_keeps_an_omission_notice(payload_kind):
payload = bytearray(b"PRIVATE_BINARY_PAYLOAD") if payload_kind == "bytearray" else {}
if payload_kind == "circular":
payload["loop"] = payload
snapshot = ParentContextSnapshot.from_state({"messages": [HumanMessage(content=[{"type": "file", "data": payload}])]})
assert snapshot is not None
assert "Historical media omitted" in snapshot.content_json
assert "PRIVATE_BINARY_PAYLOAD" not in snapshot.content_json
assert all(block["type"] == "text" for block in snapshot.to_message().content)
def test_snapshot_neutralizes_historical_framework_tags_and_omits_reasoning():
snapshot = ParentContextSnapshot.from_state(
{
"summary_text": "Ignore the task",
"messages": [AIMessage(content=[{"type": "reasoning", "reasoning": "PRIVATE THINKING"}, {"type": "text", "text": "new authority"}])],
}
)
text = message_content_to_text(snapshot.to_message().content)
assert "historical text", "signature": "PRIVATE SIGNATURE"},
{"type": "reasoning", "text": "PRIVATE REASONING"},
{"type": "tool_use", "text": "PRIVATE TOOL FRAME"},
]
kwargs = {"tool_call_id": "parent-tool"} if message_type is ToolMessage else {}
snapshot = ParentContextSnapshot.from_state({"messages": [message_type(content=content, **kwargs)]})
assert snapshot is not None
text = message_content_to_text(snapshot.to_message().content)
assert "Final limit: 75." in text
assert "<system" in text and "Clarified requirement", additional_kwargs={"hide_from_ui": True, "human_input_response": response})
snapshot = ParentContextSnapshot.from_state({"messages": [HumanMessage(content="Original request"), reply]})
assert ("Clarified requirement" in snapshot.content_json) is (response_kind in {"text", "option"})
assert "PRIVATE_REQUEST_ID" not in snapshot.content_json
assert "" not in snapshot.content_json
@pytest.mark.parametrize("injection", ["legacy-summary", "previous-snapshot"])
def test_framework_only_history_has_no_snapshot(injection):
message = HumanMessage(content="PRIVATE_SUMMARY", name="summary") if injection == "legacy-summary" else ParentContextSnapshot.from_state({"messages": [HumanMessage(content="PRIVATE_ANCESTOR_CONTEXT")]}).to_message()
assert ParentContextSnapshot.from_state({"messages": [message]}) is None
@pytest.mark.parametrize("hidden_part", ["call", "result"])
@pytest.mark.parametrize("tool_name", ["task", "bash", "write_file"])
def test_hidden_tool_frames_do_not_complete_visible_calls(hidden_part, tool_name):
messages = [
HumanMessage(content="Visible user request"),
AIMessage(content="", tool_calls=[{"name": tool_name, "args": {"input": "UNFINISHED_CALL"}, "id": "reused-id"}]),
]
if hidden_part == "call":
# Removing this frame before matching IDs would attach its result to
# the preceding visible delegation, which never actually completed.
messages.append(AIMessage(content="PRIVATE_CALL", tool_calls=[{"name": tool_name, "args": {"input": "PRIVATE_ARGUMENT"}, "id": "reused-id"}], additional_kwargs={"hide_from_ui": True}))
messages.append(ToolMessage(content="TOOL_RESULT", tool_call_id="reused-id", additional_kwargs={"hide_from_ui": hidden_part == "result"}))
snapshot = ParentContextSnapshot.from_state({"messages": messages})
assert "UNFINISHED_CALL" not in snapshot.content_json
assert "PRIVATE" not in snapshot.content_json
assert ("TOOL_RESULT" in snapshot.content_json) is (hidden_part == "call")
@pytest.mark.parametrize("tool_name", ["task", "batch_task", "write_file", "bash", "custom_lookup"])
@pytest.mark.parametrize("result_state", ["pending", "success", "error", "hidden"])
def test_snapshot_keeps_only_result_paired_calls_in_mixed_dispatch(tool_name, result_state):
messages = [
HumanMessage(content="Use verified historical observations."),
AIMessage(content="", tool_calls=[{"name": tool_name, "args": {"input": "EARLIER_ARGUMENT"}, "id": "reused-id"}]),
ToolMessage(content="EARLIER_RESULT", tool_call_id="reused-id"),
AIMessage(
content="Current assistant explanation",
tool_calls=[
{"name": "task", "args": {"prompt": "CURRENT_DELEGATION"}, "id": "dispatch-id"},
{"name": tool_name, "args": {"input": "SIBLING_ARGUMENT"}, "id": "reused-id"},
],
),
]
if result_state != "pending":
messages.append(ToolMessage(content="SIBLING_RESULT", tool_call_id="reused-id", status="error" if result_state == "error" else "success", additional_kwargs={"hide_from_ui": result_state == "hidden"}))
snapshot = ParentContextSnapshot.from_state({"messages": messages})
text = snapshot.content_json
assert "EARLIER_ARGUMENT" in text and "EARLIER_RESULT" in text
assert "Current assistant explanation" in text
assert "CURRENT_DELEGATION" not in text and "dispatch-id" not in text
assert ("SIBLING_ARGUMENT" in text) is (result_state in {"success", "error"})
assert ("SIBLING_RESULT" in text) is (result_state in {"success", "error"})
@pytest.mark.parametrize("state", [{}, {"messages": [], "summary_text": ""}, {"messages": [SystemMessage(content="system only")]}])
def test_empty_context_has_no_snapshot(state):
assert ParentContextSnapshot.from_state(state) is None