From a38d085fd65fb631d32ef088209616f1c959594f Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Tue, 4 Nov 2025 14:48:54 -0500 Subject: [PATCH 1/2] Bump Version --- aider/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aider/__init__.py b/aider/__init__.py index 84d65a203b4..b30f630f31f 100644 --- a/aider/__init__.py +++ b/aider/__init__.py @@ -1,6 +1,6 @@ from packaging import version -__version__ = "0.88.6.dev" +__version__ = "0.88.7.dev" safe_version = __version__ try: From 38a45fbef9f17693fecaa6e4ef0fff9bb059b39b Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Tue, 4 Nov 2025 15:29:16 -0500 Subject: [PATCH 2/2] 2 changes, one to deduplicate repeated tool call id usage and another for #91 and #93 to start the spinner after confirmations so the system is more obviously responsive --- aider/coders/base_coder.py | 13 ++++++++----- aider/io.py | 9 ++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index b2a783f0cf5..5cd335e4a69 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -672,10 +672,6 @@ def show_pretty(self): return True - def _stop_waiting_spinner(self): - """Stop and clear the waiting spinner if it is running.""" - self.io.stop_spinner() - def get_abs_fnames_content(self): for fname in list(self.abs_fnames): content = self.io.read_text(fname) @@ -1281,6 +1277,7 @@ async def _processing_logic(self, user_message, preproc): finally: self.run_one_completed = True self.compact_context_completed = True + self.io.stop_spinner() def copy_context(self): if self.auto_copy_context: @@ -1994,7 +1991,7 @@ async def send_message(self, inp): self.mdstream = None # Ensure any waiting spinner is stopped - self._stop_waiting_spinner() + self.io.start_spinner("Processing Answer...") self.partial_response_content = self.get_multi_response_content_in_progress(True) self.remove_reasoning_content() @@ -2064,7 +2061,13 @@ async def send_message(self, inp): try: if self.partial_response_tool_calls: tool_calls = [] + tool_id_set = set() + for tool_call_dict in self.partial_response_tool_calls: + # LLM APIs sometimes return duplicates and that's annoying + if tool_call_dict.get("id") in tool_id_set: + continue + tool_calls.append( ChatCompletionMessageToolCall( id=tool_call_dict.get("id"), diff --git a/aider/io.py b/aider/io.py index 90e353ee802..6b8aafa605a 100644 --- a/aider/io.py +++ b/aider/io.py @@ -424,6 +424,7 @@ def __init__( # Spinner state self.spinner_running = False self.spinner_text = "" + self.last_spinner_text = "" self.spinner_frame_index = 0 self.spinner_last_frame_index = 0 self.unicode_palette = "░█" @@ -493,7 +494,7 @@ def _spinner_supports_unicode(self) -> bool: except Exception: return False - def start_spinner(self, text): + def start_spinner(self, text, update_last_text=True): """Start the spinner.""" self.stop_spinner() @@ -501,6 +502,9 @@ def start_spinner(self, text): self.spinner_running = True self.spinner_text = text self.spinner_frame_index = self.spinner_last_frame_index + + if update_last_text: + self.last_spinner_text = text else: self.fallback_spinner = Spinner(text) self.fallback_spinner.step() @@ -1115,6 +1119,7 @@ async def _confirm_ask( else: # Ring the bell if needed self.ring_bell() + self.start_spinner("Awaiting Confirmation...", False) while True: try: @@ -1157,7 +1162,9 @@ async def _confirm_ask( break res = res.lower() good = any(valid_response.startswith(res) for valid_response in valid_responses) + if good: + self.start_spinner(self.last_spinner_text) break error_message = f"Please answer with one of: {', '.join(valid_responses)}"