Files
opensquilla--opensquilla/tests/test_core_lightweight_contracts.py
2026-07-13 13:12:33 +08:00

230 lines
7.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import json
from opensquilla.engine.session_sanitize import sanitize_session_messages
from opensquilla.engine.tool_text_compat import (
ProtocolTextLeakGuard,
strip_protocol_text_leak,
strip_synthetic_tool_call_suffix,
)
from opensquilla.provider.openai import _build_openai_messages, _usage_fields
from opensquilla.provider.openrouter_attribution import openrouter_app_headers
from opensquilla.provider.types import ContentBlockText, ContentBlockToolResult, Message
from opensquilla.session.keys import (
allows_private_memory_prompt_injection,
build_subagent_session_key,
build_webchat_key,
canonicalize_session_key,
is_subagent_key,
normalize_account_id,
normalize_agent_id,
)
def test_session_keys_keep_default_agent_canonical() -> None:
assert normalize_agent_id(None) == "main"
assert normalize_agent_id("default") == "main"
assert build_webchat_key("default") == "agent:main:webchat:default"
assert canonicalize_session_key("webchat:default") == "agent:main:webchat:default"
def test_session_keys_defend_account_id_segments() -> None:
assert normalize_account_id("__proto__") == "default"
assert normalize_account_id(" Team Alpha / Prod ") == "team-alpha---prod"
def test_subagent_keys_are_canonical_and_detected() -> None:
key = build_subagent_session_key("Ops Agent", "Run 123!!")
assert key == "agent:ops-agent:subagent:run-123"
assert is_subagent_key(key)
assert is_subagent_key("subagent:agent:main:webchat:default")
def test_private_memory_prompt_injection_is_denied_for_shared_or_runtime_keys() -> None:
assert allows_private_memory_prompt_injection("agent:main:webchat:default") is True
assert allows_private_memory_prompt_injection("agent:main:slack:group:g1") is False
assert allows_private_memory_prompt_injection("agent:main:subagent:run-1") is False
assert allows_private_memory_prompt_injection("cron:dream:run:1") is False
def test_text_encoded_tool_call_suffix_is_removed_without_losing_prose() -> None:
text = 'Here is the answer.\n\nweb_search{"query": "opensquilla"}'
assert strip_synthetic_tool_call_suffix(text, ["web_search"]) == "Here is the answer."
def test_minimax_tool_call_text_is_removed_as_machine_payload() -> None:
text = "<minimax:tool_call>{}</minimax:tool_call>"
assert strip_synthetic_tool_call_suffix(text, ["web_search"]) == ""
def test_malformed_text_tool_protocol_is_removed_before_user_display() -> None:
text = (
"Let me write the dashboard now.\n\n"
'<tvoe_calls><invoke name="write_file">'
'<parameter name="path">index.html</parameter>'
'<parameter name="content"><!DOCTYPE html><html><body>app</body></html>'
"</parameter></invoke></tvoe_calls>"
)
assert strip_protocol_text_leak(text) == "Let me write the dashboard now."
def test_dsml_text_tool_protocol_is_removed_before_user_display() -> None:
text = (
"Let me create the printable daily record sheet as well:\n\n"
'<DSMLtool_calls><DSMLinvoke name="create_xlsx">'
'<DSMLparameter name="name" string="true">'
"bean-sprout-daily-record-sheet.xlsx"
"</DSMLparameter>"
'<DSMLparameter name="sheets" string="false">'
'[{"name":"Record Sheet","rows":[["Day","Height"]]}]'
"</DSMLparameter></DSMLinvoke></DSMLtool_calls>"
)
assert strip_protocol_text_leak(text) == (
"Let me create the printable daily record sheet as well:"
)
def test_tool_scaffold_details_summary_is_removed_before_user_display() -> None:
text = (
"Let me read the specific problematic areas to fix them.\n\n"
"<details>"
"<summary>View areas around line 10393, 14751, and nearby</summary>\n\n"
"<parameter>\n\n"
"I see two real HTML issues."
)
assert strip_protocol_text_leak(text) == (
"Let me read the specific problematic areas to fix them."
)
def test_streaming_protocol_guard_holds_split_tool_protocol() -> None:
guard = ProtocolTextLeakGuard()
assert guard.push("Let me write the dashboard now.\n\n<tvoe") == (
"Let me write the dashboard now."
)
assert (
guard.push(
'_calls><invoke name="write_file">'
'<parameter name="content"><!DOCTYPE html><html></html>'
)
== ""
)
assert guard.flush() == ""
def test_streaming_protocol_guard_holds_split_dsml_tool_protocol() -> None:
guard = ProtocolTextLeakGuard()
assert guard.push("Let me make the sheet.\n\n<DS") == "Let me make the sheet."
assert (
guard.push(
'MLtool_calls><DSMLinvoke name="create_xlsx">'
'<DSMLparameter name="sheets">[]</DSMLparameter>'
)
== ""
)
assert guard.flush() == ""
def test_streaming_protocol_guard_releases_unconfirmed_literal_marker() -> None:
guard = ProtocolTextLeakGuard()
assert guard.push("Explain literal <invoke") == "Explain literal"
assert guard.flush() == " <invoke"
def test_streaming_protocol_guard_drops_tool_scaffold_before_tool_use() -> None:
guard = ProtocolTextLeakGuard()
assert guard.push("Let me read the specific problematic areas.\n\n<details>") == (
"Let me read the specific problematic areas."
)
assert (
guard.push(
"<summary>View areas around line 10393, 14751, and nearby</summary>"
)
== ""
)
assert guard.flush_before_tool_use() == ""
assert guard.push("Fixed the issues.") == "Fixed the issues."
def test_streaming_protocol_guard_releases_regular_details_without_tool_use() -> None:
guard = ProtocolTextLeakGuard()
assert guard.push("Here is a collapsible note.\n\n<details>") == (
"Here is a collapsible note."
)
assert guard.push("<summary>More</summary>Visible note.</details>") == ""
assert guard.flush() == "\n\n<details><summary>More</summary>Visible note.</details>"
def test_session_sanitize_removes_block_metadata_without_mutating_original_content() -> None:
message = Message.model_construct(
role="assistant",
content=[
{
"type": "text",
"text": "visible answer",
"debug": {"provider": "test"},
}
],
reasoning_content=None,
)
sanitized, result = sanitize_session_messages([message])
assert result.metadata_keys_removed == 1
assert isinstance(sanitized[0].content[0], ContentBlockText)
assert sanitized[0].content[0].text == "visible answer"
assert "debug" in message.content[0]
def test_openai_payload_splits_tool_results_into_provider_tool_messages() -> None:
message = Message(
role="user",
content=[
ContentBlockToolResult(
tool_use_id="call_1",
content=json.dumps({"ok": True}),
is_error=False,
)
],
)
assert _build_openai_messages(message) == [
{
"role": "tool",
"tool_call_id": "call_1",
"content": '{"ok": true}',
}
]
def test_usage_fields_treat_explicit_canonical_zero_as_real_value() -> None:
usage = {
"prompt_tokens": 10,
"completion_tokens": 2,
"cache_creation_input_tokens": 0,
"prompt_cache_miss_tokens": 999,
}
*_, cache_write_tokens, _ = _usage_fields(usage)
assert cache_write_tokens == 0
def test_openrouter_attribution_headers_are_scoped_to_openrouter_hosts() -> None:
assert openrouter_app_headers("https://api.openrouter.ai/v1")[
"X-Title"
] == "OpenSquilla"
assert openrouter_app_headers("https://api.openai.com/v1") == {}