Skip to content

Commit 5962504

Browse files
authored
Merge pull request #331 from dwash96/v0.91.3
V0.91.3
2 parents 87cd27e + c6a90d5 commit 5962504

33 files changed

Lines changed: 2400 additions & 592 deletions

.github/workflows/ubuntu-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
uv pip install --system \
5151
pytest \
5252
pytest-asyncio \
53+
pytest-mock \
5354
-r requirements/requirements.in \
5455
-r requirements/requirements-help.in \
5556
-r requirements/requirements-playwright.in \

.github/workflows/windows-tests.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,10 @@ jobs:
4242
run: |
4343
python -m pip install --upgrade pip
4444
pip install uv
45-
uv pip install --system pytest pytest-asyncio -r requirements/requirements.in -r requirements/requirements-help.in -r requirements/requirements-playwright.in '.[help,playwright]'
45+
uv pip install --system pytest pytest-asyncio pytest-mock -r requirements/requirements.in -r requirements/requirements-help.in -r requirements/requirements-playwright.in '.[help,playwright]'
4646
4747
- name: Run tests
4848
env:
4949
AIDER_ANALYTICS: false
5050
run: |
5151
pytest
52-

aider/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from packaging import version
22

3-
__version__ = "0.91.2.dev"
3+
__version__ = "0.91.3.dev"
44
safe_version = __version__
55

66
try:

