mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-04 10:11:46 +03:00
feat(tui): add agent interaction workflows
This commit is contained in:
@@ -1819,6 +1819,33 @@ async def test_system_subagent_followup_is_persisted_before_prompt_assembly(tmp_
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_turn_usage_is_persisted_with_the_saved_session(tmp_path: Path) -> None:
|
||||
loop = _make_full_loop(tmp_path)
|
||||
loop.consolidator.maybe_consolidate_by_tokens = AsyncMock(return_value=False) # type: ignore[method-assign]
|
||||
|
||||
async def fake_run_agent_loop(initial_messages, **_kwargs):
|
||||
loop._last_usage = {"prompt_tokens": 64, "completion_tokens": 9}
|
||||
return (
|
||||
"done",
|
||||
[],
|
||||
[*initial_messages, {"role": "assistant", "content": "done"}],
|
||||
"stop",
|
||||
False,
|
||||
)
|
||||
|
||||
loop._run_agent_loop = fake_run_agent_loop # type: ignore[method-assign]
|
||||
await loop._process_message(
|
||||
InboundMessage(channel="cli", sender_id="user", chat_id="usage", content="hello")
|
||||
)
|
||||
|
||||
loop.sessions.invalidate("cli:usage")
|
||||
assert loop.sessions.get_or_create("cli:usage").metadata["_last_usage"] == {
|
||||
"prompt_tokens": 64,
|
||||
"completion_tokens": 9,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_system_subagent_followup_does_not_log_content(tmp_path: Path) -> None:
|
||||
loop = _make_full_loop(tmp_path)
|
||||
|
||||
@@ -99,6 +99,7 @@ async def test_runtime_event_publisher_consumes_turn_metadata_on_complete() -> N
|
||||
bus.subscribe(seen.append)
|
||||
publisher.record_turn_runtime("cli:direct", "runtime")
|
||||
publisher.record_turn_latency("cli:direct", 123)
|
||||
publisher.record_turn_usage("cli:direct", {"prompt_tokens": 40, "completion_tokens": 2})
|
||||
|
||||
await publisher.turn_completed(
|
||||
channel="cli",
|
||||
@@ -119,9 +120,11 @@ async def test_runtime_event_publisher_consumes_turn_metadata_on_complete() -> N
|
||||
assert first.context.metadata == {"source": "test"}
|
||||
assert first.latency_ms == 123
|
||||
assert first.runtime == "runtime"
|
||||
assert first.usage == {"prompt_tokens": 40, "completion_tokens": 2}
|
||||
assert isinstance(second, TurnCompleted)
|
||||
assert second.latency_ms is None
|
||||
assert second.runtime is None
|
||||
assert second.usage == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -40,6 +40,7 @@ def test_session_context_separates_archive_progress_from_replay() -> None:
|
||||
"estimated_session_tokens": replay_tokens + summary_tokens,
|
||||
"archived_summary": "The archived conversation settled the old question.",
|
||||
"archived_summary_at": "2026-08-13T10:00:00Z",
|
||||
"last_usage": None,
|
||||
}
|
||||
|
||||
|
||||
@@ -54,3 +55,22 @@ def test_session_context_tolerates_untrusted_summary_metadata() -> None:
|
||||
|
||||
assert payload["archived_summary"] is None
|
||||
assert payload["archived_summary_at"] is None
|
||||
|
||||
|
||||
def test_session_context_sanitizes_usage_metadata() -> None:
|
||||
session = Session(
|
||||
key="websocket:context",
|
||||
metadata={
|
||||
"_last_usage": {
|
||||
"prompt_tokens": 120,
|
||||
"completion_tokens": 8,
|
||||
"negative": -1,
|
||||
"boolean": True,
|
||||
"text": "invalid",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
payload = session_context_payload(session)
|
||||
|
||||
assert payload["last_usage"] == {"prompt_tokens": 120, "completion_tokens": 8}
|
||||
|
||||
Reference in New Issue
Block a user