feat: enhance spinner output handling in display module
- Added a new function `_raw_write` to write directly to stdout, bypassing prompt_toolkit's interference with ANSI escapes and carriage returns. - Updated the `KawaiiSpinner` class to utilize `_raw_write` for rendering spinner animations and final messages, ensuring proper display in terminal environments. - Improved the clarity of output handling during spinner operations, enhancing user experience during tool execution.
This commit is contained in:
parent
e049441d93
commit
d64f62c2ef
1 changed files with 23 additions and 4 deletions
|
|
@ -7,6 +7,7 @@ Used by AIAgent._execute_tool_calls for CLI feedback.
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
@ -15,6 +16,22 @@ _RED = "\033[31m"
|
||||||
_RESET = "\033[0m"
|
_RESET = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
def _raw_write(text: str):
|
||||||
|
"""Write directly to the real stdout, bypassing prompt_toolkit's patch_stdout proxy.
|
||||||
|
|
||||||
|
prompt_toolkit's StdoutProxy intercepts sys.stdout and can swallow or
|
||||||
|
mishandle \\r carriage returns and inline ANSI escapes that the spinner
|
||||||
|
relies on. sys.__stdout__ is the original file object before any monkey
|
||||||
|
patching, so writes go straight to the terminal.
|
||||||
|
"""
|
||||||
|
out = sys.__stdout__
|
||||||
|
try:
|
||||||
|
out.write(text)
|
||||||
|
out.flush()
|
||||||
|
except (ValueError, OSError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# Tool preview (one-line summary of a tool call's primary argument)
|
# Tool preview (one-line summary of a tool call's primary argument)
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
|
@ -169,8 +186,10 @@ class KawaiiSpinner:
|
||||||
frame = self.spinner_frames[self.frame_idx % len(self.spinner_frames)]
|
frame = self.spinner_frames[self.frame_idx % len(self.spinner_frames)]
|
||||||
elapsed = time.time() - self.start_time
|
elapsed = time.time() - self.start_time
|
||||||
line = f" {frame} {self.message} ({elapsed:.1f}s)"
|
line = f" {frame} {self.message} ({elapsed:.1f}s)"
|
||||||
clear = '\r' + ' ' * self.last_line_len + '\r'
|
# \033[2K erases the entire current line, \r moves cursor to col 0.
|
||||||
print(clear + line, end='', flush=True)
|
# Using _raw_write bypasses patch_stdout so the animation renders
|
||||||
|
# even when prompt_toolkit owns the terminal.
|
||||||
|
_raw_write(f"\033[2K\r{line}")
|
||||||
self.last_line_len = len(line)
|
self.last_line_len = len(line)
|
||||||
self.frame_idx += 1
|
self.frame_idx += 1
|
||||||
time.sleep(0.12)
|
time.sleep(0.12)
|
||||||
|
|
@ -190,9 +209,9 @@ class KawaiiSpinner:
|
||||||
self.running = False
|
self.running = False
|
||||||
if self.thread:
|
if self.thread:
|
||||||
self.thread.join(timeout=0.5)
|
self.thread.join(timeout=0.5)
|
||||||
print('\r' + ' ' * (self.last_line_len + 5) + '\r', end='', flush=True)
|
_raw_write(f"\033[2K\r")
|
||||||
if final_message:
|
if final_message:
|
||||||
print(f" {final_message}", flush=True)
|
_raw_write(f" {final_message}\n")
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.start()
|
self.start()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue