feat(agent): add persistent runtime context providers
This commit is contained in:
@@ -9,6 +9,7 @@ from importlib.resources import files as pkg_files
|
||||
from pathlib import Path
|
||||
|
||||
from nanobot.agent.context import ContextBuilder
|
||||
from nanobot.runtime_context import RuntimeContextBlock
|
||||
|
||||
|
||||
class _FakeDatetime(real_datetime):
|
||||
@@ -61,8 +62,7 @@ def test_system_prompt_reflects_current_dream_memory_contract(tmp_path) -> None:
|
||||
assert "write important facts here" not in prompt
|
||||
|
||||
|
||||
def test_runtime_context_is_separate_untrusted_user_message(tmp_path) -> None:
|
||||
"""Runtime metadata should be merged with the user message."""
|
||||
def test_default_user_message_has_no_runtime_context(tmp_path) -> None:
|
||||
workspace = _make_workspace(tmp_path)
|
||||
builder = ContextBuilder(workspace)
|
||||
|
||||
@@ -76,19 +76,13 @@ def test_runtime_context_is_separate_untrusted_user_message(tmp_path) -> None:
|
||||
assert messages[0]["role"] == "system"
|
||||
assert "## Current Session" not in messages[0]["content"]
|
||||
|
||||
# Runtime context is now merged with user message into a single message
|
||||
assert messages[-1]["role"] == "user"
|
||||
user_content = messages[-1]["content"]
|
||||
assert isinstance(user_content, str)
|
||||
assert ContextBuilder._RUNTIME_CONTEXT_TAG in user_content
|
||||
assert "Current Time:" in user_content
|
||||
assert "Channel: cli" in user_content
|
||||
assert "Chat ID: direct" in user_content
|
||||
assert "Return exactly: OK" in user_content
|
||||
assert user_content == "Return exactly: OK"
|
||||
assert "_meta" not in messages[-1]
|
||||
|
||||
|
||||
def test_runtime_context_appended_after_user_content(tmp_path) -> None:
|
||||
"""User content must precede runtime context for prompt-cache prefix stability."""
|
||||
def test_provider_context_appended_after_user_content(tmp_path) -> None:
|
||||
workspace = _make_workspace(tmp_path)
|
||||
builder = ContextBuilder(workspace)
|
||||
|
||||
@@ -97,16 +91,18 @@ def test_runtime_context_appended_after_user_content(tmp_path) -> None:
|
||||
current_message="hello world",
|
||||
channel="cli",
|
||||
chat_id="direct",
|
||||
runtime_context_blocks=[
|
||||
RuntimeContextBlock(source="test", content="provider context"),
|
||||
],
|
||||
)
|
||||
|
||||
content = messages[-1]["content"]
|
||||
user_pos = content.find("hello world")
|
||||
tag_pos = content.find(ContextBuilder._RUNTIME_CONTEXT_TAG)
|
||||
assert user_pos < tag_pos, "user content must precede runtime context for prefix stability"
|
||||
context_pos = content.find("provider context")
|
||||
assert user_pos < context_pos, "user content must precede provider context"
|
||||
|
||||
|
||||
def test_runtime_context_includes_sender_id_when_provided(tmp_path) -> None:
|
||||
"""Sender ID should be included in runtime context when provided."""
|
||||
def test_sender_id_is_not_injected_without_provider(tmp_path) -> None:
|
||||
workspace = _make_workspace(tmp_path)
|
||||
builder = ContextBuilder(workspace)
|
||||
|
||||
@@ -120,7 +116,8 @@ def test_runtime_context_includes_sender_id_when_provided(tmp_path) -> None:
|
||||
|
||||
user_content = messages[-1]["content"]
|
||||
assert isinstance(user_content, str)
|
||||
assert "Sender ID: user-12345" in user_content
|
||||
assert user_content == "Return exactly: OK"
|
||||
assert "Sender ID:" not in user_content
|
||||
|
||||
|
||||
def test_runtime_context_excludes_sender_id_when_not_provided(tmp_path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user