Skip to content

Commit 0f50da9

Browse files
committed
Fix: Revert REPL to v0.2.7 stable version
1 parent a2508e8 commit 0f50da9

1 file changed

Lines changed: 60 additions & 98 deletions

File tree

supercoder/repl.py

Lines changed: 60 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -153,56 +153,21 @@ def run(self):
153153
self.console.print("[green]Goodbye![/]")
154154

155155
def _handle_chat(self, message):
156-
"""Handle chat interaction with clean, incremental output."""
156+
"""Handle chat interaction with clean output (no streaming)."""
157157
# User message is already displayed by the main loop with styling
158158

159-
# State tracking
160-
current_block_type = None # 'reasoning', 'response', or None
161-
current_buffer = ""
162-
163-
# Accumulators for logging/final processing, NOT for display (display is immediate)
164-
full_response_text = ""
165-
full_reasoning_text = "" # Just for internal consistency if needed
166-
# We still collect tool calls/results for logging logic if needed, but display them immediately
167-
159+
# Collect full response first, then display
160+
response_text = ""
161+
tool_calls = []
162+
tool_results = []
168163
errors = []
169164
was_aborted = False
170165
rollback_info = None
171166

172167
# Track active files (files touched by tools)
173168
touched_files = set()
174169

175-
# Helper to flush current text buffer to display
176-
def flush_buffer():
177-
nonlocal current_block_type, current_buffer
178-
if not current_buffer or not current_buffer.strip():
179-
return
180-
181-
content_to_print = current_buffer.strip()
182-
183-
if current_block_type == 'reasoning':
184-
self.console.print(Panel(
185-
Markdown(content_to_print),
186-
title="[bold magenta]💭 Reasoning[/]",
187-
border_style="magenta",
188-
box=self._get_box_style(),
189-
padding=(0, 1)
190-
))
191-
elif current_block_type == 'response':
192-
clean_text = self._filter_special_tokens(content_to_print)
193-
if clean_text:
194-
self.console.print(Panel(
195-
Markdown(clean_text),
196-
title="[bold blue]SuperCoder[/]",
197-
border_style="blue",
198-
box=self._get_box_style(),
199-
padding=(0, 1)
200-
))
201-
202-
# Reset buffer
203-
current_buffer = ""
204-
current_block_type = None
205-
170+
# Show spinner while processing
206171
# Show spinner while processing
207172
with self.console.status("[bold blue]SuperCoder is thinking...[/]", spinner="dots") as status:
208173
# Start keyboard listener for abort
@@ -214,66 +179,27 @@ def flush_buffer():
214179
event_type = event.get("type")
215180
content = event.get("content")
216181

217-
# Handle state transitions
218-
if event_type == "reasoning":
219-
# If we were doing something else (e.g. response), flush it
220-
if current_block_type != 'reasoning':
221-
flush_buffer()
222-
current_block_type = 'reasoning'
223-
current_buffer += content
224-
full_reasoning_text += content
225-
226-
elif event_type == "token":
227-
# If we were doing reasoning, flush it
228-
if current_block_type != 'response':
229-
flush_buffer()
230-
current_block_type = 'response'
231-
current_buffer += content
232-
full_response_text += content
233-
182+
if event_type == "token":
183+
response_text += content
234184
elif event_type == "tool_call":
235-
# Tool call interrupts any text generation
236-
flush_buffer()
237-
238-
# Display tool call immediately
239-
# We might want to clear spinner, print, resume spinner -
240-
# but Rich handles prints during active spinner gracefully usually.
241-
status.stop()
242-
self._display_tool_call(content)
243-
status.start()
244-
245-
# Track files
185+
tool_calls.append(content)
186+
# Track files from tool args
246187
self._track_files(content, touched_files)
247-
248188
elif event_type == "tool_result":
249-
# Tool result interrupts
250-
flush_buffer()
251-
self._display_tool_result(content)
252-
189+
tool_results.append(content)
253190
elif event_type == "error":
254-
flush_buffer()
255191
errors.append(content)
256-
self.console.print(Panel(f"[red]{content}[/]", title="[bold red]Error[/]", border_style="red"))
257-
258192
elif event_type == "aborted":
259-
flush_buffer()
260193
was_aborted = True
261194
status.stop()
262-
263195
elif event_type == "rollback":
264196
rollback_info = content
265-
266197
elif event_type == "command_waiting":
267-
# Need user interaction
268-
flush_buffer()
269-
status.stop()
198+
# Process is waiting - need user interaction
199+
status.stop() # Stop spinner to allow interaction
270200
self._handle_command_waiting(event)
271-
# Process handled, maybe loops back
272-
201+
# Continue iteration - the process has been handled
273202
finally:
274-
# Ensure pending buffer is printed
275-
flush_buffer()
276-
277203
# Stop keyboard listener
278204
if hasattr(self, 'keyboard_listener'):
279205
self.keyboard_listener.stop()
@@ -298,7 +224,30 @@ def flush_buffer():
298224
border_style="cyan",
299225
box=self._get_box_style()
300226
))
301-
227+
228+
# 1. Display Tool Calls & Results first (Implementation Detail)
229+
if tool_calls:
230+
self.console.print() # Spacer
231+
for i, tc in enumerate(tool_calls):
232+
self._display_tool_call(tc)
233+
if i < len(tool_results):
234+
self._display_tool_result(tool_results[i])
235+
self.console.print() # Spacer
236+
237+
# 2. Display Errors
238+
for error in errors:
239+
self.console.print(Panel(f"[red]{error}[/]", title="[bold red]Error[/]", border_style="red"))
240+
241+
# 3. Display Assistant Response
242+
clean_text = self._filter_special_tokens(response_text)
243+
if clean_text:
244+
self.console.print(Panel(
245+
Markdown(clean_text),
246+
title="[bold blue]SuperCoder[/]",
247+
border_style="blue",
248+
box=self._get_box_style()
249+
))
250+
302251
# 4. Display Status Footer (Tokens & Files)
303252
self._display_status_footer(touched_files)
304253

