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
2 changes: 1 addition & 1 deletion aider/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from packaging import version

__version__ = "0.88.38.dev"
__version__ = "0.88.39.dev"
safe_version = __version__

try:
Expand Down
8 changes: 4 additions & 4 deletions aider/coders/agent_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ def format_chat_chunks(self):
if repetitive_tools:
tool_context = self._generate_tool_context(repetitive_tools)
if tool_context:
pre_dynamic_blocks.append(tool_context)
post_dynamic_blocks.append(tool_context)

if pre_dynamic_blocks:
dynamic_message = "\n\n".join(pre_dynamic_blocks)
Expand Down Expand Up @@ -1717,7 +1717,7 @@ def _get_repetitive_tools(self):
history_len = len(self.tool_usage_history)

# Not enough history to detect a pattern
if history_len < 2:
if history_len < 5:
return set()

# Check for similarity-based repetition
Expand All @@ -1741,12 +1741,12 @@ def _get_repetitive_tools(self):
if all(tool.lower() in self.read_tools for tool in all_tools):
return set(all_tools)

# Check for any read tool used more than once across rounds
# Check for any read tool used more than 5 times across rounds
tool_counts = Counter(all_tools)
count_repetitive_tools = {
tool
for tool, count in tool_counts.items()
if count >= 2 and tool.lower() in self.read_tools
if count >= 5 and tool.lower() in self.read_tools
}

# Combine both detection methods
Expand Down
3 changes: 3 additions & 0 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,9 @@ def add_assistant_reply_to_cur_messages(self):
elif self.partial_response_function_call:
msg["function_call"] = self.partial_response_function_call

if "reasoning_content" not in msg:
msg["reasoning_content"] = self.partial_response_reasoning_content

# Only add a message if it's not empty.
if msg is not None:
self.cur_messages.append(msg)
Expand Down
34 changes: 33 additions & 1 deletion aider/helpers/requests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
from ..sendchat import ensure_alternating_roles


def add_reasoning_content(messages):
"""Add empty reasoning content field to assistant messages if not present.

Args:
messages: List of message dictionaries

Returns:
List of messages with reasoning content added to assistant messages
"""
for msg in messages:
if msg.get("role") == "assistant" and "reasoning_content" not in msg:
msg["reasoning_content"] = ""
return messages


def remove_empty_tool_calls(messages):
"""Remove messages with tool_calls that are empty arrays.

Args:
messages: List of message dictionaries

Returns:
List of messages with empty tool_calls messages removed
"""
return [
msg
for msg in messages
if not (msg.get("role") == "assistant" and "tool_calls" in msg and msg["tool_calls"] == [])
]


def thought_signature(model, messages):
# Add thought signatures for Vertex AI and Gemini models
if model.name.startswith("vertex_ai/") or model.name.startswith("gemini/"):
Expand Down Expand Up @@ -40,6 +71,7 @@ def thought_signature(model, messages):

def model_request_parser(model, messages):
messages = thought_signature(model, messages)
messages = remove_empty_tool_calls(messages)
messages = ensure_alternating_roles(messages)

messages = add_reasoning_content(messages)
return messages
Loading