113 lines
3.5 KiB
Python
113 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from opensquilla.engine.runtime import TurnRunner
|
|
from opensquilla.engine.types import ErrorEvent
|
|
|
|
|
|
class _RecordingSessionManager:
|
|
def __init__(self) -> None:
|
|
self.compact_calls: list[tuple[str, int]] = []
|
|
self.messages: list[tuple[str, str, str]] = []
|
|
|
|
async def compact(self, session_key: str, budget: int) -> str:
|
|
self.compact_calls.append((session_key, budget))
|
|
return "summary"
|
|
|
|
async def append_message(self, session_key: str, *, role: str, content: str) -> None:
|
|
self.messages.append((session_key, role, content))
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_provider_request_too_large_error_persistence_does_not_compact_transcript() -> None:
|
|
manager = _RecordingSessionManager()
|
|
runner = TurnRunner(
|
|
provider_selector=None,
|
|
session_manager=manager,
|
|
config=SimpleNamespace(context_window_tokens=100_000),
|
|
)
|
|
|
|
await runner._persist_turn_error(
|
|
"agent:main:webchat:test",
|
|
ErrorEvent(
|
|
message=(
|
|
"The request is too large for the provider context window after "
|
|
"automatic context compaction and payload reduction."
|
|
),
|
|
code="provider_request_too_large",
|
|
),
|
|
)
|
|
|
|
assert manager.compact_calls == []
|
|
assert manager.messages == [
|
|
(
|
|
"agent:main:webchat:test",
|
|
"system",
|
|
"Error: The request is too large for the provider context window after "
|
|
"automatic context compaction and payload reduction. OpenSquilla "
|
|
"preserved the recoverable state; retry with a narrower request "
|
|
"or a larger-context model.",
|
|
)
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_provider_output_truncation_error_persistence_uses_terminal_reply() -> None:
|
|
manager = _RecordingSessionManager()
|
|
runner = TurnRunner(
|
|
provider_selector=None,
|
|
session_manager=manager,
|
|
config=SimpleNamespace(context_window_tokens=100_000),
|
|
)
|
|
|
|
await runner._persist_turn_error(
|
|
"agent:main:webchat:test",
|
|
ErrorEvent(
|
|
message="Provider output limit reached before completion",
|
|
code="provider_output_truncated",
|
|
),
|
|
)
|
|
|
|
assert manager.compact_calls == []
|
|
assert manager.messages == [
|
|
(
|
|
"agent:main:webchat:test",
|
|
"system",
|
|
"The provider stopped because the output limit was reached before the task finished.",
|
|
)
|
|
]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_provider_output_truncation_error_persistence_uses_message_fallback() -> None:
|
|
manager = _RecordingSessionManager()
|
|
runner = TurnRunner(
|
|
provider_selector=None,
|
|
session_manager=manager,
|
|
config=SimpleNamespace(context_window_tokens=100_000),
|
|
)
|
|
|
|
with patch("opensquilla.engine.runtime.log") as log:
|
|
await runner._persist_turn_error(
|
|
"agent:main:webchat:test",
|
|
ErrorEvent(
|
|
message="Provider output limit reached before completion",
|
|
code="agent_error",
|
|
),
|
|
)
|
|
|
|
assert manager.messages == [
|
|
(
|
|
"agent:main:webchat:test",
|
|
"system",
|
|
"The provider stopped because the output limit was reached before the task finished.",
|
|
)
|
|
]
|
|
log.info.assert_called_once()
|
|
assert log.info.call_args.kwargs["code"] == "provider_output_truncated"
|
|
assert log.info.call_args.kwargs["turn_outcome"]["kind"] == "partial"
|