From 4ff959f55b32dff9e486437e8ff774e808367b11 Mon Sep 17 00:00:00 2001 From: Bill Dengler Date: Thu, 11 Dec 2025 11:13:35 -0800 Subject: [PATCH 1/9] Add gpt-5.2 models --- aider/resources/model-settings.yml | 121 +++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml index bb6e0981ebd..e4ec13d8cc7 100644 --- a/aider/resources/model-settings.yml +++ b/aider/resources/model-settings.yml @@ -1899,6 +1899,33 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: gpt-5.2-pro + streaming: false + edit_format: diff + weak_model_name: gpt-5-mini + use_repo_map: true + editor_model_name: gpt-5.2 + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + accepts_settings: ["reasoning_effort"] + examples_as_sys_msg: true + use_temperature: false + +- name: gpt-5.2 + edit_format: diff + weak_model_name: gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + overeager: true + +- name: gpt-5.2-2025-12-11 + edit_format: diff + weak_model_name: gpt-5-nano-2025-08-07 + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: gpt-5-mini edit_format: diff weak_model_name: gpt-5-nano @@ -1955,6 +1982,13 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: gpt-5.2-chat-latest + edit_format: diff + weak_model_name: gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: gpt-5-codex edit_format: diff weak_model_name: gpt-5-nano @@ -2009,6 +2043,20 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: azure/gpt-5.2 + edit_format: diff + weak_model_name: azure/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + +- name: azure/gpt-5.2-2025-12-11 + edit_format: diff + weak_model_name: azure/gpt-5-nano-2025-08-07 + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: azure/gpt-5-mini edit_format: diff weak_model_name: azure/gpt-5-nano @@ -2065,6 +2113,13 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: azure/gpt-5.2-chat-latest + edit_format: diff + weak_model_name: azure/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: openai/gpt-5 edit_format: diff weak_model_name: openai/gpt-5-nano @@ -2105,6 +2160,32 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: openai/gpt-5.2-pro + streaming: false + edit_format: diff + weak_model_name: openai/gpt-5-mini + use_repo_map: true + editor_model_name: openai/gpt-5.2 + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + accepts_settings: ["reasoning_effort"] + examples_as_sys_msg: true + use_temperature: false + +- name: openai/gpt-5.2 + edit_format: diff + weak_model_name: openai/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + +- name: openai/gpt-5.2-2025-12-11 + edit_format: diff + weak_model_name: openai/gpt-5-nano-2025-08-07 + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: openai/gpt-5-mini edit_format: diff weak_model_name: openai/gpt-5-nano @@ -2161,6 +2242,13 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: openai/gpt-5.2-chat-latest + edit_format: diff + weak_model_name: openai/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: openrouter/openai/gpt-5 edit_format: diff weak_model_name: openrouter/openai/gpt-5-nano @@ -2201,6 +2289,32 @@ use_temperature: false accepts_settings: ["reasoning_effort"] +- name: openrouter/openai/gpt-5.2-pro + streaming: false + edit_format: diff + weak_model_name: openrouter/openai/gpt-5-mini + use_repo_map: true + editor_model_name: openrouter/openai/gpt-5.2 + editor_edit_format: editor-diff + system_prompt_prefix: "Formatting re-enabled. " + accepts_settings: ["reasoning_effort"] + examples_as_sys_msg: true + use_temperature: false + +- name: openrouter/openai/gpt-5.2 + edit_format: diff + weak_model_name: openrouter/openai/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + +- name: openrouter/openai/gpt-5.2-2025-12-11 + edit_format: diff + weak_model_name: openrouter/openai/gpt-5-nano-2025-08-07 + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] + - name: openrouter/openai/gpt-5-mini edit_format: diff weak_model_name: openrouter/openai/gpt-5-nano @@ -2256,3 +2370,10 @@ use_repo_map: true use_temperature: false accepts_settings: ["reasoning_effort"] + +- name: openrouter/openai/gpt-5.2-chat-latest + edit_format: diff + weak_model_name: openrouter/openai/gpt-5-nano + use_repo_map: true + use_temperature: false + accepts_settings: ["reasoning_effort"] From 06880de90227be147c0d0b896ed888021f6b9f34 Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Thu, 11 Dec 2025 20:38:56 -0500 Subject: [PATCH 2/9] Bump Version --- aider/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aider/__init__.py b/aider/__init__.py index 0569fee8b73..7f24b49cc19 100644 --- a/aider/__init__.py +++ b/aider/__init__.py @@ -1,6 +1,6 @@ from packaging import version -__version__ = "0.89.5.dev" +__version__ = "0.89.6.dev" safe_version = __version__ try: From 90c4a8cd0f076363dc51f782dba9209c14f6fa96 Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Thu, 11 Dec 2025 20:50:10 -0500 Subject: [PATCH 3/9] Fix truststore import --- aider/main.py | 15 +++++++++----- requirements.txt | 32 ++++------------------------- requirements/common-constraints.txt | 26 +++++------------------ 3 files changed, 19 insertions(+), 54 deletions(-) diff --git a/aider/main.py b/aider/main.py index 475cf07335a..db83d45dcf7 100644 --- a/aider/main.py +++ b/aider/main.py @@ -1,3 +1,13 @@ +import os + +try: + if not os.environ["CECLI_DEFAULT_TLS"] or os.environ["SIDER_CE_DEFAULT_TLS"]: + import truststore + + truststore.inject_into_ssl() +except Exception: + pass + import asyncio import glob import json @@ -11,8 +21,6 @@ from dataclasses import fields from pathlib import Path -import truststore - try: import git except ImportError: @@ -542,9 +550,6 @@ async def main_async(argv=None, input=None, output=None, force_git_root=None, re return await graceful_exit(None, 1) raise e - if args.native_tls: - truststore.inject_into_ssl() - if args.verbose: print("Config files search order, if no --config:") for file in default_config_files: diff --git a/requirements.txt b/requirements.txt index b85f28e7246..45df632bcf2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,10 +25,6 @@ anyio==4.11.0 # sse-starlette # starlette # watchfiles -asgiref==3.11.0 - # via - # -c requirements/common-constraints.txt - # mixpanel attrs==25.4.0 # via # -c requirements/common-constraints.txt @@ -39,7 +35,6 @@ backoff==2.2.1 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in - # posthog beautifulsoup4==4.14.2 # via # -c requirements/common-constraints.txt @@ -89,7 +84,6 @@ distro==1.9.0 # via # -c requirements/common-constraints.txt # openai - # posthog fastuuid==0.14.0 # via # -c requirements/common-constraints.txt @@ -190,7 +184,6 @@ httpx==0.28.1 # -c requirements/common-constraints.txt # litellm # mcp - # mixpanel # openai httpx-sse==0.4.3 # via @@ -262,10 +255,6 @@ mdurl==0.1.2 # via # -c requirements/common-constraints.txt # markdown-it-py -mixpanel==5.0.0 - # via - # -c requirements/common-constraints.txt - # -r requirements/requirements.in mslex==1.3.0 # via # -c requirements/common-constraints.txt @@ -310,10 +299,6 @@ pillow==12.0.0 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in -posthog==7.0.1 - # via - # -c requirements/common-constraints.txt - # -r requirements/requirements.in prompt-toolkit==3.0.52 # via # -c requirements/common-constraints.txt @@ -368,7 +353,6 @@ pydantic==2.12.4 # google-generativeai # litellm # mcp - # mixpanel # openai # pydantic-settings pydantic-core==2.41.5 @@ -407,10 +391,6 @@ pyperclip==1.11.0 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in -python-dateutil==2.9.0.post0 - # via - # -c requirements/common-constraints.txt - # posthog python-dotenv==1.2.1 # via # -c requirements/common-constraints.txt @@ -439,8 +419,6 @@ requests==2.32.5 # -c requirements/common-constraints.txt # google-api-core # huggingface-hub - # mixpanel - # posthog # tiktoken rich==14.2.0 # via @@ -463,11 +441,6 @@ shtab==1.8.0 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in -six==1.17.0 - # via - # -c requirements/common-constraints.txt - # posthog - # python-dateutil smmap==5.0.2 # via # -c requirements/common-constraints.txt @@ -535,6 +508,10 @@ tree-sitter-yaml==0.7.2 # via # -c requirements/common-constraints.txt # tree-sitter-language-pack +truststore==0.10.4 + # via + # -c requirements/common-constraints.txt + # -r requirements/requirements.in typing-extensions==4.15.0 # via # -c requirements/common-constraints.txt @@ -546,7 +523,6 @@ typing-extensions==4.15.0 # huggingface-hub # mcp # openai - # posthog # pydantic # pydantic-core # referencing diff --git a/requirements/common-constraints.txt b/requirements/common-constraints.txt index bca94710130..a73d66cf561 100644 --- a/requirements/common-constraints.txt +++ b/requirements/common-constraints.txt @@ -23,17 +23,13 @@ anyio==4.11.0 # sse-starlette # starlette # watchfiles -asgiref==3.11.0 - # via mixpanel attrs==25.4.0 # via # aiohttp # jsonschema # referencing backoff==2.2.1 - # via - # -r requirements/requirements.in - # posthog + # via -r requirements/requirements.in banks==2.2.0 # via llama-index-core beautifulsoup4==4.14.2 @@ -98,9 +94,7 @@ diskcache==5.6.3 distlib==0.4.0 # via virtualenv distro==1.9.0 - # via - # openai - # posthog + # via openai fastuuid==0.14.0 # via litellm filelock==3.20.0 @@ -197,7 +191,6 @@ httpx==0.28.1 # litellm # llama-index-core # mcp - # mixpanel # openai httpx-sse==0.4.3 # via mcp @@ -276,8 +269,6 @@ mcp==1.22.0 # via -r requirements/requirements.in mdurl==0.1.2 # via markdown-it-py -mixpanel==5.0.0 - # via -r requirements/requirements.in mpmath==1.3.0 # via sympy mslex==1.3.0 @@ -399,8 +390,6 @@ playwright==1.56.0 # via -r requirements/requirements-playwright.in pluggy==1.6.0 # via pytest -posthog==7.0.1 - # via -r requirements/requirements.in pre-commit==4.5.0 # via -r requirements/requirements-dev.in prompt-toolkit==3.0.52 @@ -447,7 +436,6 @@ pydantic==2.12.4 # llama-index-instrumentation # llama-index-workflows # mcp - # mixpanel # openai # pydantic-settings pydantic-core==2.41.5 @@ -494,7 +482,6 @@ python-dateutil==2.9.0.post0 # google-cloud-bigquery # matplotlib # pandas - # posthog python-dotenv==1.2.1 # via # litellm @@ -525,8 +512,6 @@ requests==2.32.5 # google-cloud-bigquery # huggingface-hub # llama-index-core - # mixpanel - # posthog # streamlit # tiktoken # transformers @@ -563,9 +548,7 @@ shellingham==1.5.4 shtab==1.8.0 # via -r requirements/requirements.in six==1.17.0 - # via - # posthog - # python-dateutil + # via python-dateutil smmap==5.0.2 # via gitdb sniffio==1.3.1 @@ -635,6 +618,8 @@ tree-sitter-yaml==0.7.2 # via tree-sitter-language-pack triton==3.5.1 # via torch +truststore==0.10.4 + # via -r requirements/requirements.in typer==0.20.0 # via -r requirements/requirements-dev.in typing-extensions==4.15.0 @@ -651,7 +636,6 @@ typing-extensions==4.15.0 # llama-index-workflows # mcp # openai - # posthog # pydantic # pydantic-core # pyee From 3a64fb4eafc1df9b55003bf897e62740c03d7313 Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Thu, 11 Dec 2025 21:02:32 -0500 Subject: [PATCH 4/9] Don't error on non-existent arguments so we can actually remove ocnfig arguments eventually --- aider/args.py | 52 ------------------------ aider/deprecated.py | 96 ++++++++++++++++++++++++++++++++++----------- aider/main.py | 5 ++- 3 files changed, 78 insertions(+), 75 deletions(-) diff --git a/aider/args.py b/aider/args.py index feb5bce69fd..67e91a29373 100644 --- a/aider/args.py +++ b/aider/args.py @@ -77,22 +77,6 @@ def get_parser(default_config_files, git_root): "--openai-api-base", help="Specify the api base url", ) - group.add_argument( - "--openai-api-type", - help="(deprecated, use --set-env OPENAI_API_TYPE=)", - ) - group.add_argument( - "--openai-api-version", - help="(deprecated, use --set-env OPENAI_API_VERSION=)", - ) - group.add_argument( - "--openai-api-deployment-id", - help="(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=)", - ) - group.add_argument( - "--openai-organization-id", - help="(deprecated, use --set-env OPENAI_ORGANIZATION=)", - ) group.add_argument( "--set-env", action="append", @@ -154,12 +138,6 @@ def get_parser(default_config_files, git_root): default=True, help="Verify the SSL cert when connecting to models (default: True)", ) - group.add_argument( - "--native-tls", - action=argparse.BooleanOptionalAction, - default=True, - help="Use system defined ssl certificates, instead of python's defaults (Default: True)", - ) group.add_argument( "--timeout", type=float, @@ -687,36 +665,6 @@ def get_parser(default_config_files, git_root): default=False, ) - ########## - group = parser.add_argument_group("Analytics") - group.add_argument( - "--analytics", - action=argparse.BooleanOptionalAction, - default=None, - help=argparse.SUPPRESS, - ) - group.add_argument( - "--analytics-log", - metavar="ANALYTICS_LOG_FILE", - help=argparse.SUPPRESS, - ).complete = shtab.FILE - group.add_argument( - "--analytics-disable", - action="store_true", - help=argparse.SUPPRESS, - default=False, - ) - group.add_argument( - "--analytics-posthog-host", - metavar="ANALYTICS_POSTHOG_HOST", - help=argparse.SUPPRESS, - ) - group.add_argument( - "--analytics-posthog-project-api-key", - metavar="ANALYTICS_POSTHOG_PROJECT_API_KEY", - help=argparse.SUPPRESS, - ) - ######### group = parser.add_argument_group("Upgrading") group.add_argument( diff --git a/aider/deprecated.py b/aider/deprecated.py index e40924f5c4e..99eb989dd1c 100644 --- a/aider/deprecated.py +++ b/aider/deprecated.py @@ -1,87 +1,139 @@ +import argparse + + def add_deprecated_model_args(parser, group): """Add deprecated model shortcut arguments to the argparse parser.""" - opus_model = "claude-3-opus-20240229" + group.add_argument( "--opus", action="store_true", - help=f"Use {opus_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - sonnet_model = "anthropic/claude-3-7-sonnet-20250219" + group.add_argument( "--sonnet", action="store_true", - help=f"Use {sonnet_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - haiku_model = "claude-3-5-haiku-20241022" + group.add_argument( "--haiku", action="store_true", - help=f"Use {haiku_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - gpt_4_model = "gpt-4-0613" + group.add_argument( "--4", "-4", action="store_true", - help=f"Use {gpt_4_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - gpt_4o_model = "gpt-4o" + group.add_argument( "--4o", action="store_true", - help=f"Use {gpt_4o_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - gpt_4o_mini_model = "gpt-4o-mini" + group.add_argument( "--mini", action="store_true", - help=f"Use {gpt_4o_mini_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - gpt_4_turbo_model = "gpt-4-1106-preview" + group.add_argument( "--4-turbo", action="store_true", - help=f"Use {gpt_4_turbo_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - gpt_3_model_name = "gpt-3.5-turbo" + group.add_argument( "--35turbo", "--35-turbo", "--3", "-3", action="store_true", - help=f"Use {gpt_3_model_name} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - deepseek_model = "deepseek/deepseek-chat" + group.add_argument( "--deepseek", action="store_true", - help=f"Use {deepseek_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - o1_mini_model = "o1-mini" + group.add_argument( "--o1-mini", action="store_true", - help=f"Use {o1_mini_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) - o1_preview_model = "o1-preview" + group.add_argument( "--o1-preview", action="store_true", - help=f"Use {o1_preview_model} model for the main chat (deprecated, use --model)", + help=argparse.SUPPRESS, default=False, ) + ######### + group = parser.add_argument_group("API Keys and Settings (Deprecated)") + group.add_argument( + "--openai-api-type", + help=argparse.SUPPRESS, + ) + group.add_argument( + "--openai-api-version", + help=argparse.SUPPRESS, + ) + group.add_argument( + "--openai-api-deployment-id", + help=argparse.SUPPRESS, + ) + group.add_argument( + "--openai-organization-id", + help=argparse.SUPPRESS, + ) + + ########## + group = parser.add_argument_group("Analytics") + group.add_argument( + "--analytics", + action=argparse.BooleanOptionalAction, + default=None, + help=argparse.SUPPRESS, + ) + group.add_argument( + "--analytics-log", + metavar="ANALYTICS_LOG_FILE", + help=argparse.SUPPRESS, + ) + group.add_argument( + "--analytics-disable", + action="store_true", + help=argparse.SUPPRESS, + default=False, + ) + group.add_argument( + "--analytics-posthog-host", + metavar="ANALYTICS_POSTHOG_HOST", + help=argparse.SUPPRESS, + ) + group.add_argument( + "--analytics-posthog-project-api-key", + metavar="ANALYTICS_POSTHOG_PROJECT_API_KEY", + help=argparse.SUPPRESS, + ) + def handle_deprecated_model_args(args, io): """Handle deprecated model shortcut arguments and provide appropriate warnings.""" diff --git a/aider/main.py b/aider/main.py index db83d45dcf7..ef7313e4b52 100644 --- a/aider/main.py +++ b/aider/main.py @@ -566,9 +566,12 @@ async def main_async(argv=None, input=None, output=None, force_git_root=None, re loaded_dotenvs = load_dotenv_files(git_root, args.env_file, args.encoding) # Parse again to include any arguments that might have been defined in .env - args = parser.parse_args(argv) + args, unknown = parser.parse_known_args(argv) set_args_error_data(args) + if len(unknown): + print("Unknown Args: ", unknown) + # Convert YAML dict arguments to JSON strings for compatibility # configargparse.YAMLConfigFileParser converts YAML to Python objects, # but some arguments expect JSON strings From eaa75d305e33e726854c0629dcae1dbe59981723 Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Fri, 12 Dec 2025 00:08:42 -0500 Subject: [PATCH 5/9] Make repo map calculation slightly more efficient --- aider/repomap.py | 61 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/aider/repomap.py b/aider/repomap.py index db16671009d..e140a5468c6 100644 --- a/aider/repomap.py +++ b/aider/repomap.py @@ -6,7 +6,7 @@ import sys import time import warnings -from collections import Counter, defaultdict, namedtuple +from collections import defaultdict, namedtuple from importlib import resources from pathlib import Path @@ -602,7 +602,8 @@ def get_ranked_tags( import networkx as nx defines = defaultdict(set) - references = defaultdict(list) + references = defaultdict(lambda: defaultdict(int)) + total_ref_count = defaultdict(int) # Track total references per identifier definitions = defaultdict(set) file_imports = defaultdict(set) import_ast_mode = False @@ -615,9 +616,11 @@ def get_ranked_tags( fnames = sorted(fnames) # Default personalization for unspecified files is 1/num_nodes - # https://networkx.org/documentation/stable/_modules/networkx/algorithms/link_analysis/pagerank_alg.html#pagerank personalize = 100 / len(fnames) + fname_to_parts = {} + fname_to_suffix = {} + try: cache_size = len(self.TAGS_CACHE) except SQLITE_ERRORS as e: @@ -667,6 +670,8 @@ def get_ranked_tags( # Check path components against mentioned_idents path_obj = Path(rel_fname) + fname_to_parts[rel_fname] = path_obj.parts + fname_to_suffix[rel_fname] = path_obj.suffix path_components = set(path_obj.parts) basename_with_ext = path_obj.name basename_without_ext, _ = os.path.splitext(basename_with_ext) @@ -692,7 +697,8 @@ def get_ranked_tags( definitions[key].add(tag) elif tag.kind == "ref": - references[tag.name].append(rel_fname) + references[tag.name][rel_fname] += 1 + total_ref_count[tag.name] += 1 if tag.specific_kind == "import": file_imports[rel_fname].add(tag.name) @@ -702,8 +708,12 @@ def get_ranked_tags( if self.use_enhanced_map and len(file_imports) > 0: import_ast_mode = True - if not references: - references = dict((k, list(v)) for k, v in defines.items()) + if len(references) == 0: + # Convert defines to the new references structure: dict of dicts with counts + references = {} + for ident, files in defines.items(): + references[ident] = {file: 1 for file in files} + total_ref_count[ident] = len(files) # Each file has count 1 idents = set(defines.keys()).intersection(set(references.keys())) @@ -712,11 +722,13 @@ def get_ranked_tags( # Add a small self-edge for every definition that has no references # Helps with tree-sitter 0.23.2 with ruby, where "def greet(name)" # isn't counted as a def AND a ref. tree-sitter 0.24.0 does. + + unreferenced_weight = 2**-32 / (len(idents) + 1) for ident in defines.keys(): if ident in references: continue for definer in defines[ident]: - G.add_edge(definer, definer, weight=0.000001, ident=ident) + G.add_edge(definer, definer, weight=unreferenced_weight, ident=ident) for ident in idents: if progress: @@ -755,14 +767,17 @@ def get_ranked_tags( # Combined with the above downweighting # There should be a push/pull that balances repetitiveness of identifier defs # With absolute number of references throughout a codebase - unique_file_refs = len(set(references[ident])) - total_refs = len(references[ident]) + unique_file_refs = len(references[ident]) + total_refs = total_ref_count[ident] ext_mul = round(math.log2(unique_file_refs * total_refs**2 + 1)) - for referencer, num_refs in Counter(references[ident]).items(): + for referencer, num_refs in references[ident].items(): relevant_definers = [] if import_ast_mode else definers - if import_ast_mode: + # A referencer should not link to any definiers of an identifier it also defines + if referencer in definers: + relevant_definers = [referencer] + elif import_ast_mode: if referencer in file_imports: matches = [ d @@ -774,10 +789,9 @@ def get_ranked_tags( for definer in relevant_definers: # dump(referencer, definer, num_refs, mul) - # Only add edge if file extensions match - referencer_ext = Path(referencer).suffix - definer_ext = Path(definer).suffix + referencer_ext = fname_to_suffix[referencer] + definer_ext = fname_to_suffix[definer] if referencer_ext != definer_ext: continue @@ -786,12 +800,25 @@ def get_ranked_tags( if referencer in chat_rel_fnames: use_mul *= 64 elif referencer == definer: - use_mul *= 1 / 128 + use_mul *= num_refs / 128 # scale down so high freq (low value) mentions don't dominate # num_refs = math.sqrt(num_refs) - path_distance = self.shared_path_components(referencer, definer) - weight = num_refs * use_mul * 2 ** (-1 * path_distance) + + p1 = fname_to_parts[referencer] + p2 = fname_to_parts[definer] + + # Count common leading parts + common_count = 0 + for c1, c2 in zip(p1, p2): + if c1 == c2: + common_count += 1 + else: + break + + path_distance = len(p1) + len(p2) - (2 * common_count) + + weight = use_mul * 2 ** (-1 * path_distance) G.add_edge(referencer, definer, weight=weight, key=ident, ident=ident) self.io.profile("Build Graph") From 3fda9dbe6987c54ba87291dd7389f0df5025325b Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Fri, 12 Dec 2025 00:15:07 -0500 Subject: [PATCH 6/9] Add GPT-5.2 support litellm --- aider/resources/model-metadata.json | 249 +++++++++++++++++++++++++--- 1 file changed, 227 insertions(+), 22 deletions(-) diff --git a/aider/resources/model-metadata.json b/aider/resources/model-metadata.json index 0513ed6a60d..2ab5a702a19 100644 --- a/aider/resources/model-metadata.json +++ b/aider/resources/model-metadata.json @@ -1271,7 +1271,7 @@ "output_cost_per_token": 1.5e-05, "supports_function_calling": true }, - "azure/claude-haiku-4-5": { + "azure_ai/claude-haiku-4-5": { "input_cost_per_token": 1e-06, "litellm_provider": "azure_ai", "max_input_tokens": 200000, @@ -1289,7 +1289,7 @@ "supports_tool_choice": true, "supports_vision": true }, - "azure/claude-opus-4-1": { + "azure_ai/claude-opus-4-1": { "input_cost_per_token": 1.5e-05, "litellm_provider": "azure_ai", "max_input_tokens": 200000, @@ -1307,7 +1307,7 @@ "supports_tool_choice": true, "supports_vision": true }, - "azure/claude-sonnet-4-5": { + "azure_ai/claude-sonnet-4-5": { "input_cost_per_token": 3e-06, "litellm_provider": "azure_ai", "max_input_tokens": 200000, @@ -9717,25 +9717,18 @@ "supports_tool_choice": true }, "deepseek/deepseek-reasoner": { - "cache_read_input_token_cost": 3e-08, - "input_cost_per_token": 3e-07, + "input_cost_per_token": 5.5e-07, + "input_cost_per_token_cache_hit": 1.4e-07, "litellm_provider": "deepseek", - "max_input_tokens": 128000, - "max_output_tokens": 65536, - "max_tokens": 128000, + "max_input_tokens": 65536, + "max_output_tokens": 8192, + "max_tokens": 8192, "mode": "chat", - "output_cost_per_token": 5e-07, - "source": "https://api-docs.deepseek.com/quick_start/pricing", - "supported_endpoints": [ - "/v1/chat/completions" - ], - "supports_function_calling": false, - "supports_native_streaming": true, - "supports_parallel_function_calling": false, + "output_cost_per_token": 2.19e-06, + "supports_assistant_prefill": true, + "supports_function_calling": true, "supports_prompt_caching": true, "supports_reasoning": true, - "supports_response_schema": true, - "supports_system_messages": true, "supports_tool_choice": true }, "deepseek/deepseek-v3": { @@ -15100,15 +15093,15 @@ "tool_use_system_prompt_tokens": 159 }, "global.anthropic.claude-haiku-4-5-20251001-v1:0": { - "cache_creation_input_token_cost": 1.375e-06, - "cache_read_input_token_cost": 1.1e-07, - "input_cost_per_token": 1.1e-06, + "cache_creation_input_token_cost": 1.25e-06, + "cache_read_input_token_cost": 1e-07, + "input_cost_per_token": 1e-06, "litellm_provider": "bedrock_converse", "max_input_tokens": 200000, "max_output_tokens": 64000, "max_tokens": 64000, "mode": "chat", - "output_cost_per_token": 5.5e-06, + "output_cost_per_token": 5e-06, "source": "https://aws.amazon.com/about-aws/whats-new/2025/10/claude-4-5-haiku-anthropic-amazon-bedrock", "supports_assistant_prefill": true, "supports_computer_use": true, @@ -16312,6 +16305,176 @@ "supports_tool_choice": false, "supports_vision": true }, + "gpt-5.2": { + "cache_read_input_token_cost": 1.75e-07, + "cache_read_input_token_cost_priority": 3.5e-07, + "input_cost_per_token": 1.75e-06, + "input_cost_per_token_priority": 3.5e-06, + "litellm_provider": "openai", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "output_cost_per_token": 1.4e-05, + "output_cost_per_token_priority": 2.8e-05, + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text", + "image" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_service_tier": true, + "supports_vision": true + }, + "gpt-5.2-2025-12-11": { + "cache_read_input_token_cost": 1.75e-07, + "cache_read_input_token_cost_priority": 3.5e-07, + "input_cost_per_token": 1.75e-06, + "input_cost_per_token_priority": 3.5e-06, + "litellm_provider": "openai", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "output_cost_per_token": 1.4e-05, + "output_cost_per_token_priority": 2.8e-05, + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text", + "image" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_service_tier": true, + "supports_vision": true + }, + "gpt-5.2-chat-latest": { + "cache_read_input_token_cost": 1.75e-07, + "cache_read_input_token_cost_priority": 3.5e-07, + "input_cost_per_token": 1.75e-06, + "input_cost_per_token_priority": 3.5e-06, + "litellm_provider": "openai", + "max_input_tokens": 128000, + "max_output_tokens": 16384, + "max_tokens": 16384, + "mode": "chat", + "output_cost_per_token": 1.4e-05, + "output_cost_per_token_priority": 2.8e-05, + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "gpt-5.2-pro": { + "input_cost_per_token": 2.1e-05, + "litellm_provider": "openai", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "output_cost_per_token": 1.68e-04, + "supported_endpoints": [ + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": true, + "supports_web_search": true + }, + "gpt-5.2-pro-2025-12-11": { + "input_cost_per_token": 2.1e-05, + "litellm_provider": "openai", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "output_cost_per_token": 1.68e-04, + "supported_endpoints": [ + "/v1/batch", + "/v1/responses" + ], + "supported_modalities": [ + "text", + "image" + ], + "supported_output_modalities": [ + "text" + ], + "supports_function_calling": true, + "supports_native_streaming": true, + "supports_parallel_function_calling": true, + "supports_pdf_input": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_system_messages": true, + "supports_tool_choice": true, + "supports_vision": true, + "supports_web_search": true + }, "gpt-5-pro": { "input_cost_per_token": 1.5e-05, "input_cost_per_token_batches": 7.5e-06, @@ -18822,6 +18985,20 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "mistral/codestral-2508": { + "input_cost_per_token": 3e-07, + "litellm_provider": "mistral", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "output_cost_per_token": 9e-07, + "source": "https://mistral.ai/news/codestral-25-08", + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, "mistral/codestral-latest": { "input_cost_per_token": 1e-06, "litellm_provider": "mistral", @@ -18888,6 +19065,34 @@ "supports_response_schema": true, "supports_tool_choice": true }, + "mistral/labs-devstral-small-2512": { + "input_cost_per_token": 1e-07, + "litellm_provider": "mistral", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "output_cost_per_token": 3e-07, + "source": "https://docs.mistral.ai/models/devstral-small-2-25-12", + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "mistral/devstral-2512": { + "input_cost_per_token": 4e-07, + "litellm_provider": "mistral", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "chat", + "output_cost_per_token": 2e-06, + "source": "https://mistral.ai/news/devstral-2-vibe-cli", + "supports_assistant_prefill": true, + "supports_function_calling": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, "mistral/magistral-medium-2506": { "input_cost_per_token": 2e-06, "litellm_provider": "mistral", From cf83200dca7c6b5a7b123673b15948369ae3ee40 Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Fri, 12 Dec 2025 01:13:00 -0500 Subject: [PATCH 7/9] Keep running after adding test and lint results to chat so agent can auto fix it --- aider/coders/base_coder.py | 4 +++- aider/commands.py | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index a35be3f4d45..bb93144d09e 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -1521,7 +1521,9 @@ async def run_one(self, user_message, preproc): else: message = user_message - if self.commands.is_command(user_message): + if self.commands.is_command(user_message) and not self.commands.is_test_command( + user_message + ): return while True: diff --git a/aider/commands.py b/aider/commands.py index 7162be45d08..ea4d0a0f663 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -301,7 +301,12 @@ def is_command(self, inp): return inp[0] in "/!" def is_run_command(self, inp): - return inp and (inp[0] in "!" or inp[:5] == "/test" or inp[:4] == "/run") + return inp and ( + inp[0] in "!" or inp[:5] == "/lint" or inp[:5] == "/test" or inp[:4] == "/run" + ) + + def is_test_command(self, inp): + return inp and (inp[:5] == "/lint" or inp[:5] == "/test") def get_raw_completions(self, cmd): assert cmd.startswith("/") From 0511235a37ca01da93ced49627a9e8ba8a764ffc Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Fri, 12 Dec 2025 01:27:04 -0500 Subject: [PATCH 8/9] #253: Make sure new coder classes recieve an args object --- aider/coders/base_coder.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index bb93144d09e..2bea2b0f224 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -183,6 +183,9 @@ async def create( io = from_coder.io if from_coder: + if not args: + args = from_coder.args + use_kwargs = dict(from_coder.original_kwargs) # copy orig kwargs # If the edit format changes, we can't leave old ASSISTANT From 26fb85dfd67b3527d59ac3696d0e1ee45fdc2eae Mon Sep 17 00:00:00 2001 From: Dustin Washington Date: Fri, 12 Dec 2025 01:36:57 -0500 Subject: [PATCH 9/9] Spelling mistake, how embarassing --- aider/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aider/main.py b/aider/main.py index ef7313e4b52..5ab643b759f 100644 --- a/aider/main.py +++ b/aider/main.py @@ -1,7 +1,7 @@ import os try: - if not os.environ["CECLI_DEFAULT_TLS"] or os.environ["SIDER_CE_DEFAULT_TLS"]: + if not os.environ["CECLI_DEFAULT_TLS"] or os.environ["AIDER_CE_DEFAULT_TLS"]: import truststore truststore.inject_into_ssl()