aider/args.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ def get_parser(default_config_files, git_root):
838838
)
839839
group.add_argument(
840840
"--yes-always",
841+
"--yes",
841842
action="store_true",
842843
help="Always say yes to every confirmation (not including cli commands)",
843844
default=None,

aider/coders/agent_coder.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -369,23 +369,26 @@ def get_local_tool_schemas(self):
369369
async def initialize_mcp_tools(self):
370370
await super().initialize_mcp_tools()
371371

372-
local_tools = self.get_local_tool_schemas()
373-
if not local_tools:
374-
return
372+
server_name = "Local"
373+
374+
if server_name not in [name for name, _ in self.mcp_tools]:
375+
local_tools = self.get_local_tool_schemas()
376+
if not local_tools:
377+
return
375378

376-
local_server_config = {"name": "Local"}
377-
local_server = LocalServer(local_server_config)
379+
local_server_config = {"name": server_name}
380+
local_server = LocalServer(local_server_config)
378381

379-
if not self.mcp_servers:
380-
self.mcp_servers = []
381-
if not any(isinstance(s, LocalServer) for s in self.mcp_servers):
382-
self.mcp_servers.append(local_server)
382+
if not self.mcp_servers:
383+
self.mcp_servers = []
384+
if not any(isinstance(s, LocalServer) for s in self.mcp_servers):
385+
self.mcp_servers.append(local_server)
383386

384-
if not self.mcp_tools:
385-
self.mcp_tools = []
387+
if not self.mcp_tools:
388+
self.mcp_tools = []
386389

387-
if "local_tools" not in [name for name, _ in self.mcp_tools]:
388-
self.mcp_tools.append((local_server.name, local_tools))
390+
if server_name not in [name for name, _ in self.mcp_tools]:
391+
self.mcp_tools.append((local_server.name, local_tools))
389392

390393
async def _execute_local_tool_calls(self, tool_calls_list):
391394
tool_responses = []

aider/coders/architect_coder.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,6 @@ async def reply_completed(self):
4141
kwargs["cache_prompts"] = False
4242
kwargs["num_cache_warming_pings"] = 0
4343
kwargs["summarize_from_coder"] = False
44-
kwargs["mcp_servers"] = [] # Empty to skip initialization
45-
46-
coder = await Coder.create(**kwargs)
47-
# Transfer MCP state to avoid re-initialization
48-
coder.mcp_servers = self.mcp_servers
49-
coder.mcp_tools = self.mcp_tools
50-
# Transfer TUI app weak reference
51-
coder.tui = self.tui
5244

5345
new_kwargs = dict(io=self.io, from_coder=self)
5446
new_kwargs.update(kwargs)

aider/coders/base_coder.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -233,22 +233,32 @@ async def create(
233233
kwargs = use_kwargs
234234
from_coder.ok_to_warm_cache = False
235235

236+
res = None
236237
if (
237238
getattr(main_model, "copy_paste_mode", False)
238239
and getattr(main_model, "copy_paste_transport", "api") == "clipboard"
239240
):
240241
res = coders.CopyPasteCoder(main_model, io, args=args, **kwargs)
242+
243+
if not res:
244+
for coder in coders.__all__:
245+
if hasattr(coder, "edit_format") and coder.edit_format == edit_format:
246+
res = coder(main_model, io, args=args, **kwargs)
247+
248+
if res is not None:
249+
if from_coder:
250+
if from_coder.mcp_servers and kwargs.get("mcp_servers", False):
251+
res.mcp_servers = from_coder.mcp_servers
252+
res.mcp_tools = from_coder.mcp_tools
253+
254+
# Transfer TUI app weak reference
255+
res.tui = from_coder.tui
256+
241257
await res.initialize_mcp_tools()
258+
242259
res.original_kwargs = dict(kwargs)
243260
return res
244261

245-
for coder in coders.__all__:
246-
if hasattr(coder, "edit_format") and coder.edit_format == edit_format:
247-
res = coder(main_model, io, args=args, **kwargs)
248-
await res.initialize_mcp_tools()
249-
res.original_kwargs = dict(kwargs)
250-
return res
251-
252262
valid_formats = [
253263
str(c.edit_format)
254264
for c in coders.__all__
@@ -2703,6 +2713,12 @@ async def initialize_mcp_tools(self):
27032713
tools = []
27042714

27052715
async def get_server_tools(server):
2716+
# Check if we already have tools for this server in mcp_tools
2717+
if self.mcp_tools:
2718+
for server_name, server_tools in self.mcp_tools:
2719+
if server_name == server.name:
2720+
return (server.name, server_tools)
2721+
27062722
try:
27072723
session = await server.connect()
27082724
server_tools = await experimental_mcp_client.load_mcp_tools(
@@ -3266,8 +3282,20 @@ def consolidate_chunks(self):
32663282
self.partial_response_reasoning_content = reasoning_content or ""
32673283

32683284
try:
3269-
if not self.partial_response_reasoning_content:
3270-
self.partial_response_content = response.choices[0].message.content or ""
3285+
content = response.choices[0].message.content
3286+
if isinstance(content, list):
3287+
# OpenAI-compatible APIs sometimes return content as a list
3288+
# of blocks; join the textual pieces for display.
3289+
content = "".join(
3290+
block.get("text", "")
3291+
for block in content
3292+
if isinstance(block, dict) and block.get("type") == "output_text"
3293+
) or "".join(
3294+
block.get("text", "")
3295+
for block in content
3296+
if isinstance(block, dict) and block.get("type") == "text"
3297+
)
3298+
self.partial_response_content = content or ""
32713299
except AttributeError as e:
32723300
content_err = e
32733301

aider/commands/help.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,8 @@ async def execute(cls, io, coder, args, **kwargs):
5252
kwargs["suggest_shell_commands"] = False
5353
kwargs["cache_prompts"] = False
5454
kwargs["num_cache_warming_pings"] = 0
55-
kwargs["mcp_servers"] = [] # Empty to skip initialization
5655

5756
help_coder = await Coder.create(**kwargs)
58-
# Transfer MCP state to avoid re-initialization
59-
help_coder.mcp_servers = coder.mcp_servers
60-
help_coder.mcp_tools = coder.mcp_tools
61-
# Transfer TUI app weak reference
62-
help_coder.tui = coder.tui
6357
user_msg = help_instance.ask(args)
6458
user_msg += """
6559
# Announcement lines from when this session of aider was launched:

aider/commands/lint.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from aider.commands.utils.base_command import BaseCommand
44
from aider.commands.utils.helpers import format_command_result
5+
from aider.utils import expand_glob_patterns
56

67

78
class LintCommand(BaseCommand):
@@ -11,7 +12,16 @@ class LintCommand(BaseCommand):
1112
@classmethod
1213
async def execute(cls, io, coder, args, **kwargs):
1314
"""Execute the lint command with given parameters."""
14-
fnames = kwargs.get("fnames", None)
15+
fnames = None
16+
17+
# Get files from CLI arguments if available
18+
system_args = kwargs.get("system_args")
19+
if system_args:
20+
cli_files = getattr(system_args, "files", []) or []
21+
cli_file_arg = getattr(system_args, "file", []) or []
22+
all_cli_files = cli_files + cli_file_arg
23+
if all_cli_files:
24+
fnames = expand_glob_patterns(all_cli_files)
1525

1626
if not coder.repo:
1727
io.tool_error("No git repository found.")
@@ -21,7 +31,7 @@ async def execute(cls, io, coder, args, **kwargs):
2131
fnames = coder.get_inchat_relative_files()
2232

2333
# If still no files, get all dirty files in the repo
24-
if not fnames and coder.repo:
34+
if not fnames:
2535
fnames = coder.repo.get_dirty_files()
2636

2737
if not fnames:

aider/commands/model.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,7 @@ async def execute(cls, io, coder, args, **kwargs):
9494
@classmethod
9595
def get_completions(cls, io, coder, args) -> List[str]:
9696
"""Get completion options for model command."""
97-
from aider.llm import litellm
98-
99-
model_names = litellm.model_cost.keys()
100-
return list(model_names)
97+
return models.get_chat_model_names()
10198

10299
@classmethod
103100
def get_help(cls) -> str:

0 commit comments

Comments
 (0)