@@ -348,6 +297,11 @@ def _display_status_footer(self, touched_files):
348297
files_str = ", ".join(sorted(touched_files))
349298
parts.append(f"[dim]Active Files: {files_str}[/]")
350299

300+
# Cost estimate (rough approximation)
301+
# Assuming generic pricing, just to show we can
302+
# cost = (stats.used_tokens / 1000) * 0.002 # Example
303+
# parts.append(f"[dim]Est. Cost: ${cost:.4f}[/]")
304+
351305
self.console.print(" | ".join(parts), justify="right")
352306

353307
def _get_box_style(self):
@@ -359,13 +313,15 @@ def _handle_command_waiting(self, event):
359313
"""Handle a command that appears to be waiting for input."""
360314
content = event.get("content", "")
361315
process = event.get("process")
316+
tool_name = event.get("tool_name", "command-exec")
362317

363318
# Display warning
364319
self.console.print(Panel(
365320
f"[yellow]{content}[/]",
366321
title="[bold yellow]⚠️ Process Stalled[/]",
367322
border_style="yellow",
368323
box=self._get_box_style()
324+
369325
))
370326

371327
# Simple stdin-based menu (most reliable across terminals)
@@ -403,6 +359,10 @@ def _handle_command_waiting(self, event):
403359
except Exception:
404360
pass
405361
return "killed"
362+
363+
364+
365+
406366

407367
def _filter_special_tokens(self, text: str) -> str:
408368
"""Remove special tokens from display text while preserving normal content."""
@@ -447,11 +407,10 @@ def _display_tool_call(self, tool_call):
447407
args_str = json.dumps(args, indent=2)
448408

449409
self.console.print(Panel(
450-
Syntax(args_str.strip(), "json", theme="monokai", word_wrap=True, padding=0),
410+
Syntax(args_str, "json", theme="monokai", word_wrap=True),
451411
title=f"[bold yellow]🔧 Tool Call: {name}[/]",
452412
border_style="yellow",
453-
box=self._get_box_style(),
454-
padding=(0, 1)
413+
box=self._get_box_style()
455414
))
456415

457416
def _display_tool_result(self, result_data):
@@ -468,11 +427,10 @@ def _display_tool_result(self, result_data):
468427
display_result = result[:500] + "..." if len(result) > 500 else result
469428

470429
self.console.print(Panel(
471-
f"[dim]{display_result.strip()}[/]",
430+
f"[dim]{display_result}[/]",
472431
title=f"[bold green]✔ Result: {name}[/]",
473432
border_style="green",
474-
box=self._get_box_style(),
475-
padding=(0, 1)
433+
box=self._get_box_style()
476434
))
477435

478436
def _is_diff_result(self, result: str) -> bool:
@@ -493,28 +451,32 @@ def _display_diff_result(self, name: str, result: str):
493451
in_diff = False
494452

495453
for line in lines:
454+
# Check for unified diff markers to start capturing diff
455+
# --- file header, +++ file header, @@ hunk header
496456
if line.startswith("--- ") or line.startswith("+++ ") or line.startswith("@@"):
497457
in_diff = True
498458

499459
if in_diff:
460+
# Once in diff mode, capture all lines (including +/- content lines)
500461
diff_lines.append(line)
501462
else:
502463
message_lines.append(line)
503464

465+
# Display message part (success message)
504466
if message_lines:
505467
message = "\n".join(message_lines).strip()
506468
if message:
507469
self.console.print(f"[bold green]✔ {name}[/]: {message}")
508470

471+
# Display diff with syntax highlighting
509472
if diff_lines:
510473
diff_text = "\n".join(diff_lines)
511-
syntax = Syntax(diff_text, "diff", theme="monokai", line_numbers=False, padding=0)
474+
syntax = Syntax(diff_text, "diff", theme="monokai", line_numbers=False)
512475
self.console.print(Panel(
513476
syntax,
514477
title="[bold cyan]Changes[/]",
515478
border_style="cyan",
516-
box=self._get_box_style(),
517-
padding=(0, 1)
479+
box=self._get_box_style()
518480
))
519481

520482

0 commit comments

Comments
 (0)