From d759b90aa124372d4b86c64aa28ee1f0dead6595 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 26 Apr 2026 21:40:29 -0400 Subject: [PATCH] fix: plumb narrate_skip timeout_s through to client.generate (T76) --- chat/services/skip_narration.py | 1 + tests/test_skip_narration.py | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/chat/services/skip_narration.py b/chat/services/skip_narration.py index 4590a7b..9fd191e 100644 --- a/chat/services/skip_narration.py +++ b/chat/services/skip_narration.py @@ -96,6 +96,7 @@ async def narrate_skip( model=narrative_model, max_tokens=200, temperature=0.7, + timeout_s=timeout_s, ) text = (result or "").strip() if not text: diff --git a/tests/test_skip_narration.py b/tests/test_skip_narration.py index 577ddee..aa69fc6 100644 --- a/tests/test_skip_narration.py +++ b/tests/test_skip_narration.py @@ -98,6 +98,49 @@ class _RaisingMock: yield # pragma: no cover - make this a generator +class _RecordingMock: + """Mock LLMClient that records the kwargs passed to ``generate``. + + Used to assert that callers plumb through optional parameters like + ``timeout_s`` instead of swallowing them. Returns a fixed string so + the surrounding fallback path is not exercised. + """ + + def __init__(self) -> None: + self.captured_kwargs: dict | None = None + + async def generate( + self, messages: Sequence[Message], *, model: str, **params + ) -> str: + self.captured_kwargs = dict(params) + return "ok" + + async def stream( + self, messages: Sequence[Message], *, model: str, **params + ) -> AsyncIterator[str]: + raise RuntimeError("not used") + yield # pragma: no cover - make this a generator + + +@pytest.mark.asyncio +async def test_narrate_skip_passes_timeout_through(): + mock = _RecordingMock() + await narrate_skip( + mock, + narrative_model="x", + skip_kind="jump", + speaker_bot=_SPEAKER, + you_name="Me", + current_time="late evening", + new_time="next morning", + current_activity="winding down for the night", + landing_state_hint="having coffee in the kitchen", + timeout_s=12.5, + ) + assert mock.captured_kwargs is not None + assert mock.captured_kwargs.get("timeout_s") == 12.5 + + @pytest.mark.asyncio async def test_narrate_falls_back_on_generation_failure(): new_time = "next morning"