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
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,12 @@ repos:
args: ["--skip", "aider/website/docs/languages.md"]
additional_dependencies:
- tomli
- repo: local
hooks:
- id: filter-model-metadata
name: Filter model metadata to chat mode only
entry: node scripts/filter-chat-mode.js
args: ["aider/resources/model-metadata.json"]
language: system
files: ^aider/resources/model-metadata\.json$
pass_filenames: false
5 changes: 4 additions & 1 deletion aider/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--preserve-todo-list",
action="store_true",
help="Preserve the existing .aider.todo.txt file on startup (default: False)",
help=(
"Deprecated: no longer needed because the todo list is saved and restored with"
" sessions. This flag has no effect and will be removed."
),
default=False,
)
group.add_argument(
Expand Down
27 changes: 16 additions & 11 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ def __init__(
self.auto_accept_architect = auto_accept_architect
self.preserve_todo_list = preserve_todo_list

if self.preserve_todo_list:
self.io.tool_warning(
"--preserve-todo-list is deprecated; todo lists are now saved and restored with"
" sessions. The flag will be removed in a future release."
)

self.ignore_mentions = ignore_mentions
if not self.ignore_mentions:
self.ignore_mentions = set()
Expand Down Expand Up @@ -524,17 +530,16 @@ def __init__(
self.auto_test = auto_test
self.test_cmd = test_cmd

# Clean up todo list file on startup unless preserve_todo_list is True
if not getattr(self, "preserve_todo_list", False):
todo_file_path = ".aider.todo.txt"
abs_path = self.abs_root_path(todo_file_path)
if os.path.isfile(abs_path):
try:
os.remove(abs_path)
if self.verbose:
self.io.tool_output(f"Removed existing todo list file: {todo_file_path}")
except Exception as e:
self.io.tool_warning(f"Could not remove todo list file {todo_file_path}: {e}")
# Clean up todo list file on startup; sessions will restore it when needed
todo_file_path = ".aider.todo.txt"
abs_path = self.abs_root_path(todo_file_path)
if os.path.isfile(abs_path):
try:
os.remove(abs_path)
if self.verbose:
self.io.tool_output(f"Removed existing todo list file: {todo_file_path}")
except Exception as e:
self.io.tool_warning(f"Could not remove todo list file {todo_file_path}: {e}")

# validate the functions jsonschema
if self.functions:
Expand Down
53 changes: 29 additions & 24 deletions aider/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -962,33 +962,38 @@ def get_io(pretty):
model_overrides[model_name] = {}
model_overrides[model_name].update(tags)

# Parse model names with suffixes and apply overrides
def parse_model_with_suffix(model_name, overrides):
"""Parse model name with optional :suffix and apply overrides."""
# Build an index from full "base:suffix" names to (base_model, override_dict)
# so we don't have to parse/split user-provided model names at runtime.
override_index = {}
for base_model, suffixes in model_overrides.items():
if not isinstance(suffixes, dict):
continue
for suffix, cfg in suffixes.items():
if not isinstance(cfg, dict):
continue
full_name = f"{base_model}:{suffix}"
# Later entries override earlier ones
override_index[full_name] = (base_model, cfg)

def apply_model_overrides(model_name):
"""Return (effective_model_name, override_kwargs) for a given model_name.

If model_name exactly matches a configured "base:suffix" override, we
switch to the base model and apply that override dict. Otherwise we
leave the name unchanged and return empty overrides.
"""
if not model_name:
return model_name, {}
entry = override_index.get(model_name)
if not entry:
return model_name, {}
base_model, cfg = entry
return base_model, cfg.copy()

# Split on last colon to get model name and suffix
if ":" in model_name:
base_model, suffix = model_name.rsplit(":", 1)
else:
base_model, suffix = model_name, None

# Apply overrides if suffix exists
override_kwargs = {}
if suffix and base_model in overrides and suffix in overrides[base_model]:
override_kwargs = overrides[base_model][suffix].copy()

return base_model, override_kwargs

# Parse main model
main_model_name, main_model_overrides = parse_model_with_suffix(args.model, model_overrides)
weak_model_name, weak_model_overrides = parse_model_with_suffix(
args.weak_model, model_overrides
)
editor_model_name, editor_model_overrides = parse_model_with_suffix(
args.editor_model, model_overrides
)
# Apply overrides (if any) to the selected models
main_model_name, main_model_overrides = apply_model_overrides(args.model)
weak_model_name, weak_model_overrides = apply_model_overrides(args.weak_model)
editor_model_name, editor_model_overrides = apply_model_overrides(args.editor_model)

# Create weak model if specified with overrides
weak_model_obj = None
Expand Down
Loading
Loading