feat(cli): display model reasoning content during streaming
Add show_reasoning config (default: False) to display model thinking/reasoning content in the TUI during streaming. Reasoning is emitted via a new emit_reasoning hook on AgentHook, gated by the channels config. Display uses ✻ prefix with dim italic styling. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
d630ac90d1
commit
3a27af0018
@@ -156,17 +156,65 @@ def test_stream_renderer_stop_for_input_stops_spinner():
|
||||
# Create renderer with mocked console
|
||||
with patch.object(stream_mod, "_make_console", return_value=mock_console):
|
||||
renderer = stream_mod.StreamRenderer(show_spinner=True)
|
||||
|
||||
|
||||
# Verify spinner started
|
||||
spinner.start.assert_called_once()
|
||||
|
||||
|
||||
# Stop for input
|
||||
renderer.stop_for_input()
|
||||
|
||||
|
||||
# Verify spinner stopped
|
||||
spinner.stop.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_on_end_writes_final_content_to_stdout_after_stopping_live():
|
||||
"""on_end should stop Live (transient erases it) then print final content to stdout."""
|
||||
mock_live = MagicMock()
|
||||
mock_console = MagicMock()
|
||||
mock_console.capture.return_value.__enter__ = MagicMock(
|
||||
return_value=MagicMock(get=lambda: "final output\n")
|
||||
)
|
||||
mock_console.capture.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
with patch.object(stream_mod, "_make_console", return_value=mock_console):
|
||||
renderer = stream_mod.StreamRenderer(show_spinner=False)
|
||||
renderer._live = mock_live
|
||||
renderer._buf = "final output"
|
||||
|
||||
written: list[str] = []
|
||||
with patch("sys.stdout") as mock_stdout:
|
||||
mock_stdout.write = lambda s: written.append(s)
|
||||
mock_stdout.flush = MagicMock()
|
||||
await renderer.on_end()
|
||||
|
||||
mock_live.stop.assert_called_once()
|
||||
assert renderer._live is None
|
||||
assert written == ["final output\n"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_on_end_resuming_clears_buffer_and_restarts_spinner():
|
||||
"""on_end(resuming=True) should reset state for the next iteration."""
|
||||
spinner = MagicMock()
|
||||
mock_console = MagicMock()
|
||||
mock_console.status.return_value = spinner
|
||||
mock_console.capture.return_value.__enter__ = MagicMock(
|
||||
return_value=MagicMock(get=lambda: "")
|
||||
)
|
||||
mock_console.capture.return_value.__exit__ = MagicMock(return_value=False)
|
||||
|
||||
with patch.object(stream_mod, "_make_console", return_value=mock_console):
|
||||
renderer = stream_mod.StreamRenderer(show_spinner=True)
|
||||
renderer._buf = "some content"
|
||||
|
||||
await renderer.on_end(resuming=True)
|
||||
|
||||
assert renderer._buf == ""
|
||||
# Spinner should have been restarted (start called twice: __init__ + resuming)
|
||||
assert spinner.start.call_count == 2
|
||||
|
||||
|
||||
def test_make_console_force_terminal_when_stdout_is_tty():
|
||||
"""Console should set force_terminal=True when stdout is a TTY (rich output)."""
|
||||
import sys
|
||||
|
||||
Reference in New Issue
Block a user