Skip to content

Commit 95244a6

Browse files
author
Build Tools
committed
Compact tool output with spinner in display_progress
Replace per-tool-invocation lines with a single updating spinner line showing aggregated tool counts. Prints a one-line tool summary at session end.
1 parent a5ea82d commit 95244a6

File tree

1 file changed

+54
-32
lines changed

1 file changed

+54
-32
lines changed

bin/ci_tool/display_progress.py

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,30 @@ def format_elapsed(start_time):
7070
return f"{seconds}s"
7171

7272

73+
def format_tool_status(tool_counts, start_time):
74+
"""Format spinner status text showing tool activity summary."""
75+
if not tool_counts:
76+
return "[cyan]Working...[/cyan]"
77+
parts = []
78+
for name, count in tool_counts.items():
79+
if count > 1:
80+
parts.append(f"{name} x{count}")
81+
else:
82+
parts.append(name)
83+
return f"[cyan]{', '.join(parts)}[/cyan] [dim][{format_elapsed(start_time)}][/dim]"
84+
85+
86+
def format_tool_summary(tool_counts):
87+
"""Format a final one-line summary of all tools used."""
88+
parts = []
89+
for name, count in tool_counts.items():
90+
if count > 1:
91+
parts.append(f"{name} x{count}")
92+
else:
93+
parts.append(name)
94+
return ", ".join(parts)
95+
96+
7397
def flush_text_buffer(text_buffer):
7498
"""Render accumulated text as rich markdown and clear the buffer."""
7599
if not text_buffer:
@@ -80,7 +104,7 @@ def flush_text_buffer(text_buffer):
80104
console.print(Markdown(combined))
81105

82106

83-
def handle_assistant_event(message, start_time, text_buffer):
107+
def handle_assistant_event(message, start_time, text_buffer, tool_counts, status):
84108
"""Display content blocks from an assistant message event."""
85109
for block in message.get("content", []):
86110
block_type = block.get("type", "")
@@ -93,33 +117,31 @@ def handle_assistant_event(message, start_time, text_buffer):
93117
elif block_type == "tool_use":
94118
flush_text_buffer(text_buffer)
95119
tool_name = block.get("name", "unknown")
96-
console.print(
97-
f"\n [dim]tool:[/dim] [bold]{tool_name}[/bold] "
98-
f"[dim][{format_elapsed(start_time)}][/dim]"
99-
)
120+
tool_counts[tool_name] = tool_counts.get(tool_name, 0) + 1
121+
status.update(format_tool_status(tool_counts, start_time))
100122

101123

102-
def handle_event(event, start_time, text_buffer):
124+
def handle_event(event, start_time, text_buffer, tool_counts, status):
103125
"""Handle a single stream-json event. Returns session_id if found, else None."""
104126
session_id = event.get("session_id") or None
105127
event_type = event.get("type", "")
106128

107129
if event_type == "assistant":
108130
message = event.get("message", {})
109-
handle_assistant_event(message, start_time, text_buffer)
131+
handle_assistant_event(message, start_time, text_buffer, tool_counts, status)
110132

111133
elif event_type == "tool_result":
112134
flush_text_buffer(text_buffer)
113-
console.print(
114-
f" [dim]done[/dim] [{format_elapsed(start_time)}]"
115-
)
135+
status.update(format_tool_status(tool_counts, start_time))
116136

117137
return session_id
118138

119139

120-
def print_session_summary(session_id, start_time):
140+
def print_session_summary(session_id, start_time, tool_counts):
121141
"""Print the final session summary after stream ends."""
122142
elapsed = format_elapsed(start_time)
143+
if tool_counts:
144+
console.print(f" [dim]Tools: {format_tool_summary(tool_counts)}[/dim]")
123145
if session_id:
124146
console.print(
125147
f"\n[green]Session saved ({session_id}). "
@@ -145,28 +167,28 @@ def main():
145167
phase = "fixing"
146168
start_time = time.time()
147169
text_buffer = []
170+
tool_counts = {}
148171

149172
try:
150-
console.print("[cyan] Working...[/cyan]")
151-
152-
with open(EVENT_DEBUG_LOG, "w", encoding="utf-8") as debug_log:
153-
for line in sys.stdin:
154-
line = line.strip()
155-
if not line:
156-
continue
157-
158-
debug_log.write(line + "\n")
159-
debug_log.flush()
160-
161-
try:
162-
event = json.loads(line)
163-
except json.JSONDecodeError:
164-
sys.stderr.write(f" {line}\n")
165-
continue
166-
167-
event_session_id = handle_event(event, start_time, text_buffer)
168-
if event_session_id:
169-
session_id = event_session_id
173+
with console.status("[cyan]Working...[/cyan]", spinner="dots") as status:
174+
with open(EVENT_DEBUG_LOG, "w", encoding="utf-8") as debug_log:
175+
for line in sys.stdin:
176+
line = line.strip()
177+
if not line:
178+
continue
179+
180+
debug_log.write(line + "\n")
181+
debug_log.flush()
182+
183+
try:
184+
event = json.loads(line)
185+
except json.JSONDecodeError:
186+
sys.stderr.write(f" {line}\n")
187+
continue
188+
189+
event_session_id = handle_event(event, start_time, text_buffer, tool_counts, status)
190+
if event_session_id:
191+
session_id = event_session_id
170192

171193
flush_text_buffer(text_buffer)
172194
phase = "completed"
@@ -180,7 +202,7 @@ def main():
180202
phase = "stuck"
181203

182204
write_state(session_id, phase, attempt_count)
183-
print_session_summary(session_id, start_time)
205+
print_session_summary(session_id, start_time, tool_counts)
184206

185207

186208
if __name__ == "__main__":

0 commit comments

Comments
 (0)