Python · 1898 bytes Raw Blame History
1 """Runtime coverage for Sprint 04 workflow tools."""
2
3 from __future__ import annotations
4
5 import pytest
6
7 from loader.agent.loop import AgentConfig
8 from loader.llm.base import CompletionResponse, ToolCall
9 from tests.helpers.runtime_harness import ScriptedBackend, run_scenario
10
11
12 def non_streaming_config() -> AgentConfig:
13 """Shared deterministic config for runtime tool tests."""
14
15 return AgentConfig(auto_context=False, stream=False, max_iterations=4)
16
17
18 async def _answer(question: str, options: list[str] | None) -> str:
19 assert "Which path" in question
20 assert options == ["Plan first", "Execute now"]
21 return "1"
22
23
24 @pytest.mark.asyncio
25 async def test_ask_user_question_round_trips_through_runtime() -> None:
26 backend = ScriptedBackend(
27 completions=[
28 CompletionResponse(
29 content="I need one clarification.",
30 tool_calls=[
31 ToolCall(
32 id="ask-1",
33 name="AskUserQuestion",
34 arguments={
35 "question": "Which path should we take?",
36 "options": ["Plan first", "Execute now"],
37 },
38 )
39 ],
40 ),
41 CompletionResponse(content="We'll plan first."),
42 ]
43 )
44
45 run = await run_scenario(
46 "Implement the task, but ask me which path to take first.",
47 backend,
48 config=non_streaming_config(),
49 on_user_question=_answer,
50 )
51
52 tool_events = [event for event in run.events if event.type == "tool_call"]
53 tool_results = [event for event in run.events if event.type == "tool_result"]
54
55 assert "We'll plan first." in run.response
56 assert [event.tool_name for event in tool_events] == ["AskUserQuestion"]
57 assert any("Plan first" in event.content for event in tool_results)