119 lines
3.7 KiB
Python
119 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from nanobot.agent.tools.context import RequestContext
|
|
from nanobot.runtime_context import (
|
|
RUNTIME_CONTEXT_HISTORY_META,
|
|
RuntimeContextBlock,
|
|
append_runtime_context,
|
|
public_history_message,
|
|
resolve_runtime_context,
|
|
)
|
|
from nanobot.sdk.types import snapshot_from_session
|
|
from nanobot.session.manager import Session, _message_preview_text
|
|
from nanobot.session.webui_turns import _title_inputs
|
|
from nanobot.webui.transcript import _session_user_event
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_resolve_runtime_context_preserves_provider_order() -> None:
|
|
calls: list[str] = []
|
|
|
|
async def first(_request: RequestContext):
|
|
calls.append("first")
|
|
return RuntimeContextBlock(source="first", content="one")
|
|
|
|
async def second(_request: RequestContext):
|
|
calls.append("second")
|
|
return [RuntimeContextBlock(source="second", content="two")]
|
|
|
|
blocks = await resolve_runtime_context(
|
|
[first, second],
|
|
RequestContext(channel="cli", chat_id="direct"),
|
|
)
|
|
|
|
assert calls == ["first", "second"]
|
|
assert [(block.source, block.content) for block in blocks] == [
|
|
("first", "one"),
|
|
("second", "two"),
|
|
]
|
|
|
|
|
|
def test_public_history_removes_only_trusted_exact_suffix() -> None:
|
|
block = RuntimeContextBlock(source="goal", content="private goal context")
|
|
content, marker = append_runtime_context("visible user text", [block])
|
|
assert marker is not None
|
|
persisted = {
|
|
"role": "user",
|
|
"content": content,
|
|
RUNTIME_CONTEXT_HISTORY_META: marker,
|
|
}
|
|
|
|
assert public_history_message(persisted) == {
|
|
"role": "user",
|
|
"content": "visible user text",
|
|
}
|
|
|
|
user_authored = {
|
|
"role": "user",
|
|
"content": "visible user text\n\nprivate goal context",
|
|
}
|
|
assert public_history_message(user_authored) == user_authored
|
|
|
|
|
|
def test_public_history_keeps_content_when_marker_does_not_match() -> None:
|
|
message = {
|
|
"role": "user",
|
|
"content": "user-edited content",
|
|
RUNTIME_CONTEXT_HISTORY_META: {
|
|
"version": 1,
|
|
"sources": ["goal"],
|
|
"suffix": "different suffix",
|
|
},
|
|
}
|
|
|
|
assert public_history_message(message) == {
|
|
"role": "user",
|
|
"content": "user-edited content",
|
|
}
|
|
|
|
|
|
def test_sdk_snapshot_hides_runtime_context() -> None:
|
|
block = RuntimeContextBlock(source="goal", content="private goal context")
|
|
content, marker = append_runtime_context("visible user text", [block])
|
|
session = SimpleNamespace(
|
|
key="cli:direct",
|
|
created_at=SimpleNamespace(isoformat=lambda: "created"),
|
|
updated_at=SimpleNamespace(isoformat=lambda: "updated"),
|
|
metadata={},
|
|
messages=[{
|
|
"role": "user",
|
|
"content": content,
|
|
RUNTIME_CONTEXT_HISTORY_META: marker,
|
|
}],
|
|
)
|
|
|
|
snapshot = snapshot_from_session(session)
|
|
|
|
assert snapshot.messages == [{"role": "user", "content": "visible user text"}]
|
|
|
|
|
|
def test_webui_preview_title_and_backfill_hide_runtime_context() -> None:
|
|
block = RuntimeContextBlock(source="goal", content="private goal context")
|
|
content, marker = append_runtime_context("visible user text", [block])
|
|
persisted = {
|
|
"role": "user",
|
|
"content": content,
|
|
RUNTIME_CONTEXT_HISTORY_META: marker,
|
|
}
|
|
session = Session(key="websocket:chat", messages=[persisted])
|
|
|
|
assert _message_preview_text(persisted) == "visible user text"
|
|
assert _title_inputs(session) == ("visible user text", "")
|
|
event = _session_user_event("websocket:chat", persisted)
|
|
assert event is not None
|
|
assert event["text"] == "visible user text"
|