Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/foundation/live_turn.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,19 @@ def render_detail_panel(state: TurnLiveState, *, elapsed_seconds: float) -> Rend
return Panel(table, border_style="cyan", title="foundation · live turn", title_align="left")


def render_collapsed(state: TurnLiveState, *, elapsed_seconds: float) -> RenderableType:
def render_collapsed(
state: TurnLiveState,
*,
elapsed_seconds: float,
spinner: Spinner | None = None,
) -> RenderableType:
status = render_status_line(state, elapsed_seconds=elapsed_seconds)
if state.finished:
return status
spinner = Spinner("dots", text=status, style="cyan")
if spinner is None:
spinner = Spinner("dots", text=status, style="cyan")
else:
spinner.update(text=status, style="cyan")
return Group(
spinner,
Text("press ? for detail · Ctrl-C to cancel", style="dim"),
Expand Down Expand Up @@ -410,6 +418,7 @@ def __init__(
self._expanded = False
self._started_at = 0.0
self._live: Live | None = None
self._spinner = Spinner("dots", style="cyan")
self._keypress_thread: threading.Thread | None = None
self._keypress_stop = threading.Event()
self._old_termios: Any = None
Expand Down Expand Up @@ -528,7 +537,7 @@ def _render(self) -> RenderableType:
state_copy = self.state
if self._expanded:
return render_detail_panel(state_copy, elapsed_seconds=elapsed)
return render_collapsed(state_copy, elapsed_seconds=elapsed)
return render_collapsed(state_copy, elapsed_seconds=elapsed, spinner=self._spinner)

# --- keypress handling ------------------------------------------------

Expand Down
25 changes: 25 additions & 0 deletions tests/test_live_turn.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,18 @@ def _render_to_text(renderable) -> str:
return console.export_text()


def _render_to_text_at(renderable, now: float) -> str:
console = Console(
file=io.StringIO(),
force_terminal=False,
width=80,
record=True,
get_time=lambda: now,
)
console.print(renderable)
return console.export_text()


def test_render_status_line_shows_running_action():
state = TurnLiveState(
iteration=2,
Expand Down Expand Up @@ -258,6 +270,19 @@ def test_render_collapsed_includes_help_hint():
assert "?" in text


def test_renderer_reuses_spinner_across_collapsed_refreshes():
renderer = LiveTurnRenderer(
console=Console(file=io.StringIO(), force_terminal=False, width=80),
enable_keypress=False,
)
renderer.on_event(EVENT_SESSION_START, {"request_id": "r"})

first = _render_to_text_at(renderer._render(), now=0.0)
second = _render_to_text_at(renderer._render(), now=0.5)

assert first[0] != second[0]


def test_render_detail_panel_lists_completed_steps():
state = TurnLiveState(
iteration=1,
Expand Down
Loading