`MockLlmClient`: turn-factory closures for live request-shape assertions
#2,074 opened on 2026年5月25日
説明
Problem. crates/tui/src/llm_client/mock.rs:75 is queue-driven: tests push canned MessageRequest shapes and the mock dequeues. There is no way to assert on what the engine actually sent on each turn — specifically, whether reasoning_content was replayed on the assistant turn that produced the previous tool call. The v0.4.9–v0.5.1 regression that broke every DeepSeek V4 user (HTTP 400 on follow-up turns when thinking tokens were dropped) would not be caught by today's tests. The comment at mock.rs:6-8 already acknowledges the gap.
Shape.
pub enum FauxStep {
Canned(CannedTurn),
Factory(Box<dyn Fn(&MessageRequest) -> CannedTurn + Send + Sync>),
}
When a Factory step is dequeued, its closure runs against the real outgoing MessageRequest, may assert! inline, then returns the response. No change to existing canned-turn callers.
Acceptance.
FauxStep::Factoryvariant added.- One regression test at
crates/tui/tests/reasoning_content_replayed_after_tool_call.rswhose factory assertsrequest.messages.last().reasoning_content.is_some()after a thinking + tool-call round. - Doc comment on the factory variant explains the V4
reasoning_contentinvariant and links to the original regression range. - No behavior change for existing tests.
Whale notes. Lowest-effort, highest-leverage change in this slate. Pays for itself the first time it catches a thinking-replay regression, and is the bridge we need before any integration test can exercise the real SSE stream (serve --http).
Slate item 1/18. Tracking doc: .private/issue-slate.md (maintainer-only).