From c980fd0e775e2d61d4bd88f7cc85f29717b0d1e6 Mon Sep 17 00:00:00 2001
From: Jon Keys
Date: Tue, 25 Feb 2025 18:26:36 -0800
Subject: [PATCH 001/482] use playwright if available when invoking scraper via
cli
---
aider/gui.py | 4 ++--
aider/scrape.py | 14 ++++++++++++--
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/aider/gui.py b/aider/gui.py
index 7fa90bc38..6c5b012dc 100755
--- a/aider/gui.py
+++ b/aider/gui.py
@@ -11,7 +11,7 @@ from aider.coders import Coder
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.main import main as cli_main
-from aider.scrape import Scraper
+from aider.scrape import Scraper, has_playwright
class CaptureIO(InputOutput):
@@ -484,7 +484,7 @@ class GUI:
url = self.web_content
if not self.state.scraper:
- self.scraper = Scraper(print_error=self.info)
+ self.scraper = Scraper(print_error=self.info, playwright_available=has_playwright())
content = self.scraper.scrape(url) or ""
if content.strip():
diff --git a/aider/scrape.py b/aider/scrape.py
index 7977a8548..04e44bc81 100755
--- a/aider/scrape.py
+++ b/aider/scrape.py
@@ -14,7 +14,7 @@ aider_user_agent = f"Aider/{__version__} +{urls.website}"
# platforms.
-def install_playwright(io):
+def check_env():
try:
from playwright.sync_api import sync_playwright
@@ -29,6 +29,16 @@ def install_playwright(io):
except Exception:
has_chromium = False
+ return has_pip, has_chromium
+
+
+def has_playwright():
+ has_pip, has_chromium = check_env()
+ return has_pip and has_chromium
+
+
+def install_playwright(io):
+ has_pip, has_chromium = check_env()
if has_pip and has_chromium:
return True
@@ -261,7 +271,7 @@ def slimdown_html(soup):
def main(url):
- scraper = Scraper()
+ scraper = Scraper(playwright_available=has_playwright())
content = scraper.scrape(url)
print(content)
From c1b2ff20de98236c3f2bff4af578619eec1003a2 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:02:19 +0700
Subject: [PATCH 002/482] feat: Add method to fetch model info from openrouter
pages
---
aider/models.py | 45 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 42 insertions(+), 3 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index cc54f03d3..8289a424a 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -211,7 +211,7 @@ class ModelInfoManager:
def get_model_info(self, model):
cached_info = self.get_model_from_cached_json_db(model)
-
+
litellm_info = None
if litellm._lazy_module or not cached_info:
try:
@@ -219,13 +219,52 @@ class ModelInfoManager:
except Exception as ex:
if "model_prices_and_context_window.json" not in str(ex):
print(str(ex))
-
+
if litellm_info:
return litellm_info
-
+
+ if not cached_info and model.startswith("openrouter/"):
+ openrouter_info = self.fetch_openrouter_model_info(model)
+ if openrouter_info:
+ return openrouter_info
+
return cached_info
+ def fetch_openrouter_model_info(self, model):
+ """
+ Fetch model info by scraping the openrouter model page.
+ Expected URL: https://openrouter.ai/
+ Example: openrouter/qwen/qwen-2.5-72b-instruct:free
+ Returns a dict with keys: max_input_tokens, input_cost, output_cost.
+ """
+ url_part = model[len("openrouter/"):]
+ url = "https://openrouter.ai/" + url_part
+ import requests
+ try:
+ response = requests.get(url, timeout=5)
+ if response.status_code != 200:
+ return {}
+ html = response.text
+ from bs4 import BeautifulSoup
+ soup = BeautifulSoup(html, "html.parser")
+ text = soup.get_text()
+ import re
+ context_match = re.search(r"([\d,]+)\s*context", text)
+ if context_match:
+ context_str = context_match.group(1).replace(",", "")
+ context_size = int(context_str)
+ else:
+ context_size = None
+ input_cost_match = re.search(r"\$\s*0\s*/M input tokens", text, re.IGNORECASE)
+ output_cost_match = re.search(r"\$\s*0\s*/M output tokens", text, re.IGNORECASE)
+ input_cost = 0 if input_cost_match else None
+ output_cost = 0 if output_cost_match else None
+ return {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
+ except Exception as e:
+ print("Error fetching openrouter info:", str(e))
+ return {}
+
model_info_manager = ModelInfoManager()
From 4600dbcda5c991b9f630cfd571bb8f884c5e41ab Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:05:55 +0700
Subject: [PATCH 003/482] feat: Print parsed model parameters in
fetch_openrouter_model_info() method
---
aider/models.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index 8289a424a..108dd9a97 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -260,7 +260,9 @@ class ModelInfoManager:
output_cost_match = re.search(r"\$\s*0\s*/M output tokens", text, re.IGNORECASE)
input_cost = 0 if input_cost_match else None
output_cost = 0 if output_cost_match else None
- return {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
+ params = {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
+ print("Parsed model parameters:", params)
+ return params
except Exception as e:
print("Error fetching openrouter info:", str(e))
return {}
From 08d48f42ad6c826ad108d5d3becef2c602c27fe3 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:08:57 +0700
Subject: [PATCH 004/482] refactor: Remove BeautifulSoup dependency and use
regex to strip HTML tags
---
aider/models.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 108dd9a97..28bc05f85 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -246,10 +246,8 @@ class ModelInfoManager:
if response.status_code != 200:
return {}
html = response.text
- from bs4 import BeautifulSoup
- soup = BeautifulSoup(html, "html.parser")
- text = soup.get_text()
import re
+ text = re.sub(r'<[^>]+>', ' ', html)
context_match = re.search(r"([\d,]+)\s*context", text)
if context_match:
context_str = context_match.group(1).replace(",", "")
From 5e48f6898d17163e94a30c15df4507a6c23711cb Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:10:23 +0700
Subject: [PATCH 005/482] fix: Improve print statement to include model name in
parameters output
---
aider/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index 28bc05f85..fbe6ed181 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -259,7 +259,7 @@ class ModelInfoManager:
input_cost = 0 if input_cost_match else None
output_cost = 0 if output_cost_match else None
params = {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
- print("Parsed model parameters:", params)
+ print(f"Model '{model}': Parsed parameters: {params}")
return params
except Exception as e:
print("Error fetching openrouter info:", str(e))
From 44e5525e6f46f04b020b3feea19b63669d214dd7 Mon Sep 17 00:00:00 2001
From: Stefan Hladnik
Date: Tue, 18 Mar 2025 03:17:56 +0700
Subject: [PATCH 006/482] style: Remove unnecessary blank lines in
ModelInfoManager class
---
aider/models.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index fbe6ed181..1bf2168b6 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -211,7 +211,7 @@ class ModelInfoManager:
def get_model_info(self, model):
cached_info = self.get_model_from_cached_json_db(model)
-
+
litellm_info = None
if litellm._lazy_module or not cached_info:
try:
@@ -219,15 +219,15 @@ class ModelInfoManager:
except Exception as ex:
if "model_prices_and_context_window.json" not in str(ex):
print(str(ex))
-
+
if litellm_info:
return litellm_info
-
+
if not cached_info and model.startswith("openrouter/"):
openrouter_info = self.fetch_openrouter_model_info(model)
if openrouter_info:
return openrouter_info
-
+
return cached_info
@@ -264,7 +264,7 @@ class ModelInfoManager:
except Exception as e:
print("Error fetching openrouter info:", str(e))
return {}
-
+
model_info_manager = ModelInfoManager()
From 2651d9967681accad317e1b7023a7303e20c1a0a Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:17:57 +0700
Subject: [PATCH 007/482] feat: Update cost extraction to capture non-zero
input/output costs
---
aider/models.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 1bf2168b6..53b99c772 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -254,10 +254,10 @@ class ModelInfoManager:
context_size = int(context_str)
else:
context_size = None
- input_cost_match = re.search(r"\$\s*0\s*/M input tokens", text, re.IGNORECASE)
- output_cost_match = re.search(r"\$\s*0\s*/M output tokens", text, re.IGNORECASE)
- input_cost = 0 if input_cost_match else None
- output_cost = 0 if output_cost_match else None
+ input_cost_match = re.search(r"\$\s*([\d.]+)\s*/M input tokens", text, re.IGNORECASE)
+ output_cost_match = re.search(r"\$\s*([\d.]+)\s*/M output tokens", text, re.IGNORECASE)
+ input_cost = float(input_cost_match.group(1)) if input_cost_match else None
+ output_cost = float(output_cost_match.group(1)) if output_cost_match else None
params = {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
print(f"Model '{model}': Parsed parameters: {params}")
return params
From 29587cd07cc824ce2795f9b255540dd4c7f66575 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:24:04 +0700
Subject: [PATCH 008/482] fix: Update return keys in
fetch_openrouter_model_info() to match JSON metadata
---
aider/models.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 53b99c772..1ca6276fd 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -236,7 +236,7 @@ class ModelInfoManager:
Fetch model info by scraping the openrouter model page.
Expected URL: https://openrouter.ai/
Example: openrouter/qwen/qwen-2.5-72b-instruct:free
- Returns a dict with keys: max_input_tokens, input_cost, output_cost.
+ Returns a dict with keys: max_tokens, max_input_tokens, max_output_tokens, input_cost_per_token, output_cost_per_token.
"""
url_part = model[len("openrouter/"):]
url = "https://openrouter.ai/" + url_part
@@ -258,7 +258,13 @@ class ModelInfoManager:
output_cost_match = re.search(r"\$\s*([\d.]+)\s*/M output tokens", text, re.IGNORECASE)
input_cost = float(input_cost_match.group(1)) if input_cost_match else None
output_cost = float(output_cost_match.group(1)) if output_cost_match else None
- params = {"max_input_tokens": context_size, "input_cost": input_cost, "output_cost": output_cost}
+ params = {
+ "max_input_tokens": context_size,
+ "max_tokens": context_size,
+ "max_output_tokens": context_size,
+ "input_cost_per_token": input_cost,
+ "output_cost_per_token": output_cost,
+ }
print(f"Model '{model}': Parsed parameters: {params}")
return params
except Exception as e:
From 4765a90f97722b124ea9166c7442b4baec6d48ef Mon Sep 17 00:00:00 2001
From: Stefan Hladnik
Date: Tue, 18 Mar 2025 03:38:24 +0700
Subject: [PATCH 009/482] fix: Adjust input and output cost calculations to use
million scale
---
aider/models.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 1ca6276fd..3499e7820 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -256,8 +256,8 @@ class ModelInfoManager:
context_size = None
input_cost_match = re.search(r"\$\s*([\d.]+)\s*/M input tokens", text, re.IGNORECASE)
output_cost_match = re.search(r"\$\s*([\d.]+)\s*/M output tokens", text, re.IGNORECASE)
- input_cost = float(input_cost_match.group(1)) if input_cost_match else None
- output_cost = float(output_cost_match.group(1)) if output_cost_match else None
+ input_cost = float(input_cost_match.group(1)) / 1000000 if input_cost_match else None
+ output_cost = float(output_cost_match.group(1)) / 1000000 if output_cost_match else None
params = {
"max_input_tokens": context_size,
"max_tokens": context_size,
From b37773c6300428c5d7ac277f927862431601b01b Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:38:25 +0700
Subject: [PATCH 010/482] style: Update import location and add SSL
verification in fetch_openrouter_model_info()
---
aider/models.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 3499e7820..ed014bb54 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -240,9 +240,9 @@ class ModelInfoManager:
"""
url_part = model[len("openrouter/"):]
url = "https://openrouter.ai/" + url_part
- import requests
try:
- response = requests.get(url, timeout=5)
+ import requests
+ response = requests.get(url, timeout=5, verify=self.verify_ssl)
if response.status_code != 200:
return {}
html = response.text
From 87ccacb99f79aeab6d3747d3b6c05d55377d9e30 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:46:36 +0700
Subject: [PATCH 011/482] fix: Return empty dict if any required parameters are
missing
---
aider/models.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/aider/models.py b/aider/models.py
index ed014bb54..749b2c79c 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -258,6 +258,8 @@ class ModelInfoManager:
output_cost_match = re.search(r"\$\s*([\d.]+)\s*/M output tokens", text, re.IGNORECASE)
input_cost = float(input_cost_match.group(1)) / 1000000 if input_cost_match else None
output_cost = float(output_cost_match.group(1)) / 1000000 if output_cost_match else None
+ if context_size is None or input_cost is None or output_cost is None:
+ return {}
params = {
"max_input_tokens": context_size,
"max_tokens": context_size,
From d64427d726685f8687bd7400041b16fce2170c95 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:49:59 +0700
Subject: [PATCH 012/482] feat: Add error handling for unavailable model in
response text
---
aider/models.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/aider/models.py b/aider/models.py
index 749b2c79c..dc55e0a8a 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -246,6 +246,9 @@ class ModelInfoManager:
if response.status_code != 200:
return {}
html = response.text
+ if f'The model "{url_part}" is not available' in html:
+ print(f"Error: Model '{url_part}' is not available")
+ sys.exit(1)
import re
text = re.sub(r'<[^>]+>', ' ', html)
context_match = re.search(r"([\d,]+)\s*context", text)
From 21cca34392a8bac0bb6ffbc1226a8877578944ad Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:53:27 +0700
Subject: [PATCH 013/482] fix: Allow arbitrary characters in model availability
check regex
---
aider/models.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index dc55e0a8a..fe92e8aa5 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -246,10 +246,10 @@ class ModelInfoManager:
if response.status_code != 200:
return {}
html = response.text
- if f'The model "{url_part}" is not available' in html:
+ import re
+ if re.search(rf'The model\s*.*{re.escape(url_part)}.* is not available', html, re.IGNORECASE):
print(f"Error: Model '{url_part}' is not available")
sys.exit(1)
- import re
text = re.sub(r'<[^>]+>', ' ', html)
context_match = re.search(r"([\d,]+)\s*context", text)
if context_match:
From cdd730e627e7e9f2a18d77e72c96b1600706e6eb Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 03:54:27 +0700
Subject: [PATCH 014/482] feat: Print error message in red for unavailable
models
---
aider/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index fe92e8aa5..f78376948 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -248,7 +248,7 @@ class ModelInfoManager:
html = response.text
import re
if re.search(rf'The model\s*.*{re.escape(url_part)}.* is not available', html, re.IGNORECASE):
- print(f"Error: Model '{url_part}' is not available")
+ print(f"\033[91mError: Model '{url_part}' is not available\033[0m")
sys.exit(1)
text = re.sub(r'<[^>]+>', ' ', html)
context_match = re.search(r"([\d,]+)\s*context", text)
From 7c3d96d0e7a9360f60e4148c585f6553bb73b2c5 Mon Sep 17 00:00:00 2001
From: Stefan Hladnik
Date: Tue, 18 Mar 2025 04:13:40 +0700
Subject: [PATCH 015/482] fix: Remove debug print statement from
ModelInfoManager class
---
aider/models.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index f78376948..a190f5f97 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -270,7 +270,6 @@ class ModelInfoManager:
"input_cost_per_token": input_cost,
"output_cost_per_token": output_cost,
}
- print(f"Model '{model}': Parsed parameters: {params}")
return params
except Exception as e:
print("Error fetching openrouter info:", str(e))
From b3d9e0d1b058da0f9a560e3a6637b0cd446da7d8 Mon Sep 17 00:00:00 2001
From: "Stefan Hladnik (aider)"
Date: Tue, 18 Mar 2025 12:18:48 +0700
Subject: [PATCH 016/482] fix: Return empty dict instead of exiting on model
availability error
---
aider/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index a190f5f97..bc1d54e12 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -249,7 +249,7 @@ class ModelInfoManager:
import re
if re.search(rf'The model\s*.*{re.escape(url_part)}.* is not available', html, re.IGNORECASE):
print(f"\033[91mError: Model '{url_part}' is not available\033[0m")
- sys.exit(1)
+ return {}
text = re.sub(r'<[^>]+>', ' ', html)
context_match = re.search(r"([\d,]+)\s*context", text)
if context_match:
From e980973621da2a20d95b6a477756cb01e3f8cca9 Mon Sep 17 00:00:00 2001
From: Andrey Popp <8mayday@gmail.com>
Date: Sun, 30 Mar 2025 22:09:06 +0400
Subject: [PATCH 017/482] feat: add repomap support for ocaml/ocaml_interface
---
.../tree-sitter-language-pack/ocaml-tags.scm | 115 ++++++++++++++++++
.../ocaml_interface-tags.scm | 98 +++++++++++++++
.../ocaml_interface-tags.scm | 98 +++++++++++++++
tests/basic/test_repomap.py | 9 +-
.../languages/ocaml_interface/test.mli | 14 +++
5 files changed, 332 insertions(+), 2 deletions(-)
create mode 100644 aider/queries/tree-sitter-language-pack/ocaml-tags.scm
create mode 100644 aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm
create mode 100644 aider/queries/tree-sitter-languages/ocaml_interface-tags.scm
create mode 100644 tests/fixtures/languages/ocaml_interface/test.mli
diff --git a/aider/queries/tree-sitter-language-pack/ocaml-tags.scm b/aider/queries/tree-sitter-language-pack/ocaml-tags.scm
new file mode 100644
index 000000000..52d5a857e
--- /dev/null
+++ b/aider/queries/tree-sitter-language-pack/ocaml-tags.scm
@@ -0,0 +1,115 @@
+; Modules
+;--------
+
+(
+ (comment)? @doc .
+ (module_definition (module_binding (module_name) @name.definition.module) @definition.module)
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+(module_path (module_name) @name.reference.module) @reference.module
+
+; Module types
+;--------------
+
+(
+ (comment)? @doc .
+ (module_type_definition (module_type_name) @name.definition.interface) @definition.interface
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+(module_type_path (module_type_name) @name.reference.implementation) @reference.implementation
+
+; Functions
+;----------
+
+(
+ (comment)? @doc .
+ (value_definition
+ [
+ (let_binding
+ pattern: (value_name) @name.definition.function
+ (parameter))
+ (let_binding
+ pattern: (value_name) @name.definition.function
+ body: [(fun_expression) (function_expression)])
+ ] @definition.function
+ )
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+(
+ (comment)? @doc .
+ (external (value_name) @name.definition.function) @definition.function
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+(application_expression
+ function: (value_path (value_name) @name.reference.call)) @reference.call
+
+(infix_expression
+ left: (value_path (value_name) @name.reference.call)
+ operator: (concat_operator) @reference.call
+ (#eq? @reference.call "@@"))
+
+(infix_expression
+ operator: (rel_operator) @reference.call
+ right: (value_path (value_name) @name.reference.call)
+ (#eq? @reference.call "|>"))
+
+; Operator
+;---------
+
+(
+ (comment)? @doc .
+ (value_definition
+ (let_binding
+ pattern: (parenthesized_operator (_) @name.definition.function)) @definition.function)
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+[
+ (prefix_operator)
+ (sign_operator)
+ (pow_operator)
+ (mult_operator)
+ (add_operator)
+ (concat_operator)
+ (rel_operator)
+ (and_operator)
+ (or_operator)
+ (assign_operator)
+ (hash_operator)
+ (indexing_operator)
+ (let_operator)
+ (let_and_operator)
+ (match_operator)
+] @name.reference.call @reference.call
+
+; Classes
+;--------
+
+(
+ (comment)? @doc .
+ [
+ (class_definition (class_binding (class_name) @name.definition.class) @definition.class)
+ (class_type_definition (class_type_binding (class_type_name) @name.definition.class) @definition.class)
+ ]
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+[
+ (class_path (class_name) @name.reference.class)
+ (class_type_path (class_type_name) @name.reference.class)
+] @reference.class
+
+; Methods
+;--------
+
+(
+ (comment)? @doc .
+ (method_definition (method_name) @name.definition.method) @definition.method
+ (#strip! @doc "^\\(\\*\\*?\\s*|\\s\\*\\)$")
+)
+
+(method_invocation (method_name) @name.reference.call) @reference.call
diff --git a/aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm b/aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm
new file mode 100644
index 000000000..d7a8f8b97
--- /dev/null
+++ b/aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm
@@ -0,0 +1,98 @@
+; Modules
+;--------
+
+(
+ (comment)? @doc .
+ (module_definition
+ (module_binding (module_name) @name) @definition.module
+ )
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(module_path (module_name) @name) @reference.module
+(extended_module_path (module_name) @name) @reference.module
+
+(
+ (comment)? @doc .
+ (module_type_definition (module_type_name) @name) @definition.interface
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(module_type_path (module_type_name) @name) @reference.implementation
+
+
+; Classes
+;--------
+
+(
+ (comment)? @doc .
+ [
+ (class_definition
+ (class_binding (class_name) @name) @definition.class
+ )
+ (class_type_definition
+ (class_type_binding (class_type_name) @name) @definition.class
+ )
+ ]
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+[
+ (class_path (class_name) @name)
+ (class_type_path (class_type_name) @name)
+] @reference.class
+
+(
+ (comment)? @doc .
+ (method_definition (method_name) @name) @definition.method
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(method_invocation (method_name) @name) @reference.call
+
+
+; Types
+;------
+
+(
+ (comment)? @doc .
+ (type_definition
+ (type_binding
+ name: [
+ (type_constructor) @name
+ (type_constructor_path (type_constructor) @name)
+ ]
+ ) @definition.type
+ )
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(type_constructor_path (type_constructor) @name) @reference.type
+
+[
+ (constructor_declaration (constructor_name) @name)
+ (tag_specification (tag) @name)
+] @definition.enum_variant
+
+[
+ (constructor_path (constructor_name) @name)
+ (tag) @name
+] @reference.enum_variant
+
+(field_declaration (field_name) @name) @definition.field
+
+(field_path (field_name) @name) @reference.field
+
+(
+ (comment)? @doc .
+ (external (value_name) @name) @definition.function
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(
+ (comment)? @doc .
+ (value_specification
+ (value_name) @name.definition.function
+ ) @definition.function
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
diff --git a/aider/queries/tree-sitter-languages/ocaml_interface-tags.scm b/aider/queries/tree-sitter-languages/ocaml_interface-tags.scm
new file mode 100644
index 000000000..d7a8f8b97
--- /dev/null
+++ b/aider/queries/tree-sitter-languages/ocaml_interface-tags.scm
@@ -0,0 +1,98 @@
+; Modules
+;--------
+
+(
+ (comment)? @doc .
+ (module_definition
+ (module_binding (module_name) @name) @definition.module
+ )
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(module_path (module_name) @name) @reference.module
+(extended_module_path (module_name) @name) @reference.module
+
+(
+ (comment)? @doc .
+ (module_type_definition (module_type_name) @name) @definition.interface
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(module_type_path (module_type_name) @name) @reference.implementation
+
+
+; Classes
+;--------
+
+(
+ (comment)? @doc .
+ [
+ (class_definition
+ (class_binding (class_name) @name) @definition.class
+ )
+ (class_type_definition
+ (class_type_binding (class_type_name) @name) @definition.class
+ )
+ ]
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+[
+ (class_path (class_name) @name)
+ (class_type_path (class_type_name) @name)
+] @reference.class
+
+(
+ (comment)? @doc .
+ (method_definition (method_name) @name) @definition.method
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(method_invocation (method_name) @name) @reference.call
+
+
+; Types
+;------
+
+(
+ (comment)? @doc .
+ (type_definition
+ (type_binding
+ name: [
+ (type_constructor) @name
+ (type_constructor_path (type_constructor) @name)
+ ]
+ ) @definition.type
+ )
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(type_constructor_path (type_constructor) @name) @reference.type
+
+[
+ (constructor_declaration (constructor_name) @name)
+ (tag_specification (tag) @name)
+] @definition.enum_variant
+
+[
+ (constructor_path (constructor_name) @name)
+ (tag) @name
+] @reference.enum_variant
+
+(field_declaration (field_name) @name) @definition.field
+
+(field_path (field_name) @name) @reference.field
+
+(
+ (comment)? @doc .
+ (external (value_name) @name) @definition.function
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
+
+(
+ (comment)? @doc .
+ (value_specification
+ (value_name) @name.definition.function
+ ) @definition.function
+ (#strip! @doc "^\\(\\*+\\s*|\\s*\\*+\\)$")
+)
diff --git a/tests/basic/test_repomap.py b/tests/basic/test_repomap.py
index 17a5753c3..322bac954 100644
--- a/tests/basic/test_repomap.py
+++ b/tests/basic/test_repomap.py
@@ -314,8 +314,6 @@ class TestRepoMapAllLanguages(unittest.TestCase):
def test_language_lua(self):
self._test_language_repo_map("lua", "lua", "greet")
- # "ocaml": ("ml", "Greeter"), # not supported in tsl-pack (yet?)
-
def test_language_php(self):
self._test_language_repo_map("php", "php", "greet")
@@ -384,6 +382,12 @@ class TestRepoMapAllLanguages(unittest.TestCase):
def test_language_scala(self):
self._test_language_repo_map("scala", "scala", "Greeter")
+ def test_language_ocaml(self):
+ self._test_language_repo_map("ocaml", "ml", "Greeter")
+
+ def test_language_ocaml_interface(self):
+ self._test_language_repo_map("ocaml_interface", "mli", "Greeter")
+
def _test_language_repo_map(self, lang, key, symbol):
"""Helper method to test repo map generation for a specific language."""
# Get the fixture file path and name based on language
@@ -407,6 +411,7 @@ class TestRepoMapAllLanguages(unittest.TestCase):
dump(lang)
dump(result)
+ print(result)
self.assertGreater(len(result.strip().splitlines()), 1)
# Check if the result contains all the expected files and symbols
diff --git a/tests/fixtures/languages/ocaml_interface/test.mli b/tests/fixtures/languages/ocaml_interface/test.mli
new file mode 100644
index 000000000..8289f9fc5
--- /dev/null
+++ b/tests/fixtures/languages/ocaml_interface/test.mli
@@ -0,0 +1,14 @@
+(* Module definition *)
+module Greeter : sig
+ type person = {
+ name: string;
+ age: int
+ }
+
+ val create_person : string -> int -> person
+
+ val greet : person -> unit
+end
+
+(* Outside the module *)
+val main : unit -> unit
From 67bb4f95524d1d4d47cf55f17be2189626784569 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 16:52:45 +0300
Subject: [PATCH 018/482] feat: add co-authored-by commit attribution
---
aider/args.py | 6 +++
aider/coders/base_coder.py | 4 +-
aider/repo.py | 76 +++++++++++++++++++++++++++++++-------
3 files changed, 70 insertions(+), 16 deletions(-)
diff --git a/aider/args.py b/aider/args.py
index 6df19778b..4f91a9cbd 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -448,6 +448,12 @@ def get_parser(default_config_files, git_root):
default=False,
help="Prefix all commit messages with 'aider: ' (default: False)",
)
+ group.add_argument(
+ "--attribute-co-authored-by",
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help="Attribute aider edits using the Co-authored-by trailer in the commit message (default: False).",
+ )
group.add_argument(
"--git-commit-verify",
action=argparse.BooleanOptionalAction,
diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py
index 19d375afb..5c64475eb 100755
--- a/aider/coders/base_coder.py
+++ b/aider/coders/base_coder.py
@@ -2248,7 +2248,7 @@ class Coder:
context = self.get_context_from_history(self.cur_messages)
try:
- res = self.repo.commit(fnames=edited, context=context, aider_edits=True)
+ res = self.repo.commit(fnames=edited, context=context, aider_edits=True, coder=self)
if res:
self.show_auto_commit_outcome(res)
commit_hash, commit_message = res
@@ -2284,7 +2284,7 @@ class Coder:
if not self.repo:
return
- self.repo.commit(fnames=self.need_commit_before_edits)
+ self.repo.commit(fnames=self.need_commit_before_edits, coder=self)
# files changed, move cur messages back behind the files messages
# self.move_back_cur_messages(self.gpt_prompts.files_content_local_edits)
diff --git a/aider/repo.py b/aider/repo.py
index 5ece5147c..999a07269 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -111,7 +111,7 @@ class GitRepo:
if aider_ignore_file:
self.aider_ignore_file = Path(aider_ignore_file)
- def commit(self, fnames=None, context=None, message=None, aider_edits=False):
+ def commit(self, fnames=None, context=None, message=None, aider_edits=False, coder=None):
if not fnames and not self.repo.is_dirty():
return
@@ -124,15 +124,52 @@ class GitRepo:
else:
commit_message = self.get_commit_message(diffs, context)
- if aider_edits and self.attribute_commit_message_author:
- commit_message = "aider: " + commit_message
- elif self.attribute_commit_message_committer:
- commit_message = "aider: " + commit_message
+ commit_message_trailer = ""
+ if aider_edits:
+ # Use coder.args if available, otherwise default to config/defaults
+ attribute_author = (
+ coder.args.attribute_author
+ if coder and hasattr(coder, "args")
+ else self.attribute_author
+ )
+ attribute_committer = (
+ coder.args.attribute_committer
+ if coder and hasattr(coder, "args")
+ else self.attribute_committer
+ )
+ attribute_commit_message_author = (
+ coder.args.attribute_commit_message_author
+ if coder and hasattr(coder, "args")
+ else self.attribute_commit_message_author
+ )
+ attribute_commit_message_committer = (
+ coder.args.attribute_commit_message_committer
+ if coder and hasattr(coder, "args")
+ else self.attribute_commit_message_committer
+ )
+ attribute_co_authored_by = (
+ coder.args.attribute_co_authored_by
+ if coder and hasattr(coder, "args")
+ else False # Default to False if not found
+ )
+
+ # Add Co-authored-by trailer if configured
+ if attribute_co_authored_by:
+ model_name = "unknown-model"
+ if coder and hasattr(coder, "main_model") and coder.main_model.name:
+ model_name = coder.main_model.name
+ commit_message_trailer = (
+ f"\n\nCo-authored-by: aider ({model_name}) "
+ )
+
+ # Prefix commit message if configured
+ if attribute_commit_message_author or attribute_commit_message_committer:
+ commit_message = "aider: " + commit_message
if not commit_message:
commit_message = "(no commit message provided)"
- full_commit_message = commit_message
+ full_commit_message = commit_message + commit_message_trailer
# if context:
# full_commit_message += "\n\n# Aider chat conversation:\n\n" + context
@@ -152,13 +189,25 @@ class GitRepo:
original_user_name = self.repo.git.config("--get", "user.name")
original_committer_name_env = os.environ.get("GIT_COMMITTER_NAME")
+ original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
committer_name = f"{original_user_name} (aider)"
- if self.attribute_committer:
+ # Use coder.args if available, otherwise default to config/defaults
+ use_attribute_committer = (
+ coder.args.attribute_committer
+ if coder and hasattr(coder, "args")
+ else self.attribute_committer
+ )
+ use_attribute_author = (
+ coder.args.attribute_author
+ if coder and hasattr(coder, "args")
+ else self.attribute_author
+ )
+
+ if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name
- if aider_edits and self.attribute_author:
- original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
+ if aider_edits and use_attribute_author:
os.environ["GIT_AUTHOR_NAME"] = committer_name
try:
@@ -170,17 +219,16 @@ class GitRepo:
self.io.tool_error(f"Unable to commit: {err}")
finally:
# Restore the env
-
- if self.attribute_committer:
+ if use_attribute_committer:
if original_committer_name_env is not None:
os.environ["GIT_COMMITTER_NAME"] = original_committer_name_env
- else:
+ elif "GIT_COMMITTER_NAME" in os.environ:
del os.environ["GIT_COMMITTER_NAME"]
- if aider_edits and self.attribute_author:
+ if aider_edits and use_attribute_author:
if original_author_name_env is not None:
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
- else:
+ elif "GIT_AUTHOR_NAME" in os.environ:
del os.environ["GIT_AUTHOR_NAME"]
def get_rel_repo_dir(self):
From b6b8f30378cae0cab844989142eec5efb39f6554 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 16:57:21 +0300
Subject: [PATCH 019/482] test: add tests for co-authored-by commit attribution
---
tests/basic/test_repo.py | 83 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 82 insertions(+), 1 deletion(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index aa863c570..7e288e063 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -4,7 +4,7 @@ import tempfile
import time
import unittest
from pathlib import Path
-from unittest.mock import patch
+from unittest.mock import MagicMock, patch
import git
@@ -211,6 +211,87 @@ class TestRepo(unittest.TestCase):
original_author_name = os.environ.get("GIT_AUTHOR_NAME")
self.assertIsNone(original_author_name)
+ def test_commit_with_co_authored_by(self):
+ # Cleanup of the git temp dir explodes on windows
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # new repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+
+ # add a file and commit it
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ # Mock coder args
+ mock_coder = MagicMock()
+ mock_coder.args.attribute_co_authored_by = True
+ mock_coder.args.attribute_author = None # Explicitly None to test override
+ mock_coder.args.attribute_committer = None # Explicitly None to test override
+ mock_coder.args.attribute_commit_message_author = False
+ mock_coder.args.attribute_commit_message_committer = False
+ mock_coder.model.name = "gpt-test"
+
+ io = InputOutput()
+ git_repo = GitRepo(io, None, None)
+
+ # commit a change with aider_edits=True and co-authored-by flag
+ fname.write_text("new content")
+ git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+
+ # check the commit message and author/committer
+ commit = raw_repo.head.commit
+ self.assertIn("Co-authored-by: aider (gpt-test) ", commit.message)
+ self.assertEqual(commit.message.splitlines()[0], "Aider edit")
+ self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
+ self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
+
+ def test_commit_without_co_authored_by(self):
+ # Cleanup of the git temp dir explodes on windows
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # new repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+
+ # add a file and commit it
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ # Mock coder args (default behavior)
+ mock_coder = MagicMock()
+ mock_coder.args.attribute_co_authored_by = False
+ mock_coder.args.attribute_author = True
+ mock_coder.args.attribute_committer = True
+ mock_coder.args.attribute_commit_message_author = False
+ mock_coder.args.attribute_commit_message_committer = False
+ mock_coder.model.name = "gpt-test"
+
+ io = InputOutput()
+ git_repo = GitRepo(io, None, None)
+
+ # commit a change with aider_edits=True and default flags
+ fname.write_text("new content")
+ git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+
+ # check the commit message and author/committer
+ commit = raw_repo.head.commit
+ self.assertNotIn("Co-authored-by:", commit.message)
+ self.assertEqual(commit.message.splitlines()[0], "Aider edit")
+ self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified
+
+
def test_get_tracked_files(self):
# Create a temporary directory
tempdir = Path(tempfile.mkdtemp())
From eb28e228913fdc0c90b62168bb4b57475a91e22c Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:07:41 +0300
Subject: [PATCH 020/482] test: fix mock setup for model name in co-authored-by
test
---
tests/basic/test_repo.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 7e288e063..4ff694714 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -235,7 +235,9 @@ class TestRepo(unittest.TestCase):
mock_coder.args.attribute_committer = None # Explicitly None to test override
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- mock_coder.model.name = "gpt-test"
+ # Set the model name correctly on the nested mock
+ mock_coder.model = MagicMock(name="gpt-test")
+
io = InputOutput()
git_repo = GitRepo(io, None, None)
From 192f8bec26ca0348cf43b1ec7bf00ac7e459f565 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:09:12 +0300
Subject: [PATCH 021/482] test: fix mock model name setup in co-authored-by
test
---
tests/basic/test_repo.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 4ff694714..d0441a4da 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -236,7 +236,8 @@ class TestRepo(unittest.TestCase):
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
# Set the model name correctly on the nested mock
- mock_coder.model = MagicMock(name="gpt-test")
+ mock_coder.model = MagicMock()
+ mock_coder.model.configure_mock(name="gpt-test")
io = InputOutput()
From a5327af5e9ef31b68a4345a6679b66b72a9c09fc Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:12:30 +0300
Subject: [PATCH 022/482] test: fix mock setup for co-authored-by commit test
---
tests/basic/test_repo.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index d0441a4da..631e6f606 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -236,8 +236,9 @@ class TestRepo(unittest.TestCase):
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
# Set the model name correctly on the nested mock
- mock_coder.model = MagicMock()
- mock_coder.model.configure_mock(name="gpt-test")
+ # The code uses coder.main_model.name for the co-authored-by line
+ mock_coder.main_model = MagicMock()
+ mock_coder.main_model.name = "gpt-test"
io = InputOutput()
From b22c9b8542cda2a5e45df0a919039d484378d2b9 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:32:15 +0300
Subject: [PATCH 023/482] feat: implement Co-authored-by attribution option
---
aider/repo.py | 74 ++++++++++++++++++++--------------------
tests/basic/test_repo.py | 55 +++++++++++++++++++++++++++--
2 files changed, 89 insertions(+), 40 deletions(-)
diff --git a/aider/repo.py b/aider/repo.py
index 999a07269..efa0fda8c 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -125,7 +125,41 @@ class GitRepo:
commit_message = self.get_commit_message(diffs, context)
commit_message_trailer = ""
+ attribute_author = self.attribute_author
+ attribute_committer = self.attribute_committer
+ attribute_commit_message_author = self.attribute_commit_message_author
+ attribute_commit_message_committer = self.attribute_commit_message_committer
+ attribute_co_authored_by = False # Default if coder or args not available
+
+ if coder and hasattr(coder, "args"):
+ attribute_author = coder.args.attribute_author
+ attribute_committer = coder.args.attribute_committer
+ attribute_commit_message_author = coder.args.attribute_commit_message_author
+ attribute_commit_message_committer = coder.args.attribute_commit_message_committer
+ attribute_co_authored_by = coder.args.attribute_co_authored_by
+
if aider_edits:
+ # Add Co-authored-by trailer if configured
+ if attribute_co_authored_by:
+ model_name = "unknown-model"
+ if coder and hasattr(coder, "main_model") and coder.main_model.name:
+ model_name = coder.main_model.name
+ commit_message_trailer = (
+ f"\n\nCo-authored-by: aider ({model_name}) "
+ )
+
+ # Prefix commit message if configured
+ if attribute_commit_message_author or attribute_commit_message_committer:
+ commit_message = "aider: " + commit_message
+
+ # Prepare author/committer modification flags (used later)
+ use_attribute_author = attribute_author
+ use_attribute_committer = attribute_committer
+ else:
+ # Don't modify author/committer/message for non-aider edits
+ use_attribute_author = False
+ use_attribute_committer = self.attribute_committer # Keep committer modification for non-aider edits if configured
+
# Use coder.args if available, otherwise default to config/defaults
attribute_author = (
coder.args.attribute_author
@@ -143,29 +177,6 @@ class GitRepo:
else self.attribute_commit_message_author
)
attribute_commit_message_committer = (
- coder.args.attribute_commit_message_committer
- if coder and hasattr(coder, "args")
- else self.attribute_commit_message_committer
- )
- attribute_co_authored_by = (
- coder.args.attribute_co_authored_by
- if coder and hasattr(coder, "args")
- else False # Default to False if not found
- )
-
- # Add Co-authored-by trailer if configured
- if attribute_co_authored_by:
- model_name = "unknown-model"
- if coder and hasattr(coder, "main_model") and coder.main_model.name:
- model_name = coder.main_model.name
- commit_message_trailer = (
- f"\n\nCo-authored-by: aider ({model_name}) "
- )
-
- # Prefix commit message if configured
- if attribute_commit_message_author or attribute_commit_message_committer:
- commit_message = "aider: " + commit_message
-
if not commit_message:
commit_message = "(no commit message provided)"
@@ -192,22 +203,11 @@ class GitRepo:
original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
committer_name = f"{original_user_name} (aider)"
- # Use coder.args if available, otherwise default to config/defaults
- use_attribute_committer = (
- coder.args.attribute_committer
- if coder and hasattr(coder, "args")
- else self.attribute_committer
- )
- use_attribute_author = (
- coder.args.attribute_author
- if coder and hasattr(coder, "args")
- else self.attribute_author
- )
-
+ # Apply author/committer modifications based on flags determined earlier
if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name
- if aider_edits and use_attribute_author:
+ if use_attribute_author: # Already checks for aider_edits implicitly
os.environ["GIT_AUTHOR_NAME"] = committer_name
try:
@@ -225,7 +225,7 @@ class GitRepo:
elif "GIT_COMMITTER_NAME" in os.environ:
del os.environ["GIT_COMMITTER_NAME"]
- if aider_edits and use_attribute_author:
+ if use_attribute_author: # Already checks for aider_edits implicitly
if original_author_name_env is not None:
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
elif "GIT_AUTHOR_NAME" in os.environ:
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 631e6f606..945de84f8 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -229,10 +229,11 @@ class TestRepo(unittest.TestCase):
raw_repo.git.commit("-m", "initial commit")
# Mock coder args
+ # Mock coder args: Co-authored-by enabled, author/committer modification disabled
mock_coder = MagicMock()
mock_coder.args.attribute_co_authored_by = True
- mock_coder.args.attribute_author = None # Explicitly None to test override
- mock_coder.args.attribute_committer = None # Explicitly None to test override
+ mock_coder.args.attribute_author = False # Explicitly disable name modification
+ mock_coder.args.attribute_committer = False # Explicitly disable name modification
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
# Set the model name correctly on the nested mock
@@ -255,6 +256,51 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
+ def test_commit_with_co_authored_by_and_name_modification(self):
+ # Test scenario where Co-authored-by is true AND author/committer modification is also true (default)
+ # Cleanup of the git temp dir explodes on windows
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # new repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+
+ # add a file and commit it
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ # Mock coder args: Co-authored-by enabled, author/committer modification enabled (default)
+ mock_coder = MagicMock()
+ mock_coder.args.attribute_co_authored_by = True
+ mock_coder.args.attribute_author = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_committer = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_commit_message_author = False
+ mock_coder.args.attribute_commit_message_committer = False
+ # Set the model name correctly on the nested mock
+ mock_coder.main_model = MagicMock()
+ mock_coder.main_model.name = "gpt-test-combo"
+
+
+ io = InputOutput()
+ git_repo = GitRepo(io, None, None)
+
+ # commit a change with aider_edits=True and combo flags
+ fname.write_text("new content combo")
+ git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider combo edit")
+
+ # check the commit message and author/committer
+ commit = raw_repo.head.commit
+ self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
+ self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
+ self.assertEqual(commit.author.name, "Test User (aider)") # Should BE modified
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Should BE modified
+
+
def test_commit_without_co_authored_by(self):
# Cleanup of the git temp dir explodes on windows
if platform.system() == "Windows":
@@ -279,7 +325,10 @@ class TestRepo(unittest.TestCase):
mock_coder.args.attribute_committer = True
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- mock_coder.model.name = "gpt-test"
+ # Set the model name correctly on the nested mock (though not used in this test assertion)
+ mock_coder.main_model = MagicMock()
+ mock_coder.main_model.name = "gpt-test-no-coauthor"
+
io = InputOutput()
git_repo = GitRepo(io, None, None)
From c73b987cd099cc73e1be17d3084df444b1e70491 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:32:57 +0300
Subject: [PATCH 024/482] fix: fix syntax error in commit logic
---
aider/repo.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/aider/repo.py b/aider/repo.py
index efa0fda8c..5ad84d36d 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -177,6 +177,10 @@ class GitRepo:
else self.attribute_commit_message_author
)
attribute_commit_message_committer = (
+ coder.args.attribute_commit_message_committer
+ if coder and hasattr(coder, "args")
+ else self.attribute_commit_message_committer
+ )
if not commit_message:
commit_message = "(no commit message provided)"
From e9511643998d4868bc261b3ec0479e6a2a362b3a Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:35:45 +0300
Subject: [PATCH 025/482] chore: Add test comment to dump function
---
aider/dump.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/dump.py b/aider/dump.py
index 2c8bf31c2..6098d0b73 100644
--- a/aider/dump.py
+++ b/aider/dump.py
@@ -12,6 +12,7 @@ def cvt(s):
def dump(*vals):
+ # This is a test comment
# http://docs.python.org/library/traceback.html
stack = traceback.extract_stack()
vars = stack[-2][3]
From 482e0c2d0b5cdfe60281f13bab2ead4aa540e9e6 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:37:00 +0300
Subject: [PATCH 026/482] chore: Add test comment
---
aider/prompts.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/prompts.py b/aider/prompts.py
index 84ed75e9b..1dacf10d0 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -1,5 +1,6 @@
# flake8: noqa: E501
+# This is a test comment.
# COMMIT
From 4783ad3a73530c174f664505b65fe2e587ef27aa Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:39:49 +0300
Subject: [PATCH 027/482] feat: add attribute-co-authored-by option for commit
attribution
---
aider/args.py | 2 +-
aider/repo.py | 83 +++++++++++++++++++++++----------------------------
2 files changed, 38 insertions(+), 47 deletions(-)
diff --git a/aider/args.py b/aider/args.py
index 4f91a9cbd..3571faa5e 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -428,7 +428,7 @@ def get_parser(default_config_files, git_root):
"--attribute-author",
action=argparse.BooleanOptionalAction,
default=True,
- help="Attribute aider code changes in the git author name (default: True)",
+ help="Attribute aider code changes in the git author name (default: True, ignored if attribute-co-authored-by is True unless explicitly set)",
)
group.add_argument(
"--attribute-committer",
diff --git a/aider/repo.py b/aider/repo.py
index 5ad84d36d..e0bcef2de 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -69,6 +69,8 @@ class GitRepo:
self.attribute_committer = attribute_committer
self.attribute_commit_message_author = attribute_commit_message_author
self.attribute_commit_message_committer = attribute_commit_message_committer
+ # Ensure attribute_co_authored_by is initialized, default to False if not provided
+ self.attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
self.commit_prompt = commit_prompt
self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify
@@ -124,66 +126,56 @@ class GitRepo:
else:
commit_message = self.get_commit_message(diffs, context)
- commit_message_trailer = ""
- attribute_author = self.attribute_author
- attribute_committer = self.attribute_committer
- attribute_commit_message_author = self.attribute_commit_message_author
- attribute_commit_message_committer = self.attribute_commit_message_committer
- attribute_co_authored_by = False # Default if coder or args not available
-
+ # Retrieve attribute settings, prioritizing coder.args if available
if coder and hasattr(coder, "args"):
attribute_author = coder.args.attribute_author
attribute_committer = coder.args.attribute_committer
attribute_commit_message_author = coder.args.attribute_commit_message_author
attribute_commit_message_committer = coder.args.attribute_commit_message_committer
attribute_co_authored_by = coder.args.attribute_co_authored_by
+ else:
+ # Fallback to self attributes (initialized from config/defaults)
+ attribute_author = self.attribute_author
+ attribute_committer = self.attribute_committer
+ attribute_commit_message_author = self.attribute_commit_message_author
+ attribute_commit_message_committer = self.attribute_commit_message_committer
+ attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
+
+ commit_message_trailer = ""
+ prefix_commit_message = False
+ use_attribute_author = False
+ use_attribute_committer = False
if aider_edits:
- # Add Co-authored-by trailer if configured
+ # Determine commit message prefixing
+ if attribute_commit_message_author or attribute_commit_message_committer:
+ prefix_commit_message = True
+
+ # Determine author/committer modification and trailer
if attribute_co_authored_by:
model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name
- commit_message_trailer = (
- f"\n\nCo-authored-by: aider ({model_name}) "
- )
-
- # Prefix commit message if configured
- if attribute_commit_message_author or attribute_commit_message_committer:
- commit_message = "aider: " + commit_message
-
- # Prepare author/committer modification flags (used later)
- use_attribute_author = attribute_author
- use_attribute_committer = attribute_committer
- else:
- # Don't modify author/committer/message for non-aider edits
+ commit_message_trailer = f"\n\nCo-authored-by: aider ({model_name}) "
+ # Only modify author/committer if explicitly requested alongside co-authored-by
+ use_attribute_author = attribute_author
+ use_attribute_committer = attribute_committer
+ else:
+ # Original behavior when co-authored-by is false
+ use_attribute_author = attribute_author
+ use_attribute_committer = attribute_committer
+ else: # not aider_edits
+ # Keep original behavior for non-aider edits
use_attribute_author = False
- use_attribute_committer = self.attribute_committer # Keep committer modification for non-aider edits if configured
+ use_attribute_committer = attribute_committer # Respect config for committer
+ prefix_commit_message = False # Don't prefix non-aider commits
- # Use coder.args if available, otherwise default to config/defaults
- attribute_author = (
- coder.args.attribute_author
- if coder and hasattr(coder, "args")
- else self.attribute_author
- )
- attribute_committer = (
- coder.args.attribute_committer
- if coder and hasattr(coder, "args")
- else self.attribute_committer
- )
- attribute_commit_message_author = (
- coder.args.attribute_commit_message_author
- if coder and hasattr(coder, "args")
- else self.attribute_commit_message_author
- )
- attribute_commit_message_committer = (
- coder.args.attribute_commit_message_committer
- if coder and hasattr(coder, "args")
- else self.attribute_commit_message_committer
- )
if not commit_message:
commit_message = "(no commit message provided)"
+ if prefix_commit_message:
+ commit_message = "aider: " + commit_message
+
full_commit_message = commit_message + commit_message_trailer
# if context:
# full_commit_message += "\n\n# Aider chat conversation:\n\n" + context
@@ -210,8 +202,7 @@ class GitRepo:
# Apply author/committer modifications based on flags determined earlier
if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name
-
- if use_attribute_author: # Already checks for aider_edits implicitly
+ if use_attribute_author:
os.environ["GIT_AUTHOR_NAME"] = committer_name
try:
@@ -229,7 +220,7 @@ class GitRepo:
elif "GIT_COMMITTER_NAME" in os.environ:
del os.environ["GIT_COMMITTER_NAME"]
- if use_attribute_author: # Already checks for aider_edits implicitly
+ if use_attribute_author:
if original_author_name_env is not None:
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
elif "GIT_AUTHOR_NAME" in os.environ:
From 43cb4d68f7b6a31beddf130b9b09c5c448221005 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:45:48 +0300
Subject: [PATCH 028/482] test: Temporarily disable co-author attribution to
verify test failure
---
aider/repo.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/repo.py b/aider/repo.py
index e0bcef2de..aa6cffb4f 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -132,7 +132,7 @@ class GitRepo:
attribute_committer = coder.args.attribute_committer
attribute_commit_message_author = coder.args.attribute_commit_message_author
attribute_commit_message_committer = coder.args.attribute_commit_message_committer
- attribute_co_authored_by = coder.args.attribute_co_authored_by
+ # attribute_co_authored_by = coder.args.attribute_co_authored_by # <-- Intentionally commented out for testing
else:
# Fallback to self attributes (initialized from config/defaults)
attribute_author = self.attribute_author
From dede701423342f2dd40d1493c21874e92111a4ba Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:47:20 +0300
Subject: [PATCH 029/482] test: intentionally break co-authored-by logic
---
aider/repo.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/aider/repo.py b/aider/repo.py
index aa6cffb4f..4ba96d920 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -132,7 +132,7 @@ class GitRepo:
attribute_committer = coder.args.attribute_committer
attribute_commit_message_author = coder.args.attribute_commit_message_author
attribute_commit_message_committer = coder.args.attribute_commit_message_committer
- # attribute_co_authored_by = coder.args.attribute_co_authored_by # <-- Intentionally commented out for testing
+ attribute_co_authored_by = coder.args.attribute_co_authored_by # <-- Restored
else:
# Fallback to self attributes (initialized from config/defaults)
attribute_author = self.attribute_author
@@ -152,7 +152,13 @@ class GitRepo:
prefix_commit_message = True
# Determine author/committer modification and trailer
- if attribute_co_authored_by:
+
+ # --- Intentionally break the behavior for testing ---
+ original_attribute_co_authored_by = attribute_co_authored_by # Keep original value if needed elsewhere
+ attribute_co_authored_by = False # Force to False to ignore the setting
+ # --- End intentional break ---
+
+ if attribute_co_authored_by: # This condition will now always be false
model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name
From 80114e7a24faa004d7131f47364a28f8fae8d694 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:48:52 +0300
Subject: [PATCH 030/482] chore: revert intentional break introduced for
testing
---
aider/repo.py | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/aider/repo.py b/aider/repo.py
index 4ba96d920..7e04d89ee 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -153,12 +153,7 @@ class GitRepo:
# Determine author/committer modification and trailer
- # --- Intentionally break the behavior for testing ---
- original_attribute_co_authored_by = attribute_co_authored_by # Keep original value if needed elsewhere
- attribute_co_authored_by = False # Force to False to ignore the setting
- # --- End intentional break ---
-
- if attribute_co_authored_by: # This condition will now always be false
+ if attribute_co_authored_by:
model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name
From d5671c2879c85f581bd504a962e8b54b6567c776 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:50:16 +0300
Subject: [PATCH 031/482] chore: Add test comment
---
tests/fixtures/sample-code-base/sample.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/fixtures/sample-code-base/sample.js b/tests/fixtures/sample-code-base/sample.js
index f3f2eaf58..a934b428c 100644
--- a/tests/fixtures/sample-code-base/sample.js
+++ b/tests/fixtures/sample-code-base/sample.js
@@ -1,3 +1,4 @@
+// Aider test commit
// Sample JavaScript script with 7 functions
// 1. A simple greeting function
From 48f89f226fac3d407d40574d921bf5df065cda71 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:51:58 +0300
Subject: [PATCH 032/482] fix: prevent name modification when using
co-authored-by
---
aider/repo.py | 10 +++++-----
tests/basic/test_repo.py | 5 +++--
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/aider/repo.py b/aider/repo.py
index 7e04d89ee..f0d436526 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -58,6 +58,7 @@ class GitRepo:
commit_prompt=None,
subtree_only=False,
git_commit_verify=True,
+ attribute_co_authored_by=False, # Added parameter
):
self.io = io
self.models = models
@@ -69,8 +70,7 @@ class GitRepo:
self.attribute_committer = attribute_committer
self.attribute_commit_message_author = attribute_commit_message_author
self.attribute_commit_message_committer = attribute_commit_message_committer
- # Ensure attribute_co_authored_by is initialized, default to False if not provided
- self.attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
+ self.attribute_co_authored_by = attribute_co_authored_by # Assign from parameter
self.commit_prompt = commit_prompt
self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify
@@ -158,9 +158,9 @@ class GitRepo:
if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name
commit_message_trailer = f"\n\nCo-authored-by: aider ({model_name}) "
- # Only modify author/committer if explicitly requested alongside co-authored-by
- use_attribute_author = attribute_author
- use_attribute_committer = attribute_committer
+ # If co-authored-by is used, disable author/committer name modification
+ use_attribute_author = False
+ use_attribute_committer = False
else:
# Original behavior when co-authored-by is false
use_attribute_author = attribute_author
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 945de84f8..2c68c8f00 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -297,8 +297,9 @@ class TestRepo(unittest.TestCase):
commit = raw_repo.head.commit
self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
- self.assertEqual(commit.author.name, "Test User (aider)") # Should BE modified
- self.assertEqual(commit.committer.name, "Test User (aider)") # Should BE modified
+ # When co-authored-by is true, name modification should be disabled
+ self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
+ self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
def test_commit_without_co_authored_by(self):
From 072bd30443ce0b3bb8cb7df2f9550446b4edb240 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:53:11 +0300
Subject: [PATCH 033/482] test: add comment for testing
---
tests/fixtures/sample-code-base/sample.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/fixtures/sample-code-base/sample.js b/tests/fixtures/sample-code-base/sample.js
index a934b428c..31280539f 100644
--- a/tests/fixtures/sample-code-base/sample.js
+++ b/tests/fixtures/sample-code-base/sample.js
@@ -1,4 +1,5 @@
// Aider test commit
+// Another test comment
// Sample JavaScript script with 7 functions
// 1. A simple greeting function
From f648a018a2a738f03576acb4e4998e8b2be17341 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:55:13 +0300
Subject: [PATCH 034/482] fix: Pass attribute_co_authored_by arg to GitRepo
constructor
---
aider/main.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/main.py b/aider/main.py
index 9da90e161..a8535d02c 100644
--- a/aider/main.py
+++ b/aider/main.py
@@ -904,6 +904,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
commit_prompt=args.commit_prompt,
subtree_only=args.subtree_only,
git_commit_verify=args.git_commit_verify,
+ attribute_co_authored_by=args.attribute_co_authored_by, # Pass the arg
)
except FileNotFoundError:
pass
From ff8e9850ba2dd61a5ff1cc6f5b2cb30d0469082e Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:55:54 +0300
Subject: [PATCH 035/482] chore: add test comment to dump function
---
aider/dump.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/dump.py b/aider/dump.py
index 6098d0b73..85065a97d 100644
--- a/aider/dump.py
+++ b/aider/dump.py
@@ -13,6 +13,7 @@ def cvt(s):
def dump(*vals):
# This is a test comment
+ # This is another test comment
# http://docs.python.org/library/traceback.html
stack = traceback.extract_stack()
vars = stack[-2][3]
From d1437b76665a4e4f51d6ea21200a0b817e6157c3 Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:57:04 +0300
Subject: [PATCH 036/482] chore: add debug prints for attribute_co_authored_by
---
aider/main.py | 2 ++
aider/repo.py | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/aider/main.py b/aider/main.py
index a8535d02c..61100d14a 100644
--- a/aider/main.py
+++ b/aider/main.py
@@ -501,6 +501,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# Parse again to include any arguments that might have been defined in .env
args = parser.parse_args(argv)
+ print(f"DEBUG: After final parse, args.attribute_co_authored_by = {args.attribute_co_authored_by}") # DEBUG
if git is None:
args.git = False
@@ -891,6 +892,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
repo = None
if args.git:
try:
+ print(f"DEBUG: Before GitRepo init, args.attribute_co_authored_by = {args.attribute_co_authored_by}") # DEBUG
repo = GitRepo(
io,
fnames,
diff --git a/aider/repo.py b/aider/repo.py
index f0d436526..5a57ffb46 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -60,6 +60,7 @@ class GitRepo:
git_commit_verify=True,
attribute_co_authored_by=False, # Added parameter
):
+ print(f"DEBUG: GitRepo.__init__ received attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
self.io = io
self.models = models
@@ -71,6 +72,7 @@ class GitRepo:
self.attribute_commit_message_author = attribute_commit_message_author
self.attribute_commit_message_committer = attribute_commit_message_committer
self.attribute_co_authored_by = attribute_co_authored_by # Assign from parameter
+ print(f"DEBUG: GitRepo.__init__ set self.attribute_co_authored_by = {self.attribute_co_authored_by}") # DEBUG
self.commit_prompt = commit_prompt
self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify
@@ -117,6 +119,8 @@ class GitRepo:
if not fnames and not self.repo.is_dirty():
return
+ print(f"DEBUG: GitRepo.commit start, self.attribute_co_authored_by = {self.attribute_co_authored_by}") # DEBUG
+
diffs = self.get_diffs(fnames)
if not diffs:
return
@@ -141,6 +145,8 @@ class GitRepo:
attribute_commit_message_committer = self.attribute_commit_message_committer
attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
+ print(f"DEBUG: GitRepo.commit after retrieval, attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
+
commit_message_trailer = ""
prefix_commit_message = False
use_attribute_author = False
@@ -153,6 +159,7 @@ class GitRepo:
# Determine author/committer modification and trailer
+ print(f"DEBUG: GitRepo.commit before logic check, attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
if attribute_co_authored_by:
model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name:
@@ -201,6 +208,7 @@ class GitRepo:
committer_name = f"{original_user_name} (aider)"
# Apply author/committer modifications based on flags determined earlier
+ print(f"DEBUG: GitRepo.commit before setting env, use_attribute_author={use_attribute_author}, use_attribute_committer={use_attribute_committer}") # DEBUG
if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name
if use_attribute_author:
From 15d623f2c085478e43ceafda98dffefcc44eec7d Mon Sep 17 00:00:00 2001
From: "Andrew Grigorev (aider)"
Date: Sat, 12 Apr 2025 17:57:44 +0300
Subject: [PATCH 037/482] chore: add another test comment to prompts
---
aider/prompts.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/prompts.py b/aider/prompts.py
index 1dacf10d0..87f14a5ec 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -1,6 +1,7 @@
# flake8: noqa: E501
# This is a test comment.
+# This is another test comment.
# COMMIT
From 316d8f8e9bf919fa431cda7250ea33d4f5b230bd Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:06:09 +0300
Subject: [PATCH 038/482] chore: add third test comment
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/prompts.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/aider/prompts.py b/aider/prompts.py
index 87f14a5ec..50830978a 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -2,6 +2,7 @@
# This is a test comment.
# This is another test comment.
+# This is a third test comment.
# COMMIT
From 66fdeceb3b39f1ca25ed9cd7cf2a041b9d1e5f66 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:06 +0300
Subject: [PATCH 039/482] Revert "chore: add third test comment"
This reverts commit 316d8f8e9bf919fa431cda7250ea33d4f5b230bd.
---
aider/prompts.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/prompts.py b/aider/prompts.py
index 50830978a..87f14a5ec 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -2,7 +2,6 @@
# This is a test comment.
# This is another test comment.
-# This is a third test comment.
# COMMIT
From 0a59c38f31ff82137b219013693386efd4a13b96 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:07 +0300
Subject: [PATCH 040/482] Revert "chore: add another test comment to prompts"
This reverts commit 15d623f2c085478e43ceafda98dffefcc44eec7d.
---
aider/prompts.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/prompts.py b/aider/prompts.py
index 87f14a5ec..1dacf10d0 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -1,7 +1,6 @@
# flake8: noqa: E501
# This is a test comment.
-# This is another test comment.
# COMMIT
From e1820522db7eb006306d6396e09f5f1b94b633f2 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:07 +0300
Subject: [PATCH 041/482] Revert "chore: add debug prints for
attribute_co_authored_by"
This reverts commit d1437b76665a4e4f51d6ea21200a0b817e6157c3.
---
aider/main.py | 2 --
aider/repo.py | 8 --------
2 files changed, 10 deletions(-)
diff --git a/aider/main.py b/aider/main.py
index 61100d14a..a8535d02c 100644
--- a/aider/main.py
+++ b/aider/main.py
@@ -501,7 +501,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# Parse again to include any arguments that might have been defined in .env
args = parser.parse_args(argv)
- print(f"DEBUG: After final parse, args.attribute_co_authored_by = {args.attribute_co_authored_by}") # DEBUG
if git is None:
args.git = False
@@ -892,7 +891,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
repo = None
if args.git:
try:
- print(f"DEBUG: Before GitRepo init, args.attribute_co_authored_by = {args.attribute_co_authored_by}") # DEBUG
repo = GitRepo(
io,
fnames,
diff --git a/aider/repo.py b/aider/repo.py
index 5a57ffb46..f0d436526 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -60,7 +60,6 @@ class GitRepo:
git_commit_verify=True,
attribute_co_authored_by=False, # Added parameter
):
- print(f"DEBUG: GitRepo.__init__ received attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
self.io = io
self.models = models
@@ -72,7 +71,6 @@ class GitRepo:
self.attribute_commit_message_author = attribute_commit_message_author
self.attribute_commit_message_committer = attribute_commit_message_committer
self.attribute_co_authored_by = attribute_co_authored_by # Assign from parameter
- print(f"DEBUG: GitRepo.__init__ set self.attribute_co_authored_by = {self.attribute_co_authored_by}") # DEBUG
self.commit_prompt = commit_prompt
self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify
@@ -119,8 +117,6 @@ class GitRepo:
if not fnames and not self.repo.is_dirty():
return
- print(f"DEBUG: GitRepo.commit start, self.attribute_co_authored_by = {self.attribute_co_authored_by}") # DEBUG
-
diffs = self.get_diffs(fnames)
if not diffs:
return
@@ -145,8 +141,6 @@ class GitRepo:
attribute_commit_message_committer = self.attribute_commit_message_committer
attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
- print(f"DEBUG: GitRepo.commit after retrieval, attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
-
commit_message_trailer = ""
prefix_commit_message = False
use_attribute_author = False
@@ -159,7 +153,6 @@ class GitRepo:
# Determine author/committer modification and trailer
- print(f"DEBUG: GitRepo.commit before logic check, attribute_co_authored_by = {attribute_co_authored_by}") # DEBUG
if attribute_co_authored_by:
model_name = "unknown-model"
if coder and hasattr(coder, "main_model") and coder.main_model.name:
@@ -208,7 +201,6 @@ class GitRepo:
committer_name = f"{original_user_name} (aider)"
# Apply author/committer modifications based on flags determined earlier
- print(f"DEBUG: GitRepo.commit before setting env, use_attribute_author={use_attribute_author}, use_attribute_committer={use_attribute_committer}") # DEBUG
if use_attribute_committer:
os.environ["GIT_COMMITTER_NAME"] = committer_name
if use_attribute_author:
From 02bc9a85c026ab4dd8aadea73156247f0d5d3131 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:08 +0300
Subject: [PATCH 042/482] Revert "chore: add test comment to dump function"
This reverts commit ff8e9850ba2dd61a5ff1cc6f5b2cb30d0469082e.
---
aider/dump.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/dump.py b/aider/dump.py
index 85065a97d..6098d0b73 100644
--- a/aider/dump.py
+++ b/aider/dump.py
@@ -13,7 +13,6 @@ def cvt(s):
def dump(*vals):
# This is a test comment
- # This is another test comment
# http://docs.python.org/library/traceback.html
stack = traceback.extract_stack()
vars = stack[-2][3]
From cf7b35f90d45766f33327d7dbcd31c5a90c130d1 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:08 +0300
Subject: [PATCH 043/482] Revert "test: add comment for testing"
This reverts commit 072bd30443ce0b3bb8cb7df2f9550446b4edb240.
---
tests/fixtures/sample-code-base/sample.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/fixtures/sample-code-base/sample.js b/tests/fixtures/sample-code-base/sample.js
index 31280539f..a934b428c 100644
--- a/tests/fixtures/sample-code-base/sample.js
+++ b/tests/fixtures/sample-code-base/sample.js
@@ -1,5 +1,4 @@
// Aider test commit
-// Another test comment
// Sample JavaScript script with 7 functions
// 1. A simple greeting function
From 7b8c7edfd5a122967ee03eefa0c5077ae1031d90 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:08 +0300
Subject: [PATCH 044/482] Revert "chore: Add test comment"
This reverts commit d5671c2879c85f581bd504a962e8b54b6567c776.
---
tests/fixtures/sample-code-base/sample.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/fixtures/sample-code-base/sample.js b/tests/fixtures/sample-code-base/sample.js
index a934b428c..f3f2eaf58 100644
--- a/tests/fixtures/sample-code-base/sample.js
+++ b/tests/fixtures/sample-code-base/sample.js
@@ -1,4 +1,3 @@
-// Aider test commit
// Sample JavaScript script with 7 functions
// 1. A simple greeting function
From aa07e16f1833fb78269286f114e2eb2ccb07b2e9 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:09 +0300
Subject: [PATCH 045/482] Revert "chore: Add test comment"
This reverts commit 482e0c2d0b5cdfe60281f13bab2ead4aa540e9e6.
---
aider/prompts.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/prompts.py b/aider/prompts.py
index 1dacf10d0..84ed75e9b 100644
--- a/aider/prompts.py
+++ b/aider/prompts.py
@@ -1,6 +1,5 @@
# flake8: noqa: E501
-# This is a test comment.
# COMMIT
From 427f9c5b00fb3964d71344e86452209df1422616 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:14:09 +0300
Subject: [PATCH 046/482] Revert "chore: Add test comment to dump function"
This reverts commit e9511643998d4868bc261b3ec0479e6a2a362b3a.
---
aider/dump.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/aider/dump.py b/aider/dump.py
index 6098d0b73..2c8bf31c2 100644
--- a/aider/dump.py
+++ b/aider/dump.py
@@ -12,7 +12,6 @@ def cvt(s):
def dump(*vals):
- # This is a test comment
# http://docs.python.org/library/traceback.html
stack = traceback.extract_stack()
vars = stack[-2][3]
From c56e836d22be0139adb3d976ac49ed4db8a45ab8 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:19:55 +0300
Subject: [PATCH 047/482] refactor: simplify commit logic and use context
manager for git env
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/args.py | 5 ++-
aider/repo.py | 105 +++++++++++++++++++++++++-------------------------
2 files changed, 56 insertions(+), 54 deletions(-)
diff --git a/aider/args.py b/aider/args.py
index 3571faa5e..6d62b6dbf 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -428,7 +428,10 @@ def get_parser(default_config_files, git_root):
"--attribute-author",
action=argparse.BooleanOptionalAction,
default=True,
- help="Attribute aider code changes in the git author name (default: True, ignored if attribute-co-authored-by is True unless explicitly set)",
+ help=(
+ "Attribute aider code changes in the git author name (default: True). This is ignored"
+ " if --attribute-co-authored-by is True."
+ ),
)
group.add_argument(
"--attribute-committer",
diff --git a/aider/repo.py b/aider/repo.py
index f0d436526..f8a5cacfc 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -1,3 +1,4 @@
+import contextlib
import os
import time
from pathlib import Path, PurePosixPath
@@ -34,6 +35,19 @@ ANY_GIT_ERROR += [
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
+@contextlib.contextmanager
+def set_git_env(var_name, value, original_value):
+ """Temporarily set a Git environment variable."""
+ os.environ[var_name] = value
+ try:
+ yield
+ finally:
+ if original_value is not None:
+ os.environ[var_name] = original_value
+ elif var_name in os.environ:
+ del os.environ[var_name]
+
+
class GitRepo:
repo = None
aider_ignore_file = None
@@ -139,37 +153,29 @@ class GitRepo:
attribute_committer = self.attribute_committer
attribute_commit_message_author = self.attribute_commit_message_author
attribute_commit_message_committer = self.attribute_commit_message_committer
- attribute_co_authored_by = getattr(self, 'attribute_co_authored_by', False)
+ attribute_co_authored_by = getattr(self, "attribute_co_authored_by", False)
+ # Determine commit message prefixing
+ prefix_commit_message = aider_edits and (
+ attribute_commit_message_author or attribute_commit_message_committer
+ )
+
+ # Determine Co-authored-by trailer
commit_message_trailer = ""
- prefix_commit_message = False
- use_attribute_author = False
- use_attribute_committer = False
+ if aider_edits and attribute_co_authored_by:
+ model_name = "unknown-model"
+ if coder and hasattr(coder, "main_model") and coder.main_model.name:
+ model_name = coder.main_model.name
+ commit_message_trailer = (
+ f"\n\nCo-authored-by: aider ({model_name}) "
+ )
- if aider_edits:
- # Determine commit message prefixing
- if attribute_commit_message_author or attribute_commit_message_committer:
- prefix_commit_message = True
-
- # Determine author/committer modification and trailer
-
- if attribute_co_authored_by:
- model_name = "unknown-model"
- if coder and hasattr(coder, "main_model") and coder.main_model.name:
- model_name = coder.main_model.name
- commit_message_trailer = f"\n\nCo-authored-by: aider ({model_name}) "
- # If co-authored-by is used, disable author/committer name modification
- use_attribute_author = False
- use_attribute_committer = False
- else:
- # Original behavior when co-authored-by is false
- use_attribute_author = attribute_author
- use_attribute_committer = attribute_committer
- else: # not aider_edits
- # Keep original behavior for non-aider edits
- use_attribute_author = False
- use_attribute_committer = attribute_committer # Respect config for committer
- prefix_commit_message = False # Don't prefix non-aider commits
+ # Determine if author/committer names should be modified
+ # If co-authored-by is used for aider edits, it takes precedence over direct name modification.
+ use_attribute_author = attribute_author and aider_edits and not attribute_co_authored_by
+ use_attribute_committer = attribute_committer and not (
+ aider_edits and attribute_co_authored_by
+ )
if not commit_message:
commit_message = "(no commit message provided)"
@@ -178,8 +184,6 @@ class GitRepo:
commit_message = "aider: " + commit_message
full_commit_message = commit_message + commit_message_trailer
- # if context:
- # full_commit_message += "\n\n# Aider chat conversation:\n\n" + context
cmd = ["-m", full_commit_message]
if not self.git_commit_verify:
@@ -200,32 +204,27 @@ class GitRepo:
original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
committer_name = f"{original_user_name} (aider)"
- # Apply author/committer modifications based on flags determined earlier
- if use_attribute_committer:
- os.environ["GIT_COMMITTER_NAME"] = committer_name
- if use_attribute_author:
- os.environ["GIT_AUTHOR_NAME"] = committer_name
-
try:
- self.repo.git.commit(cmd)
- commit_hash = self.get_head_commit_sha(short=True)
- self.io.tool_output(f"Commit {commit_hash} {commit_message}", bold=True)
- return commit_hash, commit_message
+ # Use context managers to handle environment variables
+ with contextlib.ExitStack() as stack:
+ if use_attribute_committer:
+ stack.enter_context(
+ set_git_env("GIT_COMMITTER_NAME", committer_name, original_committer_name_env)
+ )
+ if use_attribute_author:
+ stack.enter_context(
+ set_git_env("GIT_AUTHOR_NAME", committer_name, original_author_name_env)
+ )
+
+ # Perform the commit
+ self.repo.git.commit(cmd)
+ commit_hash = self.get_head_commit_sha(short=True)
+ self.io.tool_output(f"Commit {commit_hash} {commit_message}", bold=True)
+ return commit_hash, commit_message
+
except ANY_GIT_ERROR as err:
self.io.tool_error(f"Unable to commit: {err}")
- finally:
- # Restore the env
- if use_attribute_committer:
- if original_committer_name_env is not None:
- os.environ["GIT_COMMITTER_NAME"] = original_committer_name_env
- elif "GIT_COMMITTER_NAME" in os.environ:
- del os.environ["GIT_COMMITTER_NAME"]
-
- if use_attribute_author:
- if original_author_name_env is not None:
- os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
- elif "GIT_AUTHOR_NAME" in os.environ:
- del os.environ["GIT_AUTHOR_NAME"]
+ # No return here, implicitly returns None
def get_rel_repo_dir(self):
try:
From dd4b61da207dfe45cca6e9dee16490b048b3ed8e Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 18:26:46 +0300
Subject: [PATCH 048/482] test: add test for co-authored-by precedence over
author/committer
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 54 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 2c68c8f00..57bad6625 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -301,6 +301,60 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
+ def test_commit_co_authored_by_precedence(self):
+ # Test that co-authored-by takes precedence over name modification when both are enabled
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # new repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+
+ # add a file and commit it
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ # Mock coder args: All relevant flags enabled
+ mock_coder = MagicMock()
+ mock_coder.args.attribute_co_authored_by = True
+ mock_coder.args.attribute_author = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_committer = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_commit_message_author = False
+ mock_coder.args.attribute_commit_message_committer = False
+ mock_coder.main_model = MagicMock()
+ mock_coder.main_model.name = "gpt-precedence"
+
+ io = InputOutput()
+ # Initialize GitRepo directly with flags, simulating config/defaults if coder wasn't passed
+ # This ensures the test covers the case where coder might not provide args
+ git_repo = GitRepo(
+ io,
+ None,
+ None,
+ attribute_co_authored_by=True,
+ attribute_author=True,
+ attribute_committer=True,
+ )
+
+
+ # commit a change with aider_edits=True and conflicting flags
+ fname.write_text("new content precedence")
+ # Pass the coder object here to ensure its args are used if available,
+ # but the GitRepo init already set the fallback values.
+ git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider precedence edit")
+
+ # check the commit message and author/committer
+ commit = raw_repo.head.commit
+ self.assertIn("Co-authored-by: aider (gpt-precedence) ", commit.message)
+ self.assertEqual(commit.message.splitlines()[0], "Aider precedence edit")
+ # Co-authored-by should take precedence, names should NOT be modified
+ self.assertEqual(commit.author.name, "Test User")
+ self.assertEqual(commit.committer.name, "Test User")
+
def test_commit_without_co_authored_by(self):
# Cleanup of the git temp dir explodes on windows
From ea74f31b3e98550611e95e7108a9a63c0dd8d5c5 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:09:46 +0300
Subject: [PATCH 049/482] feat: Explicit author/committer flags override
co-authored-by
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/args.py | 13 +++---
aider/repo.py | 28 ++++++++++---
tests/basic/test_repo.py | 87 +++++++++++++++++++++-------------------
3 files changed, 77 insertions(+), 51 deletions(-)
diff --git a/aider/args.py b/aider/args.py
index 6d62b6dbf..7aaf10f2a 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -427,17 +427,20 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--attribute-author",
action=argparse.BooleanOptionalAction,
- default=True,
+ default=None,
help=(
- "Attribute aider code changes in the git author name (default: True). This is ignored"
- " if --attribute-co-authored-by is True."
+ "Attribute aider code changes in the git author name (default: True). If explicitly set"
+ " to True, overrides --attribute-co-authored-by precedence."
),
)
group.add_argument(
"--attribute-committer",
action=argparse.BooleanOptionalAction,
- default=True,
- help="Attribute aider commits in the git committer name (default: True)",
+ default=None,
+ help=(
+ "Attribute aider commits in the git committer name (default: True). If explicitly set"
+ " to True, overrides --attribute-co-authored-by precedence for aider edits."
+ ),
)
group.add_argument(
"--attribute-commit-message-author",
diff --git a/aider/repo.py b/aider/repo.py
index f8a5cacfc..31bcc7957 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -153,7 +153,16 @@ class GitRepo:
attribute_committer = self.attribute_committer
attribute_commit_message_author = self.attribute_commit_message_author
attribute_commit_message_committer = self.attribute_commit_message_committer
- attribute_co_authored_by = getattr(self, "attribute_co_authored_by", False)
+ attribute_co_authored_by = getattr(self, "attribute_co_authored_by", False) # Should be False if not set
+
+ # Determine explicit settings (None means use default behavior)
+ author_explicit = attribute_author is not None
+ committer_explicit = attribute_committer is not None
+
+ # Determine effective settings (apply default True if not explicit)
+ effective_author = True if attribute_author is None else attribute_author
+ effective_committer = True if attribute_committer is None else attribute_committer
+
# Determine commit message prefixing
prefix_commit_message = aider_edits and (
@@ -171,12 +180,21 @@ class GitRepo:
)
# Determine if author/committer names should be modified
- # If co-authored-by is used for aider edits, it takes precedence over direct name modification.
- use_attribute_author = attribute_author and aider_edits and not attribute_co_authored_by
- use_attribute_committer = attribute_committer and not (
- aider_edits and attribute_co_authored_by
+ # Author modification applies only to aider edits.
+ # It's used if effective_author is True AND (co-authored-by is False OR author was explicitly set).
+ use_attribute_author = (
+ aider_edits
+ and effective_author
+ and (not attribute_co_authored_by or author_explicit)
)
+ # Committer modification applies regardless of aider_edits (based on tests).
+ # It's used if effective_committer is True AND (it's not an aider edit with co-authored-by OR committer was explicitly set).
+ use_attribute_committer = effective_committer and (
+ not (aider_edits and attribute_co_authored_by) or committer_explicit
+ )
+
+
if not commit_message:
commit_message = "(no commit message provided)"
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 57bad6625..e7026a242 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -185,26 +185,35 @@ class TestRepo(unittest.TestCase):
raw_repo.git.commit("-m", "initial commit")
io = InputOutput()
- git_repo = GitRepo(io, None, None)
+ # Initialize GitRepo with default None values for attributes
+ git_repo = GitRepo(io, None, None, attribute_author=None, attribute_committer=None)
- # commit a change
+ # commit a change with aider_edits=True (using default attributes)
fname.write_text("new content")
git_repo.commit(fnames=[str(fname)], aider_edits=True)
- # check the committer name
+ # check the committer name (defaults interpreted as True)
commit = raw_repo.head.commit
self.assertEqual(commit.author.name, "Test User (aider)")
self.assertEqual(commit.committer.name, "Test User (aider)")
- # commit a change without aider_edits
+ # commit a change without aider_edits (using default attributes)
fname.write_text("new content again!")
git_repo.commit(fnames=[str(fname)], aider_edits=False)
- # check the committer name
+ # check the committer name (author not modified, committer still modified by default)
commit = raw_repo.head.commit
self.assertEqual(commit.author.name, "Test User")
self.assertEqual(commit.committer.name, "Test User (aider)")
+ # Now test with explicit False
+ git_repo_explicit_false = GitRepo(io, None, None, attribute_author=False, attribute_committer=False)
+ fname.write_text("explicit false content")
+ git_repo_explicit_false.commit(fnames=[str(fname)], aider_edits=True)
+ commit = raw_repo.head.commit
+ self.assertEqual(commit.author.name, "Test User") # Explicit False
+ self.assertEqual(commit.committer.name, "Test User") # Explicit False
+
# check that the original committer name is restored
original_committer_name = os.environ.get("GIT_COMMITTER_NAME")
self.assertIsNone(original_committer_name)
@@ -228,15 +237,13 @@ class TestRepo(unittest.TestCase):
raw_repo.git.add(str(fname))
raw_repo.git.commit("-m", "initial commit")
- # Mock coder args
- # Mock coder args: Co-authored-by enabled, author/committer modification disabled
+ # Mock coder args: Co-authored-by enabled, author/committer use default (None)
mock_coder = MagicMock()
mock_coder.args.attribute_co_authored_by = True
- mock_coder.args.attribute_author = False # Explicitly disable name modification
- mock_coder.args.attribute_committer = False # Explicitly disable name modification
+ mock_coder.args.attribute_author = None # Default
+ mock_coder.args.attribute_committer = None # Default
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- # Set the model name correctly on the nested mock
# The code uses coder.main_model.name for the co-authored-by line
mock_coder.main_model = MagicMock()
mock_coder.main_model.name = "gpt-test"
@@ -253,16 +260,17 @@ class TestRepo(unittest.TestCase):
commit = raw_repo.head.commit
self.assertIn("Co-authored-by: aider (gpt-test) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider edit")
+ # With default (None), co-authored-by takes precedence
self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
- def test_commit_with_co_authored_by_and_name_modification(self):
- # Test scenario where Co-authored-by is true AND author/committer modification is also true (default)
- # Cleanup of the git temp dir explodes on windows
+ def test_commit_co_authored_by_with_explicit_name_modification(self):
+ # Test scenario where Co-authored-by is true AND author/committer modification are explicitly True
if platform.system() == "Windows":
return
with GitTemporaryDirectory():
+ # Setup repo...
# new repo
raw_repo = git.Repo()
raw_repo.config_writer().set_value("user", "name", "Test User").release()
@@ -274,14 +282,13 @@ class TestRepo(unittest.TestCase):
raw_repo.git.add(str(fname))
raw_repo.git.commit("-m", "initial commit")
- # Mock coder args: Co-authored-by enabled, author/committer modification enabled (default)
+ # Mock coder args: Co-authored-by enabled, author/committer modification explicitly enabled
mock_coder = MagicMock()
mock_coder.args.attribute_co_authored_by = True
- mock_coder.args.attribute_author = True # Explicitly enable (or rely on default)
- mock_coder.args.attribute_committer = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_author = True # Explicitly enable
+ mock_coder.args.attribute_committer = True # Explicitly enable
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- # Set the model name correctly on the nested mock
mock_coder.main_model = MagicMock()
mock_coder.main_model.name = "gpt-test-combo"
@@ -297,12 +304,12 @@ class TestRepo(unittest.TestCase):
commit = raw_repo.head.commit
self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
- # When co-authored-by is true, name modification should be disabled
- self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
- self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
+ # When co-authored-by is true BUT author/committer are explicit True, modification SHOULD happen
+ self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified
- def test_commit_co_authored_by_precedence(self):
- # Test that co-authored-by takes precedence over name modification when both are enabled
+ def test_commit_co_authored_by_precedence_over_default(self):
+ # Test that co-authored-by takes precedence over default (None) name modification
if platform.system() == "Windows":
return
@@ -318,30 +325,29 @@ class TestRepo(unittest.TestCase):
raw_repo.git.add(str(fname))
raw_repo.git.commit("-m", "initial commit")
- # Mock coder args: All relevant flags enabled
+ # Mock coder args: Co-authored-by enabled, author/committer use default (None)
mock_coder = MagicMock()
mock_coder.args.attribute_co_authored_by = True
- mock_coder.args.attribute_author = True # Explicitly enable (or rely on default)
- mock_coder.args.attribute_committer = True # Explicitly enable (or rely on default)
+ mock_coder.args.attribute_author = None # Default
+ mock_coder.args.attribute_committer = None # Default
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- mock_coder.main_model = MagicMock()
+ mock_coder.main_model = MagicMock() # Define main_model before accessing name
mock_coder.main_model.name = "gpt-precedence"
io = InputOutput()
- # Initialize GitRepo directly with flags, simulating config/defaults if coder wasn't passed
- # This ensures the test covers the case where coder might not provide args
+ # Initialize GitRepo directly with flags, simulating config/defaults
+ # Use None for author/committer to test default behavior
git_repo = GitRepo(
io,
None,
None,
attribute_co_authored_by=True,
- attribute_author=True,
- attribute_committer=True,
+ attribute_author=None, # Default
+ attribute_committer=None, # Default
)
-
- # commit a change with aider_edits=True and conflicting flags
+ # commit a change with aider_edits=True and default flags
fname.write_text("new content precedence")
# Pass the coder object here to ensure its args are used if available,
# but the GitRepo init already set the fallback values.
@@ -351,13 +357,13 @@ class TestRepo(unittest.TestCase):
commit = raw_repo.head.commit
self.assertIn("Co-authored-by: aider (gpt-precedence) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider precedence edit")
- # Co-authored-by should take precedence, names should NOT be modified
+ # Co-authored-by should take precedence over default (None), names should NOT be modified
self.assertEqual(commit.author.name, "Test User")
self.assertEqual(commit.committer.name, "Test User")
def test_commit_without_co_authored_by(self):
- # Cleanup of the git temp dir explodes on windows
+ # Test standard name modification when co-authored-by is False
if platform.system() == "Windows":
return
@@ -373,14 +379,13 @@ class TestRepo(unittest.TestCase):
raw_repo.git.add(str(fname))
raw_repo.git.commit("-m", "initial commit")
- # Mock coder args (default behavior)
+ # Mock coder args (co-authored-by False, author/committer default None)
mock_coder = MagicMock()
mock_coder.args.attribute_co_authored_by = False
- mock_coder.args.attribute_author = True
- mock_coder.args.attribute_committer = True
+ mock_coder.args.attribute_author = None # Default
+ mock_coder.args.attribute_committer = None # Default
mock_coder.args.attribute_commit_message_author = False
mock_coder.args.attribute_commit_message_committer = False
- # Set the model name correctly on the nested mock (though not used in this test assertion)
mock_coder.main_model = MagicMock()
mock_coder.main_model.name = "gpt-test-no-coauthor"
@@ -392,12 +397,12 @@ class TestRepo(unittest.TestCase):
fname.write_text("new content")
git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
- # check the commit message and author/committer
+ # check the commit message and author/committer (defaults interpreted as True)
commit = raw_repo.head.commit
self.assertNotIn("Co-authored-by:", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider edit")
- self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified
- self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified
+ self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified (default True)
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified (default True)
def test_get_tracked_files(self):
From 278a596bfafd8f9e596f64732d83194271bc0e4d Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:21:03 +0300
Subject: [PATCH 050/482] docs: clarify commit author/committer/co-authored-by
logic
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/repo.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/aider/repo.py b/aider/repo.py
index 31bcc7957..ad87a379a 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -128,6 +128,70 @@ class GitRepo:
self.aider_ignore_file = Path(aider_ignore_file)
def commit(self, fnames=None, context=None, message=None, aider_edits=False, coder=None):
+ """
+ Commit the specified files or all dirty files if none are specified.
+
+ Args:
+ fnames (list, optional): List of filenames to commit. Defaults to None (commit all
+ dirty files).
+ context (str, optional): Context for generating the commit message. Defaults to None.
+ message (str, optional): Explicit commit message. Defaults to None (generate message).
+ aider_edits (bool, optional): Whether the changes were made by Aider. Defaults to False.
+ This affects attribution logic.
+ coder (Coder, optional): The Coder instance, used to access config and model info.
+ Defaults to None.
+
+ Returns:
+ tuple(str, str) or None: The commit hash and commit message if successful, else None.
+
+ Attribution Logic:
+ ------------------
+ This method handles Git commit attribution based on configuration flags and whether
+ Aider generated the changes (`aider_edits`).
+
+ Key Concepts:
+ - Author: The person who originally wrote the code changes.
+ - Committer: The person who last applied the commit to the repository.
+ - aider_edits=True: Changes were generated by Aider (LLM).
+ - aider_edits=False: Commit is user-driven (e.g., /commit manually staged changes).
+ - Explicit Setting: A flag (--attribute-...) is set to True or False via command line
+ or config file.
+ - Implicit Default: A flag is not explicitly set, defaulting to None in args, which is
+ interpreted as True unless overridden by other logic.
+
+ Flags:
+ - --attribute-author: Modify Author name to "User Name (aider)".
+ - --attribute-committer: Modify Committer name to "User Name (aider)".
+ - --attribute-co-authored-by: Add "Co-authored-by: aider () "
+ trailer to the commit message.
+
+ Behavior Summary:
+
+ 1. When aider_edits = True (AI Changes):
+ - If --attribute-co-authored-by=True:
+ - Co-authored-by trailer IS ADDED.
+ - Author/Committer names are NOT modified by default (co-authored-by takes precedence).
+ - EXCEPTION: If --attribute-author/--attribute-committer is EXPLICITLY True,
+ the respective name IS modified (explicit overrides precedence).
+ - If --attribute-co-authored-by=False:
+ - Co-authored-by trailer is NOT added.
+ - Author/Committer names ARE modified by default (implicit True).
+ - EXCEPTION: If --attribute-author/--attribute-committer is EXPLICITLY False,
+ the respective name is NOT modified.
+
+ 2. When aider_edits = False (User Changes):
+ - --attribute-co-authored-by is IGNORED (trailer never added).
+ - Author name is NEVER modified (--attribute-author ignored).
+ - Committer name IS modified by default (implicit True, as Aider runs `git commit`).
+ - EXCEPTION: If --attribute-committer is EXPLICITLY False, the name is NOT modified.
+
+ Resulting Scenarios:
+ - Standard AI edit (defaults): Co-authored-by=False -> Author=You(aider), Committer=You(aider)
+ - AI edit with Co-authored-by (default): Co-authored-by=True -> Author=You, Committer=You, Trailer added
+ - AI edit with Co-authored-by + Explicit Author: Co-authored-by=True, --attribute-author -> Author=You(aider), Committer=You, Trailer added
+ - User commit (defaults): aider_edits=False -> Author=You, Committer=You(aider)
+ - User commit with explicit no-committer: aider_edits=False, --no-attribute-committer -> Author=You, Committer=You
+ """
if not fnames and not self.repo.is_dirty():
return
From 5664b5b195aa53f507376efc407dc49e204f3a0b Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:41:24 +0300
Subject: [PATCH 051/482] test: Assert commit return value in more tests
Co-authored-by: aider (vertex_ai/gemini-2.0-flash-lite-001)
---
tests/basic/test_repo.py | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index e7026a242..287d5ea16 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -190,7 +190,8 @@ class TestRepo(unittest.TestCase):
# commit a change with aider_edits=True (using default attributes)
fname.write_text("new content")
- git_repo.commit(fnames=[str(fname)], aider_edits=True)
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True)
+ self.assertIsNotNone(commit_result)
# check the committer name (defaults interpreted as True)
commit = raw_repo.head.commit
@@ -199,7 +200,8 @@ class TestRepo(unittest.TestCase):
# commit a change without aider_edits (using default attributes)
fname.write_text("new content again!")
- git_repo.commit(fnames=[str(fname)], aider_edits=False)
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=False)
+ self.assertIsNotNone(commit_result)
# check the committer name (author not modified, committer still modified by default)
commit = raw_repo.head.commit
@@ -209,7 +211,8 @@ class TestRepo(unittest.TestCase):
# Now test with explicit False
git_repo_explicit_false = GitRepo(io, None, None, attribute_author=False, attribute_committer=False)
fname.write_text("explicit false content")
- git_repo_explicit_false.commit(fnames=[str(fname)], aider_edits=True)
+ commit_result = git_repo_explicit_false.commit(fnames=[str(fname)], aider_edits=True)
+ self.assertIsNotNone(commit_result)
commit = raw_repo.head.commit
self.assertEqual(commit.author.name, "Test User") # Explicit False
self.assertEqual(commit.committer.name, "Test User") # Explicit False
@@ -254,7 +257,8 @@ class TestRepo(unittest.TestCase):
# commit a change with aider_edits=True and co-authored-by flag
fname.write_text("new content")
- git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+ self.assertIsNotNone(commit_result)
# check the commit message and author/committer
commit = raw_repo.head.commit
@@ -298,7 +302,8 @@ class TestRepo(unittest.TestCase):
# commit a change with aider_edits=True and combo flags
fname.write_text("new content combo")
- git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider combo edit")
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider combo edit")
+ self.assertIsNotNone(commit_result)
# check the commit message and author/committer
commit = raw_repo.head.commit
@@ -351,7 +356,8 @@ class TestRepo(unittest.TestCase):
fname.write_text("new content precedence")
# Pass the coder object here to ensure its args are used if available,
# but the GitRepo init already set the fallback values.
- git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider precedence edit")
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider precedence edit")
+ self.assertIsNotNone(commit_result)
# check the commit message and author/committer
commit = raw_repo.head.commit
@@ -395,7 +401,8 @@ class TestRepo(unittest.TestCase):
# commit a change with aider_edits=True and default flags
fname.write_text("new content")
- git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+ commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
+ self.assertIsNotNone(commit_result)
# check the commit message and author/committer (defaults interpreted as True)
commit = raw_repo.head.commit
@@ -598,7 +605,8 @@ class TestRepo(unittest.TestCase):
git_repo = GitRepo(InputOutput(), None, None)
- git_repo.commit(fnames=[str(fname)])
+ commit_result = git_repo.commit(fnames=[str(fname)])
+ self.assertIsNotNone(commit_result)
def test_git_commit_verify(self):
"""Test that git_commit_verify controls whether --no-verify is passed to git commit"""
From 37a252748a68bb26398ea38e92472e94166abbb5 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:45:01 +0300
Subject: [PATCH 052/482] test: Fix commit result assertion in test_noop_commit
---
tests/basic/test_repo.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 287d5ea16..88c4b4edf 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -606,7 +606,7 @@ class TestRepo(unittest.TestCase):
git_repo = GitRepo(InputOutput(), None, None)
commit_result = git_repo.commit(fnames=[str(fname)])
- self.assertIsNotNone(commit_result)
+ self.assertIsNone(commit_result)
def test_git_commit_verify(self):
"""Test that git_commit_verify controls whether --no-verify is passed to git commit"""
From d991cb67219e0728679bf5d00773f12619c97279 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:54:56 +0300
Subject: [PATCH 053/482] test: cover user commit with no committer attribution
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 88c4b4edf..9633ec208 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -223,6 +223,15 @@ class TestRepo(unittest.TestCase):
original_author_name = os.environ.get("GIT_AUTHOR_NAME")
self.assertIsNone(original_author_name)
+ # Test user commit with explicit no-committer attribution
+ git_repo_user_no_committer = GitRepo(io, None, None, attribute_committer=False)
+ fname.write_text("user no committer content")
+ commit_result = git_repo_user_no_committer.commit(fnames=[str(fname)], aider_edits=False)
+ self.assertIsNotNone(commit_result)
+ commit = raw_repo.head.commit
+ self.assertEqual(commit.author.name, "Test User") # Author never modified for user commits
+ self.assertEqual(commit.committer.name, "Test User") # Explicit False prevents modification
+
def test_commit_with_co_authored_by(self):
# Cleanup of the git temp dir explodes on windows
if platform.system() == "Windows":
From 3e1bc77bf20ceec54699fc1141b6d90aaf1adc1a Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:56:18 +0300
Subject: [PATCH 054/482] test: add tests for commit author/committer
attribution logic
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 115 +++++++++++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 9633ec208..5d1ff335b 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -420,6 +420,121 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified (default True)
self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified (default True)
+ def test_commit_ai_edits_no_coauthor_explicit_false(self):
+ # Test AI edits (aider_edits=True) when co-authored-by is False,
+ # but author or committer attribution is explicitly disabled.
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # Setup repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ io = InputOutput()
+
+ # Case 1: attribute_author = False, attribute_committer = None (default True)
+ mock_coder_no_author = MagicMock()
+ mock_coder_no_author.args.attribute_co_authored_by = False
+ mock_coder_no_author.args.attribute_author = False # Explicit False
+ mock_coder_no_author.args.attribute_committer = None # Default True
+ mock_coder_no_author.args.attribute_commit_message_author = False
+ mock_coder_no_author.args.attribute_commit_message_committer = False
+ mock_coder_no_author.main_model = MagicMock()
+ mock_coder_no_author.main_model.name = "gpt-test-no-author"
+
+ git_repo_no_author = GitRepo(io, None, None)
+ fname.write_text("no author content")
+ commit_result = git_repo_no_author.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder_no_author, message="Aider no author")
+ self.assertIsNotNone(commit_result)
+ commit = raw_repo.head.commit
+ self.assertNotIn("Co-authored-by:", commit.message)
+ self.assertEqual(commit.author.name, "Test User") # Explicit False
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Default True
+
+ # Case 2: attribute_author = None (default True), attribute_committer = False
+ mock_coder_no_committer = MagicMock()
+ mock_coder_no_committer.args.attribute_co_authored_by = False
+ mock_coder_no_committer.args.attribute_author = None # Default True
+ mock_coder_no_committer.args.attribute_committer = False # Explicit False
+ mock_coder_no_committer.args.attribute_commit_message_author = False
+ mock_coder_no_committer.args.attribute_commit_message_committer = False
+ mock_coder_no_committer.main_model = MagicMock()
+ mock_coder_no_committer.main_model.name = "gpt-test-no-committer"
+
+ git_repo_no_committer = GitRepo(io, None, None)
+ fname.write_text("no committer content")
+ commit_result = git_repo_no_committer.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder_no_committer, message="Aider no committer")
+ self.assertIsNotNone(commit_result)
+ commit = raw_repo.head.commit
+ self.assertNotIn("Co-authored-by:", commit.message)
+ self.assertEqual(commit.author.name, "Test User (aider)") # Default True
+ self.assertEqual(commit.committer.name, "Test User") # Explicit False
+
+
+ def test_commit_user_edits_ignores_co_author(self):
+ # Test user edits (aider_edits=False) behavior regarding co-author and name attribution.
+ # Co-author should be ignored, Author never modified, Committer follows flag.
+ if platform.system() == "Windows":
+ return
+
+ with GitTemporaryDirectory():
+ # Setup repo
+ raw_repo = git.Repo()
+ raw_repo.config_writer().set_value("user", "name", "Test User").release()
+ raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
+ fname = Path("file.txt")
+ fname.touch()
+ raw_repo.git.add(str(fname))
+ raw_repo.git.commit("-m", "initial commit")
+
+ io = InputOutput()
+
+ # Case 1: co_author=True, committer=None (default True)
+ mock_coder_user_default = MagicMock()
+ mock_coder_user_default.args.attribute_co_authored_by = True # Should be ignored
+ mock_coder_user_default.args.attribute_author = True # Should be ignored
+ mock_coder_user_default.args.attribute_committer = None # Default True
+ mock_coder_user_default.args.attribute_commit_message_author = False
+ mock_coder_user_default.args.attribute_commit_message_committer = False
+ mock_coder_user_default.main_model = MagicMock()
+ mock_coder_user_default.main_model.name = "gpt-user-default"
+
+ git_repo_user_default = GitRepo(io, None, None)
+ fname.write_text("user default content")
+ commit_result = git_repo_user_default.commit(fnames=[str(fname)], aider_edits=False, coder=mock_coder_user_default, message="User default")
+ self.assertIsNotNone(commit_result)
+ commit = raw_repo.head.commit
+ self.assertNotIn("Co-authored-by:", commit.message) # Ignored
+ self.assertEqual(commit.author.name, "Test User") # Never modified
+ self.assertEqual(commit.committer.name, "Test User (aider)") # Default True
+
+ # Case 2: co_author=True, committer=False
+ mock_coder_user_no_committer = MagicMock()
+ mock_coder_user_no_committer.args.attribute_co_authored_by = True # Should be ignored
+ mock_coder_user_no_committer.args.attribute_author = True # Should be ignored
+ mock_coder_user_no_committer.args.attribute_committer = False # Explicit False
+ mock_coder_user_no_committer.args.attribute_commit_message_author = False
+ mock_coder_user_no_committer.args.attribute_commit_message_committer = False
+ mock_coder_user_no_committer.main_model = MagicMock()
+ mock_coder_user_no_committer.main_model.name = "gpt-user-no-committer"
+
+ # Need to init GitRepo with attribute_committer=False for this case
+ git_repo_user_no_committer = GitRepo(io, None, None, attribute_committer=False)
+ fname.write_text("user no committer content")
+ # Pass coder to simulate args being present, though GitRepo init matters more here
+ commit_result = git_repo_user_no_committer.commit(fnames=[str(fname)], aider_edits=False, coder=mock_coder_user_no_committer, message="User no committer")
+ self.assertIsNotNone(commit_result)
+ commit = raw_repo.head.commit
+ self.assertNotIn("Co-authored-by:", commit.message) # Ignored
+ self.assertEqual(commit.author.name, "Test User") # Never modified
+ self.assertEqual(commit.committer.name, "Test User") # Explicit False
+
def test_get_tracked_files(self):
# Create a temporary directory
From 9e91e8f1b2d2a0b13567da85da85fbfe046314bb Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:58:06 +0300
Subject: [PATCH 055/482] test: remove redundant commit attribution tests
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 104 ---------------------------------------
1 file changed, 104 deletions(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 5d1ff335b..a1224ce02 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -376,50 +376,6 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User")
self.assertEqual(commit.committer.name, "Test User")
-
- def test_commit_without_co_authored_by(self):
- # Test standard name modification when co-authored-by is False
- if platform.system() == "Windows":
- return
-
- with GitTemporaryDirectory():
- # new repo
- raw_repo = git.Repo()
- raw_repo.config_writer().set_value("user", "name", "Test User").release()
- raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
-
- # add a file and commit it
- fname = Path("file.txt")
- fname.touch()
- raw_repo.git.add(str(fname))
- raw_repo.git.commit("-m", "initial commit")
-
- # Mock coder args (co-authored-by False, author/committer default None)
- mock_coder = MagicMock()
- mock_coder.args.attribute_co_authored_by = False
- mock_coder.args.attribute_author = None # Default
- mock_coder.args.attribute_committer = None # Default
- mock_coder.args.attribute_commit_message_author = False
- mock_coder.args.attribute_commit_message_committer = False
- mock_coder.main_model = MagicMock()
- mock_coder.main_model.name = "gpt-test-no-coauthor"
-
-
- io = InputOutput()
- git_repo = GitRepo(io, None, None)
-
- # commit a change with aider_edits=True and default flags
- fname.write_text("new content")
- commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider edit")
- self.assertIsNotNone(commit_result)
-
- # check the commit message and author/committer (defaults interpreted as True)
- commit = raw_repo.head.commit
- self.assertNotIn("Co-authored-by:", commit.message)
- self.assertEqual(commit.message.splitlines()[0], "Aider edit")
- self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified (default True)
- self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified (default True)
-
def test_commit_ai_edits_no_coauthor_explicit_false(self):
# Test AI edits (aider_edits=True) when co-authored-by is False,
# but author or committer attribution is explicitly disabled.
@@ -476,66 +432,6 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User (aider)") # Default True
self.assertEqual(commit.committer.name, "Test User") # Explicit False
-
- def test_commit_user_edits_ignores_co_author(self):
- # Test user edits (aider_edits=False) behavior regarding co-author and name attribution.
- # Co-author should be ignored, Author never modified, Committer follows flag.
- if platform.system() == "Windows":
- return
-
- with GitTemporaryDirectory():
- # Setup repo
- raw_repo = git.Repo()
- raw_repo.config_writer().set_value("user", "name", "Test User").release()
- raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
- fname = Path("file.txt")
- fname.touch()
- raw_repo.git.add(str(fname))
- raw_repo.git.commit("-m", "initial commit")
-
- io = InputOutput()
-
- # Case 1: co_author=True, committer=None (default True)
- mock_coder_user_default = MagicMock()
- mock_coder_user_default.args.attribute_co_authored_by = True # Should be ignored
- mock_coder_user_default.args.attribute_author = True # Should be ignored
- mock_coder_user_default.args.attribute_committer = None # Default True
- mock_coder_user_default.args.attribute_commit_message_author = False
- mock_coder_user_default.args.attribute_commit_message_committer = False
- mock_coder_user_default.main_model = MagicMock()
- mock_coder_user_default.main_model.name = "gpt-user-default"
-
- git_repo_user_default = GitRepo(io, None, None)
- fname.write_text("user default content")
- commit_result = git_repo_user_default.commit(fnames=[str(fname)], aider_edits=False, coder=mock_coder_user_default, message="User default")
- self.assertIsNotNone(commit_result)
- commit = raw_repo.head.commit
- self.assertNotIn("Co-authored-by:", commit.message) # Ignored
- self.assertEqual(commit.author.name, "Test User") # Never modified
- self.assertEqual(commit.committer.name, "Test User (aider)") # Default True
-
- # Case 2: co_author=True, committer=False
- mock_coder_user_no_committer = MagicMock()
- mock_coder_user_no_committer.args.attribute_co_authored_by = True # Should be ignored
- mock_coder_user_no_committer.args.attribute_author = True # Should be ignored
- mock_coder_user_no_committer.args.attribute_committer = False # Explicit False
- mock_coder_user_no_committer.args.attribute_commit_message_author = False
- mock_coder_user_no_committer.args.attribute_commit_message_committer = False
- mock_coder_user_no_committer.main_model = MagicMock()
- mock_coder_user_no_committer.main_model.name = "gpt-user-no-committer"
-
- # Need to init GitRepo with attribute_committer=False for this case
- git_repo_user_no_committer = GitRepo(io, None, None, attribute_committer=False)
- fname.write_text("user no committer content")
- # Pass coder to simulate args being present, though GitRepo init matters more here
- commit_result = git_repo_user_no_committer.commit(fnames=[str(fname)], aider_edits=False, coder=mock_coder_user_no_committer, message="User no committer")
- self.assertIsNotNone(commit_result)
- commit = raw_repo.head.commit
- self.assertNotIn("Co-authored-by:", commit.message) # Ignored
- self.assertEqual(commit.author.name, "Test User") # Never modified
- self.assertEqual(commit.committer.name, "Test User") # Explicit False
-
-
def test_get_tracked_files(self):
# Create a temporary directory
tempdir = Path(tempfile.mkdtemp())
From 6a970c35152c350797bf44ee10f69ca23cd61dfa Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 19:58:29 +0300
Subject: [PATCH 056/482] test: remove redundant co-authored-by precedence test
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 54 ----------------------------------------
1 file changed, 54 deletions(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index a1224ce02..11523996f 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -322,60 +322,6 @@ class TestRepo(unittest.TestCase):
self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified
self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified
- def test_commit_co_authored_by_precedence_over_default(self):
- # Test that co-authored-by takes precedence over default (None) name modification
- if platform.system() == "Windows":
- return
-
- with GitTemporaryDirectory():
- # new repo
- raw_repo = git.Repo()
- raw_repo.config_writer().set_value("user", "name", "Test User").release()
- raw_repo.config_writer().set_value("user", "email", "test@example.com").release()
-
- # add a file and commit it
- fname = Path("file.txt")
- fname.touch()
- raw_repo.git.add(str(fname))
- raw_repo.git.commit("-m", "initial commit")
-
- # Mock coder args: Co-authored-by enabled, author/committer use default (None)
- mock_coder = MagicMock()
- mock_coder.args.attribute_co_authored_by = True
- mock_coder.args.attribute_author = None # Default
- mock_coder.args.attribute_committer = None # Default
- mock_coder.args.attribute_commit_message_author = False
- mock_coder.args.attribute_commit_message_committer = False
- mock_coder.main_model = MagicMock() # Define main_model before accessing name
- mock_coder.main_model.name = "gpt-precedence"
-
- io = InputOutput()
- # Initialize GitRepo directly with flags, simulating config/defaults
- # Use None for author/committer to test default behavior
- git_repo = GitRepo(
- io,
- None,
- None,
- attribute_co_authored_by=True,
- attribute_author=None, # Default
- attribute_committer=None, # Default
- )
-
- # commit a change with aider_edits=True and default flags
- fname.write_text("new content precedence")
- # Pass the coder object here to ensure its args are used if available,
- # but the GitRepo init already set the fallback values.
- commit_result = git_repo.commit(fnames=[str(fname)], aider_edits=True, coder=mock_coder, message="Aider precedence edit")
- self.assertIsNotNone(commit_result)
-
- # check the commit message and author/committer
- commit = raw_repo.head.commit
- self.assertIn("Co-authored-by: aider (gpt-precedence) ", commit.message)
- self.assertEqual(commit.message.splitlines()[0], "Aider precedence edit")
- # Co-authored-by should take precedence over default (None), names should NOT be modified
- self.assertEqual(commit.author.name, "Test User")
- self.assertEqual(commit.committer.name, "Test User")
-
def test_commit_ai_edits_no_coauthor_explicit_false(self):
# Test AI edits (aider_edits=True) when co-authored-by is False,
# but author or committer attribution is explicitly disabled.
From 5851d66174af65ffea837c57c22e51893898b229 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 20:00:44 +0300
Subject: [PATCH 057/482] test: improve test clarity with skipIf and assertion
messages
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
tests/basic/test_repo.py | 39 +++++++++++++--------------------------
1 file changed, 13 insertions(+), 26 deletions(-)
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 11523996f..4d5abac86 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -165,14 +165,11 @@ class TestRepo(unittest.TestCase):
args = mock_send.call_args[0] # Get positional args
self.assertEqual(args[0][0]["content"], custom_prompt) # Check first message content
+ @unittest.skipIf(platform.system() == "Windows", "Git env var behavior differs on Windows")
@patch("aider.repo.GitRepo.get_commit_message")
def test_commit_with_custom_committer_name(self, mock_send):
mock_send.return_value = '"a good commit message"'
- # Cleanup of the git temp dir explodes on windows
- if platform.system() == "Windows":
- return
-
with GitTemporaryDirectory():
# new repo
raw_repo = git.Repo()
@@ -229,14 +226,11 @@ class TestRepo(unittest.TestCase):
commit_result = git_repo_user_no_committer.commit(fnames=[str(fname)], aider_edits=False)
self.assertIsNotNone(commit_result)
commit = raw_repo.head.commit
- self.assertEqual(commit.author.name, "Test User") # Author never modified for user commits
- self.assertEqual(commit.committer.name, "Test User") # Explicit False prevents modification
+ self.assertEqual(commit.author.name, "Test User", msg="Author name should not be modified for user commits")
+ self.assertEqual(commit.committer.name, "Test User", msg="Committer name should not be modified when attribute_committer=False")
+ @unittest.skipIf(platform.system() == "Windows", "Git env var behavior differs on Windows")
def test_commit_with_co_authored_by(self):
- # Cleanup of the git temp dir explodes on windows
- if platform.system() == "Windows":
- return
-
with GitTemporaryDirectory():
# new repo
raw_repo = git.Repo()
@@ -274,14 +268,12 @@ class TestRepo(unittest.TestCase):
self.assertIn("Co-authored-by: aider (gpt-test) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider edit")
# With default (None), co-authored-by takes precedence
- self.assertEqual(commit.author.name, "Test User") # Should NOT be modified
- self.assertEqual(commit.committer.name, "Test User") # Should NOT be modified
+ self.assertEqual(commit.author.name, "Test User", msg="Author name should not be modified when co-authored-by takes precedence")
+ self.assertEqual(commit.committer.name, "Test User", msg="Committer name should not be modified when co-authored-by takes precedence")
+ @unittest.skipIf(platform.system() == "Windows", "Git env var behavior differs on Windows")
def test_commit_co_authored_by_with_explicit_name_modification(self):
# Test scenario where Co-authored-by is true AND author/committer modification are explicitly True
- if platform.system() == "Windows":
- return
-
with GitTemporaryDirectory():
# Setup repo...
# new repo
@@ -319,15 +311,13 @@ class TestRepo(unittest.TestCase):
self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
# When co-authored-by is true BUT author/committer are explicit True, modification SHOULD happen
- self.assertEqual(commit.author.name, "Test User (aider)") # Should be modified
- self.assertEqual(commit.committer.name, "Test User (aider)") # Should be modified
+ self.assertEqual(commit.author.name, "Test User (aider)", msg="Author name should be modified when explicitly True, even with co-author")
+ self.assertEqual(commit.committer.name, "Test User (aider)", msg="Committer name should be modified when explicitly True, even with co-author")
+ @unittest.skipIf(platform.system() == "Windows", "Git env var behavior differs on Windows")
def test_commit_ai_edits_no_coauthor_explicit_false(self):
# Test AI edits (aider_edits=True) when co-authored-by is False,
# but author or committer attribution is explicitly disabled.
- if platform.system() == "Windows":
- return
-
with GitTemporaryDirectory():
# Setup repo
raw_repo = git.Repo()
@@ -375,8 +365,8 @@ class TestRepo(unittest.TestCase):
self.assertIsNotNone(commit_result)
commit = raw_repo.head.commit
self.assertNotIn("Co-authored-by:", commit.message)
- self.assertEqual(commit.author.name, "Test User (aider)") # Default True
- self.assertEqual(commit.committer.name, "Test User") # Explicit False
+ self.assertEqual(commit.author.name, "Test User (aider)", msg="Author name should be modified (default True) when co-author=False")
+ self.assertEqual(commit.committer.name, "Test User", msg="Committer name should not be modified (explicit False) when co-author=False")
def test_get_tracked_files(self):
# Create a temporary directory
@@ -574,12 +564,9 @@ class TestRepo(unittest.TestCase):
commit_result = git_repo.commit(fnames=[str(fname)])
self.assertIsNone(commit_result)
+ @unittest.skipIf(platform.system() == "Windows", "Git hook execution differs on Windows")
def test_git_commit_verify(self):
"""Test that git_commit_verify controls whether --no-verify is passed to git commit"""
- # Skip on Windows as hook execution works differently
- if platform.system() == "Windows":
- return
-
with GitTemporaryDirectory():
# Create a new repo
raw_repo = git.Repo()
From 38dfd6f4f96110d0e9bb5fcd9fcea044f744b3c5 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 20:07:33 +0300
Subject: [PATCH 058/482] docs: clarify --attribute-co-authored-by precedence
---
aider/args.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/aider/args.py b/aider/args.py
index 7aaf10f2a..dfa84b6c2 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -458,7 +458,11 @@ def get_parser(default_config_files, git_root):
"--attribute-co-authored-by",
action=argparse.BooleanOptionalAction,
default=False,
- help="Attribute aider edits using the Co-authored-by trailer in the commit message (default: False).",
+ help=(
+ "Attribute aider edits using the Co-authored-by trailer in the commit message"
+ " (default: False). If True, this takes precedence over default --attribute-author and"
+ " --attribute-committer behavior unless they are explicitly set to True."
+ ),
)
group.add_argument(
"--git-commit-verify",
From 165e237be78c36437d1f2b5f0101546a1f4e2026 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 20:25:01 +0300
Subject: [PATCH 059/482] chore: remove unnecessary comment in repo.py
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/repo.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/repo.py b/aider/repo.py
index ad87a379a..85130e105 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -210,7 +210,7 @@ class GitRepo:
attribute_committer = coder.args.attribute_committer
attribute_commit_message_author = coder.args.attribute_commit_message_author
attribute_commit_message_committer = coder.args.attribute_commit_message_committer
- attribute_co_authored_by = coder.args.attribute_co_authored_by # <-- Restored
+ attribute_co_authored_by = coder.args.attribute_co_authored_by
else:
# Fallback to self attributes (initialized from config/defaults)
attribute_author = self.attribute_author
From 3f94fd5e4edd2205a24d5716c4dec3e9075f3b56 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 20:38:25 +0300
Subject: [PATCH 060/482] refactor: Simplify access to attribute_co_authored_by
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/repo.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/repo.py b/aider/repo.py
index 85130e105..0fa58ab7d 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -217,7 +217,7 @@ class GitRepo:
attribute_committer = self.attribute_committer
attribute_commit_message_author = self.attribute_commit_message_author
attribute_commit_message_committer = self.attribute_commit_message_committer
- attribute_co_authored_by = getattr(self, "attribute_co_authored_by", False) # Should be False if not set
+ attribute_co_authored_by = self.attribute_co_authored_by
# Determine explicit settings (None means use default behavior)
author_explicit = attribute_author is not None
From 1d42690824f4208c612210b73b6d002830aa7882 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Sat, 12 Apr 2025 20:50:29 +0300
Subject: [PATCH 061/482] fix: update co-authored-by domain to aider.chat
Co-authored-by: aider (vertex_ai/gemini-2.5-pro-exp-03-25)
---
aider/repo.py | 4 ++--
tests/basic/test_repo.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/aider/repo.py b/aider/repo.py
index 0fa58ab7d..aa2d525f7 100644
--- a/aider/repo.py
+++ b/aider/repo.py
@@ -162,7 +162,7 @@ class GitRepo:
Flags:
- --attribute-author: Modify Author name to "User Name (aider)".
- --attribute-committer: Modify Committer name to "User Name (aider)".
- - --attribute-co-authored-by: Add "Co-authored-by: aider () "
+ - --attribute-co-authored-by: Add "Co-authored-by: aider () "
trailer to the commit message.
Behavior Summary:
@@ -240,7 +240,7 @@ class GitRepo:
if coder and hasattr(coder, "main_model") and coder.main_model.name:
model_name = coder.main_model.name
commit_message_trailer = (
- f"\n\nCo-authored-by: aider ({model_name}) "
+ f"\n\nCo-authored-by: aider ({model_name}) "
)
# Determine if author/committer names should be modified
diff --git a/tests/basic/test_repo.py b/tests/basic/test_repo.py
index 4d5abac86..400c307a8 100644
--- a/tests/basic/test_repo.py
+++ b/tests/basic/test_repo.py
@@ -265,7 +265,7 @@ class TestRepo(unittest.TestCase):
# check the commit message and author/committer
commit = raw_repo.head.commit
- self.assertIn("Co-authored-by: aider (gpt-test) ", commit.message)
+ self.assertIn("Co-authored-by: aider (gpt-test) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider edit")
# With default (None), co-authored-by takes precedence
self.assertEqual(commit.author.name, "Test User", msg="Author name should not be modified when co-authored-by takes precedence")
@@ -308,7 +308,7 @@ class TestRepo(unittest.TestCase):
# check the commit message and author/committer
commit = raw_repo.head.commit
- self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
+ self.assertIn("Co-authored-by: aider (gpt-test-combo) ", commit.message)
self.assertEqual(commit.message.splitlines()[0], "Aider combo edit")
# When co-authored-by is true BUT author/committer are explicit True, modification SHOULD happen
self.assertEqual(commit.author.name, "Test User (aider)", msg="Author name should be modified when explicitly True, even with co-author")
From f106993cd1704a20e102c3e987031b7becee0a56 Mon Sep 17 00:00:00 2001
From: Andrew Grigorev
Date: Tue, 15 Apr 2025 01:35:00 +0300
Subject: [PATCH 062/482] fix: add --disable-playwright option to suppress
Playwright prompts and usage
Co-authored-by: aider (openai/gpt-4.1)
---
aider/args.py | 6 ++
aider/commands.py | 14 ++-
tests/scrape/test_playwright_disable.py | 120 ++++++++++++++++++++++++
3 files changed, 136 insertions(+), 4 deletions(-)
create mode 100644 tests/scrape/test_playwright_disable.py
diff --git a/aider/args.py b/aider/args.py
index 6df19778b..1bc1aaed2 100644
--- a/aider/args.py
+++ b/aider/args.py
@@ -670,6 +670,12 @@ def get_parser(default_config_files, git_root):
######
group = parser.add_argument_group("Other settings")
+ group.add_argument(
+ "--disable-playwright",
+ action="store_true",
+ help="Never prompt for or attempt to install Playwright for web scraping (default: False).",
+ default=False,
+ )
group.add_argument(
"--file",
action="append",
diff --git a/aider/commands.py b/aider/commands.py
index 81fc80093..29f20a976 100644
--- a/aider/commands.py
+++ b/aider/commands.py
@@ -220,12 +220,18 @@ class Commands:
self.io.tool_output(f"Scraping {url}...")
if not self.scraper:
- res = install_playwright(self.io)
- if not res:
- self.io.tool_warning("Unable to initialize playwright.")
+ disable_playwright = getattr(self.args, "disable_playwright", False)
+ if disable_playwright:
+ res = False
+ else:
+ res = install_playwright(self.io)
+ if not res:
+ self.io.tool_warning("Unable to initialize playwright.")
self.scraper = Scraper(
- print_error=self.io.tool_error, playwright_available=res, verify_ssl=self.verify_ssl
+ print_error=self.io.tool_error,
+ playwright_available=res,
+ verify_ssl=self.verify_ssl,
)
content = self.scraper.scrape(url) or ""
diff --git a/tests/scrape/test_playwright_disable.py b/tests/scrape/test_playwright_disable.py
new file mode 100644
index 000000000..df777752b
--- /dev/null
+++ b/tests/scrape/test_playwright_disable.py
@@ -0,0 +1,120 @@
+import pytest
+from unittest.mock import MagicMock
+
+from aider.scrape import install_playwright, Scraper
+
+class DummyIO:
+ def __init__(self):
+ self.outputs = []
+ self.confirmed = False
+
+ def tool_output(self, msg):
+ self.outputs.append(msg)
+
+ def confirm_ask(self, msg, default="y"):
+ self.outputs.append(f"confirm: {msg}")
+ return self.confirmed
+
+ def tool_error(self, msg):
+ self.outputs.append(f"error: {msg}")
+
+
+def test_scraper_disable_playwright_flag(monkeypatch):
+ io = DummyIO()
+ # Simulate that playwright is not available (disable_playwright just means playwright_available=False)
+ scraper = Scraper(print_error=io.tool_error, playwright_available=False)
+ # Patch scrape_with_httpx to check it is called
+ called = {}
+ def fake_httpx(url):
+ called['called'] = True
+ return "plain text", "text/plain"
+ scraper.scrape_with_httpx = fake_httpx
+ content = scraper.scrape("http://example.com")
+ assert content == "plain text"
+ assert called['called']
+
+def test_scraper_enable_playwright(monkeypatch):
+ io = DummyIO()
+ # Simulate that playwright is available and should be used
+ scraper = Scraper(print_error=io.tool_error, playwright_available=True)
+ # Patch scrape_with_playwright to check it is called
+ called = {}
+ def fake_playwright(url):
+ called['called'] = True
+ return "hi", "text/html"
+ scraper.scrape_with_playwright = fake_playwright
+ content = scraper.scrape("http://example.com")
+ assert content.startswith("hi") or "" in content
+ assert called['called']
+
+def test_commands_web_disable_playwright(monkeypatch):
+ """
+ Test that Commands.cmd_web does not emit a misleading warning when --disable-playwright is set.
+ """
+ from aider.commands import Commands
+
+ # Dummy IO to capture outputs and warnings
+ class DummyIO:
+ def __init__(self):
+ self.outputs = []
+ self.warnings = []
+ self.errors = []
+ def tool_output(self, msg, *a, **k):
+ self.outputs.append(msg)
+ def tool_warning(self, msg, *a, **k):
+ self.warnings.append(msg)
+ def tool_error(self, msg, *a, **k):
+ self.errors.append(msg)
+ def read_text(self, filename, silent=False):
+ return ""
+ def confirm_ask(self, *a, **k):
+ return True
+ def print(self, *a, **k):
+ pass
+
+ # Dummy coder to satisfy Commands
+ class DummyCoder:
+ def __init__(self):
+ self.cur_messages = []
+ self.main_model = type("M", (), {"edit_format": "code", "name": "dummy", "info": {}})
+ def get_rel_fname(self, fname):
+ return fname
+ def get_inchat_relative_files(self):
+ return []
+ def abs_root_path(self, fname):
+ return fname
+ def get_all_abs_files(self):
+ return []
+ def get_announcements(self):
+ return []
+ def format_chat_chunks(self):
+ return type("Chunks", (), {"repo": [], "readonly_files": [], "chat_files": []})()
+ def event(self, *a, **k):
+ pass
+
+ # Patch install_playwright to always return False (simulate not available)
+ monkeypatch.setattr("aider.scrape.install_playwright", lambda io: False)
+
+ # Patch Scraper to always use scrape_with_httpx and never warn
+ class DummyScraper:
+ def __init__(self, **kwargs):
+ self.called = False
+ def scrape(self, url):
+ self.called = True
+ return "dummy content"
+
+ monkeypatch.setattr("aider.commands.Scraper", DummyScraper)
+
+ io = DummyIO()
+ coder = DummyCoder()
+ args = type("Args", (), {"disable_playwright": True})()
+ commands = Commands(io, coder, args=args)
+
+ commands.cmd_web("http://example.com")
+ # Should not emit a warning about playwright
+ assert not io.warnings
+ # Should not contain message "For the best web scraping, install Playwright:"
+ assert all("install Playwright:" not in msg for msg in io.outputs)
+ # Should output scraping and added to chat
+ assert any("Scraping" in msg for msg in io.outputs)
+ assert any("added to chat" in msg for msg in io.outputs)
From 80909e17c7296a66fa35a873f4a6a3b200266b50 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Wed, 16 Apr 2025 18:16:55 -0700
Subject: [PATCH 063/482] set version to 0.82.2.dev
---
aider/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/__init__.py b/aider/__init__.py
index d2570493f..4f91e3f8a 100644
--- a/aider/__init__.py
+++ b/aider/__init__.py
@@ -1,6 +1,6 @@
from packaging import version
-__version__ = "0.82.1"
+__version__ = "0.82.2.dev"
safe_version = __version__
try:
From ed14be4e705644e2c05bf60a4a5bed2eca092d7a Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Wed, 16 Apr 2025 19:00:18 -0700
Subject: [PATCH 064/482] refactor: Use constant for max display cost cap in
leaderboard table
---
aider/website/_includes/leaderboard_table.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index ff7b13f0f..a71811fa8 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -1,6 +1,7 @@
document.addEventListener('DOMContentLoaded', function() {
let currentMode = 'view'; // 'view', 'select', 'detail'
let selectedRows = new Set(); // Store indices of selected rows
+ const MAX_DISPLAY_COST_CAP = 50; // Define the constant here
const allMainRows = document.querySelectorAll('tr[id^="main-row-"]');
const allDetailsRows = document.querySelectorAll('tr[id^="details-"]');
@@ -219,7 +220,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Function to calculate the appropriate max display cost based on visible/selected entries
function calculateDisplayMaxCost() {
// Get the appropriate set of rows based on the current mode and selection state
- let rowsToConsider;
+ let rowsToConsider;
if (currentMode === 'view' && selectedRows.size > 0) {
// In view mode with selections, only consider selected rows
@@ -242,8 +243,8 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
- // Cap at 50 if any entries exceed that amount, otherwise use actual max
- return maxCost > 50 ? 50 : Math.max(1, maxCost); // Ensure at least 1 to avoid division by zero
+ // Cap at MAX_DISPLAY_COST_CAP if any entries exceed that amount, otherwise use actual max
+ return maxCost > MAX_DISPLAY_COST_CAP ? MAX_DISPLAY_COST_CAP : Math.max(1, maxCost); // Ensure at least 1 to avoid division by zero
}
// Process cost bars with dynamic scale
@@ -264,7 +265,7 @@ document.addEventListener('DOMContentLoaded', function() {
bar.style.width = Math.max(0, Math.min(100, percent)) + '%';
// Mark bars that exceed the limit (only if our display max is capped at 50)
- if (currentMaxDisplayCost === 50 && cost > 50) {
+ if (currentMaxDisplayCost === MAX_DISPLAY_COST_CAP && cost > MAX_DISPLAY_COST_CAP) {
// Create a darker section at the end with diagonal stripes
const darkSection = document.createElement('div');
darkSection.className = 'bar-viz dark-section';
From 57abaf7500daf781834c2fd438a0f891d8414b3c Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Wed, 16 Apr 2025 19:02:09 -0700
Subject: [PATCH 065/482] add o3+4.1
---
aider/website/_data/polyglot_leaderboard.yml | 30 +++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/aider/website/_data/polyglot_leaderboard.yml b/aider/website/_data/polyglot_leaderboard.yml
index 66e1c84dd..40340a4d9 100644
--- a/aider/website/_data/polyglot_leaderboard.yml
+++ b/aider/website/_data/polyglot_leaderboard.yml
@@ -1143,4 +1143,32 @@
date: 2025-04-16
versions: 0.82.1.dev
seconds_per_case: 176.5
- total_cost: 19.6399
\ No newline at end of file
+ total_cost: 19.6399
+
+- dirname: 2025-04-17-01-20-35--o3-mini-high-diff-arch
+ test_cases: 225
+ model: o3 (high) + gpt-4.1
+ edit_format: architect
+ commit_hash: 80909e1-dirty
+ editor_model: gpt-4.1
+ editor_edit_format: editor-diff
+ pass_rate_1: 36.0
+ pass_rate_2: 82.7
+ pass_num_1: 81
+ pass_num_2: 186
+ percent_cases_well_formed: 100.0
+ error_outputs: 9
+ num_malformed_responses: 0
+ num_with_malformed_responses: 0
+ user_asks: 166
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 0
+ test_timeouts: 0
+ total_tests: 225
+ command: aider --model o3 --architect
+ date: 2025-04-17
+ versions: 0.82.2.dev
+ seconds_per_case: 110.0
+ total_cost: 69.2921
\ No newline at end of file
From 00e5c334446ed556df636279d82cfdd8a8c34caf Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Wed, 16 Apr 2025 19:02:19 -0700
Subject: [PATCH 066/482] copy
---
HISTORY.md | 6 +
aider/website/HISTORY.md | 9 +
aider/website/_includes/leaderboard_table.js | 2 +-
aider/website/assets/sample-analytics.jsonl | 280 +++++++++---------
.../website/docs/config/adv-model-settings.md | 4 +
aider/website/docs/faq.md | 17 +-
6 files changed, 166 insertions(+), 152 deletions(-)
diff --git a/HISTORY.md b/HISTORY.md
index a466de37e..99398aa22 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,11 @@
# Release history
+### Aider v0.82.1
+- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
+- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
+- Disabled streaming for `o3` models since you need identity verification to stream.
+- Fixed handling of file paths in unified diffs, especially those generated by git.
+
### Aider v0.82.0
- Support for GPT 4.1, mini and nano.
diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md
index 33888c80c..379babfc0 100644
--- a/aider/website/HISTORY.md
+++ b/aider/website/HISTORY.md
@@ -24,6 +24,15 @@ cog.out(text)
]]]-->
+### main branch
+- Aider wrote 52% of the code in this release.
+
+### Aider v0.82.1
+- Added support for `o3` (GPT-4 Omni) and `o4-mini` (GPT-4 Omni Mini) model aliases, including provider-specific versions for OpenAI, OpenRouter, and Azure.
+- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
+- Disabled streaming for `o3` models to improve reliability.
+- Fixed handling of file paths in unified diffs, especially those generated by git.
+
### Aider v0.82.0
- Support for GPT 4.1, mini and nano.
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index a71811fa8..2b51d07eb 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -1,7 +1,7 @@
document.addEventListener('DOMContentLoaded', function() {
let currentMode = 'view'; // 'view', 'select', 'detail'
let selectedRows = new Set(); // Store indices of selected rows
- const MAX_DISPLAY_COST_CAP = 50; // Define the constant here
+ const MAX_DISPLAY_COST_CAP = 75; // Define the constant here
const allMainRows = document.querySelectorAll('tr[id^="main-row-"]');
const allDetailsRows = document.querySelectorAll('tr[id^="details-"]');
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index c834c66fd..73b57ec5e 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,143 +1,3 @@
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10040, "completion_tokens": 256, "total_tokens": 10296, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559424}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559424}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 7710, "completion_tokens": 409, "total_tokens": 8119, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559431}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559545}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10574, "completion_tokens": 978, "total_tokens": 11552, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559562}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559562}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8660, "completion_tokens": 1352, "total_tokens": 10012, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559577}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559638}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559641}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559649}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10656, "completion_tokens": 280, "total_tokens": 10936, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559655}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559655}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8273, "completion_tokens": 7064, "total_tokens": 15337, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559712}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559733}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10986, "completion_tokens": 186, "total_tokens": 11172, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559738}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559738}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8187, "completion_tokens": 258, "total_tokens": 8445, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559743}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559784}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 11211, "completion_tokens": 284, "total_tokens": 11495, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559789}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559789}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8284, "completion_tokens": 352, "total_tokens": 8636, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559795}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559905}
-{"event": "command_edit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559915}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559969}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559978}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559979}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10433, "completion_tokens": 178, "total_tokens": 10611, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559990}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559990}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8176, "completion_tokens": 239, "total_tokens": 8415, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744559995}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560006}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560033}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10661, "completion_tokens": 214, "total_tokens": 10875, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560052}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560052}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8213, "completion_tokens": 247, "total_tokens": 8460, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560058}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560071}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560096}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560114}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10376, "completion_tokens": 225, "total_tokens": 10601, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560125}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560125}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8224, "completion_tokens": 228, "total_tokens": 8452, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560130}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560133}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560139}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10674, "completion_tokens": 364, "total_tokens": 11038, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560152}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560153}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8363, "completion_tokens": 349, "total_tokens": 8712, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560158}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560172}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560468}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 11076, "completion_tokens": 195, "total_tokens": 11271, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560473}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560473}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8193, "completion_tokens": 208, "total_tokens": 8401, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560477}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560537}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 11372, "completion_tokens": 295, "total_tokens": 11667, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560548}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560548}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8362, "completion_tokens": 295, "total_tokens": 8657, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560552}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560615}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560617}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560619}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560659}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10365, "completion_tokens": 2227, "total_tokens": 12592, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560689}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560689}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 10226, "completion_tokens": 2576, "total_tokens": 12802, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560713}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560796}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12824, "completion_tokens": 803, "total_tokens": 13627, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560811}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560811}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8998, "completion_tokens": 994, "total_tokens": 9992, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560821}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560865}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 13799, "completion_tokens": 419, "total_tokens": 14218, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560874}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560874}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8744, "completion_tokens": 477, "total_tokens": 9221, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744560899}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562425}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 14378, "completion_tokens": 161, "total_tokens": 14539, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562430}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562431}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8587, "completion_tokens": 174, "total_tokens": 8761, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562434}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562467}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 14584, "completion_tokens": 260, "total_tokens": 14844, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562487}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562487}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8700, "completion_tokens": 192, "total_tokens": 8892, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562491}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562503}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562505}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562518}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 14863, "completion_tokens": 549, "total_tokens": 15412, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562541}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562541}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8974, "completion_tokens": 359, "total_tokens": 9333, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562546}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562572}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562588}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562837}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10772, "completion_tokens": 138, "total_tokens": 10910, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562847}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562847}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 8536, "completion_tokens": 193, "total_tokens": 8729, "cost": 0, "total_cost": 1.4117526000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562851}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562858}
-{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562861}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562864}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562866}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10296, "completion_tokens": 583, "total_tokens": 10879, "cost": 0.039633, "total_cost": 1.4513856000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562879}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562879}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "None", "edit_format": "editor-diff", "prompt_tokens": 8305, "completion_tokens": 164, "total_tokens": 8469, "cost": 0, "total_cost": 1.4513856000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562882}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562896}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562901}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562935}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10312, "completion_tokens": 956, "total_tokens": 11268, "cost": 0.045276000000000004, "total_cost": 1.4966616000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562959}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562959}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "None", "edit_format": "editor-diff", "prompt_tokens": 8404, "completion_tokens": 511, "total_tokens": 8915, "cost": 0, "total_cost": 1.4966616000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562966}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562978}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744562999}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563017}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10277, "completion_tokens": 1270, "total_tokens": 11547, "cost": 0.049881, "total_cost": 1.5465426000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563037}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563038}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "None", "edit_format": "editor-diff", "prompt_tokens": 8964, "completion_tokens": 1003, "total_tokens": 9967, "cost": 0, "total_cost": 1.5465426000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563046}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563123}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 11344, "completion_tokens": 1059, "total_tokens": 12403, "cost": 0.049917, "total_cost": 1.5964596000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563141}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563142}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "None", "edit_format": "editor-diff", "prompt_tokens": 8956, "completion_tokens": 1124, "total_tokens": 10080, "cost": 0, "total_cost": 1.5964596000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563151}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563241}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12399, "completion_tokens": 407, "total_tokens": 12806, "cost": 0.043302, "total_cost": 1.6397616000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563250}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563250}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "None", "edit_format": "editor-diff", "prompt_tokens": 8558, "completion_tokens": 517, "total_tokens": 9075, "cost": 0, "total_cost": 1.6397616000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744563257}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564634}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564749}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564751}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564751}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564751}
-{"event": "message_send", "properties": {"main_model": "openrouter/REDACTED", "weak_model": "openrouter/REDACTED", "editor_model": "openrouter/REDACTED", "edit_format": "whole", "prompt_tokens": 1705, "completion_tokens": 353, "total_tokens": 2058, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564759}
-{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564759}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564778}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564780}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564780}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564780}
-{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744564782}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565369}
-{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565371}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565405}
-{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565407}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565462}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565463}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565463}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565464}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565470}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565496}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 22090, "completion_tokens": 843, "total_tokens": 22933, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565511}
-{"event": "command_diff", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565528}
{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565542}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565555}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 23619, "completion_tokens": 284, "total_tokens": 23903, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565560}
@@ -998,3 +858,143 @@
{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852322}
{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852322}
{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852324}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852418}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852419}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852419}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852419}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852419}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852419}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852420}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852421}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852422}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852422}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852422}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852422}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852422}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852423}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852424}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852425}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852426}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852427}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852427}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852427}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852427}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852513}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852514}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852514}
+{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852514}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852514}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852514}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852515}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852515}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852515}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852551}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852553}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852553}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852553}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852556}
+{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852556}
+{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852556}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852577}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852579}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852579}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852579}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gpt-4.1-mini", "editor_model": "gpt-4.1", "edit_format": "diff", "prompt_tokens": 2371, "completion_tokens": 70, "total_tokens": 2441, "cost": 0.026510000000000002, "total_cost": 0.026510000000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852582}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852582}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852785}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852788}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852788}
+{"event": "cli session", "properties": {"main_model": "huggingface/REDACTED", "weak_model": "huggingface/REDACTED", "editor_model": "huggingface/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852788}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852789}
+{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852857}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852879}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852879}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852879}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852880}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852896}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852905}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852987}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852990}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852990}
+{"event": "cli session", "properties": {"main_model": "huggingface/REDACTED", "weak_model": "huggingface/REDACTED", "editor_model": "huggingface/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852990}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744852991}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853024}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853033}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853036}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853036}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853036}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853057}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853059}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853059}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853059}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853069}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853206}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853209}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853209}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853209}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853216}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853270}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853270}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853270}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853270}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 7310, "completion_tokens": 173, "total_tokens": 7483, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853291}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853291}
diff --git a/aider/website/docs/config/adv-model-settings.md b/aider/website/docs/config/adv-model-settings.md
index 5dedf94b0..c4c29e21e 100644
--- a/aider/website/docs/config/adv-model-settings.md
+++ b/aider/website/docs/config/adv-model-settings.md
@@ -904,6 +904,10 @@ cog.out("```\n")
weak_model_name: gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
+ extra_params:
+ extra_body:
+ reasoning_effort: high
+ streaming: false
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index d8fe3ba8f..5c9b67795 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,20 +264,15 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 3,259,444 84.4%
-openrouter/anthropic/claude-3.7-sonnet 534,009 13.8%
-gemini/gemini-2.5-pro-preview-03-25 16,524 0.4%
-o4-mini 16,499 0.4%
-gpt-4.1-mini 11,775 0.3%
+gemini/gemini-2.5-pro-exp-03-25 2,810,456 83.8%
+openrouter/anthropic/claude-3.7-sonnet 475,106 14.2%
+gemini/gemini-2.5-pro-preview-03-25 16,524 0.5%
+o4-mini 16,499 0.5%
+gpt-4.1-mini 11,775 0.4%
gpt-4.1 10,687 0.3%
None 8,001 0.2%
-o3 2,521 0.1%
-openrouter/REDACTED 2,058 0.1%
+o3 4,962 0.1%
-
-{: .note :}
-Some models show as REDACTED, because they are new or unpopular models.
-Aider's analytics only records the names of "well known" LLMs.
## How are the "aider wrote xx% of code" stats computed?
From 3e0af2cc846b611f3f85be823d31fa3dce5f4dcd Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Wed, 16 Apr 2025 19:04:13 -0700
Subject: [PATCH 067/482] copy
---
aider/website/_includes/leaderboard_table.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index 2b51d07eb..a71811fa8 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -1,7 +1,7 @@
document.addEventListener('DOMContentLoaded', function() {
let currentMode = 'view'; // 'view', 'select', 'detail'
let selectedRows = new Set(); // Store indices of selected rows
- const MAX_DISPLAY_COST_CAP = 75; // Define the constant here
+ const MAX_DISPLAY_COST_CAP = 50; // Define the constant here
const allMainRows = document.querySelectorAll('tr[id^="main-row-"]');
const allDetailsRows = document.querySelectorAll('tr[id^="details-"]');
From 739e01da95ea4b2f7860b35a4d5562ab9742bcb2 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Wed, 16 Apr 2025 19:10:24 -0700
Subject: [PATCH 068/482] copy
---
aider/website/_includes/leaderboard_table.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index 2b51d07eb..8f9f40a82 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', function() {
const selectAllCheckbox = document.getElementById('select-all-checkbox');
const leaderboardTitle = document.getElementById('leaderboard-title'); // Get title element
const defaultTitle = "Aider polyglot coding leaderboard";
- const filteredTitle = "Aider polyglot coding benchmark results";
+ const filteredTitle = "Aider polyglot coding benchmark results (selected)";
function applySearchFilter() {
const searchTerm = searchInput.value.toLowerCase();
From 9e548988666c5ce1bcc81e74197b5c2284e5bf86 Mon Sep 17 00:00:00 2001
From: zjy1412
Date: Thu, 17 Apr 2025 14:30:13 +0800
Subject: [PATCH 069/482] fix: correctly detect edit blocks in diff-fenced mode
---
aider/coders/editblock_coder.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py
index 321a6a921..4d7776278 100644
--- a/aider/coders/editblock_coder.py
+++ b/aider/coders/editblock_coder.py
@@ -454,7 +454,10 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
"```csh",
"```tcsh",
]
- next_is_editblock = i + 1 < len(lines) and head_pattern.match(lines[i + 1].strip())
+
+ # Check if the next line or the one after that is an editblock
+ next_is_editblock = (i + 1 < len(lines) and head_pattern.match(lines[i + 1].strip())
+ or i + 2 < len(lines) and head_pattern.match(lines[i + 2].strip()))
if any(line.strip().startswith(start) for start in shell_starts) and not next_is_editblock:
shell_content = []
From a564f94bf34ef9611f14fda40640ffc4aaf64423 Mon Sep 17 00:00:00 2001
From: zjy1412
Date: Thu, 17 Apr 2025 16:50:54 +0800
Subject: [PATCH 070/482] Added two test cases
---
tests/basic/test_editblock.py | 63 +++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/tests/basic/test_editblock.py b/tests/basic/test_editblock.py
index 0a1f1bf5b..d80952bbe 100644
--- a/tests/basic/test_editblock.py
+++ b/tests/basic/test_editblock.py
@@ -575,6 +575,69 @@ Hope you like it!
edits = list(eb.find_original_update_blocks(edit, fence=quad_backticks))
self.assertEqual(edits, [("foo.txt", "", "Tooooo\n")])
+ #Test for shell script blocks with sh language identifier (issue #3785)
+ def test_find_original_update_blocks_with_sh_language_identifier(self):
+ # https://github.com/Aider-AI/aider/issues/3785
+ edit = """
+Here's a shell script:
+
+```sh
+test_hello.sh
+<<<<<<< SEARCH
+=======
+#!/bin/bash
+# Check if exactly one argument is provided
+if [ "$#" -ne 1 ]; then
+ echo "Usage: $0 " >&2
+ exit 1
+fi
+
+# Echo the first argument
+echo "$1"
+
+exit 0
+>>>>>>> REPLACE
+```
+"""
+
+ edits = list(eb.find_original_update_blocks(edit))
+ # Instead of comparing exact strings, check that we got the right file and structure
+ self.assertEqual(len(edits), 1)
+ self.assertEqual(edits[0][0], "test_hello.sh")
+ self.assertEqual(edits[0][1], "")
+
+ # Check that the content contains the expected shell script elements
+ result_content = edits[0][2]
+ self.assertIn("#!/bin/bash", result_content)
+ self.assertIn("if [ \"$#\" -ne 1 ];", result_content)
+ self.assertIn("echo \"Usage: $0 \"", result_content)
+ self.assertIn("exit 1", result_content)
+ self.assertIn("echo \"$1\"", result_content)
+ self.assertIn("exit 0", result_content)
+
+ #Test for C# code blocks with csharp language identifier
+ def test_find_original_update_blocks_with_csharp_language_identifier(self):
+ edit = """
+Here's a C# code change:
+
+```csharp
+Program.cs
+<<<<<<< SEARCH
+Console.WriteLine("Hello World!");
+=======
+Console.WriteLine("Hello, C# World!");
+>>>>>>> REPLACE
+```
+"""
+
+ edits = list(eb.find_original_update_blocks(edit))
+ search_text = "Console.WriteLine(\"Hello World!\");\n"
+ replace_text = "Console.WriteLine(\"Hello, C# World!\");\n"
+ self.assertEqual(
+ edits,
+ [("Program.cs", search_text, replace_text)]
+ )
+
if __name__ == "__main__":
unittest.main()
From a08ffc3513ead0484c253d4089d0e9598654cd3f Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 17 Apr 2025 09:28:07 -0700
Subject: [PATCH 071/482] scale
---
aider/website/_includes/leaderboard_table.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index 8e1decee5..8f9f40a82 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -1,7 +1,7 @@
document.addEventListener('DOMContentLoaded', function() {
let currentMode = 'view'; // 'view', 'select', 'detail'
let selectedRows = new Set(); // Store indices of selected rows
- const MAX_DISPLAY_COST_CAP = 50; // Define the constant here
+ const MAX_DISPLAY_COST_CAP = 75; // Define the constant here
const allMainRows = document.querySelectorAll('tr[id^="main-row-"]');
const allDetailsRows = document.querySelectorAll('tr[id^="details-"]');
From bdfda399cb5af478775c94550de18062c268deeb Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 17 Apr 2025 09:29:35 -0700
Subject: [PATCH 072/482] copy
---
aider/website/HISTORY.md | 7 ++--
aider/website/assets/sample-analytics.jsonl | 36 +++++++++----------
.../website/docs/config/adv-model-settings.md | 3 --
aider/website/docs/faq.md | 6 ++--
4 files changed, 23 insertions(+), 29 deletions(-)
diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md
index 379babfc0..20b70ec6a 100644
--- a/aider/website/HISTORY.md
+++ b/aider/website/HISTORY.md
@@ -24,13 +24,10 @@ cog.out(text)
]]]-->
-### main branch
-- Aider wrote 52% of the code in this release.
-
### Aider v0.82.1
-- Added support for `o3` (GPT-4 Omni) and `o4-mini` (GPT-4 Omni Mini) model aliases, including provider-specific versions for OpenAI, OpenRouter, and Azure.
+- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
-- Disabled streaming for `o3` models to improve reliability.
+- Disabled streaming for `o3` models since you need identity verification to stream.
- Fixed handling of file paths in unified diffs, especially those generated by git.
### Aider v0.82.0
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index 73b57ec5e..6400c1af4 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,21 +1,3 @@
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565542}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565555}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 23619, "completion_tokens": 284, "total_tokens": 23903, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565560}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565583}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 24022, "completion_tokens": 273, "total_tokens": 24295, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565589}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565610}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 24408, "completion_tokens": 210, "total_tokens": 24618, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744565615}
-{"event": "command_reset", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566181}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566183}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566197}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 10775, "completion_tokens": 319, "total_tokens": 11094, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566203}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566225}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 11779, "completion_tokens": 29, "total_tokens": 11808, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566229}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566695}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566696}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566696}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566696}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566703}
{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566707}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566733}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 12803, "completion_tokens": 139, "total_tokens": 12942, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566740}
@@ -998,3 +980,21 @@
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853270}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 7310, "completion_tokens": 173, "total_tokens": 7483, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853291}
{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744853291}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855133}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855134}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855134}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855134}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855140}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855150}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 9490, "completion_tokens": 2108, "total_tokens": 11598, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855168}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855169}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 12680, "completion_tokens": 2039, "total_tokens": 14719, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855184}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855185}
+{"event": "command_architect", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855188}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855202}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855204}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855205}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 8474, "completion_tokens": 301, "total_tokens": 8775, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855212}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855212}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 6080, "completion_tokens": 477, "total_tokens": 6557, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855217}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855261}
diff --git a/aider/website/docs/config/adv-model-settings.md b/aider/website/docs/config/adv-model-settings.md
index c4c29e21e..ded10691a 100644
--- a/aider/website/docs/config/adv-model-settings.md
+++ b/aider/website/docs/config/adv-model-settings.md
@@ -904,9 +904,6 @@ cog.out("```\n")
weak_model_name: gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
- extra_params:
- extra_body:
- reasoning_effort: high
streaming: false
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index 5c9b67795..b86aaf0c3 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,14 +264,14 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 2,810,456 83.8%
-openrouter/anthropic/claude-3.7-sonnet 475,106 14.2%
+gemini/gemini-2.5-pro-exp-03-25 2,756,387 83.5%
+openrouter/anthropic/claude-3.7-sonnet 475,106 14.4%
gemini/gemini-2.5-pro-preview-03-25 16,524 0.5%
o4-mini 16,499 0.5%
gpt-4.1-mini 11,775 0.4%
gpt-4.1 10,687 0.3%
None 8,001 0.2%
-o3 4,962 0.1%
+o3 4,962 0.2%
From 6f1b6f5f317735495af89de1a9f929c8bb7b5272 Mon Sep 17 00:00:00 2001
From: Greg OmniMind
Date: Thu, 17 Apr 2025 20:42:34 +0200
Subject: [PATCH 073/482] docs: update editor usage instructions in multi-line
guide
* Added keybinding `Ctrl-X Ctrl-E` for invoking editor via terminal compatibility.
* Enhances user ergonomics for terminals supporting this shortcut, streamlining workflow.
* Maintains reference to editor configuration documentation.
---
aider/website/_includes/multi-line.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/_includes/multi-line.md b/aider/website/_includes/multi-line.md
index b1fe74211..079113b14 100644
--- a/aider/website/_includes/multi-line.md
+++ b/aider/website/_includes/multi-line.md
@@ -4,7 +4,7 @@ You can send long, multi-line messages in the chat in a few ways:
- Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
- Use `/paste` to paste text from the clipboard into the chat.
- - Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
+ - Use the `/editor` command (or press `Ctrl-X Ctrl-E` if your terminal allows) to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
- Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. To enable multiline mode:
- Use the `/multiline-mode` command to toggle it during a session.
- Use the `--multiline` switch.
From 8e689d35af11807105b546a68ccc8c839707055b Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:01:26 -0700
Subject: [PATCH 074/482] Feat: Add --reasoning-effort switch to benchmark
script
---
benchmark/benchmark.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index f05c4b039..eaf3d25e6 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -206,6 +206,9 @@ def main(
read_model_settings: str = typer.Option(
None, "--read-model-settings", help="Load aider model settings from YAML file"
),
+ reasoning_effort: Optional[float] = typer.Option(
+ None, "--reasoning-effort", help="Set reasoning effort for models that support it"
+ ),
exercises_dir: str = typer.Option(
EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files"
),
@@ -362,6 +365,7 @@ def main(
editor_edit_format,
num_ctx,
sleep,
+ reasoning_effort,
)
all_results.append(results)
@@ -384,6 +388,7 @@ def main(
replay,
editor_model,
editor_edit_format,
+ reasoning_effort,
)
all_results = run_test_threaded.gather(tqdm=True)
@@ -481,6 +486,7 @@ def summarize_results(dirname, stats_languages=None):
res.indentation_errors = 0
res.lazy_comments = 0
+ res.reasoning_effort = None
variants = defaultdict(set)
for results in all_results:
@@ -509,7 +515,10 @@ def summarize_results(dirname, stats_languages=None):
res.syntax_errors += results.get("syntax_errors", 0)
res.indentation_errors += results.get("indentation_errors", 0)
+ res.reasoning_effort = results.get("reasoning_effort")
+
for key in "model edit_format commit_hash editor_model editor_edit_format".split():
+
val = results.get(key)
if val:
variants[key].add(val)
@@ -552,6 +561,9 @@ def summarize_results(dirname, stats_languages=None):
setattr(res, key, val)
console.print(f" {key}: {val}", style=style)
+ if res.reasoning_effort is not None:
+ print(f" reasoning_effort: {res.reasoning_effort}")
+
for i in range(tries):
print(f" pass_rate_{i + 1}: {percents[i]:.1f}")
for i in range(tries):
@@ -663,6 +675,7 @@ def run_test_real(
editor_edit_format,
num_ctx=None,
sleep=0,
+ reasoning_effort=None,
read_model_settings=None,
):
if not os.path.isdir(testdir):
@@ -769,6 +782,9 @@ def run_test_real(
editor_edit_format=editor_edit_format,
)
+ if reasoning_effort is not None:
+ main_model.set_reasoning_effort(reasoning_effort)
+
dump(main_model.max_chat_history_tokens)
if num_ctx:
@@ -919,6 +935,7 @@ def run_test_real(
syntax_errors=syntax_errors,
indentation_errors=indentation_errors,
lazy_comments=lazy_comments, # Add the count of pattern matches to the results
+ reasoning_effort=reasoning_effort,
chat_hashes=list(
zip(
coder.chat_completion_call_hashes,
From ec9327dcb46ded96a4fe93869e602e1b00d1ff36 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:01:30 -0700
Subject: [PATCH 075/482] style: Apply linter to benchmark.py
---
benchmark/benchmark.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index eaf3d25e6..f13cb2cb1 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -518,7 +518,6 @@ def summarize_results(dirname, stats_languages=None):
res.reasoning_effort = results.get("reasoning_effort")
for key in "model edit_format commit_hash editor_model editor_edit_format".split():
-
val = results.get(key)
if val:
variants[key].add(val)
From 5c8150fd160f6ac39db6bc76c6530dbeefaf2895 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:02:09 -0700
Subject: [PATCH 076/482] fix: Change reasoning_effort type to string in
benchmark script
---
benchmark/benchmark.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index f13cb2cb1..1ce34a002 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -206,7 +206,7 @@ def main(
read_model_settings: str = typer.Option(
None, "--read-model-settings", help="Load aider model settings from YAML file"
),
- reasoning_effort: Optional[float] = typer.Option(
+ reasoning_effort: Optional[str] = typer.Option(
None, "--reasoning-effort", help="Set reasoning effort for models that support it"
),
exercises_dir: str = typer.Option(
@@ -674,7 +674,7 @@ def run_test_real(
editor_edit_format,
num_ctx=None,
sleep=0,
- reasoning_effort=None,
+ reasoning_effort: Optional[str] = None,
read_model_settings=None,
):
if not os.path.isdir(testdir):
From 05eaf82b36509e6207ce0852ba077e0e52a8bc67 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:02:31 -0700
Subject: [PATCH 077/482] feat: Pass verbose flag to Model class for detailed
output
---
benchmark/benchmark.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index 1ce34a002..18799cdf2 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -779,6 +779,7 @@ def run_test_real(
weak_model=weak_model_name,
editor_model=editor_model,
editor_edit_format=editor_edit_format,
+ verbose=verbose,
)
if reasoning_effort is not None:
From 622bf349c50a679b66285457b250582c18533713 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 17 Apr 2025 20:08:57 -0700
Subject: [PATCH 078/482] chore: Add num_ctx and sleep to
run_test_threaded.gather arguments
---
benchmark/benchmark.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index 18799cdf2..71d3cec3e 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -388,6 +388,8 @@ def main(
replay,
editor_model,
editor_edit_format,
+ num_ctx,
+ sleep,
reasoning_effort,
)
all_results = run_test_threaded.gather(tqdm=True)
From 541b496d0914b7546a2365a9ac7121785b1eccb8 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:19:52 -0700
Subject: [PATCH 079/482] feat: Allow multiple update/delete actions for the
same file in patch coder
---
aider/coders/patch_coder.py | 49 ++++++++++++++++++++++++++++---------
1 file changed, 38 insertions(+), 11 deletions(-)
diff --git a/aider/coders/patch_coder.py b/aider/coders/patch_coder.py
index 2e9497bc9..802e6b9c3 100644
--- a/aider/coders/patch_coder.py
+++ b/aider/coders/patch_coder.py
@@ -312,11 +312,8 @@ class PatchCoder(Coder):
index += 1
if not path:
raise DiffError("Update File action missing path.")
- if path in patch.actions:
- raise DiffError(f"Duplicate action for file: {path}")
- if path not in current_files:
- raise DiffError(f"Update File Error - missing file content for: {path}")
+ # Optional move target
move_to = None
if index < len(lines) and _norm(lines[index]).startswith("*** Move to: "):
move_to = _norm(lines[index])[len("*** Move to: ") :].strip()
@@ -324,12 +321,36 @@ class PatchCoder(Coder):
if not move_to:
raise DiffError("Move to action missing path.")
+ if path not in current_files:
+ raise DiffError(f"Update File Error - missing file content for: {path}")
+
file_content = current_files[path]
- action, index, fuzz = self._parse_update_file_sections(lines, index, file_content)
- action.path = path # Ensure path is set
- action.move_path = move_to
- patch.actions[path] = action
- fuzz_accumulator += fuzz
+
+ existing_action = patch.actions.get(path)
+ if existing_action is not None:
+ # Merge additional UPDATE block into the existing one
+ if existing_action.type != ActionType.UPDATE:
+ raise DiffError(f"Conflicting actions for file: {path}")
+
+ new_action, index, fuzz = self._parse_update_file_sections(
+ lines, index, file_content
+ )
+ existing_action.chunks.extend(new_action.chunks)
+
+ if move_to:
+ if existing_action.move_path and existing_action.move_path != move_to:
+ raise DiffError(f"Conflicting move targets for file: {path}")
+ existing_action.move_path = move_to
+ fuzz_accumulator += fuzz
+ else:
+ # First UPDATE block for this file
+ action, index, fuzz = self._parse_update_file_sections(
+ lines, index, file_content
+ )
+ action.path = path
+ action.move_path = move_to
+ patch.actions[path] = action
+ fuzz_accumulator += fuzz
continue
# ---------- DELETE ---------- #
@@ -338,8 +359,14 @@ class PatchCoder(Coder):
index += 1
if not path:
raise DiffError("Delete File action missing path.")
- if path in patch.actions:
- raise DiffError(f"Duplicate action for file: {path}")
+ existing_action = patch.actions.get(path)
+ if existing_action:
+ if existing_action.type == ActionType.DELETE:
+ # Duplicate delete – ignore the extra block
+ self.io.tool_warning(f"Duplicate delete action for file: {path} ignored.")
+ continue
+ else:
+ raise DiffError(f"Conflicting actions for file: {path}")
if path not in current_files:
raise DiffError(
f"Delete File Error - file not found: {path}"
From c08336fdb086b3edab97870b1361a52a62e9180f Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 17 Apr 2025 20:23:16 -0700
Subject: [PATCH 080/482] feat: Update prompts to request one block per file in
patches
---
aider/coders/patch_prompts.py | 82 +++++++++++++++++++++--------------
1 file changed, 49 insertions(+), 33 deletions(-)
diff --git a/aider/coders/patch_prompts.py b/aider/coders/patch_prompts.py
index a2deddc24..830a04f2b 100644
--- a/aider/coders/patch_prompts.py
+++ b/aider/coders/patch_prompts.py
@@ -5,6 +5,9 @@ from .editblock_prompts import EditBlockPrompts
class PatchPrompts(EditBlockPrompts):
+ # --------------------------------------------------------------------- #
+ # SYSTEM PROMPT
+ # --------------------------------------------------------------------- #
main_system = """Act as an expert software developer.
Always use best practices when coding.
Respect and use existing conventions, libraries, etc that are already present in the code base.
@@ -18,44 +21,47 @@ Once you understand the request you MUST:
1. Decide if you need to propose edits to any files that haven't been added to the chat. You can create new files without asking!
-But if you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*.
-End your reply and wait for their approval.
-You can keep asking if you then decide you need to edit more files.
+ • If you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*.
+ • End your reply and wait for their approval.
+ • You can keep asking if you then decide you need to edit more files.
-2. Think step-by-step and explain the needed changes in a few short sentences.
+2. Think step‑by‑step and explain the needed changes in a few short sentences.
3. Describe the changes using the V4A diff format, enclosed within `*** Begin Patch` and `*** End Patch` markers.
-All changes to files must use the V4A diff format specified in the examples and reminder section.
-ONLY EVER RETURN CODE IN THE SPECIFIED V4A DIFF FORMAT!
+IMPORTANT: Each file MUST appear only once in the patch.
+Consolidate **all** edits for a given file into a single `*** [ACTION] File:` block.
{shell_cmd_prompt}
"""
+ # --------------------------------------------------------------------- #
+ # EXAMPLE MESSAGES
+ # --------------------------------------------------------------------- #
example_messages = [
+ # --- Example 1 ---------------------------------------------------- #
dict(
role="user",
content="Change get_factorial() to use math.factorial",
),
dict(
role="assistant",
- content="""To make this change we need to modify `mathweb/flask/app.py` to:
+ content="""To make this change we need to modify `mathweb/flask/app.py`:
-1. Import the math package.
-2. Remove the existing factorial() function.
-3. Update get_factorial() to call math.factorial instead.
+1. Import the `math` module.
+2. Replace the custom recursive `factorial()` helper with `math.factorial`.
+3. Update `get_factorial()` to call `math.factorial`.
Here is the patch:
*** Begin Patch
*** Update File: mathweb/flask/app.py
-@@ class MathWeb:
- from flask import Flask
-
- import math
- from flask import Flask
-
-*** Update File: mathweb/flask/app.py
-@@ def get_factorial(self, n):
+@@
+-from flask import Flask
+-
+-from flask import Flask
++from flask import Flask
++import math
+@@
-def factorial(n):
- "compute factorial"
-
@@ -63,26 +69,27 @@ Here is the patch:
- return 1
- else:
- return n * factorial(n-1)
--
-
-*** Update File: mathweb/flask/app.py
++def factorial(n):
++ "compute factorial"
++
++ return math.factorial(n)
@@ def get_factorial(self, n):
- return str(factorial(n))
+ return str(math.factorial(n))
-
*** End Patch
""",
),
+ # --- Example 2 ---------------------------------------------------- #
dict(
role="user",
content="Refactor hello() into its own file.",
),
dict(
role="assistant",
- content="""To make this change we need to modify `main.py` and make a new file `hello.py`:
+ content="""To make this change we need to modify `main.py` and create a new file `hello.py`:
-1. Make a new hello.py file with hello() in it.
-2. Remove hello() from main.py and replace it with an import.
+1. Create `hello.py` with the `hello()` function.
+2. Remove `hello()` from `main.py` and import it instead.
Here is the patch:
@@ -93,20 +100,21 @@ Here is the patch:
+ "print a greeting"
+
+ print("hello")
-
*** Update File: main.py
-@@ def main():
+@@
-def hello():
- "print a greeting"
-
- print("hello")
+from hello import hello
-
*** End Patch
""",
),
]
+ # --------------------------------------------------------------------- #
+ # SYSTEM REMINDER
+ # --------------------------------------------------------------------- #
system_reminder = """# V4A Diff Format Rules:
Your entire response containing the patch MUST start with `*** Begin Patch` on a line by itself.
@@ -114,10 +122,18 @@ Your entire response containing the patch MUST end with `*** End Patch` on a lin
Use the *FULL* file path, as shown to you by the user.
{quad_backtick_reminder}
+
For each file you need to modify, start with a marker line:
-`*** [ACTION] File: [path/to/file]`
+
+ *** [ACTION] File: [path/to/file]
+
Where `[ACTION]` is one of `Add`, `Update`, or `Delete`.
-Use the *FULL* file path, as shown to you by the user.
+
+⇨ **Each file MUST appear only once in the patch.**
+ Consolidate all changes for that file into the same block.
+ If you are moving code within a file, include both the deletions and the
+ insertions as separate hunks inside this single `*** Update File:` block
+ (do *not* open a second block for the same file).
For `Update` actions, describe each snippet of code that needs to be changed using the following format:
1. Context lines: Include 3 lines of context *before* the change. These lines MUST start with a single space ` `.
@@ -132,9 +148,9 @@ Do not include line numbers.
Only create patches for files that the user has added to the chat!
-To move code within a file, use two `*** Update File:` sections: one to delete the code (using `-` lines) from its original location, and another to add the code (using `+` lines) in the new location.
-
-Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file.
+When moving code *within* a single file, keep everything inside one
+`*** Update File:` block. Provide one hunk that deletes the code from its
+original location and another hunk that inserts it at the new location.
For `Add` actions, use the `*** Add File: [path/to/new/file]` marker, followed by the lines of the new file, each preceded by a plus sign `+`.
From a4d32221086968c2f6dd5ce77b754e3981f5c076 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sat, 19 Apr 2025 11:27:50 -0700
Subject: [PATCH 081/482] feat: Add openhands-lm-32b-v0.1 to polyglot
leaderboard data
---
aider/website/_data/polyglot_leaderboard.yml | 28 +++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/aider/website/_data/polyglot_leaderboard.yml b/aider/website/_data/polyglot_leaderboard.yml
index 40340a4d9..5d7c651ae 100644
--- a/aider/website/_data/polyglot_leaderboard.yml
+++ b/aider/website/_data/polyglot_leaderboard.yml
@@ -1171,4 +1171,30 @@
date: 2025-04-17
versions: 0.82.2.dev
seconds_per_case: 110.0
- total_cost: 69.2921
\ No newline at end of file
+ total_cost: 69.2921
+
+- dirname: 2025-04-19-14-43-04--o4-mini-patch
+ test_cases: 225
+ model: openhands-lm-32b-v0.1
+ edit_format: whole
+ commit_hash: c08336f
+ pass_rate_1: 4.0
+ pass_rate_2: 10.2
+ pass_num_1: 9
+ pass_num_2: 23
+ percent_cases_well_formed: 95.1
+ error_outputs: 55
+ num_malformed_responses: 41
+ num_with_malformed_responses: 11
+ user_asks: 166
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 0
+ test_timeouts: 11
+ total_tests: 225
+ command: aider --model openrouter/all-hands/openhands-lm-32b-v0.1
+ date: 2025-04-19
+ versions: 0.82.2.dev
+ seconds_per_case: 195.6
+ total_cost: 0.0000
\ No newline at end of file
From 851642a1bd10c031d75a179e64e7322b056a20b7 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 08:13:04 -0700
Subject: [PATCH 082/482] copy
---
aider/website/assets/sample-analytics.jsonl | 184 ++++++++++----------
aider/website/docs/faq.md | 19 +-
aider/website/docs/leaderboards/index.md | 2 +-
aider/website/index.html | 2 +-
4 files changed, 106 insertions(+), 101 deletions(-)
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index 6400c1af4..6f29aa337 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,95 +1,3 @@
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566707}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566733}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 12803, "completion_tokens": 139, "total_tokens": 12942, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566740}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566786}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 12987, "completion_tokens": 136, "total_tokens": 13123, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566791}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566810}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566816}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13178, "completion_tokens": 140, "total_tokens": 13318, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566819}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566850}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566850}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 11062, "completion_tokens": 402, "total_tokens": 11464, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744566861}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567566}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567566}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 11501, "completion_tokens": 1553, "total_tokens": 13054, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567603}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567635}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567635}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 13895, "completion_tokens": 949, "total_tokens": 14844, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567657}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567690}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 17147, "completion_tokens": 212, "total_tokens": 17359, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567696}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567721}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 17497, "completion_tokens": 325, "total_tokens": 17822, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744567728}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744569988}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570117}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570118}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570118}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570118}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570121}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570126}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570189}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13271, "completion_tokens": 1131, "total_tokens": 14402, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570209}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570237}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14632, "completion_tokens": 402, "total_tokens": 15034, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570244}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570276}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15122, "completion_tokens": 582, "total_tokens": 15704, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570283}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570355}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15762, "completion_tokens": 477, "total_tokens": 16239, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570368}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570433}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570674}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 16325, "completion_tokens": 278, "total_tokens": 16603, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570682}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744570742}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573244}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573245}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573245}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573245}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573247}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573251}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573277}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13149, "completion_tokens": 308, "total_tokens": 13457, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573288}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573331}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13550, "completion_tokens": 295, "total_tokens": 13845, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573337}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573353}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573393}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13891, "completion_tokens": 215, "total_tokens": 14106, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573397}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573433}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14157, "completion_tokens": 336, "total_tokens": 14493, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744573441}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576312}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14544, "completion_tokens": 1568, "total_tokens": 16112, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576328}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576329}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 17358, "completion_tokens": 970, "total_tokens": 18328, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576347}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576348}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 18744, "completion_tokens": 533, "total_tokens": 19277, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576356}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576356}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 19828, "completion_tokens": 551, "total_tokens": 20379, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576365}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576393}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576394}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576396}
-{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576400}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576403}
-{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576412}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576414}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 13408, "completion_tokens": 1539, "total_tokens": 14947, "cost": 0.063309, "total_cost": 0.063309}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576445}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576446}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 14864, "completion_tokens": 104, "total_tokens": 14968, "cost": 0.046152, "total_cost": 0.109461}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576451}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576513}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 15024, "completion_tokens": 1795, "total_tokens": 16819, "cost": 0.071997, "total_cost": 0.181458}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576546}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576606}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 17246, "completion_tokens": 618, "total_tokens": 17864, "cost": 0.061008, "total_cost": 0.24246600000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576620}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576661}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 18009, "completion_tokens": 640, "total_tokens": 18649, "cost": 0.063627, "total_cost": 0.306093}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576675}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576709}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 18842, "completion_tokens": 296, "total_tokens": 19138, "cost": 0.060966, "total_cost": 0.367059}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576718}
-{"event": "command_diff", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576737}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576751}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576759}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19188, "completion_tokens": 293, "total_tokens": 19481, "cost": 0.06195900000000001, "total_cost": 0.429018}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576768}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576776}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19549, "completion_tokens": 263, "total_tokens": 19812, "cost": 0.06259200000000001, "total_cost": 0.49161}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576784}
-{"event": "command_diff", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576793}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576812}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576827}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576945}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19840, "completion_tokens": 211, "total_tokens": 20051, "cost": 0.062685, "total_cost": 0.554295}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744576953}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577003}
{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19980, "completion_tokens": 209, "total_tokens": 20189, "cost": 0.063075, "total_cost": 0.61737}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577011}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577039}
@@ -998,3 +906,95 @@
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855212}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 6080, "completion_tokens": 477, "total_tokens": 6557, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855217}
{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744855261}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916060}
+{"event": "model warning", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916063}
+{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916064}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916070}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916073}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916073}
+{"event": "cli session", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916073}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916074}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916083}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916085}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916085}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916085}
+{"event": "message_send", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED", "edit_format": "whole", "prompt_tokens": 593, "completion_tokens": 13, "total_tokens": 606, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916086}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744916086}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942667}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942668}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942668}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942668}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942675}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942678}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744942692}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945174}
+{"event": "model warning", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945175}
+{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945188}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945258}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945258}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945258}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945258}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945263}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945267}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945274}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 20283, "completion_tokens": 661, "total_tokens": 20944, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945285}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945322}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 21131, "completion_tokens": 177, "total_tokens": 21308, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945329}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945347}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 21364, "completion_tokens": 68, "total_tokens": 21432, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945350}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945722}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945734}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945735}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945735}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744945738}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946266}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946266}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946266}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946266}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946269}
+{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946278}
+{"event": "command_reasoning-effort", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946283}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946291}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946291}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 14950, "completion_tokens": 889, "total_tokens": 15839, "cost": 0.18506000000000003, "total_cost": 0.18506000000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946304}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946345}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 16775, "completion_tokens": 5498, "total_tokens": 22273, "cost": 0.38767, "total_cost": 0.5727300000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946391}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946424}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946440}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946440}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 17168, "completion_tokens": 1504, "total_tokens": 18672, "cost": 0.23184000000000005, "total_cost": 0.8045700000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946459}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946483}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19187, "completion_tokens": 683, "total_tokens": 19870, "cost": 0.21919000000000002, "total_cost": 1.0237600000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946496}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946545}
+{"event": "command_chat-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946557}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946572}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "whole", "prompt_tokens": 16552, "completion_tokens": 2609, "total_tokens": 19161, "cost": 0.26988, "total_cost": 1.2936400000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946592}
+{"event": "command_diff", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946606}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744946701}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745087266}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745087267}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745087267}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745087270}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745113992}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745113992}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745113992}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745113992}
+{"event": "command_help", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745113994}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745114112}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161720}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161720}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161720}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161720}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 1149, "completion_tokens": 23, "total_tokens": 1172, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161736}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161736}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161749}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161783}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161785}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161785}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161785}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161788}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161799}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161817}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161817}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161817}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161818}
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index b86aaf0c3..d76f5846e 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,15 +264,20 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 2,756,387 83.5%
-openrouter/anthropic/claude-3.7-sonnet 475,106 14.4%
-gemini/gemini-2.5-pro-preview-03-25 16,524 0.5%
-o4-mini 16,499 0.5%
+gemini/gemini-2.5-pro-exp-03-25 2,499,338 83.9%
+openrouter/anthropic/claude-3.7-sonnet 313,377 10.5%
+o3 100,777 3.4%
+gemini/gemini-2.5-pro-preview-03-25 16,524 0.6%
+o4-mini 16,499 0.6%
gpt-4.1-mini 11,775 0.4%
-gpt-4.1 10,687 0.3%
-None 8,001 0.2%
-o3 4,962 0.2%
+gpt-4.1 10,687 0.4%
+None 8,001 0.3%
+gemini/REDACTED 606 0.0%
+
+{: .note :}
+Some models show as REDACTED, because they are new or unpopular models.
+Aider's analytics only records the names of "well known" LLMs.
## How are the "aider wrote xx% of code" stats computed?
diff --git a/aider/website/docs/leaderboards/index.md b/aider/website/docs/leaderboards/index.md
index a76de0bbd..8d54e0bf5 100644
--- a/aider/website/docs/leaderboards/index.md
+++ b/aider/website/docs/leaderboards/index.md
@@ -285,6 +285,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
-April 16, 2025.
+April 19, 2025.
diff --git a/aider/website/index.html b/aider/website/index.html
index badfbd0ea..80611f3a9 100644
--- a/aider/website/index.html
+++ b/aider/website/index.html
@@ -69,7 +69,7 @@ cog.out(text)
]]]-->
⭐ GitHub Stars
- 31K
+ 32K
📦 Installs
From 888168f044a725479ef7766e14a346299b5d826b Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 08:21:33 -0700
Subject: [PATCH 083/482] copy
---
aider/website/docs/leaderboards/index.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/docs/leaderboards/index.md b/aider/website/docs/leaderboards/index.md
index 8d54e0bf5..fa03fb2d7 100644
--- a/aider/website/docs/leaderboards/index.md
+++ b/aider/website/docs/leaderboards/index.md
@@ -285,6 +285,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
-April 19, 2025.
+April 20, 2025.
From 20a7e3552c55dbb77b0a54e5137d4f5c0b1d94db Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 08:26:22 -0700
Subject: [PATCH 084/482] version bump to 0.82.2
---
aider/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/__init__.py b/aider/__init__.py
index 4f91e3f8a..28c763232 100644
--- a/aider/__init__.py
+++ b/aider/__init__.py
@@ -1,6 +1,6 @@
from packaging import version
-__version__ = "0.82.2.dev"
+__version__ = "0.82.2"
safe_version = __version__
try:
From c2d8d5dc82dbf07cc33811795c213a0a056fb83b Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 08:26:25 -0700
Subject: [PATCH 085/482] set version to 0.82.3.dev
---
aider/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/__init__.py b/aider/__init__.py
index 28c763232..825bf0439 100644
--- a/aider/__init__.py
+++ b/aider/__init__.py
@@ -1,6 +1,6 @@
from packaging import version
-__version__ = "0.82.2"
+__version__ = "0.82.3.dev"
safe_version = __version__
try:
From ec7ac60cfcaa3c7250558d19736f7aac975717e9 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 08:54:44 -0700
Subject: [PATCH 086/482] copy
---
HISTORY.md | 7 +
aider/website/HISTORY.md | 7 +
aider/website/assets/sample-analytics.jsonl | 214 ++++++++++----------
aider/website/docs/faq.md | 16 +-
4 files changed, 129 insertions(+), 115 deletions(-)
diff --git a/HISTORY.md b/HISTORY.md
index 99398aa22..f3f839e7d 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,6 +1,13 @@
# Release history
+### Aider v0.82.2
+
+- Fix editing shell files with diff-fenced, by zjy1412.
+- Improve robustness of patch application by allowing multiple update/delete actions for the same file within a single response.
+- Update prompts to instruct LLMs to consolidate all edits for a given file into a single block within the patch.
+
### Aider v0.82.1
+
- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
- Disabled streaming for `o3` models since you need identity verification to stream.
diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md
index 20b70ec6a..fa3fdcb22 100644
--- a/aider/website/HISTORY.md
+++ b/aider/website/HISTORY.md
@@ -24,7 +24,14 @@ cog.out(text)
]]]-->
+### Aider v0.82.2
+
+- Fix editing shell files with diff-fenced, by zjy1412.
+- Improve robustness of patch application by allowing multiple update/delete actions for the same file within a single response.
+- Update prompts to instruct LLMs to consolidate all edits for a given file into a single block within the patch.
+
### Aider v0.82.1
+
- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
- Disabled streaming for `o3` models since you need identity verification to stream.
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index 6f29aa337..3c18d8c53 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,110 +1,3 @@
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577003}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19980, "completion_tokens": 209, "total_tokens": 20189, "cost": 0.063075, "total_cost": 0.61737}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577011}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577039}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577050}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 20284, "completion_tokens": 562, "total_tokens": 20846, "cost": 0.06928200000000001, "total_cost": 0.686652}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577062}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577094}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 20748, "completion_tokens": 570, "total_tokens": 21318, "cost": 0.070794, "total_cost": 0.7574460000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577107}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577148}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577199}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577199}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 18851, "completion_tokens": 341, "total_tokens": 19192, "cost": 0.061668, "total_cost": 0.8191140000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577212}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577284}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 21544, "completion_tokens": 921, "total_tokens": 22465, "cost": 0.07844699999999999, "total_cost": 0.897561}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577304}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577305}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 23437, "completion_tokens": 960, "total_tokens": 24397, "cost": 0.084711, "total_cost": 0.982272}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577328}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577329}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 25273, "completion_tokens": 627, "total_tokens": 25900, "cost": 0.085224, "total_cost": 1.067496}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577347}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577348}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577354}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577356}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577390}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 13107, "completion_tokens": 553, "total_tokens": 13660, "cost": 0.047616000000000006, "total_cost": 1.115112}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577401}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577417}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577431}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577441}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 13101, "completion_tokens": 825, "total_tokens": 13926, "cost": 0.051678, "total_cost": 1.1667900000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577458}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577481}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 14119, "completion_tokens": 509, "total_tokens": 14628, "cost": 0.049992, "total_cost": 1.2167820000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577492}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577511}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577529}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 14688, "completion_tokens": 513, "total_tokens": 15201, "cost": 0.051759, "total_cost": 1.2685410000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577541}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577541}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 15982, "completion_tokens": 514, "total_tokens": 16496, "cost": 0.055656000000000004, "total_cost": 1.3241970000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577552}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577622}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 16560, "completion_tokens": 1044, "total_tokens": 17604, "cost": 0.06534000000000001, "total_cost": 1.3895370000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577642}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577666}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 17795, "completion_tokens": 382, "total_tokens": 18177, "cost": 0.059115, "total_cost": 1.4486520000000003}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744577676}
-{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578142}
-{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578142}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578145}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578600}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578601}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578601}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578601}
-{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578602}
-{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578602}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578602}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14829, "completion_tokens": 515, "total_tokens": 15344, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578625}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578634}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15859, "completion_tokens": 252, "total_tokens": 16111, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578640}
-{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578711}
-{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578745}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578745}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 31847, "completion_tokens": 913, "total_tokens": 32760, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578766}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578802}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 33028, "completion_tokens": 171, "total_tokens": 33199, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578814}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578882}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 33229, "completion_tokens": 1078, "total_tokens": 34307, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578896}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578896}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 35722, "completion_tokens": 1044, "total_tokens": 36766, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578907}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578914}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 37246, "completion_tokens": 219, "total_tokens": 37465, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578919}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578948}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 37520, "completion_tokens": 523, "total_tokens": 38043, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578959}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578990}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 38220, "completion_tokens": 381, "total_tokens": 38601, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744578997}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579008}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579010}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579011}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579026}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15395, "completion_tokens": 1022, "total_tokens": 16417, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579035}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579044}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 17097, "completion_tokens": 653, "total_tokens": 17750, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579053}
-{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579710}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579710}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 17585, "completion_tokens": 386, "total_tokens": 17971, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579725}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579761}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 18039, "completion_tokens": 873, "total_tokens": 18912, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579781}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579783}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 19435, "completion_tokens": 254, "total_tokens": 19689, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579793}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579798}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 20006, "completion_tokens": 227, "total_tokens": 20233, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744579804}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744586979}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744586995}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744586995}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 11494, "completion_tokens": 1239, "total_tokens": 12733, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587032}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587133}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587134}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587134}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587134}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587151}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587154}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587155}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587155}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587155}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587176}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 13376, "completion_tokens": 902, "total_tokens": 14278, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587186}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587224}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587226}
-{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587229}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587253}
-{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 13814, "completion_tokens": 296, "total_tokens": 14110, "cost": 0.045882, "total_cost": 0.045882}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587261}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587278}
-{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587283}
-{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587283}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587305}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587305}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 13075, "completion_tokens": 2645, "total_tokens": 15720, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587358}
{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591225}
{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591226}
@@ -998,3 +891,110 @@
{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161817}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161817}
{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745161818}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162550}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162555}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162555}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162555}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162555}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162555}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162556}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162557}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162558}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162558}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162558}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162558}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162558}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162559}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162560}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162561}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162562}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162563}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162564}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162564}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162564}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162564}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162620}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162621}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162621}
+{"event": "exit", "properties": {"reason": "Exit flag set"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162621}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162621}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162622}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162622}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162622}
+{"event": "exit", "properties": {"reason": "Unknown edit format"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162622}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162754}
+{"event": "gui session", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162760}
+{"event": "exit", "properties": {"reason": "GUI session ended"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745162760}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163376}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163381}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163381}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163393}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163405}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163405}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163405}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163405}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163407}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 5399, "completion_tokens": 256, "total_tokens": 5655, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163408}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163408}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163508}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index d76f5846e..71bb34aef 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,14 +264,14 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 2,499,338 83.9%
-openrouter/anthropic/claude-3.7-sonnet 313,377 10.5%
-o3 100,777 3.4%
-gemini/gemini-2.5-pro-preview-03-25 16,524 0.6%
-o4-mini 16,499 0.6%
-gpt-4.1-mini 11,775 0.4%
-gpt-4.1 10,687 0.4%
-None 8,001 0.3%
+gemini/gemini-2.5-pro-exp-03-25 2,084,414 91.2%
+o3 100,777 4.4%
+openrouter/anthropic/claude-3.7-sonnet 35,268 1.5%
+gemini/gemini-2.5-pro-preview-03-25 16,524 0.7%
+o4-mini 16,499 0.7%
+gpt-4.1-mini 11,775 0.5%
+gpt-4.1 10,687 0.5%
+None 8,001 0.4%
gemini/REDACTED 606 0.0%
From 21fa54d792a5ba25e6d93d3e93e7a6004c3c5083 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 10:28:01 -0700
Subject: [PATCH 087/482] Refactor: Update LLM docs to match gemini.md
structure
---
aider/website/docs/llms/anthropic.md | 19 +++++++++++------
aider/website/docs/llms/azure.md | 15 +++++++++++--
aider/website/docs/llms/bedrock.md | 25 +++++++++++++++-------
aider/website/docs/llms/cohere.md | 15 ++++++++++---
aider/website/docs/llms/deepseek.md | 15 +++++++++++--
aider/website/docs/llms/groq.md | 15 ++++++++++---
aider/website/docs/llms/lm-studio.md | 21 +++++++++++++-----
aider/website/docs/llms/ollama.md | 20 +++++++++++++-----
aider/website/docs/llms/openai-compat.md | 16 +++++++++++---
aider/website/docs/llms/openai.md | 27 +++++++++++++++---------
aider/website/docs/llms/openrouter.md | 25 +++++++++++-----------
aider/website/docs/llms/vertex.md | 9 +++++++-
aider/website/docs/llms/xai.md | 16 ++++++++++----
13 files changed, 173 insertions(+), 65 deletions(-)
diff --git a/aider/website/docs/llms/anthropic.md b/aider/website/docs/llms/anthropic.md
index cf69ab610..26748b101 100644
--- a/aider/website/docs/llms/anthropic.md
+++ b/aider/website/docs/llms/anthropic.md
@@ -10,21 +10,26 @@ To work with Anthropic's models, you need to provide your
either in the `ANTHROPIC_API_KEY` environment variable or
via the `--anthropic-api-key` command line switch.
-Aider has some built in shortcuts for the most popular Anthropic models and
-has been tested and benchmarked to work well with them:
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API keys:
```
-python -m pip install -U aider-chat
-
export ANTHROPIC_API_KEY= # Mac/Linux
setx ANTHROPIC_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and Anthropic on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# Aider uses Claude 3.7 Sonnet by default
aider
-# Claude 3 Opus
-aider --model claude-3-opus-20240229
-
# List models available from Anthropic
aider --list-models anthropic/
```
diff --git a/aider/website/docs/llms/azure.md b/aider/website/docs/llms/azure.md
index c342ec700..7e20fc83d 100644
--- a/aider/website/docs/llms/azure.md
+++ b/aider/website/docs/llms/azure.md
@@ -7,9 +7,13 @@ nav_order: 500
Aider can connect to the OpenAI models on Azure.
-```
-python -m pip install -U aider-chat
+First, install aider:
+{% include install.md %}
+
+Then configure your API keys and endpoint:
+
+```
# Mac/Linux:
export AZURE_API_KEY=
export AZURE_API_VERSION=2024-12-01-preview
@@ -20,6 +24,13 @@ setx AZURE_API_KEY
setx AZURE_API_VERSION 2024-12-01-preview
setx AZURE_API_BASE https://myendpt.openai.azure.com
# ... restart your shell after setx commands
+```
+
+Start working with aider and Azure on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
aider --model azure/
diff --git a/aider/website/docs/llms/bedrock.md b/aider/website/docs/llms/bedrock.md
index c7705918f..f3e2131c7 100644
--- a/aider/website/docs/llms/bedrock.md
+++ b/aider/website/docs/llms/bedrock.md
@@ -6,10 +6,7 @@ nav_order: 560
# Amazon Bedrock
Aider can connect to models provided by Amazon Bedrock.
-You will need to have an AWS account with access to the Bedrock service.
-
-To configure Aider to use the Amazon Bedrock API, you need to set up your AWS credentials.
-This can be done using the AWS CLI or by setting environment variables.
+You will need to have an AWS account with access to the Bedrock service and the specific models you wish to use.
## Select a Model from Amazon Bedrock
@@ -37,6 +34,14 @@ feature, you will receive an error message like the following:
anthropic.claude-3-7-sonnet-20250219-v1:0 with on-demand throughput isn\xe2\x80\x99t supported. Retry your
request with the ID or ARN of an inference profile that contains this model."}'
+## Installation and Configuration
+
+First, install aider:
+
+{% include install.md %}
+
+Next, configure your AWS credentials. This can be done using the AWS CLI or by setting environment variables.
+
## AWS CLI Configuration
If you haven't already, install the [AWS CLI](https://aws.amazon.com/cli/) and configure it with your credentials:
@@ -49,7 +54,7 @@ This will prompt you to enter your AWS Access Key ID, Secret Access Key, and def
## Environment Variables
-Alternatively, you can set the following environment variables:
+You can set the following environment variables:
```bash
export AWS_REGION=your_preferred_region
@@ -63,7 +68,7 @@ export AWS_PROFILE=your-profile
```
You can add these to your
-[.env file](/docs/config/dotenv.html).
+`.env` file.
### Set Environment Variables with PowerShell
@@ -77,6 +82,8 @@ $env:AWS_REGION = 'us-west-2' # Put whichever AWS region that you'd like, that
## Install boto3
+Aider needs the `boto3` library to connect to Bedrock.
+
The AWS Bedrock provider requires the `boto3` package in order to function correctly:
```bash
@@ -95,12 +102,14 @@ You must install `boto3` dependency to aider's virtual environment installed via
uv tool run --from aider-chat pip install boto3
```
-
-## Running Aider with Bedrock
+## Get Started
Once your AWS credentials are set up, you can run Aider with the `--model` command line switch, specifying the Bedrock model you want to use:
```bash
+# Change directory into your codebase
+cd /to/your/project
+
aider --model bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0
```
diff --git a/aider/website/docs/llms/cohere.md b/aider/website/docs/llms/cohere.md
index 66ab3c842..ce3e1a795 100644
--- a/aider/website/docs/llms/cohere.md
+++ b/aider/website/docs/llms/cohere.md
@@ -10,13 +10,22 @@ Their Command-R+ model works well with aider
as a *very basic* coding assistant.
You'll need a [Cohere API key](https://dashboard.cohere.com/welcome/login).
-To use **Command-R+**:
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API keys:
```
-python -m pip install -U aider-chat
-
export COHERE_API_KEY= # Mac/Linux
setx COHERE_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and Cohere on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
aider --model command-r-plus-08-2024
diff --git a/aider/website/docs/llms/deepseek.md b/aider/website/docs/llms/deepseek.md
index 72073c1df..0abbf51a9 100644
--- a/aider/website/docs/llms/deepseek.md
+++ b/aider/website/docs/llms/deepseek.md
@@ -9,11 +9,22 @@ Aider can connect to the DeepSeek.com API.
To work with DeepSeek's models, you need to set the `DEEPSEEK_API_KEY` environment variable with your [DeepSeek API key](https://platform.deepseek.com/api_keys).
The DeepSeek Chat V3 model has a top score on aider's code editing benchmark.
-```
-python -m pip install -U aider-chat
+First, install aider:
+{% include install.md %}
+
+Then configure your API keys:
+
+```
export DEEPSEEK_API_KEY= # Mac/Linux
setx DEEPSEEK_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and DeepSeek on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# Use DeepSeek Chat v3
aider --model deepseek/deepseek-chat
diff --git a/aider/website/docs/llms/groq.md b/aider/website/docs/llms/groq.md
index f258e6848..b8e60e719 100644
--- a/aider/website/docs/llms/groq.md
+++ b/aider/website/docs/llms/groq.md
@@ -10,13 +10,22 @@ The Llama 3 70B model works
well with aider and is comparable to GPT-3.5 in code editing performance.
You'll need a [Groq API key](https://console.groq.com/keys).
-To use **Llama3 70B**:
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API keys:
```
-python -m pip install -U aider-chat
-
export GROQ_API_KEY= # Mac/Linux
setx GROQ_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and Groq on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
aider --model groq/llama3-70b-8192
diff --git a/aider/website/docs/llms/lm-studio.md b/aider/website/docs/llms/lm-studio.md
index 909d3afe1..be9e53845 100644
--- a/aider/website/docs/llms/lm-studio.md
+++ b/aider/website/docs/llms/lm-studio.md
@@ -5,11 +5,15 @@ nav_order: 400
# LM Studio
-To use LM Studio:
+Aider can connect to models served by LM Studio.
+
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API key and endpoint:
```
-python -m pip install -U aider-chat
-
# Must set a value here even if its a dummy value
export LM_STUDIO_API_KEY=dummy-api-key # Mac/Linux
setx LM_STUDIO_API_KEY dummy-api-key # Windows, restart shell after setx
@@ -17,12 +21,19 @@ setx LM_STUDIO_API_KEY dummy-api-key # Windows, restart shell after setx
# LM Studio default server URL is http://localhost:1234/v1
export LM_STUDIO_API_BASE=http://localhost:1234/v1 # Mac/Linux
setx LM_STUDIO_API_BASE http://localhost:1234/v1 # Windows, restart shell after setx
-
-aider --model lm_studio/
```
**Note:** Even though LM Studio doesn't require an API Key out of the box the `LM_STUDIO_API_KEY` must have a dummy value like `dummy-api-key` set or the client request will fail trying to send an empty `Bearer` token.
+Start working with aider and LM Studio on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
+
+aider --model lm_studio/
+```
+
See the [model warnings](warnings.html)
section for information on warnings which will occur
when working with models that aider is not familiar with.
diff --git a/aider/website/docs/llms/ollama.md b/aider/website/docs/llms/ollama.md
index 463dc4a3e..a9dbf6c07 100644
--- a/aider/website/docs/llms/ollama.md
+++ b/aider/website/docs/llms/ollama.md
@@ -7,6 +7,19 @@ nav_order: 500
Aider can connect to local Ollama models.
+First, install aider:
+
+{% include install.md %}
+
+Then configure your Ollama API endpoint (usually the default):
+
+```bash
+export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
+setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
+```
+
+Start working with aider and Ollama on your codebase:
+
```
# Pull the model
ollama pull
@@ -14,11 +27,8 @@ ollama pull
# Start your ollama server, increasing the context window to 8k tokens
OLLAMA_CONTEXT_LENGTH=8192 ollama serve
-# In another terminal window...
-python -m pip install -U aider-chat
-
-export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
-setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
+# In another terminal window, change directory into your codebase
+cd /to/your/project
aider --model ollama_chat/
```
diff --git a/aider/website/docs/llms/openai-compat.md b/aider/website/docs/llms/openai-compat.md
index e1b2a73f2..ea45a574f 100644
--- a/aider/website/docs/llms/openai-compat.md
+++ b/aider/website/docs/llms/openai-compat.md
@@ -7,10 +7,13 @@ nav_order: 500
Aider can connect to any LLM which is accessible via an OpenAI compatible API endpoint.
-```
-python -m pip install aider-install
-aider-install
+First, install aider:
+{% include install.md %}
+
+Then configure your API key and endpoint:
+
+```
# Mac/Linux:
export OPENAI_API_BASE=
export OPENAI_API_KEY=
@@ -19,6 +22,13 @@ export OPENAI_API_KEY=
setx OPENAI_API_BASE
setx OPENAI_API_KEY
# ... restart shell after setx commands
+```
+
+Start working with aider and your OpenAI compatible API on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# Prefix the model name with openai/
aider --model openai/
diff --git a/aider/website/docs/llms/openai.md b/aider/website/docs/llms/openai.md
index a9d907afb..e88944644 100644
--- a/aider/website/docs/llms/openai.md
+++ b/aider/website/docs/llms/openai.md
@@ -10,27 +10,34 @@ To work with OpenAI's models, you need to provide your
either in the `OPENAI_API_KEY` environment variable or
via the `--api-key openai=` command line switch.
-Aider has some built in shortcuts for the most popular OpenAI models and
-has been tested and benchmarked to work well with them:
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API keys:
```
-python -m pip install -U aider-chat
+export OPENAI_API_KEY= # Mac/Linux
+setx OPENAI_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and OpenAI on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# o3-mini
-aider --model o3-mini --api-key openai=
+aider --model o3-mini
# o1-mini
-aider --model o1-mini --api-key openai=
+aider --model o1-mini
# GPT-4o
-aider --model gpt-4o --api-key openai=
+aider --model gpt-4o
# List models available from OpenAI
aider --list-models openai/
-
-# You can also store you API key in environment variables (or .env)
-export OPENAI_API_KEY= # Mac/Linux
-setx OPENAI_API_KEY # Windows, restart shell after setx
```
You can use `aider --model ` to use any other OpenAI model.
diff --git a/aider/website/docs/llms/openrouter.md b/aider/website/docs/llms/openrouter.md
index f9ec3ea0d..e5e8a48cc 100644
--- a/aider/website/docs/llms/openrouter.md
+++ b/aider/website/docs/llms/openrouter.md
@@ -8,11 +8,22 @@ nav_order: 500
Aider can connect to [models provided by OpenRouter](https://openrouter.ai/models?o=top-weekly):
You'll need an [OpenRouter API key](https://openrouter.ai/keys).
-```
-python -m pip install -U aider-chat
+First, install aider:
+{% include install.md %}
+
+Then configure your API keys:
+
+```
export OPENROUTER_API_KEY= # Mac/Linux
setx OPENROUTER_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and OpenRouter on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# Or any other open router model
aider --model openrouter//
@@ -23,16 +34,6 @@ aider --list-models openrouter/
In particular, many aider users access Sonnet via OpenRouter:
-```
-python -m pip install -U aider-chat
-
-export OPENROUTER_API_KEY= # Mac/Linux
-setx OPENROUTER_API_KEY # Windows, restart shell after setx
-
-aider --model openrouter/anthropic/claude-3.7-sonnet
-```
-
-
{: .tip }
If you get errors, check your
[OpenRouter privacy settings](https://openrouter.ai/settings/privacy).
diff --git a/aider/website/docs/llms/vertex.md b/aider/website/docs/llms/vertex.md
index b7afee42f..9dc82ea38 100644
--- a/aider/website/docs/llms/vertex.md
+++ b/aider/website/docs/llms/vertex.md
@@ -13,6 +13,10 @@ or service account with permission to use the Vertex AI API.
With your chosen login method, the gcloud CLI should automatically set the
`GOOGLE_APPLICATION_CREDENTIALS` environment variable which points to the credentials file.
+First, install aider:
+
+{% include install.md %}
+
To configure Aider to use the Vertex AI API, you need to set `VERTEXAI_PROJECT` (the GCP project ID)
and `VERTEXAI_LOCATION` (the GCP region) [environment variables for Aider](/docs/config/dotenv.html).
@@ -27,9 +31,12 @@ VERTEXAI_PROJECT=my-project
VERTEXAI_LOCATION=us-east5
```
-Then you can run aider with the `--model` command line switch, like this:
+Start working with aider and Vertex AI on your codebase:
```
+# Change directory into your codebase
+cd /to/your/project
+
aider --model vertex_ai/claude-3-5-sonnet@20240620
```
diff --git a/aider/website/docs/llms/xai.md b/aider/website/docs/llms/xai.md
index 3374cf487..c2334fa3c 100644
--- a/aider/website/docs/llms/xai.md
+++ b/aider/website/docs/llms/xai.md
@@ -7,14 +7,22 @@ nav_order: 400
You'll need a [xAI API key](https://console.x.ai.).
-To use xAI:
+First, install aider:
+
+{% include install.md %}
+
+Then configure your API keys:
```bash
-python -m pip install aider-install
-aider-install
-
export XAI_API_KEY= # Mac/Linux
setx XAI_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and xAI on your codebase:
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# Grok 3
aider --model xai/grok-3-beta
From 328a3c317846c15e198ed816e01fe7aa5688baf3 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 10:34:12 -0700
Subject: [PATCH 088/482] docs: Improve Amazon Bedrock setup instructions
---
aider/website/docs/llms/bedrock.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/aider/website/docs/llms/bedrock.md b/aider/website/docs/llms/bedrock.md
index f3e2131c7..c38631a36 100644
--- a/aider/website/docs/llms/bedrock.md
+++ b/aider/website/docs/llms/bedrock.md
@@ -6,7 +6,8 @@ nav_order: 560
# Amazon Bedrock
Aider can connect to models provided by Amazon Bedrock.
-You will need to have an AWS account with access to the Bedrock service and the specific models you wish to use.
+To configure Aider to use the Amazon Bedrock API, you need to set up your AWS credentials.
+This can be done using the AWS CLI or by setting environment variables.
## Select a Model from Amazon Bedrock
@@ -68,7 +69,7 @@ export AWS_PROFILE=your-profile
```
You can add these to your
-`.env` file.
+[.env file](/docs/config/dotenv.html).
### Set Environment Variables with PowerShell
From 7a50b7779a22abf753e190a8c6564362393bc304 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 10:34:13 -0700
Subject: [PATCH 089/482] docs: Update boto3 install instructions for Bedrock
---
aider/website/docs/llms/bedrock.md | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)
diff --git a/aider/website/docs/llms/bedrock.md b/aider/website/docs/llms/bedrock.md
index c38631a36..5d31beac7 100644
--- a/aider/website/docs/llms/bedrock.md
+++ b/aider/website/docs/llms/bedrock.md
@@ -82,25 +82,17 @@ $env:AWS_REGION = 'us-west-2' # Put whichever AWS region that you'd like, that
```
## Install boto3
-
-Aider needs the `boto3` library to connect to Bedrock.
-
-The AWS Bedrock provider requires the `boto3` package in order to function correctly:
-
-```bash
-pip install boto3
-```
-
-To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running
-
-```bash
-pipx inject aider-chat boto3
-```
-
-You must install `boto3` dependency to aider's virtual environment installed via one-liner or uv by running
+You may need to install the `boto3` package.
```bash
+# If you installed with aider-install or `uv tool`
uv tool run --from aider-chat pip install boto3
+
+# Or with pipx...
+pipx inject aider-chat boto3
+
+# Or with pip
+pip install -U boto3
```
## Get Started
From 84c3ac93ef1bcfb83fead60ef3326e143eab6513 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 10:37:14 -0700
Subject: [PATCH 090/482] copy
---
aider/website/_includes/get-started.md | 11 ++++++----
aider/website/_includes/install.md | 5 +++++
aider/website/docs/llms/bedrock.md | 27 ++++++++++++-----------
aider/website/docs/llms/gemini.md | 30 ++++++++++++++++++++------
4 files changed, 50 insertions(+), 23 deletions(-)
create mode 100644 aider/website/_includes/install.md
diff --git a/aider/website/_includes/get-started.md b/aider/website/_includes/get-started.md
index d5d3ff8c6..eb15d2797 100644
--- a/aider/website/_includes/get-started.md
+++ b/aider/website/_includes/get-started.md
@@ -1,10 +1,13 @@
-If you already have python 3.8-3.13 installed, you can get started quickly like this:
+If you already have python 3.8-3.13 installed, you can get started quickly like this.
+
+First, install aider:
+
+{% include install.md %}
+
+Start working with aider on your codebase:
```bash
-python -m pip install aider-install
-aider-install
-
# Change directory into your codebase
cd /to/your/project
diff --git a/aider/website/_includes/install.md b/aider/website/_includes/install.md
new file mode 100644
index 000000000..f42be5656
--- /dev/null
+++ b/aider/website/_includes/install.md
@@ -0,0 +1,5 @@
+
+```bash
+python -m pip install aider-install
+aider-install
+```
diff --git a/aider/website/docs/llms/bedrock.md b/aider/website/docs/llms/bedrock.md
index 5d31beac7..51a7d0822 100644
--- a/aider/website/docs/llms/bedrock.md
+++ b/aider/website/docs/llms/bedrock.md
@@ -81,19 +81,6 @@ $env:AWS_SECRET_ACCESS_KEY = 'your_secret_key'
$env:AWS_REGION = 'us-west-2' # Put whichever AWS region that you'd like, that the Bedrock service supports.
```
-## Install boto3
-You may need to install the `boto3` package.
-
-```bash
-# If you installed with aider-install or `uv tool`
-uv tool run --from aider-chat pip install boto3
-
-# Or with pipx...
-pipx inject aider-chat boto3
-
-# Or with pip
-pip install -U boto3
-```
## Get Started
@@ -123,6 +110,20 @@ aider --list-models bedrock/
Make sure you have access to these models in your AWS account before attempting to use them with Aider.
+## Install boto3
+You may need to install the `boto3` package.
+
+```bash
+# If you installed with aider-install or `uv tool`
+uv tool run --from aider-chat pip install boto3
+
+# Or with pipx...
+pipx inject aider-chat boto3
+
+# Or with pip
+pip install -U boto3
+```
+
# More info
For more information on Amazon Bedrock and its models, refer to the [official AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html).
diff --git a/aider/website/docs/llms/gemini.md b/aider/website/docs/llms/gemini.md
index 8cd70d5de..719f51760 100644
--- a/aider/website/docs/llms/gemini.md
+++ b/aider/website/docs/llms/gemini.md
@@ -7,17 +7,23 @@ nav_order: 300
You'll need a [Gemini API key](https://aistudio.google.com/app/u/2/apikey).
-```
-python -m pip install -U aider-chat
+First, install aider:
-# You may need to install google-generativeai
-pip install -U google-generativeai
+{% include install.md %}
-# Or with pipx...
-pipx inject aider-chat google-generativeai
+Then configure your API keys:
+```bash
export GEMINI_API_KEY= # Mac/Linux
setx GEMINI_API_KEY # Windows, restart shell after setx
+```
+
+Start working with aider and Gemini on your codebase:
+
+
+```bash
+# Change directory into your codebase
+cd /to/your/project
# You can run the Gemini 2.5 Pro model with:
aider --model gemini-2.5-pro
@@ -26,3 +32,15 @@ aider --model gemini-2.5-pro
aider --list-models gemini/
```
+You may need to install the `google-generativeai` package.
+
+```bash
+# If you installed with aider-install or `uv tool`
+uv tool run --from aider-chat pip install google-generativeai
+
+# Or with pipx...
+pipx inject aider-chat google-generativeai
+
+# Or with pip
+pip install -U google-generativeai
+```
From e560ab61b6852ddf2794f9ce719298d12f359a51 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 10:48:39 -0700
Subject: [PATCH 091/482] copy
---
aider/website/docs/llms.md | 9 ++++-----
aider/website/docs/llms/gemini.md | 7 +++++--
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/aider/website/docs/llms.md b/aider/website/docs/llms.md
index 23d4007a7..2180f9b63 100644
--- a/aider/website/docs/llms.md
+++ b/aider/website/docs/llms.md
@@ -16,9 +16,10 @@ description: Aider can connect to most LLMs for AI pair programming.
Aider works best with these models, which are skilled at editing code:
+- [Gemini 2.5 Pro](/docs/gemini.html)
- [DeepSeek R1 and V3](/docs/llms/deepseek.html)
- [Claude 3.7 Sonnet](/docs/llms/anthropic.html)
-- [OpenAI o1, o3-mini and GPT-4o](/docs/llms/openai.html)
+- [OpenAI o3, o4-mini and GPT-4.1](/docs/llms/openai.html)
## Free models
@@ -26,10 +27,8 @@ Aider works best with these models, which are skilled at editing code:
Aider works with a number of **free** API providers:
-- Google's [Gemini 1.5 Pro](/docs/llms/gemini.html) works with aider, with
-code editing capabilities similar to GPT-3.5.
-- You can use [Llama 3 70B on Groq](/docs/llms/groq.html) which is comparable to GPT-3.5 in code editing performance.
-- Cohere also offers free API access to their [Command-R+ model](/docs/llms/cohere.html), which works with aider as a *very basic* coding assistant.
+- [OpenRouter offers free access to many models](https://openrouter.ai/models/?q=free), with limitations on daily usage.
+- Google's [Gemini 2.5 Pro Exp](/docs/llms/gemini.html) works very well with aider.
## Local models
{: .no_toc }
diff --git a/aider/website/docs/llms/gemini.md b/aider/website/docs/llms/gemini.md
index 719f51760..261512fda 100644
--- a/aider/website/docs/llms/gemini.md
+++ b/aider/website/docs/llms/gemini.md
@@ -25,8 +25,11 @@ Start working with aider and Gemini on your codebase:
# Change directory into your codebase
cd /to/your/project
-# You can run the Gemini 2.5 Pro model with:
-aider --model gemini-2.5-pro
+# You can run the Gemini 2.5 Pro model with this shortcut:
+aider --model gemini
+
+# You can run the Gemini 2.5 Pro Exp for free, with usage limits:
+aider --model gemini-exp
# List models available from Gemini
aider --list-models gemini/
From d45a5747eab17cee28b91431cad078eb61b2b3ad Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 10:58:37 -0700
Subject: [PATCH 092/482] feat: Add script to clean metadata from files
---
scripts/clean_metadata.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 scripts/clean_metadata.py
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
new file mode 100644
index 000000000..e69de29bb
From 7bde345b831dd403c1c346dc86a59a5203793b00 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 10:58:38 -0700
Subject: [PATCH 093/482] feat: Add script to find common models in metadata
files.
---
scripts/clean_metadata.py | 54 +++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index e69de29bb..29328c9e8 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+
+import json
+from pathlib import Path
+
+
+def main():
+ script_dir = Path(__file__).parent.resolve()
+ litellm_path = script_dir / "../litellm/model_prices_and_context_window.json"
+ aider_path = script_dir / "../aider/resources/model-metadata.json"
+
+ if not litellm_path.exists():
+ print(f"Error: LiteLLM metadata file not found at {litellm_path}")
+ return
+
+ if not aider_path.exists():
+ print(f"Error: Aider metadata file not found at {aider_path}")
+ return
+
+ try:
+ with open(litellm_path, "r") as f:
+ litellm_data = json.load(f)
+ except json.JSONDecodeError as e:
+ print(f"Error decoding JSON from {litellm_path}: {e}")
+ return
+ except Exception as e:
+ print(f"Error reading {litellm_path}: {e}")
+ return
+
+ try:
+ with open(aider_path, "r") as f:
+ aider_data = json.load(f)
+ except json.JSONDecodeError as e:
+ print(f"Error decoding JSON from {aider_path}: {e}")
+ return
+ except Exception as e:
+ print(f"Error reading {aider_path}: {e}")
+ return
+
+ litellm_keys = set(litellm_data.keys())
+ aider_keys = set(aider_data.keys())
+
+ common_keys = litellm_keys.intersection(aider_keys)
+
+ if common_keys:
+ print("Common models found in both files:")
+ for key in sorted(list(common_keys)):
+ print(f"- {key}")
+ else:
+ print("No common models found between the two files.")
+
+
+if __name__ == "__main__":
+ main()
From 19a94e5f15e7f438bcdfe3e826b1fbbd03d10203 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 10:59:59 -0700
Subject: [PATCH 094/482] fix: Update litellm_path to correctly locate JSON
file
---
scripts/clean_metadata.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 29328c9e8..3f57bbfef 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -6,7 +6,7 @@ from pathlib import Path
def main():
script_dir = Path(__file__).parent.resolve()
- litellm_path = script_dir / "../litellm/model_prices_and_context_window.json"
+ litellm_path = script_dir / "../../litellm/model_prices_and_context_window.json"
aider_path = script_dir / "../aider/resources/model-metadata.json"
if not litellm_path.exists():
From 8596f0d4a3712cad11b0169ad1ceacf5550bf85e Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:00:00 -0700
Subject: [PATCH 095/482] feat: Use json5 to load model metadata for lenient
parsing
---
scripts/clean_metadata.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 3f57bbfef..3466f683b 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
import json
+import json5
from pathlib import Path
@@ -28,8 +29,9 @@ def main():
return
try:
+ # Use json5 for the aider metadata file as it might contain comments
with open(aider_path, "r") as f:
- aider_data = json.load(f)
+ aider_data = json5.load(f)
except json.JSONDecodeError as e:
print(f"Error decoding JSON from {aider_path}: {e}")
return
From be44b6509568f172c4c37f7283acabe263b354a5 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:00:03 -0700
Subject: [PATCH 096/482] style: Apply linting to clean_metadata.py
---
scripts/clean_metadata.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 3466f683b..dcdfbb5f4 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -1,9 +1,10 @@
#!/usr/bin/env python
import json
-import json5
from pathlib import Path
+import json5
+
def main():
script_dir = Path(__file__).parent.resolve()
From 82b26daf37e25d3a6e3a3ebce0a0857185180823 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:00:49 -0700
Subject: [PATCH 097/482] feat: display matching entries side-by-side with diff
highlighting
---
scripts/clean_metadata.py | 39 +++++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index dcdfbb5f4..defca1606 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
import json
+import difflib
from pathlib import Path
import json5
@@ -43,12 +44,42 @@ def main():
litellm_keys = set(litellm_data.keys())
aider_keys = set(aider_data.keys())
- common_keys = litellm_keys.intersection(aider_keys)
+ common_keys = sorted(list(litellm_keys.intersection(aider_keys)))
if common_keys:
- print("Common models found in both files:")
- for key in sorted(list(common_keys)):
- print(f"- {key}")
+ print("Comparing common models found in both files:\n")
+ for key in common_keys:
+ print(f"--- {key} (litellm) ---")
+ print(f"+++ {key} (aider) +++")
+
+ litellm_entry = litellm_data.get(key, {})
+ aider_entry = aider_data.get(key, {})
+
+ # Convert dicts to formatted JSON strings for comparison
+ litellm_json = json.dumps(litellm_entry, indent=4, sort_keys=True).splitlines()
+ aider_json = json.dumps(aider_entry, indent=4, sort_keys=True).splitlines()
+
+ # Generate unified diff
+ diff = difflib.unified_diff(
+ litellm_json,
+ aider_json,
+ fromfile=f"{key} (litellm)",
+ tofile=f"{key} (aider)",
+ lineterm="",
+ n=max(len(litellm_json), len(aider_json)), # Show all lines
+ )
+
+ # Print the diff, skipping the header lines generated by unified_diff
+ diff_lines = list(diff)[2:]
+ if not diff_lines:
+ print("(No differences found)")
+ else:
+ for line in diff_lines:
+ # Add color for better readability (optional, requires a library like 'termcolor' or manual ANSI codes)
+ # Simple +/- indication is standard for diffs
+ print(line)
+ print("\n" + "=" * 40 + "\n")
+
else:
print("No common models found between the two files.")
From 876569613bdda75c25bbb6535ab38eb8ba83b6ff Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:00:52 -0700
Subject: [PATCH 098/482] style: Apply linting to clean_metadata.py
---
scripts/clean_metadata.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index defca1606..024818d61 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
-import json
import difflib
+import json
from pathlib import Path
import json5
From 758020c574ff5329b67c491d2dac797db2a7c8b3 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:01:40 -0700
Subject: [PATCH 099/482] fix: Flip diff order to be from aider -> litellm in
script
---
scripts/clean_metadata.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 024818d61..4bd80925e 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -49,8 +49,8 @@ def main():
if common_keys:
print("Comparing common models found in both files:\n")
for key in common_keys:
- print(f"--- {key} (litellm) ---")
- print(f"+++ {key} (aider) +++")
+ print(f"--- {key} (aider) ---")
+ print(f"+++ {key} (litellm) +++")
litellm_entry = litellm_data.get(key, {})
aider_entry = aider_data.get(key, {})
@@ -61,10 +61,10 @@ def main():
# Generate unified diff
diff = difflib.unified_diff(
- litellm_json,
aider_json,
- fromfile=f"{key} (litellm)",
- tofile=f"{key} (aider)",
+ litellm_json,
+ fromfile=f"{key} (aider)",
+ tofile=f"{key} (litellm)",
lineterm="",
n=max(len(litellm_json), len(aider_json)), # Show all lines
)
From b2d541f1ebb0abf25674b2858266d4fa66667b64 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:02:00 -0700
Subject: [PATCH 100/482] style: Fix line length in clean_metadata.py for
flake8 compliance
---
scripts/clean_metadata.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 4bd80925e..6ae06a3eb 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -75,7 +75,8 @@ def main():
print("(No differences found)")
else:
for line in diff_lines:
- # Add color for better readability (optional, requires a library like 'termcolor' or manual ANSI codes)
+ # Add color for better readability (optional, requires a library
+ # like 'termcolor' or manual ANSI codes)
# Simple +/- indication is standard for diffs
print(line)
print("\n" + "=" * 40 + "\n")
From 226108d05d8c27450349143a4fc77c5541975a14 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:02:37 -0700
Subject: [PATCH 101/482] feat: Prompt user to remove entries from
model-metadata.json
---
scripts/clean_metadata.py | 45 +++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 6ae06a3eb..d86eaae77 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -9,7 +9,8 @@ import json5
def main():
script_dir = Path(__file__).parent.resolve()
- litellm_path = script_dir / "../../litellm/model_prices_and_context_window.json"
+ # Adjust path relative to the script's location in the aider repo
+ litellm_path = script_dir.parent / "../litellm/model_prices_and_context_window.json"
aider_path = script_dir / "../aider/resources/model-metadata.json"
if not litellm_path.exists():
@@ -44,6 +45,7 @@ def main():
litellm_keys = set(litellm_data.keys())
aider_keys = set(aider_data.keys())
+ keys_to_remove = set()
common_keys = sorted(list(litellm_keys.intersection(aider_keys)))
if common_keys:
@@ -79,10 +81,49 @@ def main():
# like 'termcolor' or manual ANSI codes)
# Simple +/- indication is standard for diffs
print(line)
- print("\n" + "=" * 40 + "\n")
+ print("\n" + "=" * 40)
+
+ # Ask user if they want to remove the entry from aider's metadata
+ response = input(
+ f"Remove '{key}' from aider/resources/model-metadata.json? (y/N): "
+ ).strip().lower()
+ if response == 'y':
+ keys_to_remove.add(key)
+ print(f"Marked '{key}' for removal.")
+ else:
+ print(f"Keeping '{key}'.")
+ print("-" * 40 + "\n") # Separator for the next model
else:
print("No common models found between the two files.")
+ return # Exit if no common keys
+
+ # Remove marked keys after iterating through all common models
+ if keys_to_remove:
+ print("\nRemoving marked entries from aider data...")
+ removed_count = 0
+ for key in keys_to_remove:
+ if key in aider_data:
+ del aider_data[key]
+ print(f" - Removed {key}")
+ removed_count += 1
+
+ if removed_count > 0:
+ # Write the modified data back to the aider metadata file
+ try:
+ with open(aider_path, "w") as f:
+ # Use json.dump for standard, clean JSON output
+ # Using sort_keys=True for consistent ordering
+ json.dump(aider_data, f, indent=4, sort_keys=True)
+ # Add a trailing newline for POSIX compatibility
+ f.write("\n")
+ print(f"\nSuccessfully updated {aider_path} with {removed_count} removal(s).")
+ except Exception as e:
+ print(f"\nError writing updated data to {aider_path}: {e}")
+ else:
+ print("\nNo entries were actually removed (perhaps they were already gone?).")
+ else:
+ print("\nNo entries marked for removal.")
if __name__ == "__main__":
From ce1266be68d526eebd80041e5454814be3ea1687 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:02:40 -0700
Subject: [PATCH 102/482] style: Run linter on clean_metadata.py
---
scripts/clean_metadata.py | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index d86eaae77..2607c7302 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -84,10 +84,12 @@ def main():
print("\n" + "=" * 40)
# Ask user if they want to remove the entry from aider's metadata
- response = input(
- f"Remove '{key}' from aider/resources/model-metadata.json? (y/N): "
- ).strip().lower()
- if response == 'y':
+ response = (
+ input(f"Remove '{key}' from aider/resources/model-metadata.json? (y/N): ")
+ .strip()
+ .lower()
+ )
+ if response == "y":
keys_to_remove.add(key)
print(f"Marked '{key}' for removal.")
else:
@@ -96,7 +98,7 @@ def main():
else:
print("No common models found between the two files.")
- return # Exit if no common keys
+ return # Exit if no common keys
# Remove marked keys after iterating through all common models
if keys_to_remove:
@@ -121,7 +123,7 @@ def main():
except Exception as e:
print(f"\nError writing updated data to {aider_path}: {e}")
else:
- print("\nNo entries were actually removed (perhaps they were already gone?).")
+ print("\nNo entries were actually removed (perhaps they were already gone?).")
else:
print("\nNo entries marked for removal.")
From b4673fdc85fa209a3eb95691c6bddfd215651603 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:03:41 -0700
Subject: [PATCH 103/482] Refactor: Remove keys immediately in
clean_metadata.py
---
scripts/clean_metadata.py | 48 ++++++++++++++++-----------------------
1 file changed, 20 insertions(+), 28 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 2607c7302..d28e45420 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -45,8 +45,8 @@ def main():
litellm_keys = set(litellm_data.keys())
aider_keys = set(aider_data.keys())
- keys_to_remove = set()
common_keys = sorted(list(litellm_keys.intersection(aider_keys)))
+ removed_count = 0
if common_keys:
print("Comparing common models found in both files:\n")
@@ -90,8 +90,21 @@ def main():
.lower()
)
if response == "y":
- keys_to_remove.add(key)
- print(f"Marked '{key}' for removal.")
+ if key in aider_data:
+ print(f"Removing '{key}' from aider data...")
+ del aider_data[key]
+ removed_count += 1
+ # Write the modified data back immediately
+ try:
+ with open(aider_path, "w") as f:
+ json.dump(aider_data, f, indent=4, sort_keys=True)
+ f.write("\n")
+ print(f"Successfully removed '{key}' and updated {aider_path}.")
+ except Exception as e:
+ print(f"Error writing updated data to {aider_path} after removing {key}: {e}")
+ # Exit or handle error appropriately? For now, just print.
+ else:
+ print(f"'{key}' not found in aider data (already removed?).")
else:
print(f"Keeping '{key}'.")
print("-" * 40 + "\n") # Separator for the next model
@@ -100,32 +113,11 @@ def main():
print("No common models found between the two files.")
return # Exit if no common keys
- # Remove marked keys after iterating through all common models
- if keys_to_remove:
- print("\nRemoving marked entries from aider data...")
- removed_count = 0
- for key in keys_to_remove:
- if key in aider_data:
- del aider_data[key]
- print(f" - Removed {key}")
- removed_count += 1
-
- if removed_count > 0:
- # Write the modified data back to the aider metadata file
- try:
- with open(aider_path, "w") as f:
- # Use json.dump for standard, clean JSON output
- # Using sort_keys=True for consistent ordering
- json.dump(aider_data, f, indent=4, sort_keys=True)
- # Add a trailing newline for POSIX compatibility
- f.write("\n")
- print(f"\nSuccessfully updated {aider_path} with {removed_count} removal(s).")
- except Exception as e:
- print(f"\nError writing updated data to {aider_path}: {e}")
- else:
- print("\nNo entries were actually removed (perhaps they were already gone?).")
+ # Final summary message
+ if removed_count > 0:
+ print(f"\nFinished comparing. A total of {removed_count} entr(y/ies) were removed.")
else:
- print("\nNo entries marked for removal.")
+ print("\nFinished comparing. No entries were removed.")
if __name__ == "__main__":
From 6656b5d973da485ff6f0cf9895489f6db2a92fa0 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:03:44 -0700
Subject: [PATCH 104/482] style: Apply linting to clean_metadata.py
---
scripts/clean_metadata.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index d28e45420..d07c41003 100644
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -101,7 +101,9 @@ def main():
f.write("\n")
print(f"Successfully removed '{key}' and updated {aider_path}.")
except Exception as e:
- print(f"Error writing updated data to {aider_path} after removing {key}: {e}")
+ print(
+ f"Error writing updated data to {aider_path} after removing {key}: {e}"
+ )
# Exit or handle error appropriately? For now, just print.
else:
print(f"'{key}' not found in aider data (already removed?).")
From ba2c4d1eb753b7a5f289f62e8a227321ab4da66d Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 11:05:35 -0700
Subject: [PATCH 105/482] chore: Make clean_metadata.py executable
---
scripts/clean_metadata.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100644 => 100755 scripts/clean_metadata.py
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
old mode 100644
new mode 100755
From 58f4db4e524e7d6d1579cd1f75ca0939eac2a344 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:05:36 -0700
Subject: [PATCH 106/482] feat: Implement surgical removal of JSON blocks from
metadata file
---
scripts/clean_metadata.py | 136 +++++++++++++++++++++++++++++++++-----
1 file changed, 121 insertions(+), 15 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index d07c41003..feb9a87ac 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -3,10 +3,124 @@
import difflib
import json
from pathlib import Path
+import re
import json5
+
+def find_block_lines(lines, key_to_remove):
+ """Finds the start and end line indices for a top-level key's block."""
+ start_line_idx = -1
+ # Regex to find the line starting the key definition, allowing for whitespace
+ # and ensuring it's the key we want (e.g., avoid matching "key1_extra": ...)
+ key_pattern = re.compile(r'^\s*"' + re.escape(key_to_remove) + r'"\s*:\s*{?')
+
+ for i, line in enumerate(lines):
+ if key_pattern.match(line.strip()):
+ start_line_idx = i
+ break
+
+ if start_line_idx == -1:
+ # Key might not start with '{' on the same line, check if it starts immediately after
+ key_pattern_no_brace = re.compile(r'^\s*"' + re.escape(key_to_remove) + r'"\s*:\s*$')
+ potential_start = -1
+ for i, line in enumerate(lines):
+ if key_pattern_no_brace.match(line.strip()):
+ potential_start = i
+ # Look for the opening brace on the next non-empty/comment line
+ j = i + 1
+ while j < len(lines):
+ stripped_next_line = lines[j].strip()
+ if not stripped_next_line or stripped_next_line.startswith("//"):
+ j += 1
+ continue
+ if stripped_next_line.startswith("{"):
+ start_line_idx = i # Start from the key definition line
+ break
+ else:
+ potential_start = -1 # False alarm
+ break
+ if start_line_idx != -1:
+ break
+
+ if start_line_idx == -1:
+ print(f"Warning: Could not reliably find start line for '{key_to_remove}'. Skipping removal.")
+ return None, None # Key block start not found clearly
+
+ brace_level = 0
+ in_string = False
+ escape_next = False
+ block_started = False
+ end_line_idx = -1
+
+ # Start brace counting from the identified start line
+ for i in range(start_line_idx, len(lines)):
+ line = lines[i]
+ # Simple brace counting - might be fooled by braces in comments or strings
+ # This is a limitation of pure text processing without full parsing
+ for char_idx, char in enumerate(line):
+ # Rudimentary string detection
+ if char == '"':
+ # Check if preceded by an odd number of backslashes (escaped quote)
+ backslashes = 0
+ temp_idx = char_idx - 1
+ while temp_idx >= 0 and line[temp_idx] == '\\':
+ backslashes += 1
+ temp_idx -= 1
+ if backslashes % 2 == 0:
+ in_string = not in_string
+
+ if not in_string:
+ if char == '{':
+ brace_level += 1
+ block_started = True # Mark that we've entered the block
+ elif char == '}':
+ brace_level -= 1
+
+ # Check if the block ends *after* processing the entire line
+ if block_started and brace_level == 0:
+ end_line_idx = i
+ break
+
+ if end_line_idx == -1:
+ print(f"Warning: Could not find end of block for '{key_to_remove}' starting at line {start_line_idx+1}. Skipping removal.")
+ return None, None # Block end not found
+
+ return start_line_idx, end_line_idx
+
+
+def remove_block_surgically(file_path, key_to_remove):
+ """Reads the file, removes the block for the key, writes back."""
+ try:
+ # Read with universal newlines, but keep track for writing
+ with open(file_path, "r") as f:
+ content = f.read()
+ lines = content.splitlines(keepends=True) # Keep original line endings
+ except Exception as e:
+ print(f"Error reading {file_path} for removal: {e}")
+ return False
+
+ start_idx, end_idx = find_block_lines(lines, key_to_remove)
+
+ if start_idx is None or end_idx is None:
+ return False # Error message already printed by find_block_lines
+
+ # Prepare the lines to be written, excluding the identified block
+ output_lines = lines[:start_idx] + lines[end_idx + 1 :]
+
+ # Note: Comma handling is omitted for simplicity. User may need manual fix.
+
+ try:
+ with open(file_path, "w") as f:
+ f.writelines(output_lines)
+ print(f"Successfully removed '{key_to_remove}' block and updated {file_path}.")
+ return True
+ except Exception as e:
+ print(f"Error writing updated data to {file_path} after removing {key_to_remove}: {e}")
+ return False
+
+
def main():
script_dir = Path(__file__).parent.resolve()
# Adjust path relative to the script's location in the aider repo
@@ -90,23 +204,15 @@ def main():
.lower()
)
if response == "y":
- if key in aider_data:
- print(f"Removing '{key}' from aider data...")
- del aider_data[key]
+ # Perform surgical removal from the text file
+ if remove_block_surgically(aider_path, key):
removed_count += 1
- # Write the modified data back immediately
- try:
- with open(aider_path, "w") as f:
- json.dump(aider_data, f, indent=4, sort_keys=True)
- f.write("\n")
- print(f"Successfully removed '{key}' and updated {aider_path}.")
- except Exception as e:
- print(
- f"Error writing updated data to {aider_path} after removing {key}: {e}"
- )
- # Exit or handle error appropriately? For now, just print.
+ # Optional: Also remove from the in-memory dict if needed later,
+ # but it's not strictly necessary if we reload or finish now.
+ # if key in aider_data: del aider_data[key]
else:
- print(f"'{key}' not found in aider data (already removed?).")
+ print(f"Failed to remove '{key}' block surgically.")
+ # Key might still be in aider_data if removal failed
else:
print(f"Keeping '{key}'.")
print("-" * 40 + "\n") # Separator for the next model
From ebfce5b0f20487c1dc469cd710b214ab1f0409ec Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:05:39 -0700
Subject: [PATCH 107/482] style: Run linter on clean_metadata.py
---
scripts/clean_metadata.py | 44 +++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index feb9a87ac..26b599633 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -2,13 +2,12 @@
import difflib
import json
-from pathlib import Path
import re
+from pathlib import Path
import json5
-
def find_block_lines(lines, key_to_remove):
"""Finds the start and end line indices for a top-level key's block."""
start_line_idx = -1
@@ -36,16 +35,18 @@ def find_block_lines(lines, key_to_remove):
j += 1
continue
if stripped_next_line.startswith("{"):
- start_line_idx = i # Start from the key definition line
+ start_line_idx = i # Start from the key definition line
break
else:
- potential_start = -1 # False alarm
+ potential_start = -1 # False alarm
break
if start_line_idx != -1:
break
if start_line_idx == -1:
- print(f"Warning: Could not reliably find start line for '{key_to_remove}'. Skipping removal.")
+ print(
+ f"Warning: Could not reliably find start line for '{key_to_remove}'. Skipping removal."
+ )
return None, None # Key block start not found clearly
brace_level = 0
@@ -62,20 +63,20 @@ def find_block_lines(lines, key_to_remove):
for char_idx, char in enumerate(line):
# Rudimentary string detection
if char == '"':
- # Check if preceded by an odd number of backslashes (escaped quote)
- backslashes = 0
- temp_idx = char_idx - 1
- while temp_idx >= 0 and line[temp_idx] == '\\':
- backslashes += 1
- temp_idx -= 1
- if backslashes % 2 == 0:
- in_string = not in_string
+ # Check if preceded by an odd number of backslashes (escaped quote)
+ backslashes = 0
+ temp_idx = char_idx - 1
+ while temp_idx >= 0 and line[temp_idx] == "\\":
+ backslashes += 1
+ temp_idx -= 1
+ if backslashes % 2 == 0:
+ in_string = not in_string
if not in_string:
- if char == '{':
+ if char == "{":
brace_level += 1
- block_started = True # Mark that we've entered the block
- elif char == '}':
+ block_started = True # Mark that we've entered the block
+ elif char == "}":
brace_level -= 1
# Check if the block ends *after* processing the entire line
@@ -84,8 +85,11 @@ def find_block_lines(lines, key_to_remove):
break
if end_line_idx == -1:
- print(f"Warning: Could not find end of block for '{key_to_remove}' starting at line {start_line_idx+1}. Skipping removal.")
- return None, None # Block end not found
+ print(
+ f"Warning: Could not find end of block for '{key_to_remove}' starting at line"
+ f" {start_line_idx+1}. Skipping removal."
+ )
+ return None, None # Block end not found
return start_line_idx, end_line_idx
@@ -96,7 +100,7 @@ def remove_block_surgically(file_path, key_to_remove):
# Read with universal newlines, but keep track for writing
with open(file_path, "r") as f:
content = f.read()
- lines = content.splitlines(keepends=True) # Keep original line endings
+ lines = content.splitlines(keepends=True) # Keep original line endings
except Exception as e:
print(f"Error reading {file_path} for removal: {e}")
return False
@@ -104,7 +108,7 @@ def remove_block_surgically(file_path, key_to_remove):
start_idx, end_idx = find_block_lines(lines, key_to_remove)
if start_idx is None or end_idx is None:
- return False # Error message already printed by find_block_lines
+ return False # Error message already printed by find_block_lines
# Prepare the lines to be written, excluding the identified block
output_lines = lines[:start_idx] + lines[end_idx + 1 :]
From 48ac1de8d370f9ec950acc95d45a1606e0a9be2a Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:05:56 -0700
Subject: [PATCH 108/482] fix: Remove unused variables and fix whitespace in
clean_metadata.py
---
scripts/clean_metadata.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 26b599633..c8c0eb077 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -23,10 +23,8 @@ def find_block_lines(lines, key_to_remove):
if start_line_idx == -1:
# Key might not start with '{' on the same line, check if it starts immediately after
key_pattern_no_brace = re.compile(r'^\s*"' + re.escape(key_to_remove) + r'"\s*:\s*$')
- potential_start = -1
for i, line in enumerate(lines):
if key_pattern_no_brace.match(line.strip()):
- potential_start = i
# Look for the opening brace on the next non-empty/comment line
j = i + 1
while j < len(lines):
@@ -51,7 +49,6 @@ def find_block_lines(lines, key_to_remove):
brace_level = 0
in_string = False
- escape_next = False
block_started = False
end_line_idx = -1
@@ -87,7 +84,7 @@ def find_block_lines(lines, key_to_remove):
if end_line_idx == -1:
print(
f"Warning: Could not find end of block for '{key_to_remove}' starting at line"
- f" {start_line_idx+1}. Skipping removal."
+ f" {start_line_idx + 1}. Skipping removal."
)
return None, None # Block end not found
From 506c3c928e65112a4cd108d316bdff9a15949d57 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:06:20 -0700
Subject: [PATCH 109/482] refactor: Remove unused variable in find_block_lines
function
---
scripts/clean_metadata.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index c8c0eb077..8028d7491 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -36,7 +36,7 @@ def find_block_lines(lines, key_to_remove):
start_line_idx = i # Start from the key definition line
break
else:
- potential_start = -1 # False alarm
+ # False alarm, the line after the key wasn't '{'
break
if start_line_idx != -1:
break
From d8caa76bc822669a576b0c26ae7d6d51a2d4ab58 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:08:53 -0700
Subject: [PATCH 110/482] feat: Compare dicts directly to avoid spurious diffs
in metadata cleaning
---
scripts/clean_metadata.py | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 8028d7491..7ee3648ea 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -173,10 +173,17 @@ def main():
aider_entry = aider_data.get(key, {})
# Convert dicts to formatted JSON strings for comparison
- litellm_json = json.dumps(litellm_entry, indent=4, sort_keys=True).splitlines()
- aider_json = json.dumps(aider_entry, indent=4, sort_keys=True).splitlines()
+ # First, compare the dictionaries directly for semantic equality
+ if litellm_entry == aider_entry:
+ print(f"'{key}': Entries are semantically identical.")
+ print("\n" + "=" * 40)
+ print("-" * 40 + "\n") # Separator for the next model
+ continue # Skip diff and removal prompt for identical entries
# Generate unified diff
+ # If dictionaries differ, generate JSON strings to show the diff
+ litellm_json = json.dumps(litellm_entry, indent=4, sort_keys=True).splitlines()
+ aider_json = json.dumps(aider_entry, indent=4, sort_keys=True).splitlines()
diff = difflib.unified_diff(
aider_json,
litellm_json,
@@ -189,7 +196,9 @@ def main():
# Print the diff, skipping the header lines generated by unified_diff
diff_lines = list(diff)[2:]
if not diff_lines:
- print("(No differences found)")
+ # This case should ideally not be reached if dict comparison was done first,
+ # but kept as a fallback.
+ print("(No textual differences found, though dictionaries might differ in type/order)")
else:
for line in diff_lines:
# Add color for better readability (optional, requires a library
From 2f38cd184cbac8516f7d82d006194fc32c972c06 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:08:57 -0700
Subject: [PATCH 111/482] style: Format clean_metadata.py with black linter
---
scripts/clean_metadata.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 7ee3648ea..0a9bcb2be 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -177,8 +177,8 @@ def main():
if litellm_entry == aider_entry:
print(f"'{key}': Entries are semantically identical.")
print("\n" + "=" * 40)
- print("-" * 40 + "\n") # Separator for the next model
- continue # Skip diff and removal prompt for identical entries
+ print("-" * 40 + "\n") # Separator for the next model
+ continue # Skip diff and removal prompt for identical entries
# Generate unified diff
# If dictionaries differ, generate JSON strings to show the diff
@@ -198,7 +198,9 @@ def main():
if not diff_lines:
# This case should ideally not be reached if dict comparison was done first,
# but kept as a fallback.
- print("(No textual differences found, though dictionaries might differ in type/order)")
+ print(
+ "(No textual differences found, though dictionaries might differ in type/order)"
+ )
else:
for line in diff_lines:
# Add color for better readability (optional, requires a library
From de28178369f2f899f2aaf2105c19f6b065141926 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:10:58 -0700
Subject: [PATCH 112/482] feat: Add dummy key to JSON dumps for diffing, then
remove it.
---
scripts/clean_metadata.py | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 0a9bcb2be..73ba2b713 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -182,15 +182,33 @@ def main():
# Generate unified diff
# If dictionaries differ, generate JSON strings to show the diff
- litellm_json = json.dumps(litellm_entry, indent=4, sort_keys=True).splitlines()
- aider_json = json.dumps(aider_entry, indent=4, sort_keys=True).splitlines()
+ # Add a dummy key to ensure the *real* last key gets a comma
+ litellm_entry_copy = litellm_entry.copy()
+ aider_entry_copy = aider_entry.copy()
+ dummy_key = "zzzdummykey"
+ litellm_entry_copy[dummy_key] = True
+ aider_entry_copy[dummy_key] = True
+
+ litellm_json_lines = json.dumps(
+ litellm_entry_copy, indent=4, sort_keys=True
+ ).splitlines()
+ aider_json_lines = json.dumps(
+ aider_entry_copy, indent=4, sort_keys=True
+ ).splitlines()
+
+ # Remove the dummy key line before diffing
+ litellm_json_filtered = [
+ line for line in litellm_json_lines if dummy_key not in line
+ ]
+ aider_json_filtered = [line for line in aider_json_lines if dummy_key not in line]
+
diff = difflib.unified_diff(
- aider_json,
- litellm_json,
+ aider_json_filtered,
+ litellm_json_filtered,
fromfile=f"{key} (aider)",
tofile=f"{key} (litellm)",
lineterm="",
- n=max(len(litellm_json), len(aider_json)), # Show all lines
+ n=max(len(litellm_json_filtered), len(aider_json_filtered)), # Show all lines
)
# Print the diff, skipping the header lines generated by unified_diff
From 13b3e75d0e328d30481fc315cd131738fe1e4a2e Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:11:01 -0700
Subject: [PATCH 113/482] style: Apply linting to clean_metadata.py
---
scripts/clean_metadata.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/scripts/clean_metadata.py b/scripts/clean_metadata.py
index 73ba2b713..c1031857b 100755
--- a/scripts/clean_metadata.py
+++ b/scripts/clean_metadata.py
@@ -192,14 +192,10 @@ def main():
litellm_json_lines = json.dumps(
litellm_entry_copy, indent=4, sort_keys=True
).splitlines()
- aider_json_lines = json.dumps(
- aider_entry_copy, indent=4, sort_keys=True
- ).splitlines()
+ aider_json_lines = json.dumps(aider_entry_copy, indent=4, sort_keys=True).splitlines()
# Remove the dummy key line before diffing
- litellm_json_filtered = [
- line for line in litellm_json_lines if dummy_key not in line
- ]
+ litellm_json_filtered = [line for line in litellm_json_lines if dummy_key not in line]
aider_json_filtered = [line for line in aider_json_lines if dummy_key not in line]
diff = difflib.unified_diff(
From 51e0fff82247d6a378f74ee83cc647ed58ca02d2 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 11:12:20 -0700
Subject: [PATCH 114/482] cleanup metadata that is now in litellm
---
aider/resources/model-metadata.json | 202 ----------------------------
1 file changed, 202 deletions(-)
diff --git a/aider/resources/model-metadata.json b/aider/resources/model-metadata.json
index 8cd469dce..336c6bee8 100644
--- a/aider/resources/model-metadata.json
+++ b/aider/resources/model-metadata.json
@@ -15,22 +15,6 @@
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
- "openrouter/deepseek/deepseek-r1": {
- "max_tokens": 8192,
- "max_input_tokens": 64000,
- "max_output_tokens": 8192,
- "input_cost_per_token": 0.00000055,
- "input_cost_per_token_cache_hit": 0.00000014,
- "cache_read_input_token_cost": 0.00000014,
- "cache_creation_input_token_cost": 0.0,
- "output_cost_per_token": 0.00000219,
- "litellm_provider": "openrouter",
- "mode": "chat",
- //"supports_function_calling": true,
- "supports_assistant_prefill": true,
- //"supports_tool_choice": true,
- "supports_prompt_caching": true
- },
"openrouter/deepseek/deepseek-r1:free": {
"max_tokens": 8192,
"max_input_tokens": 64000,
@@ -99,15 +83,6 @@
"output_cost_per_token": 0.000008,
"mode": "chat",
},
- "fireworks_ai/accounts/fireworks/models/deepseek-v3": {
- "max_tokens": 128000,
- "max_input_tokens": 100000,
- "max_output_tokens": 8192,
- "litellm_provider": "fireworks_ai",
- "input_cost_per_token": 0.0000009,
- "output_cost_per_token": 0.0000009,
- "mode": "chat",
- },
"fireworks_ai/accounts/fireworks/models/deepseek-v3-0324": {
"max_tokens": 160000,
"max_input_tokens": 100000,
@@ -117,54 +92,6 @@
"output_cost_per_token": 0.0000009,
"mode": "chat",
},
- "o3-mini": {
- "max_tokens": 100000,
- "max_input_tokens": 200000,
- "max_output_tokens": 100000,
- "input_cost_per_token": 0.0000011,
- "output_cost_per_token": 0.0000044,
- "cache_read_input_token_cost": 0.00000055,
- "litellm_provider": "openai",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_parallel_function_calling": true,
- "supports_vision": true,
- "supports_prompt_caching": true,
- "supports_system_messages": true,
- "supports_response_schema": true
- },
- "openrouter/openai/o3-mini": {
- "max_tokens": 100000,
- "max_input_tokens": 200000,
- "max_output_tokens": 100000,
- "input_cost_per_token": 0.0000011,
- "output_cost_per_token": 0.0000044,
- "cache_read_input_token_cost": 0.00000055,
- "litellm_provider": "openrouter",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_parallel_function_calling": true,
- "supports_vision": true,
- "supports_prompt_caching": true,
- "supports_system_messages": true,
- "supports_response_schema": true
- },
- "openrouter/openai/o3-mini-high": {
- "max_tokens": 100000,
- "max_input_tokens": 200000,
- "max_output_tokens": 100000,
- "input_cost_per_token": 0.0000011,
- "output_cost_per_token": 0.0000044,
- "cache_read_input_token_cost": 0.00000055,
- "litellm_provider": "openrouter",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_parallel_function_calling": true,
- "supports_vision": true,
- "supports_prompt_caching": true,
- "supports_system_messages": true,
- "supports_response_schema": true
- },
"openrouter/openrouter/quasar-alpha": {
"max_input_tokens": 1000000,
"max_output_tokens": 32000,
@@ -203,26 +130,6 @@
"supports_prompt_caching": true,
"supports_system_messages": true
},
- "claude-3-7-sonnet-20250219": {
- "max_tokens": 8192,
- "max_input_tokens": 200000,
- "max_output_tokens": 8192,
- "input_cost_per_token": 0.000003,
- "output_cost_per_token": 0.000015,
- "cache_creation_input_token_cost": 0.00000375,
- "cache_read_input_token_cost": 0.0000003,
- "litellm_provider": "anthropic",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_vision": true,
- "tool_use_system_prompt_tokens": 159,
- "supports_assistant_prefill": true,
- "supports_pdf_input": true,
- "supports_prompt_caching": true,
- "supports_response_schema": true,
- "deprecation_date": "2025-10-01",
- "supports_tool_choice": true
- },
"anthropic/claude-3-7-sonnet-20250219": {
"max_tokens": 8192,
"max_input_tokens": 200000,
@@ -243,43 +150,6 @@
"deprecation_date": "2025-10-01",
"supports_tool_choice": true
},
- "openrouter/anthropic/claude-3.7-sonnet": {
- "max_tokens": 8192,
- "max_input_tokens": 200000,
- "max_output_tokens": 8192,
- "input_cost_per_token": 0.000003,
- "output_cost_per_token": 0.000015,
- "cache_creation_input_token_cost": 0.00000375,
- "cache_read_input_token_cost": 0.0000003,
- "litellm_provider": "openrouter",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_vision": true,
- "tool_use_system_prompt_tokens": 159,
- "supports_assistant_prefill": true,
- "supports_pdf_input": true,
- "supports_prompt_caching": true,
- "supports_response_schema": true,
- "deprecation_date": "2025-10-01",
- "supports_tool_choice": true
- },
- "gpt-4.5-preview": {
- "max_tokens": 16384,
- "max_input_tokens": 128000,
- "max_output_tokens": 16384,
- "input_cost_per_token": 0.000075,
- "output_cost_per_token": 0.00015,
- "cache_read_input_token_cost": 0.0000375,
- "litellm_provider": "openai",
- "mode": "chat",
- "supports_function_calling": true,
- "supports_parallel_function_calling": true,
- "supports_response_schema": true,
- "supports_vision": true,
- "supports_prompt_caching": true,
- "supports_system_messages": true,
- "supports_tool_choice": true
- },
"openai/gpt-4.5-preview": {
"max_tokens": 16384,
"max_input_tokens": 128000,
@@ -334,42 +204,6 @@
"supports_tool_choice": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
},
- "gemini/gemini-2.5-pro-preview-03-25": {
- "max_tokens": 8192,
- "max_input_tokens": 1048576,
- "max_output_tokens": 64000,
- "max_images_per_prompt": 3000,
- "max_videos_per_prompt": 10,
- "max_video_length": 1,
- "max_audio_length_hours": 8.4,
- "max_audio_per_prompt": 1,
- "max_pdf_size_mb": 30,
- "input_cost_per_image": 0,
- "input_cost_per_video_per_second": 0,
- "input_cost_per_audio_per_second": 0,
- "input_cost_per_token": 0.00000125,
- "input_cost_per_character": 0,
- "input_cost_per_token_above_128k_tokens": 0,
- "input_cost_per_character_above_128k_tokens": 0,
- "input_cost_per_image_above_128k_tokens": 0,
- "input_cost_per_video_per_second_above_128k_tokens": 0,
- "input_cost_per_audio_per_second_above_128k_tokens": 0,
- "output_cost_per_token": 0.000010,
- "output_cost_per_character": 0,
- "output_cost_per_token_above_128k_tokens": 0,
- "output_cost_per_character_above_128k_tokens": 0,
- "litellm_provider": "gemini",
- "mode": "chat",
- "supports_system_messages": true,
- "supports_function_calling": true,
- "supports_vision": true,
- "supports_audio_input": true,
- "supports_video_input": true,
- "supports_pdf_input": true,
- "supports_response_schema": true,
- "supports_tool_choice": true,
- "source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
- },
"vertex_ai/gemini-2.5-pro-exp-03-25": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
@@ -523,15 +357,6 @@
"litellm_provider": "openrouter",
"mode": "chat"
},
- "xai/grok-3-beta": {
- "max_tokens": 131072,
- "max_input_tokens": 131072,
- "max_output_tokens": 131072,
- "input_cost_per_token": 0.000003,
- "output_cost_per_token": 0.000015,
- "litellm_provider": "xai",
- "mode": "chat"
- },
"openrouter/x-ai/grok-3-mini-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
@@ -541,15 +366,6 @@
"litellm_provider": "openrouter",
"mode": "chat"
},
- "xai/grok-3-mini-beta": {
- "max_tokens": 131072,
- "max_input_tokens": 131072,
- "max_output_tokens": 131072,
- "input_cost_per_token": 0.0000003,
- "output_cost_per_token": 0.0000005,
- "litellm_provider": "xai",
- "mode": "chat"
- },
"openrouter/x-ai/grok-3-fast-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
@@ -559,15 +375,6 @@
"litellm_provider": "openrouter",
"mode": "chat"
},
- "xai/grok-3-fast-beta": {
- "max_tokens": 131072,
- "max_input_tokens": 131072,
- "max_output_tokens": 131072,
- "input_cost_per_token": 0.000005,
- "output_cost_per_token": 0.000025,
- "litellm_provider": "xai",
- "mode": "chat"
- },
"openrouter/x-ai/grok-3-mini-fast-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
@@ -577,15 +384,6 @@
"litellm_provider": "openrouter",
"mode": "chat"
},
- "xai/grok-3-mini-fast-beta": {
- "max_tokens": 131072,
- "max_input_tokens": 131072,
- "max_output_tokens": 131072,
- "input_cost_per_token": 0.0000006,
- "output_cost_per_token": 0.000004,
- "litellm_provider": "xai",
- "mode": "chat"
- },
"openrouter/google/gemini-2.0-flash-exp:free": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
From 20a29e5cd18f85180d451603f2fbc63e2e7b7593 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 11:12:54 -0700
Subject: [PATCH 115/482] copy
---
aider/website/docs/llms.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/website/docs/llms.md b/aider/website/docs/llms.md
index 2180f9b63..c2475431c 100644
--- a/aider/website/docs/llms.md
+++ b/aider/website/docs/llms.md
@@ -16,7 +16,7 @@ description: Aider can connect to most LLMs for AI pair programming.
Aider works best with these models, which are skilled at editing code:
-- [Gemini 2.5 Pro](/docs/gemini.html)
+- [Gemini 2.5 Pro](/docs/llms/gemini.html)
- [DeepSeek R1 and V3](/docs/llms/deepseek.html)
- [Claude 3.7 Sonnet](/docs/llms/anthropic.html)
- [OpenAI o3, o4-mini and GPT-4.1](/docs/llms/openai.html)
From 1a4d3927e7eab362a8d19d54149d0963a0a91436 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:29:33 -0700
Subject: [PATCH 116/482] feat: Add --thinking-tokens option to benchmark
script
---
benchmark/benchmark.py | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index 71d3cec3e..a3c2ca850 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -209,6 +209,9 @@ def main(
reasoning_effort: Optional[str] = typer.Option(
None, "--reasoning-effort", help="Set reasoning effort for models that support it"
),
+ thinking_tokens: Optional[int] = typer.Option(
+ None, "--thinking-tokens", help="Set thinking tokens for models that support it"
+ ),
exercises_dir: str = typer.Option(
EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files"
),
@@ -366,6 +369,7 @@ def main(
num_ctx,
sleep,
reasoning_effort,
+ thinking_tokens,
)
all_results.append(results)
@@ -391,6 +395,7 @@ def main(
num_ctx,
sleep,
reasoning_effort,
+ thinking_tokens,
)
all_results = run_test_threaded.gather(tqdm=True)
@@ -489,6 +494,7 @@ def summarize_results(dirname, stats_languages=None):
res.lazy_comments = 0
res.reasoning_effort = None
+ res.thinking_tokens = None
variants = defaultdict(set)
for results in all_results:
@@ -518,6 +524,7 @@ def summarize_results(dirname, stats_languages=None):
res.indentation_errors += results.get("indentation_errors", 0)
res.reasoning_effort = results.get("reasoning_effort")
+ res.thinking_tokens = results.get("thinking_tokens")
for key in "model edit_format commit_hash editor_model editor_edit_format".split():
val = results.get(key)
@@ -564,6 +571,8 @@ def summarize_results(dirname, stats_languages=None):
if res.reasoning_effort is not None:
print(f" reasoning_effort: {res.reasoning_effort}")
+ if res.thinking_tokens is not None:
+ print(f" thinking_tokens: {res.thinking_tokens}")
for i in range(tries):
print(f" pass_rate_{i + 1}: {percents[i]:.1f}")
@@ -650,15 +659,14 @@ def get_replayed_content(replay_dname, test_dname):
def run_test(original_dname, testdir, *args, **kwargs):
try:
return run_test_real(original_dname, testdir, *args, **kwargs)
- except Exception as err:
+ except Exception:
print("=" * 40)
print("Test failed")
- print(err)
traceback.print_exc()
testdir = Path(testdir)
results_fname = testdir / ".aider.results.json"
- results_fname.write_text(json.dumps(dict(exception=str(err))))
+ results_fname.write_text(json.dumps(dict(exception=traceback.format_exc())))
def run_test_real(
@@ -677,6 +685,7 @@ def run_test_real(
num_ctx=None,
sleep=0,
reasoning_effort: Optional[str] = None,
+ thinking_tokens: Optional[int] = None,
read_model_settings=None,
):
if not os.path.isdir(testdir):
@@ -787,6 +796,9 @@ def run_test_real(
if reasoning_effort is not None:
main_model.set_reasoning_effort(reasoning_effort)
+ if thinking_tokens is not None:
+ main_model.set_thinking_tokens(thinking_tokens)
+
dump(main_model.max_chat_history_tokens)
if num_ctx:
@@ -938,6 +950,7 @@ def run_test_real(
indentation_errors=indentation_errors,
lazy_comments=lazy_comments, # Add the count of pattern matches to the results
reasoning_effort=reasoning_effort,
+ thinking_tokens=thinking_tokens,
chat_hashes=list(
zip(
coder.chat_completion_call_hashes,
From 8c3f167e8c48ed86ab4f746f7787e3a2ad04c90b Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 11:31:55 -0700
Subject: [PATCH 117/482] feat: Add simple unified diff coder
---
aider/coders/udiff_simple.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 aider/coders/udiff_simple.py
diff --git a/aider/coders/udiff_simple.py b/aider/coders/udiff_simple.py
new file mode 100644
index 000000000..e69de29bb
From 3ca3f39f1d22ca03ed85b7e5a023ffd0e06a7b15 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:31:55 -0700
Subject: [PATCH 118/482] feat: Add UnifiedDiffSimpleCoder with simpler prompt
for code edits
---
aider/coders/udiff_simple.py | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/aider/coders/udiff_simple.py b/aider/coders/udiff_simple.py
index e69de29bb..290178ed4 100644
--- a/aider/coders/udiff_simple.py
+++ b/aider/coders/udiff_simple.py
@@ -0,0 +1,16 @@
+from .udiff_coder import UnifiedDiffCoder
+
+
+class UnifiedDiffSimpleCoder(UnifiedDiffCoder):
+ """
+ A coder that uses unified diff format for code modifications.
+ This variant uses a simpler prompt that doesn't mention specific
+ diff rules like using `@@ ... @@` lines or avoiding line numbers.
+ """
+
+ edit_format = "udiff-simple"
+
+ # We can inherit the prompts if they are suitable or override them here
+ # For now, let's assume the base UnifiedDiffPrompts are sufficient
+ # If specific prompts are needed for the "simple" version, they would be defined here.
+ # gpt_prompts = UnifiedDiffSimplePrompts()
From ab11118c8afd8e309a84fab0ef1666a9c7b8ee14 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 11:32:41 -0700
Subject: [PATCH 119/482] feat: Add simple prompts for unified diff coder
---
aider/coders/udiff_simple_prompts.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 aider/coders/udiff_simple_prompts.py
diff --git a/aider/coders/udiff_simple_prompts.py b/aider/coders/udiff_simple_prompts.py
new file mode 100644
index 000000000..e69de29bb
From ba4d613cbc7dd261d400dab61931df089d92ba6b Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:32:42 -0700
Subject: [PATCH 120/482] feat: Give udiff-simple its own prompts, inheriting
from udiff prompts
---
aider/coders/udiff_simple.py | 6 ++----
aider/coders/udiff_simple_prompts.py | 16 ++++++++++++++++
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/aider/coders/udiff_simple.py b/aider/coders/udiff_simple.py
index 290178ed4..9cc51991d 100644
--- a/aider/coders/udiff_simple.py
+++ b/aider/coders/udiff_simple.py
@@ -1,4 +1,5 @@
from .udiff_coder import UnifiedDiffCoder
+from .udiff_simple_prompts import UnifiedDiffSimplePrompts
class UnifiedDiffSimpleCoder(UnifiedDiffCoder):
@@ -10,7 +11,4 @@ class UnifiedDiffSimpleCoder(UnifiedDiffCoder):
edit_format = "udiff-simple"
- # We can inherit the prompts if they are suitable or override them here
- # For now, let's assume the base UnifiedDiffPrompts are sufficient
- # If specific prompts are needed for the "simple" version, they would be defined here.
- # gpt_prompts = UnifiedDiffSimplePrompts()
+ gpt_prompts = UnifiedDiffSimplePrompts()
diff --git a/aider/coders/udiff_simple_prompts.py b/aider/coders/udiff_simple_prompts.py
index e69de29bb..b604f78dc 100644
--- a/aider/coders/udiff_simple_prompts.py
+++ b/aider/coders/udiff_simple_prompts.py
@@ -0,0 +1,16 @@
+from .udiff_prompts import UnifiedDiffPrompts
+
+
+class UnifiedDiffSimplePrompts(UnifiedDiffPrompts):
+ """
+ Prompts for the UnifiedDiffSimpleCoder.
+ Inherits from UnifiedDiffPrompts and can override specific prompts
+ if a simpler wording is desired for this edit format.
+ """
+
+ # For now, we inherit all prompts. Override specific ones below if needed.
+ # For example, to override the main_system prompt:
+ # main_system = """
+ # A simpler version of the main system prompt for udiff-simple.
+ # """
+ pass
From 5423ffe51837e6b5062907a565dc8d86dc1fc1ee Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 11:34:10 -0700
Subject: [PATCH 121/482] feat: Add UnifiedDiffSimpleCoder to coders module
---
aider/coders/__init__.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/aider/coders/__init__.py b/aider/coders/__init__.py
index e494fa3e4..88bcddfaa 100644
--- a/aider/coders/__init__.py
+++ b/aider/coders/__init__.py
@@ -10,6 +10,7 @@ from .editor_whole_coder import EditorWholeFileCoder
from .help_coder import HelpCoder
from .patch_coder import PatchCoder
from .udiff_coder import UnifiedDiffCoder
+from .udiff_simple import UnifiedDiffSimpleCoder
from .wholefile_coder import WholeFileCoder
# from .single_wholefile_func_coder import SingleWholeFileFunctionCoder
@@ -23,6 +24,7 @@ __all__ = [
WholeFileCoder,
PatchCoder,
UnifiedDiffCoder,
+ UnifiedDiffSimpleCoder,
# SingleWholeFileFunctionCoder,
ArchitectCoder,
EditorEditBlockCoder,
From ac1ff231e05b923ce1a09007dde3442aeb12459c Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 12:38:09 -0700
Subject: [PATCH 122/482] better prompt
---
aider/coders/udiff_simple_prompts.py | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/aider/coders/udiff_simple_prompts.py b/aider/coders/udiff_simple_prompts.py
index b604f78dc..706bb1026 100644
--- a/aider/coders/udiff_simple_prompts.py
+++ b/aider/coders/udiff_simple_prompts.py
@@ -8,9 +8,18 @@ class UnifiedDiffSimplePrompts(UnifiedDiffPrompts):
if a simpler wording is desired for this edit format.
"""
- # For now, we inherit all prompts. Override specific ones below if needed.
- # For example, to override the main_system prompt:
- # main_system = """
- # A simpler version of the main system prompt for udiff-simple.
- # """
- pass
+ example_messages = []
+
+ system_reminder = """# File editing rules:
+
+Return edits similar to unified diffs that `diff -U0` would produce.
+
+The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file!
+Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines.
+Make sure you mark all new or modified lines with `+`.
+Don't leave out any lines or the diff patch won't apply correctly.
+
+To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`.
+
+{lazy_prompt}
+"""
From c94340d4931617bd7d384d1e5cf4ce64a5de32c6 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 13:18:57 -0700
Subject: [PATCH 123/482] less ram
---
benchmark/docker.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/benchmark/docker.sh b/benchmark/docker.sh
index 3edde7c66..6f97b865e 100755
--- a/benchmark/docker.sh
+++ b/benchmark/docker.sh
@@ -2,8 +2,8 @@
docker run \
-it --rm \
- --memory=25g \
- --memory-swap=25g \
+ --memory=12g \
+ --memory-swap=12g \
--add-host=host.docker.internal:host-gateway \
-v `pwd`:/aider \
-v `pwd`/tmp.benchmarks/.:/benchmarks \
From 230e5065c1b07b43525916d92e39ec8e715bd5a1 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 15:47:34 -0700
Subject: [PATCH 124/482] feat: Add gemini-2.5-flash-preview-04-17 model and
leaderboard entry
---
aider/resources/model-settings.yml | 4 +++
aider/website/_data/polyglot_leaderboard.yml | 28 +++++++++++++++++++-
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml
index 7b5970d6e..4f1c8ec80 100644
--- a/aider/resources/model-settings.yml
+++ b/aider/resources/model-settings.yml
@@ -1367,3 +1367,7 @@
# extra_body:
# reasoning_effort: high
+- name: gemini/gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings: ["thinking_tokens"]
diff --git a/aider/website/_data/polyglot_leaderboard.yml b/aider/website/_data/polyglot_leaderboard.yml
index 5d7c651ae..0af93a8de 100644
--- a/aider/website/_data/polyglot_leaderboard.yml
+++ b/aider/website/_data/polyglot_leaderboard.yml
@@ -1197,4 +1197,30 @@
date: 2025-04-19
versions: 0.82.2.dev
seconds_per_case: 195.6
- total_cost: 0.0000
\ No newline at end of file
+ total_cost: 0.0000
+
+- dirname: 2025-04-20-19-54-31--flash25-diff-no-think
+ test_cases: 225
+ model: gemini-2.5-flash-preview-04-17 (default)
+ edit_format: diff
+ commit_hash: 7fcce5d-dirty
+ pass_rate_1: 21.8
+ pass_rate_2: 47.1
+ pass_num_1: 49
+ pass_num_2: 106
+ percent_cases_well_formed: 85.3
+ error_outputs: 60
+ num_malformed_responses: 55
+ num_with_malformed_responses: 33
+ user_asks: 82
+ lazy_comments: 1
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 5
+ test_timeouts: 4
+ total_tests: 225
+ command: aider --model gemini/gemini-2.5-flash-preview-04-17
+ date: 2025-04-20
+ versions: 0.82.3.dev
+ seconds_per_case: 50.1
+ total_cost: 1.8451
\ No newline at end of file
From 19de93ae39c18cb5798cd1992451089788645d92 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 15:58:54 -0700
Subject: [PATCH 125/482] fix: Update weak model name for
gemini-2.5-pro-exp-03-25
---
aider/resources/model-settings.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml
index 4f1c8ec80..870d6b669 100644
--- a/aider/resources/model-settings.yml
+++ b/aider/resources/model-settings.yml
@@ -965,7 +965,7 @@
- name: gemini/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
use_repo_map: true
- weak_model_name: gemini/gemini-2.0-flash
+ weak_model_name: gemini/gemini-2.5-flash-preview-04-17
- name: openrouter/google/gemini-2.5-pro-exp-03-25:free
edit_format: diff-fenced
From bbab0cea5e8c722814053e021eeba3cbc95b8dfd Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 16:01:03 -0700
Subject: [PATCH 126/482] feat: Add model settings for
gemini-2.5-flash-preview-04-17 models
---
aider/resources/model-settings.yml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml
index 870d6b669..8355e0c92 100644
--- a/aider/resources/model-settings.yml
+++ b/aider/resources/model-settings.yml
@@ -1371,3 +1371,13 @@
edit_format: diff
use_repo_map: true
accepts_settings: ["thinking_tokens"]
+
+- name: gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings: ["thinking_tokens"]
+
+- name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings: ["thinking_tokens"]
From 16fbff8de1e26686c962414419fb4b5841eb6cc2 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 16:04:04 -0700
Subject: [PATCH 127/482] Feat: Add gemini-2.5-flash-preview-04-17 as
editor/weak model name
---
aider/resources/model-settings.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml
index 8355e0c92..43ec1438d 100644
--- a/aider/resources/model-settings.yml
+++ b/aider/resources/model-settings.yml
@@ -975,14 +975,14 @@
- name: vertex_ai/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
use_repo_map: true
- # Need metadata for this one...
- #weak_model_name: vertex_ai/gemini-2.0-flash
+ weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
+ editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
use_repo_map: true
- # Need metadata for this one...
- #weak_model_name: vertex_ai/gemini-2.0-flash
+ weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
+ editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: openrouter/openrouter/quasar-alpha
use_repo_map: true
From 48733a315b61192f07b294881a99cb0105cb9f89 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 16:25:54 -0700
Subject: [PATCH 128/482] fix: Handle filenames starting with fence chars in
editblock coder
---
aider/coders/editblock_coder.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py
index 4d7776278..471a0c37c 100644
--- a/aider/coders/editblock_coder.py
+++ b/aider/coders/editblock_coder.py
@@ -412,7 +412,13 @@ def strip_filename(filename, fence):
return
start_fence = fence[0]
- if filename.startswith(start_fence) or filename.startswith(triple_backticks):
+ if filename.startswith(start_fence):
+ candidate = filename[len(start_fence):]
+ if candidate and "." in candidate:
+ return candidate
+
+ if filename.startswith(triple_backticks):
+ candidate = # ai!
return
filename = filename.rstrip(":")
From f28504a2eb96be99433e76a8501fd909ce6d8e46 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 16:25:55 -0700
Subject: [PATCH 129/482] fix: Properly handle filenames starting with triple
backticks
---
aider/coders/editblock_coder.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py
index 471a0c37c..32020f30f 100644
--- a/aider/coders/editblock_coder.py
+++ b/aider/coders/editblock_coder.py
@@ -418,8 +418,7 @@ def strip_filename(filename, fence):
return candidate
if filename.startswith(triple_backticks):
- candidate = # ai!
- return
+ filename = filename[len(triple_backticks):]
filename = filename.rstrip(":")
filename = filename.lstrip("#")
From c6ce87170060ea76507903622f0e47b2ed58a980 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Sun, 20 Apr 2025 16:25:59 -0700
Subject: [PATCH 130/482] style: Apply linter to editblock_coder.py
---
aider/coders/editblock_coder.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py
index 32020f30f..bb0a01914 100644
--- a/aider/coders/editblock_coder.py
+++ b/aider/coders/editblock_coder.py
@@ -413,12 +413,12 @@ def strip_filename(filename, fence):
start_fence = fence[0]
if filename.startswith(start_fence):
- candidate = filename[len(start_fence):]
+ candidate = filename[len(start_fence) :]
if candidate and "." in candidate:
return candidate
if filename.startswith(triple_backticks):
- filename = filename[len(triple_backticks):]
+ filename = filename[len(triple_backticks) :]
filename = filename.rstrip(":")
filename = filename.lstrip("#")
@@ -461,8 +461,12 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
]
# Check if the next line or the one after that is an editblock
- next_is_editblock = (i + 1 < len(lines) and head_pattern.match(lines[i + 1].strip())
- or i + 2 < len(lines) and head_pattern.match(lines[i + 2].strip()))
+ next_is_editblock = (
+ i + 1 < len(lines)
+ and head_pattern.match(lines[i + 1].strip())
+ or i + 2 < len(lines)
+ and head_pattern.match(lines[i + 2].strip())
+ )
if any(line.strip().startswith(start) for start in shell_starts) and not next_is_editblock:
shell_content = []
From 5e210c700d8f3f6f24248981bd259acdfd0410b9 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 16:36:36 -0700
Subject: [PATCH 131/482] fix: Handle filenames starting with fences or triple
backticks correctly
---
aider/coders/editblock_coder.py | 8 ++++--
tests/basic/test_editblock.py | 45 ++++++++-------------------------
2 files changed, 16 insertions(+), 37 deletions(-)
diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py
index bb0a01914..d8f85da52 100644
--- a/aider/coders/editblock_coder.py
+++ b/aider/coders/editblock_coder.py
@@ -414,11 +414,15 @@ def strip_filename(filename, fence):
start_fence = fence[0]
if filename.startswith(start_fence):
candidate = filename[len(start_fence) :]
- if candidate and "." in candidate:
+ if candidate and ("." in candidate or "/" in candidate):
return candidate
+ return
if filename.startswith(triple_backticks):
- filename = filename[len(triple_backticks) :]
+ candidate = filename[len(triple_backticks) :]
+ if candidate and ("." in candidate or "/" in candidate):
+ return candidate
+ return
filename = filename.rstrip(":")
filename = filename.lstrip("#")
diff --git a/tests/basic/test_editblock.py b/tests/basic/test_editblock.py
index d80952bbe..e93edb7c3 100644
--- a/tests/basic/test_editblock.py
+++ b/tests/basic/test_editblock.py
@@ -108,29 +108,6 @@ Hope you like it!
edits = list(eb.find_original_update_blocks(edit))
self.assertEqual(edits, [("foo.txt", "Two\n", "Tooooo\n")])
- def test_find_original_update_blocks_mangled_filename_w_source_tag(self):
- source = "source"
-
- edit = """
-Here's the change:
-
-<%s>foo.txt
-<<<<<<< SEARCH
-One
-=======
-Two
->>>>>>> REPLACE
-%s>
-
-Hope you like it!
-""" % (source, source)
-
- fence = ("<%s>" % source, "%s>" % source)
-
- with self.assertRaises(ValueError) as cm:
- _edits = list(eb.find_original_update_blocks(edit, fence))
- self.assertIn("missing filename", str(cm.exception))
-
def test_find_original_update_blocks_quote_below_filename(self):
edit = """
Here's the change:
@@ -181,10 +158,11 @@ Tooooo
oops!
+>>>>>>> REPLACE
"""
with self.assertRaises(ValueError) as cm:
- list(eb.find_original_update_blocks(edit))
+ _blocks = list(eb.find_original_update_blocks(edit))
self.assertIn("filename", str(cm.exception))
def test_find_original_update_blocks_no_final_newline(self):
@@ -575,7 +553,7 @@ Hope you like it!
edits = list(eb.find_original_update_blocks(edit, fence=quad_backticks))
self.assertEqual(edits, [("foo.txt", "", "Tooooo\n")])
- #Test for shell script blocks with sh language identifier (issue #3785)
+ # Test for shell script blocks with sh language identifier (issue #3785)
def test_find_original_update_blocks_with_sh_language_identifier(self):
# https://github.com/Aider-AI/aider/issues/3785
edit = """
@@ -609,13 +587,13 @@ exit 0
# Check that the content contains the expected shell script elements
result_content = edits[0][2]
self.assertIn("#!/bin/bash", result_content)
- self.assertIn("if [ \"$#\" -ne 1 ];", result_content)
- self.assertIn("echo \"Usage: $0 \"", result_content)
+ self.assertIn('if [ "$#" -ne 1 ];', result_content)
+ self.assertIn('echo "Usage: $0 "', result_content)
self.assertIn("exit 1", result_content)
- self.assertIn("echo \"$1\"", result_content)
+ self.assertIn('echo "$1"', result_content)
self.assertIn("exit 0", result_content)
- #Test for C# code blocks with csharp language identifier
+ # Test for C# code blocks with csharp language identifier
def test_find_original_update_blocks_with_csharp_language_identifier(self):
edit = """
Here's a C# code change:
@@ -631,12 +609,9 @@ Console.WriteLine("Hello, C# World!");
"""
edits = list(eb.find_original_update_blocks(edit))
- search_text = "Console.WriteLine(\"Hello World!\");\n"
- replace_text = "Console.WriteLine(\"Hello, C# World!\");\n"
- self.assertEqual(
- edits,
- [("Program.cs", search_text, replace_text)]
- )
+ search_text = 'Console.WriteLine("Hello World!");\n'
+ replace_text = 'Console.WriteLine("Hello, C# World!");\n'
+ self.assertEqual(edits, [("Program.cs", search_text, replace_text)])
if __name__ == "__main__":
From 7719eae0234ccdcfbb27dd1415d8225db83d7398 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 16:41:58 -0700
Subject: [PATCH 132/482] copy
---
HISTORY.md | 8 +
aider/website/HISTORY.md | 8 +
aider/website/assets/sample-analytics.jsonl | 440 +++++++++---------
.../website/docs/config/adv-model-settings.md | 24 +-
aider/website/docs/faq.md | 14 +-
5 files changed, 266 insertions(+), 228 deletions(-)
diff --git a/HISTORY.md b/HISTORY.md
index f3f839e7d..337a05e6c 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,13 @@
# Release history
+### main branch
+
+- Add support for `gemini-2.5-flash-preview-04-17` models.
+- Improved "diff" format for Gemini 2.5 Flash by accepting filenames provided on the same line as the opening fence.
+- Add new `udiff-simple` edit format, for Gemini 2.5 Pro.
+- Update default weak/editor models for Gemini 2.5 Pro models to use `gemini-2.5-flash-preview-04-17`.
+- Aider wrote 69% of the code in this release.
+
### Aider v0.82.2
- Fix editing shell files with diff-fenced, by zjy1412.
diff --git a/aider/website/HISTORY.md b/aider/website/HISTORY.md
index fa3fdcb22..abce8bd1d 100644
--- a/aider/website/HISTORY.md
+++ b/aider/website/HISTORY.md
@@ -24,6 +24,14 @@ cog.out(text)
]]]-->
+### main branch
+
+- Add support for `gemini-2.5-flash-preview-04-17` models.
+- Improved "diff" format for Gemini 2.5 Flash by accepting filenames provided on the same line as the opening fence.
+- Add new `udiff-simple` edit format, for Gemini 2.5 Pro.
+- Update default weak/editor models for Gemini 2.5 Pro models to use `gemini-2.5-flash-preview-04-17`.
+- Aider wrote 69% of the code in this release.
+
### Aider v0.82.2
- Fix editing shell files with diff-fenced, by zjy1412.
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index 3c18d8c53..90d6e65dd 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,223 +1,3 @@
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 13075, "completion_tokens": 2645, "total_tokens": 15720, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744587358}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591225}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591226}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591226}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591226}
-{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591241}
-{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591241}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591241}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14867, "completion_tokens": 214, "total_tokens": 15081, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591248}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591285}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15502, "completion_tokens": 173, "total_tokens": 15675, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591288}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591289}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 16016, "completion_tokens": 49, "total_tokens": 16065, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744591293}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744593859}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744606398}
-{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744606400}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644920}
-{"event": "repo", "properties": {"num_files": 205}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644926}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644926}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644929}
-{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644932}
-{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644932}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644932}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6260, "completion_tokens": 112, "total_tokens": 6372, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644943}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744644959}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648515}
-{"event": "repo", "properties": {"num_files": 205}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648516}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648516}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648516}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648538}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648543}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648544}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 3917, "completion_tokens": 433, "total_tokens": 4350, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648558}
-{"event": "command_code", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648573}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648574}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6666, "completion_tokens": 192, "total_tokens": 6858, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648578}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648601}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648632}
-{"event": "repo", "properties": {"num_files": 209}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648632}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648632}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648633}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648645}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6426, "completion_tokens": 113, "total_tokens": 6539, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648649}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648658}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648729}
-{"event": "repo", "properties": {"num_files": 209}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648729}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648729}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648729}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648746}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6386, "completion_tokens": 150, "total_tokens": 6536, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648754}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648848}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6704, "completion_tokens": 222, "total_tokens": 6926, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648858}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648889}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 6951, "completion_tokens": 215, "total_tokens": 7166, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648896}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648911}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 7181, "completion_tokens": 181, "total_tokens": 7362, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744648917}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744649052}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 7409, "completion_tokens": 365, "total_tokens": 7774, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744649062}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744649118}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744663883}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744663885}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744663885}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744663885}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664016}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664025}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664027}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664027}
-{"event": "cli session", "properties": {"main_model": "gpt-4.1", "weak_model": "gpt-4.1", "editor_model": "gpt-4.1", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664027}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664029}
-{"event": "message_send", "properties": {"main_model": "gpt-4.1", "weak_model": "gpt-4.1", "editor_model": "gpt-4.1", "edit_format": "diff", "prompt_tokens": 10637, "completion_tokens": 50, "total_tokens": 10687, "cost": 0.021674, "total_cost": 0.021674}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664034}
-{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664040}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664048}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664051}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664051}
-{"event": "cli session", "properties": {"main_model": "gpt-4.1", "weak_model": "gpt-4.1", "editor_model": "gpt-4.1", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664051}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664071}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664182}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664183}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664183}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664183}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664319}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 14361, "completion_tokens": 809, "total_tokens": 15170, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664339}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664340}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 15983, "completion_tokens": 334, "total_tokens": 16317, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664349}
-{"event": "command_architect", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664636}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664639}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664643}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664649}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664650}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12108, "completion_tokens": 649, "total_tokens": 12757, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664664}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664664}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 9878, "completion_tokens": 936, "total_tokens": 10814, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664674}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664709}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664727}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12196, "completion_tokens": 178, "total_tokens": 12374, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664733}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664733}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 9525, "completion_tokens": 217, "total_tokens": 9742, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664738}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664814}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12464, "completion_tokens": 452, "total_tokens": 12916, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664831}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664832}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 9839, "completion_tokens": 957, "total_tokens": 10796, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664848}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664885}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664886}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664892}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664918}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12204, "completion_tokens": 92, "total_tokens": 12296, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664926}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664926}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 9439, "completion_tokens": 114, "total_tokens": 9553, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664932}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664961}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664963}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 12251, "completion_tokens": 305, "total_tokens": 12556, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664980}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664980}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 9674, "completion_tokens": 73, "total_tokens": 9747, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744664984}
-{"event": "command_reset", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665447}
-{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665455}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665459}
-{"event": "command_tokens", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665471}
-{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665484}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665533}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 24637, "completion_tokens": 2765, "total_tokens": 27402, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665600}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665600}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 24366, "completion_tokens": 121, "total_tokens": 24487, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665607}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665905}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665906}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665906}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665906}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665914}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665949}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665951}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665951}
-{"event": "cli session", "properties": {"main_model": "gpt-4.1", "weak_model": "gpt-4.1-mini", "editor_model": "gpt-4.1-mini", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665951}
-{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665952}
-{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665952}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665966}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced", "prompt_tokens": 16140, "completion_tokens": 311, "total_tokens": 16451, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665977}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665978}
-{"event": "command_architect", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665984}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665986}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665987}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 13886, "completion_tokens": 174, "total_tokens": 14060, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665994}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665994}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 11452, "completion_tokens": 290, "total_tokens": 11742, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665999}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744665999}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 12204, "completion_tokens": 317, "total_tokens": 12521, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666007}
-{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666080}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666094}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666096}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666096}
-{"event": "cli session", "properties": {"main_model": "gpt-4.1-mini", "weak_model": "gpt-4.1-mini", "editor_model": "gpt-4.1-mini", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666096}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666098}
-{"event": "message_send", "properties": {"main_model": "gpt-4.1-mini", "weak_model": "gpt-4.1-mini", "editor_model": "gpt-4.1-mini", "edit_format": "diff", "prompt_tokens": 11733, "completion_tokens": 42, "total_tokens": 11775, "cost": 0.0047604, "total_cost": 0.0047604}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666101}
-{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666102}
-{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666102}
-{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666302}
-{"event": "repo", "properties": {"num_files": 590}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666303}
-{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666303}
-{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666303}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666308}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666367}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 27445, "completion_tokens": 2380, "total_tokens": 29825, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666387}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666387}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 23982, "completion_tokens": 2376, "total_tokens": 26358, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666406}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666590}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 30380, "completion_tokens": 987, "total_tokens": 31367, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666601}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666602}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 31879, "completion_tokens": 238, "total_tokens": 32117, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666613}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666619}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 32674, "completion_tokens": 169, "total_tokens": 32843, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666622}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666704}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666704}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 29052, "completion_tokens": 1012, "total_tokens": 30064, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666742}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666873}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666877}
-{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666885}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666893}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666893}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666923}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 14154, "completion_tokens": 137, "total_tokens": 14291, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666930}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666931}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 17505, "completion_tokens": 1217, "total_tokens": 18722, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666932}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 11623, "completion_tokens": 226, "total_tokens": 11849, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666939}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744666971}
-{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667034}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 19170, "completion_tokens": 5717, "total_tokens": 24887, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667035}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667035}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 14509, "completion_tokens": 7991, "total_tokens": 22500, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667108}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667115}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 26817, "completion_tokens": 629, "total_tokens": 27446, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667123}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667145}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667155}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667155}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 14926, "completion_tokens": 1210, "total_tokens": 16136, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667199}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667332}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667350}
-{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667366}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667367}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667408}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 14827, "completion_tokens": 2438, "total_tokens": 17265, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667443}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667449}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 15669, "completion_tokens": 2562, "total_tokens": 18231, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667470}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667479}
-{"event": "command_chat-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667492}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667498}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 15842, "completion_tokens": 1819, "total_tokens": 17661, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667522}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667523}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 18852, "completion_tokens": 2212, "total_tokens": 21064, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667547}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667547}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667563}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667564}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667659}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 11633, "completion_tokens": 1878, "total_tokens": 13511, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667686}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667738}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667769}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667769}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 11319, "completion_tokens": 1373, "total_tokens": 12692, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667791}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667864}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667877}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 12727, "completion_tokens": 1245, "total_tokens": 13972, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667888}
-{"event": "command_chat-mode", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667907}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667913}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "whole", "prompt_tokens": 13359, "completion_tokens": 1287, "total_tokens": 14646, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667925}
{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667990}
{"event": "command_architect", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667991}
@@ -998,3 +778,223 @@
{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163513}
+{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745163518}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169424}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169425}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169425}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169425}
+{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169504}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169513}
+{"event": "repo", "properties": {"num_files": 611}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169513}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169513}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169515}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169818}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169922}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 12540, "completion_tokens": 4598, "total_tokens": 17138, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169961}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169983}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169986}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745169991}
+{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170026}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170032}
+{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170033}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170035}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 11415, "completion_tokens": 3674, "total_tokens": 15089, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170079}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170445}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 15533, "completion_tokens": 259, "total_tokens": 15792, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745170451}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171263}
+{"event": "repo", "properties": {"num_files": 612}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171263}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171263}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171264}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 8867, "completion_tokens": 17, "total_tokens": 8884, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171269}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171269}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171274}
+{"event": "model warning", "properties": {"main_model": "None", "weak_model": "None", "editor_model": "None"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171276}
+{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171302}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171306}
+{"event": "repo", "properties": {"num_files": 612}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171307}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171307}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171307}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 9113, "completion_tokens": 17, "total_tokens": 9130, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171312}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171312}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171723}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171757}
+{"event": "repo", "properties": {"num_files": 612}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171758}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171758}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171758}
+{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171761}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171764}
+{"event": "repo", "properties": {"num_files": 612}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171765}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171765}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-preview-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-preview-03-25", "edit_format": "diff-fenced"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171765}
+{"event": "exit", "properties": {"reason": "Completed main CLI coder.run"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171829}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171854}
+{"event": "repo", "properties": {"num_files": 612}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171854}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171854}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171854}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171874}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171909}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 12362, "completion_tokens": 445, "total_tokens": 12807, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171917}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171960}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 13269, "completion_tokens": 262, "total_tokens": 13531, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171970}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171985}
+{"event": "command_read-only", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171988}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171994}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 20636, "completion_tokens": 177, "total_tokens": 20813, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745171998}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172037}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 20894, "completion_tokens": 496, "total_tokens": 21390, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172048}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172095}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 21739, "completion_tokens": 251, "total_tokens": 21990, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172099}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172115}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 22364, "completion_tokens": 155, "total_tokens": 22519, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172119}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172137}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 22589, "completion_tokens": 696, "total_tokens": 23285, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172157}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172200}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172211}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 23740, "completion_tokens": 695, "total_tokens": 24435, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172220}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172282}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 24460, "completion_tokens": 1797, "total_tokens": 26257, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172335}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172348}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 27939, "completion_tokens": 314, "total_tokens": 28253, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172356}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172356}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 28199, "completion_tokens": 1732, "total_tokens": 29931, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172379}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172493}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172522}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 19352, "completion_tokens": 467, "total_tokens": 19819, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172532}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172581}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172586}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172594}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 20067, "completion_tokens": 327, "total_tokens": 20394, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172610}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172650}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 22284, "completion_tokens": 426, "total_tokens": 22710, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172657}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172722}
+{"event": "repo", "properties": {"num_files": 613}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172724}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172724}
+{"event": "cli session", "properties": {"main_model": "xai/grok-3-fast-beta", "weak_model": "xai/grok-3-fast-beta", "editor_model": "xai/grok-3-fast-beta", "edit_format": "diff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172724}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172725}
+{"event": "message_send", "properties": {"main_model": "xai/grok-3-fast-beta", "weak_model": "xai/grok-3-fast-beta", "editor_model": "xai/grok-3-fast-beta", "edit_format": "diff", "prompt_tokens": 10210, "completion_tokens": 78, "total_tokens": 10288, "cost": 0.053000000000000005, "total_cost": 0.053000000000000005}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172729}
+{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172730}
+{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172730}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745172883}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173009}
+{"event": "repo", "properties": {"num_files": 613}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173009}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173009}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-flash-preview-04-17", "weak_model": "gemini/gemini-2.5-flash-preview-04-17", "editor_model": "gemini/gemini-2.5-flash-preview-04-17", "edit_format": "whole"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173009}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173017}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-flash-preview-04-17", "weak_model": "gemini/gemini-2.5-flash-preview-04-17", "editor_model": "gemini/gemini-2.5-flash-preview-04-17", "edit_format": "whole", "prompt_tokens": 8315, "completion_tokens": 25, "total_tokens": 8340, "cost": 0.00126225, "total_cost": 0.00126225}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173024}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173227}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173231}
+{"event": "model warning", "properties": {"main_model": "gemini/REDACTED", "weak_model": "gemini/REDACTED", "editor_model": "gemini/REDACTED"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173234}
+{"event": "exit", "properties": {"reason": "Keyboard interrupt during model warnings"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173235}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173477}
+{"event": "repo", "properties": {"num_files": 613}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173478}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173478}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173478}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173651}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 13344, "completion_tokens": 1294, "total_tokens": 14638, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173666}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173674}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 15409, "completion_tokens": 651, "total_tokens": 16060, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173687}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173750}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173754}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173757}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173764}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 13350, "completion_tokens": 721, "total_tokens": 14071, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173772}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173790}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173796}
+{"event": "repo", "properties": {"num_files": 613}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173796}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173796}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173796}
+{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173798}
+{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173798}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173873}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173898}
+{"event": "repo", "properties": {"num_files": 613}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173898}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173898}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173898}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173908}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 8723, "completion_tokens": 179, "total_tokens": 8902, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173914}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173939}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173954}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 7633, "completion_tokens": 328, "total_tokens": 7961, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173960}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173967}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173985}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745173997}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 25866, "completion_tokens": 543, "total_tokens": 26409, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174004}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174035}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174044}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff", "prompt_tokens": 26460, "completion_tokens": 137, "total_tokens": 26597, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174049}
+{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174055}
+{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174056}
+{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174056}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174643}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174643}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174643}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174643}
+{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174645}
+{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745174645}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745175891}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745175892}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745175892}
+{"event": "exit", "properties": {"reason": "Showed prompts"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745175896}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189251}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189251}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189251}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189254}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189929}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189931}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189931}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189934}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189982}
+{"event": "exit", "properties": {"reason": "Listed models"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189984}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745189999}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190000}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190000}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190000}
+{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190007}
+{"event": "command_edit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190022}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190053}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 16858, "completion_tokens": 143, "total_tokens": 17001, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190062}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190237}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 17173, "completion_tokens": 312, "total_tokens": 17485, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190243}
+{"event": "command_exit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190249}
+{"event": "exit", "properties": {"reason": "/exit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190249}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190260}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190262}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190262}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190262}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-flash-preview-04-17", "weak_model": "gemini/gemini-2.5-flash-preview-04-17", "editor_model": "gemini/gemini-2.5-flash-preview-04-17", "edit_format": "diff", "prompt_tokens": 10189, "completion_tokens": 116, "total_tokens": 10305, "cost": 0.0015979499999999999, "total_cost": 0.0015979499999999999}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190272}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190955}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190955}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190955}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190955}
+{"event": "command_edit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745190964}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191011}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191011}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 8442, "completion_tokens": 417, "total_tokens": 8859, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191025}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191054}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191054}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191127}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 14287, "completion_tokens": 1995, "total_tokens": 16282, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191145}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191182}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191214}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191214}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191224}
+{"event": "command_edit", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191228}
+{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191286}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191286}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 8481, "completion_tokens": 1848, "total_tokens": 10329, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191334}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191533}
+{"event": "ai-comments execute", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191535}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191535}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 8611, "completion_tokens": 89, "total_tokens": 8700, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745191553}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192191}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192191}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192191}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192196}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192301}
+{"event": "no-repo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192301}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192301}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192301}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 7873, "completion_tokens": 147, "total_tokens": 8020, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192314}
+{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192314}
+{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192315}
+{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192318}
diff --git a/aider/website/docs/config/adv-model-settings.md b/aider/website/docs/config/adv-model-settings.md
index ded10691a..e3c17035c 100644
--- a/aider/website/docs/config/adv-model-settings.md
+++ b/aider/website/docs/config/adv-model-settings.md
@@ -674,6 +674,12 @@ cog.out("```\n")
editor_edit_format: editor-diff
reasoning_tag: think
+- name: gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings:
+ - thinking_tokens
+
- name: gemini/gemini-1.5-flash-002
- name: gemini/gemini-1.5-flash-exp-0827
@@ -702,9 +708,15 @@ cog.out("```\n")
edit_format: diff
use_repo_map: true
+- name: gemini/gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings:
+ - thinking_tokens
+
- name: gemini/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
- weak_model_name: gemini/gemini-2.0-flash
+ weak_model_name: gemini/gemini-2.5-flash-preview-04-17
use_repo_map: true
- name: gemini/gemini-2.5-pro-preview-03-25
@@ -1446,6 +1458,12 @@ cog.out("```\n")
accepts_settings:
- thinking_tokens
+- name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
+ edit_format: diff
+ use_repo_map: true
+ accepts_settings:
+ - thinking_tokens
+
- name: vertex_ai/claude-3-5-haiku@20241022
edit_format: diff
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
@@ -1496,11 +1514,15 @@ cog.out("```\n")
- name: vertex_ai/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
+ weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
use_repo_map: true
+ editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
+ weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
use_repo_map: true
+ editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-pro-experimental
edit_format: diff-fenced
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index 71bb34aef..ba1207ba8 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,13 +264,13 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 2,084,414 91.2%
-o3 100,777 4.4%
-openrouter/anthropic/claude-3.7-sonnet 35,268 1.5%
-gemini/gemini-2.5-pro-preview-03-25 16,524 0.7%
-o4-mini 16,499 0.7%
-gpt-4.1-mini 11,775 0.5%
-gpt-4.1 10,687 0.5%
+gemini/gemini-2.5-pro-exp-03-25 1,852,969 90.0%
+o3 100,777 4.9%
+openrouter/anthropic/claude-3.7-sonnet 35,268 1.7%
+gemini/gemini-2.5-flash-preview-04-17 18,645 0.9%
+gemini/gemini-2.5-pro-preview-03-25 16,524 0.8%
+o4-mini 16,499 0.8%
+xai/grok-3-fast-beta 10,288 0.5%
None 8,001 0.4%
gemini/REDACTED 606 0.0%
From 7c0aac745460528c45cb7d12dd1f4fda698f80c9 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 16:43:35 -0700
Subject: [PATCH 133/482] chore: Update Gemini flash model alias to preview
version
---
aider/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index a31061f87..dd0abd452 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -88,7 +88,7 @@ MODEL_ALIASES = {
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-chat",
- "flash": "gemini/gemini-2.0-flash-exp",
+ "flash": "gemini/gemini-2.5-flash-preview-04-17",
"quasar": "openrouter/openrouter/quasar-alpha",
"r1": "deepseek/deepseek-reasoner",
"gemini-2.5-pro": "gemini/gemini-2.5-pro-exp-03-25",
From b3d32f65d3b6b64d245e572e75c8979775087c61 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 17:29:42 -0700
Subject: [PATCH 134/482] fixed quote
---
README.md | 4 ++--
aider/website/assets/home.css | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index e9db1be80..688506ab5 100644
--- a/README.md
+++ b/README.md
@@ -140,7 +140,7 @@ See the [installation instructions](https://aider.chat/docs/install.html) and [u
## Kind Words From Users
-- *"My life has changed this week. There's finally an AI coding tool that's good enough to keep up with me... Aider... It's going to rock your world."* — [Eric S. Raymond](https://x.com/esrtweet/status/1910809356381413593)
+- *"My life has changed... There's finally an AI coding tool that's good enough to keep up with me... Aider... It's going to rock your world."* — [Eric S. Raymond](https://x.com/esrtweet/status/1910809356381413593)
- *"The best free open source AI coding assistant."* — [IndyDevDan](https://youtu.be/YALpX8oOn78)
- *"The best AI coding assistant so far."* — [Matthew Berman](https://www.youtube.com/watch?v=df8afeb1FY8)
- *"Aider ... has easily quadrupled my coding productivity."* — [SOLAR_FIELDS](https://news.ycombinator.com/item?id=36212100)
@@ -168,7 +168,7 @@ See the [installation instructions](https://aider.chat/docs/install.html) and [u
- *"Aider is also my best friend."* — [jzn21](https://www.reddit.com/r/ChatGPTCoding/comments/1heuvuo/aider_vs_cline_vs_windsurf_vs_cursor/m27dcnb/)
- *"Try Aider, it's worth it."* — [jorgejhms](https://www.reddit.com/r/ChatGPTCoding/comments/1heuvuo/aider_vs_cline_vs_windsurf_vs_cursor/m27cp99/)
- *"I like aider :)"* — [Chenwei Cui](https://x.com/ccui42/status/1904965344999145698)
-- *"Aider is the precision tool of LLM code gen. It is minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control."* — [Reilly Sweetland](https://x.com/rsweetland/status/1904963807237259586)
+- *"Aider is the precision tool of LLM code gen... Minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control."* — [Reilly Sweetland](https://x.com/rsweetland/status/1904963807237259586)
- *"Cannot believe aider vibe coded a 650 LOC feature across service and cli today in 1 shot."* - [autopoietist](https://discord.com/channels/1131200896827654144/1131200896827654149/1355675042259796101)
- *"Oh no the secret is out! Yes, Aider is the best coding tool around. I highly, highly recommend it to anyone."* — [Joshua D Vander Hook](https://x.com/jodavaho/status/1911154899057795218)
- *"thanks to aider, i have started and finished three personal projects within the last two days"* — [joseph stalzyn](https://x.com/anitaheeder/status/1908338609645904160)
diff --git a/aider/website/assets/home.css b/aider/website/assets/home.css
index b46efaa23..9d64fd2e1 100644
--- a/aider/website/assets/home.css
+++ b/aider/website/assets/home.css
@@ -446,7 +446,7 @@ code, pre, .code-block {
}
.testimonial-text::before {
- content: "\201C"; /* Opening fancy quote */
+ content: "\201C\00A0"; /* Opening fancy quote */
color: var(--primary);
margin-right: 4px;
vertical-align: -0.3em;
From 303645cffae597123237967f831e0892e225d784 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Sun, 20 Apr 2025 17:30:06 -0700
Subject: [PATCH 135/482] copy
---
aider/website/assets/sample-analytics.jsonl | 80 ++++++++++-----------
aider/website/docs/config/model-aliases.md | 2 +-
aider/website/docs/faq.md | 6 +-
aider/website/index.html | 4 +-
4 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/aider/website/assets/sample-analytics.jsonl b/aider/website/assets/sample-analytics.jsonl
index 90d6e65dd..18005a8c6 100644
--- a/aider/website/assets/sample-analytics.jsonl
+++ b/aider/website/assets/sample-analytics.jsonl
@@ -1,43 +1,3 @@
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "whole", "prompt_tokens": 13359, "completion_tokens": 1287, "total_tokens": 14646, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667925}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667990}
-{"event": "command_architect", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667991}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744667996}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668002}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668016}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 21550, "completion_tokens": 885, "total_tokens": 22435, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668037}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668063}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 28286, "completion_tokens": 231, "total_tokens": 28517, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668076}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668077}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 24153, "completion_tokens": 230, "total_tokens": 24383, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668081}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668082}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 24627, "completion_tokens": 137, "total_tokens": 24764, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668088}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668088}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 25094, "completion_tokens": 201, "total_tokens": 25295, "cost": 0.0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668096}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668136}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 28588, "completion_tokens": 226, "total_tokens": 28814, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668140}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668140}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 24152, "completion_tokens": 322, "total_tokens": 24474, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668144}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668205}
-{"event": "command_drop", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668206}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668210}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668212}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 10474, "completion_tokens": 570, "total_tokens": 11044, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668262}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668263}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "editor-diff-fenced", "prompt_tokens": 7990, "completion_tokens": 342, "total_tokens": 8332, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668268}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668312}
-{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668319}
-{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668324}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668337}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668337}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668349}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668349}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668352}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668352}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 10679, "completion_tokens": 744, "total_tokens": 11423, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668379}
-{"event": "command_add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668395}
-{"event": "command_ask", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668414}
-{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668414}
-{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "ask", "prompt_tokens": 26914, "completion_tokens": 596, "total_tokens": 27510, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668429}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668482}
{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "architect", "prompt_tokens": 28214, "completion_tokens": 358, "total_tokens": 28572, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668500}
{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1744668500}
@@ -998,3 +958,43 @@
{"event": "exit", "properties": {"reason": "Completed --message"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192314}
{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192315}
{"event": "ai-comments file-add", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192318}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192612}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192612}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192612}
+{"event": "exit", "properties": {"reason": "Completed lint/test/commit"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745192615}
+{"event": "launched", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194554}
+{"event": "repo", "properties": {"num_files": 615}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194556}
+{"event": "auto_commits", "properties": {"enabled": true}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194556}
+{"event": "cli session", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194556}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194568}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194656}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 17860, "completion_tokens": 168, "total_tokens": 18028, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194665}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194715}
+{"event": "message_send", "properties": {"main_model": "gemini/gemini-2.5-pro-exp-03-25", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "udiff-simple", "prompt_tokens": 18087, "completion_tokens": 253, "total_tokens": 18340, "cost": 0, "total_cost": 0.0}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194725}
+{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194753}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194758}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194776}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194789}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19552, "completion_tokens": 1375, "total_tokens": 20927, "cost": 0.25052, "total_cost": 0.25052}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194806}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194833}
+{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194837}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194840}
+{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 20025, "completion_tokens": 286, "total_tokens": 20311, "cost": 0.064365, "total_cost": 0.314885}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194850}
+{"event": "command_think-tokens", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194889}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194910}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194912}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194925}
+{"event": "message_send", "properties": {"main_model": "openrouter/anthropic/claude-3.7-sonnet", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19887, "completion_tokens": 819, "total_tokens": 20706, "cost": 0.071946, "total_cost": 0.38683100000000004}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194945}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194972}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194973}
+{"event": "command_model", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194975}
+{"event": "command_reasoning-effort", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194980}
+{"event": "command_clear", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194982}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745194985}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19561, "completion_tokens": 3339, "total_tokens": 22900, "cost": 0.32917, "total_cost": 0.7160010000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195020}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195108}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 19855, "completion_tokens": 876, "total_tokens": 20731, "cost": 0.23359000000000002, "total_cost": 0.9495910000000001}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195117}
+{"event": "message_send_starting", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195161}
+{"event": "message_send", "properties": {"main_model": "o3", "weak_model": "gemini/gemini-2.0-flash", "editor_model": "gemini/gemini-2.5-pro-exp-03-25", "edit_format": "diff", "prompt_tokens": 20114, "completion_tokens": 1504, "total_tokens": 21618, "cost": 0.26130000000000003, "total_cost": 1.2108910000000002}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195174}
+{"event": "command_undo", "properties": {}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195213}
+{"event": "exit", "properties": {"reason": "Control-C"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1745195363}
diff --git a/aider/website/docs/config/model-aliases.md b/aider/website/docs/config/model-aliases.md
index a9b218f47..73eed2937 100644
--- a/aider/website/docs/config/model-aliases.md
+++ b/aider/website/docs/config/model-aliases.md
@@ -79,7 +79,7 @@ for alias, model in sorted(MODEL_ALIASES.items()):
- `4-turbo`: gpt-4-1106-preview
- `4o`: gpt-4o
- `deepseek`: deepseek/deepseek-chat
-- `flash`: gemini/gemini-2.0-flash-exp
+- `flash`: gemini/gemini-2.5-flash-preview-04-17
- `gemini`: gemini/gemini-2.5-pro-preview-03-25
- `gemini-2.5-pro`: gemini/gemini-2.5-pro-exp-03-25
- `gemini-exp`: gemini/gemini-2.5-pro-exp-03-25
diff --git a/aider/website/docs/faq.md b/aider/website/docs/faq.md
index ba1207ba8..eaaaa4fc2 100644
--- a/aider/website/docs/faq.md
+++ b/aider/website/docs/faq.md
@@ -264,9 +264,9 @@ tr:hover { background-color: #f5f5f5; }
Model Name Total Tokens Percent
-gemini/gemini-2.5-pro-exp-03-25 1,852,969 90.0%
-o3 100,777 4.9%
-openrouter/anthropic/claude-3.7-sonnet 35,268 1.7%
+gemini/gemini-2.5-pro-exp-03-25 1,637,700 83.1%
+o3 186,953 9.5%
+openrouter/anthropic/claude-3.7-sonnet 76,285 3.9%
gemini/gemini-2.5-flash-preview-04-17 18,645 0.9%
gemini/gemini-2.5-pro-preview-03-25 16,524 0.8%
o4-mini 16,499 0.8%
diff --git a/aider/website/index.html b/aider/website/index.html
index 80611f3a9..50947389d 100644
--- a/aider/website/index.html
+++ b/aider/website/index.html
@@ -269,7 +269,7 @@ cog.out(text)
+
+
+By [Your Name],
+last updated
+
+
+
From 043c42b2b41b2074c468d56a4303c2f81a7193de Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 8 May 2025 10:59:49 -0700
Subject: [PATCH 246/482] feat: Create Qwen3 leaderboard data file
---
aider/website/_data/qwen3_leaderboard.yml | 55 +++++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 aider/website/_data/qwen3_leaderboard.yml
diff --git a/aider/website/_data/qwen3_leaderboard.yml b/aider/website/_data/qwen3_leaderboard.yml
new file mode 100644
index 000000000..07e378674
--- /dev/null
+++ b/aider/website/_data/qwen3_leaderboard.yml
@@ -0,0 +1,55 @@
+- dirname: 2025-05-08-03-20-24--qwen3-32b-default
+ test_cases: 225
+ model: Qwen3 32B
+ edit_format: diff
+ commit_hash: aaacee5-dirty, aeaf259
+ pass_rate_1: 14.2
+ pass_rate_2: 40.0
+ pass_num_1: 32
+ pass_num_2: 90
+ percent_cases_well_formed: 83.6
+ error_outputs: 119
+ num_malformed_responses: 50
+ num_with_malformed_responses: 37
+ user_asks: 97
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 12
+ prompt_tokens: 317591
+ completion_tokens: 120418
+ test_timeouts: 5
+ total_tests: 225
+ command: aider --model openrouter/qwen/qwen3-32b
+ date: 2025-05-08
+ versions: 0.82.4.dev
+ seconds_per_case: 372.2
+ total_cost: 0.7603
+
+- dirname: 2025-05-08-03-22-37--qwen3-235b-defaults
+ test_cases: 225
+ model: Qwen3 235B A22B
+ edit_format: diff
+ commit_hash: aaacee5-dirty
+ pass_rate_1: 17.3
+ pass_rate_2: 49.8
+ pass_num_1: 39
+ pass_num_2: 112
+ percent_cases_well_formed: 91.6
+ error_outputs: 58
+ num_malformed_responses: 29
+ num_with_malformed_responses: 19
+ user_asks: 102
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 0
+ prompt_tokens: 0
+ completion_tokens: 0
+ test_timeouts: 1
+ total_tests: 225
+ command: aider --model openrouter/qwen/qwen3-235b-a22b
+ date: 2025-05-08
+ versions: 0.82.4.dev
+ seconds_per_case: 428.1
+ total_cost: 1.8037
From b5cde63b370326a3ea232837cef4aa0afec9135f Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:00:41 -0700
Subject: [PATCH 247/482] initial
---
aider/website/_posts/2025-05-08-qwen3.md | 283 +++++++++++++++++++++++
1 file changed, 283 insertions(+)
create mode 100644 aider/website/_posts/2025-05-08-qwen3.md
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
new file mode 100644
index 000000000..5279a39e1
--- /dev/null
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -0,0 +1,283 @@
+---
+layout: post
+title: Qwen3 Benchmark Results
+excerpt: "Benchmark results for Qwen3 models using the Aider polyglot coding benchmark."
+date: 2025-05-08
+---
+
+You can add some introductory text for your blog post here.
+
+Qwen3 polyglot coding leaderboard
+
+
+
+
+ View
+ Select
+ Detail
+
+
×
+
+
+
+
+
+
+
+
+
+By [Your Name],
+last updated
+
+
+
From eef0051b9335878c6e1dbd4875f00e626abcbbd3 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 8 May 2025 11:01:03 -0700
Subject: [PATCH 248/482] chore: Remove temporary comments
---
aider/website/_posts/2025-05-08-qwen3.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index 5279a39e1..da4b5bdf3 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -35,13 +35,13 @@ You can add some introductory text for your blog post here.
{% assign max_cost = 0 %}
- {% for row in site.data.qwen3_leaderboard %} {# <-- MODIFIED DATA SOURCE #}
+ {% for row in site.data.qwen3_leaderboard %}
{% if row.total_cost > max_cost %}
{% assign max_cost = row.total_cost %}
{% endif %}
{% endfor %}
{% if max_cost == 0 %}{% assign max_cost = 1 %}{% endif %}
- {% assign edit_sorted = site.data.qwen3_leaderboard | sort: 'pass_rate_2' | reverse %} {# <-- MODIFIED DATA SOURCE #}
+ {% assign edit_sorted = site.data.qwen3_leaderboard | sort: 'pass_rate_2' | reverse %}
{% for row in edit_sorted %} {% comment %} Add loop index for unique IDs {% endcomment %}
{% assign row_index = forloop.index0 %}
From 0a5c1960b36f5712f58d29dbb06df93463db93c7 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:01:15 -0700
Subject: [PATCH 249/482] cleanup
---
aider/website/_post/2025-05-08-qwen3.md | 283 ------------------------
1 file changed, 283 deletions(-)
delete mode 100644 aider/website/_post/2025-05-08-qwen3.md
diff --git a/aider/website/_post/2025-05-08-qwen3.md b/aider/website/_post/2025-05-08-qwen3.md
deleted file mode 100644
index 5279a39e1..000000000
--- a/aider/website/_post/2025-05-08-qwen3.md
+++ /dev/null
@@ -1,283 +0,0 @@
----
-layout: post
-title: Qwen3 Benchmark Results
-excerpt: "Benchmark results for Qwen3 models using the Aider polyglot coding benchmark."
-date: 2025-05-08
----
-
-You can add some introductory text for your blog post here.
-
-Qwen3 polyglot coding leaderboard
-
-
-
-
- View
- Select
- Detail
-
-
×
-
-
-
-
-
-
-
-
-
-By [Your Name],
-last updated
-
-
-
From d32d0b790987da368e3a1236010341d9ae8c227b Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:05:37 -0700
Subject: [PATCH 250/482] chore: Remove last updated date cog code
---
aider/website/_posts/2025-05-08-qwen3.md | 27 ------------------------
1 file changed, 27 deletions(-)
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index da4b5bdf3..e2a6f420a 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -254,30 +254,3 @@ You can add some introductory text for your blog post here.
-
-
-By [Your Name],
-last updated
-
-
-
From 35fe1df499056a088acfd45d358e895851e56473 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 8 May 2025 11:05:40 -0700
Subject: [PATCH 251/482] feat: Make leaderboard title configurable and set
custom title in post
---
aider/website/_includes/leaderboard_table.js | 11 ++++++++---
aider/website/_posts/2025-05-08-qwen3.md | 1 +
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/aider/website/_includes/leaderboard_table.js b/aider/website/_includes/leaderboard_table.js
index 8f9f40a82..0dacbdbe7 100644
--- a/aider/website/_includes/leaderboard_table.js
+++ b/aider/website/_includes/leaderboard_table.js
@@ -188,10 +188,15 @@ document.addEventListener('DOMContentLoaded', function() {
// Update the leaderboard title based on mode and selection
if (leaderboardTitle) {
- if (currentMode === 'view' && selectedRows.size > 0) {
- leaderboardTitle.textContent = filteredTitle;
+ // Check if a custom title is provided globally
+ if (typeof LEADERBOARD_CUSTOM_TITLE !== 'undefined' && LEADERBOARD_CUSTOM_TITLE) {
+ leaderboardTitle.textContent = LEADERBOARD_CUSTOM_TITLE;
} else {
- leaderboardTitle.textContent = defaultTitle;
+ if (currentMode === 'view' && selectedRows.size > 0) {
+ leaderboardTitle.textContent = filteredTitle;
+ } else {
+ leaderboardTitle.textContent = defaultTitle;
+ }
}
}
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index e2a6f420a..51f6d4292 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -252,5 +252,6 @@ You can add some introductory text for your blog post here.
From d89d500eabaef94c967df426eedcace24d41f216 Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 8 May 2025 11:31:07 -0700
Subject: [PATCH 252/482] chore: Update default settings for Qwen3 235b model
---
aider/models.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/aider/models.py b/aider/models.py
index 166cb3974..1e4b408e2 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -526,6 +526,11 @@ class Model(ModelSettings):
if "qwen3" in model and "235b" in model:
self.edit_format = "diff"
self.use_repo_map = True
+ self.system_prompt_prefix = "/no_think"
+ self.use_temperature = 0.7
+ self.extra_params = {
+ "max_tokens": 24000, "top_p": 0.8, "top_k": 20, "min_p": 0.0
+ }
return # <--
# use the defaults
From f047b2928b0f8e1fb75eafe284c73533ed9ed63a Mon Sep 17 00:00:00 2001
From: "Paul Gauthier (aider)"
Date: Thu, 8 May 2025 11:31:14 -0700
Subject: [PATCH 253/482] style: Format models.py
---
aider/models.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/aider/models.py b/aider/models.py
index 1e4b408e2..5abc535b1 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -528,9 +528,7 @@ class Model(ModelSettings):
self.use_repo_map = True
self.system_prompt_prefix = "/no_think"
self.use_temperature = 0.7
- self.extra_params = {
- "max_tokens": 24000, "top_p": 0.8, "top_k": 20, "min_p": 0.0
- }
+ self.extra_params = {"max_tokens": 24000, "top_p": 0.8, "top_k": 20, "min_p": 0.0}
return # <--
# use the defaults
From 43dd9ef8a5a804c7387f8f3fe8575606fcdf67c7 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:32:11 -0700
Subject: [PATCH 254/482] tweak qwen3 settings
---
aider/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/aider/models.py b/aider/models.py
index 5abc535b1..3c7affcbe 100644
--- a/aider/models.py
+++ b/aider/models.py
@@ -528,7 +528,7 @@ class Model(ModelSettings):
self.use_repo_map = True
self.system_prompt_prefix = "/no_think"
self.use_temperature = 0.7
- self.extra_params = {"max_tokens": 24000, "top_p": 0.8, "top_k": 20, "min_p": 0.0}
+ self.extra_params = {"top_p": 0.8, "top_k": 20, "min_p": 0.0}
return # <--
# use the defaults
From 87768303068fdeac4d79a31471aabd104f0cf613 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:32:24 -0700
Subject: [PATCH 255/482] copy
---
aider/resources/model-settings.yml | 44 +++----
aider/website/_data/qwen3_leaderboard.yml | 138 +++++++++++++++++++++-
aider/website/_posts/2025-05-08-qwen3.md | 87 +++++++++++++-
3 files changed, 241 insertions(+), 28 deletions(-)
diff --git a/aider/resources/model-settings.yml b/aider/resources/model-settings.yml
index c1a3ea833..338521179 100644
--- a/aider/resources/model-settings.yml
+++ b/aider/resources/model-settings.yml
@@ -1412,27 +1412,27 @@
use_repo_map: true
weak_model_name: openrouter/google/gemini-2.0-flash-001
-- name: openrouter/qwen/qwen3-235b-a22b
- system_prompt_prefix: "/no_think"
- use_temperature: 0.7
- extra_params:
- max_tokens: 24000
- top_p: 0.8
- top_k: 20
- min_p: 0.0
- temperature: 0.7
- extra_body:
- provider:
- order: ["Together"]
+#- name: openrouter/qwen/qwen3-235b-a22b
+# system_prompt_prefix: "/no_think"
+# use_temperature: 0.7
+# extra_params:
+# max_tokens: 24000
+# top_p: 0.8
+# top_k: 20
+# min_p: 0.0
+# temperature: 0.7
+# extra_body:
+# provider:
+# order: ["Together"]
-- name: together_ai/Qwen/Qwen3-235B-A22B-fp8-tput
- system_prompt_prefix: "/no_think"
- use_temperature: 0.7
- reasoning_tag: think
- extra_params:
- max_tokens: 24000
- top_p: 0.8
- top_k: 20
- min_p: 0.0
- temperature: 0.7
+#- name: together_ai/Qwen/Qwen3-235B-A22B-fp8-tput
+# system_prompt_prefix: "/no_think"
+# use_temperature: 0.7
+# reasoning_tag: think
+# extra_params:
+# max_tokens: 24000
+# top_p: 0.8
+# top_k: 20
+# min_p: 0.0
+# temperature: 0.7
\ No newline at end of file
diff --git a/aider/website/_data/qwen3_leaderboard.yml b/aider/website/_data/qwen3_leaderboard.yml
index 07e378674..faa20fab7 100644
--- a/aider/website/_data/qwen3_leaderboard.yml
+++ b/aider/website/_data/qwen3_leaderboard.yml
@@ -1,6 +1,6 @@
- dirname: 2025-05-08-03-20-24--qwen3-32b-default
test_cases: 225
- model: Qwen3 32B
+ model: Qwen3 32B on OpenRouter, all providers, default settings (thinking)
edit_format: diff
commit_hash: aaacee5-dirty, aeaf259
pass_rate_1: 14.2
@@ -28,7 +28,7 @@
- dirname: 2025-05-08-03-22-37--qwen3-235b-defaults
test_cases: 225
- model: Qwen3 235B A22B
+ model: Qwen3 235B A22B on OpenRouter, all providers, default settings (thinking)
edit_format: diff
commit_hash: aaacee5-dirty
pass_rate_1: 17.3
@@ -53,3 +53,137 @@
versions: 0.82.4.dev
seconds_per_case: 428.1
total_cost: 1.8037
+
+
+- dirname: 2025-05-08-17-39-14--qwen3-235b-or-together-only
+ test_cases: 225
+ model: Qwen3 235B A22B on OpenRouter only TogetherAI, recommended /no_think settings
+ edit_format: diff
+ commit_hash: 328584e
+ pass_rate_1: 28.0
+ pass_rate_2: 54.7
+ pass_num_1: 63
+ pass_num_2: 123
+ percent_cases_well_formed: 90.7
+ error_outputs: 39
+ num_malformed_responses: 32
+ num_with_malformed_responses: 21
+ user_asks: 106
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 0
+ prompt_tokens: 2816606
+ completion_tokens: 362346
+ test_timeouts: 2
+ total_tests: 225
+ command: aider --model openrouter/qwen/qwen3-235b-a22b
+ date: 2025-05-08
+ versions: 0.82.4.dev
+ seconds_per_case: 77.2
+ total_cost: 0.6399
+
+
+- dirname: 2025-04-30-04-49-37--Qwen3-235B-A22B-whole-nothink
+ test_cases: 225
+ model: Qwen3-235B-A22B with VLLM, bfloat16, recommended /no_think settings
+ edit_format: whole
+ commit_hash: 0c383df-dirty
+ pass_rate_1: 28.0
+ pass_rate_2: 65.3
+ pass_num_1: 63
+ pass_num_2: 147
+ percent_cases_well_formed: 100.0
+ error_outputs: 3
+ num_malformed_responses: 0
+ num_with_malformed_responses: 0
+ user_asks: 166
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 3
+ test_timeouts: 0
+ total_tests: 225
+ command: aider --model openai/Qwen3-235B-A22B
+ date: 2025-04-30
+ versions: 0.81.4.dev
+ seconds_per_case: 166.0
+ total_cost: 0.0000
+
+- dirname: 2025-04-30-04-49-50--Qwen3-235B-A22B-diff-nothink
+ test_cases: 225
+ model: Qwen3-235B-A22B with VLLM, bfloat16, recommended /no_think settings
+ edit_format: diff
+ commit_hash: 0c383df-dirty
+ pass_rate_1: 29.8
+ pass_rate_2: 61.3
+ pass_num_1: 67
+ pass_num_2: 138
+ percent_cases_well_formed: 94.7
+ error_outputs: 25
+ num_malformed_responses: 25
+ num_with_malformed_responses: 12
+ user_asks: 97
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 0
+ test_timeouts: 2
+ total_tests: 225
+ command: aider --model openai/Qwen3-235B-A22B
+ date: 2025-04-30
+ versions: 0.81.4.dev
+ seconds_per_case: 158.2
+ total_cost: 0.0000
+
+- dirname: 2025-04-30-04-08-41--Qwen3-32B-whole-nothink
+ test_cases: 225
+ model: Qwen3-32B with VLLM, bfloat16, recommended /no_think settings
+ edit_format: whole
+ commit_hash: 0c383df-dirty
+ pass_rate_1: 20.4
+ pass_rate_2: 45.8
+ pass_num_1: 46
+ pass_num_2: 103
+ percent_cases_well_formed: 100.0
+ error_outputs: 3
+ num_malformed_responses: 0
+ num_with_malformed_responses: 0
+ user_asks: 94
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 3
+ test_timeouts: 5
+ total_tests: 225
+ command: aider --model openai/Qwen3-32B
+ date: 2025-04-30
+ versions: 0.81.4.dev
+ seconds_per_case: 48.1
+ total_cost: 0.0000
+
+- dirname: 2025-04-30-04-08-51--Qwen3-32B-diff-nothink
+ test_cases: 225
+ model: Qwen3-32B with VLLM, bfloat16, recommended /no_think settings
+ edit_format: diff
+ commit_hash: 0c383df-dirty
+ pass_rate_1: 20.4
+ pass_rate_2: 41.3
+ pass_num_1: 46
+ pass_num_2: 93
+ percent_cases_well_formed: 94.2
+ error_outputs: 17
+ num_malformed_responses: 14
+ num_with_malformed_responses: 13
+ user_asks: 83
+ lazy_comments: 0
+ syntax_errors: 0
+ indentation_errors: 0
+ exhausted_context_windows: 3
+ test_timeouts: 4
+ total_tests: 225
+ command: aider --model openai/Qwen3-32B
+ date: 2025-04-30
+ versions: 0.81.4.dev
+ seconds_per_case: 59.4
+ total_cost: 0.0000
\ No newline at end of file
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index 51f6d4292..4923f5330 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -1,13 +1,29 @@
---
layout: post
-title: Qwen3 Benchmark Results
+title: Qwen3 benchmark results
excerpt: "Benchmark results for Qwen3 models using the Aider polyglot coding benchmark."
date: 2025-05-08
---
-You can add some introductory text for your blog post here.
+# Qwen3 results on the aider polyglot benchmark
-Qwen3 polyglot coding leaderboard
+As [previously discussed when Qwen2.5 was released](/2024/11/21/quantization.html),
+details matter when working with open source models for AI coding.
+Proprietary models are served by their creators or trusted providers with stable inference settings.
+Open source models are wonderful because anyone can serve them,
+but API providers can use very different inference settings, quantizations, etc.
+
+Below are collection of aider polyglot benchmark results for the new Qwen3 models.
+Results are presented with various settings against various API providers,
+with the hope of showcasing the strengths of these models and its providers.
+
+{: .note }
+This article is being updated as new results become available.
+
+
+
+
+Qwen3 results on the aider polyglot benchmark
@@ -252,6 +268,69 @@ You can add some introductory text for your blog post here.
+
+
+## OpenRouter only TogetherAI, recommended /no_think settings
+
+These results were obtained with the
+[recommended](https://huggingface.co/Qwen/Qwen3-235B-A22B#best-practices)
+non-thinking model settings in `.aider.model.settings.yml`:
+
+```yaml
+- name: openrouter/qwen/qwen3-235b-a22b
+ system_prompt_prefix: "/no_think"
+ use_temperature: 0.7
+ extra_params:
+ max_tokens: 24000
+ top_p: 0.8
+ top_k: 20
+ min_p: 0.0
+ temperature: 0.7
+ extra_body:
+ provider:
+ order: ["Together"]
+```
+
+And then running aider:
+
+```bash
+aider --model openrouter/qwen/qwen3-235b-a22b
+```
+
+
+## OpenRouter, all providers, default settings (thinking)
+
+These results were obtained by simply running aider as shown below, without any model specific settings.
+This should have enabled thinking, assuming upstream API providers honor that convention for Qwen3.
+
+```bash
+aider --model openrouter/qwen/qwen3-xxx
+```
+
+## VLLM, bfloat16, recommended /no_think
+
+These [benchmarks results were obtained by GitHub user AlongWY](https://github.com/Aider-AI/aider/pull/3908)
+with the
+[recommended](https://huggingface.co/Qwen/Qwen3-235B-A22B#best-practices)
+non-thinking model settings in `.aider.model.settings.yml`:
+
+```yaml
+- name: openai/
+ system_prompt_prefix: "/no_think"
+ use_temperature: 0.7
+ extra_params:
+ max_tokens: 24000
+ top_p: 0.8
+ top_k: 20
+ min_p: 0.0
+ temperature: 0.7
+```
+
+And then running aider:
+
+```bash
+aider --model openai/ --openai-api-base
+```
From d5ea078f24323dabe52783a7f3c0f2bf8f83a417 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:34:42 -0700
Subject: [PATCH 256/482] copy
---
aider/website/_posts/2025-05-08-qwen3.md | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index 4923f5330..01a544b25 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -15,14 +15,13 @@ but API providers can use very different inference settings, quantizations, etc.
Below are collection of aider polyglot benchmark results for the new Qwen3 models.
Results are presented with various settings against various API providers,
-with the hope of showcasing the strengths of these models and its providers.
+with the hope of showcasing the strengths of these models and their providers.
+
+See details for configuring Qwen3 after the results table.
{: .note }
This article is being updated as new results become available.
-
-
-
Qwen3 results on the aider polyglot benchmark
From acd7309b7878aab0aeda2d27fad07d56d9ed56b6 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 11:41:51 -0700
Subject: [PATCH 257/482] copy
---
aider/website/_data/qwen3_leaderboard.yml | 14 +++++++-------
aider/website/_posts/2025-05-08-qwen3.md | 9 ++++++---
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/aider/website/_data/qwen3_leaderboard.yml b/aider/website/_data/qwen3_leaderboard.yml
index faa20fab7..e773bdee2 100644
--- a/aider/website/_data/qwen3_leaderboard.yml
+++ b/aider/website/_data/qwen3_leaderboard.yml
@@ -1,6 +1,6 @@
- dirname: 2025-05-08-03-20-24--qwen3-32b-default
test_cases: 225
- model: Qwen3 32B on OpenRouter, all providers, default settings (thinking)
+ model: Qwen3 32B diff on OpenRouter, all providers, default settings (thinking)
edit_format: diff
commit_hash: aaacee5-dirty, aeaf259
pass_rate_1: 14.2
@@ -28,7 +28,7 @@
- dirname: 2025-05-08-03-22-37--qwen3-235b-defaults
test_cases: 225
- model: Qwen3 235B A22B on OpenRouter, all providers, default settings (thinking)
+ model: Qwen3 235B A22B diff on OpenRouter, all providers, default settings (thinking)
edit_format: diff
commit_hash: aaacee5-dirty
pass_rate_1: 17.3
@@ -57,7 +57,7 @@
- dirname: 2025-05-08-17-39-14--qwen3-235b-or-together-only
test_cases: 225
- model: Qwen3 235B A22B on OpenRouter only TogetherAI, recommended /no_think settings
+ model: Qwen3 235B A22B diff on OpenRouter only TogetherAI, recommended /no_think settings
edit_format: diff
commit_hash: 328584e
pass_rate_1: 28.0
@@ -86,7 +86,7 @@
- dirname: 2025-04-30-04-49-37--Qwen3-235B-A22B-whole-nothink
test_cases: 225
- model: Qwen3-235B-A22B with VLLM, bfloat16, recommended /no_think settings
+ model: Qwen3-235B-A22B whole with VLLM, bfloat16, recommended /no_think settings
edit_format: whole
commit_hash: 0c383df-dirty
pass_rate_1: 28.0
@@ -112,7 +112,7 @@
- dirname: 2025-04-30-04-49-50--Qwen3-235B-A22B-diff-nothink
test_cases: 225
- model: Qwen3-235B-A22B with VLLM, bfloat16, recommended /no_think settings
+ model: Qwen3-235B-A22B diff with VLLM, bfloat16, recommended /no_think settings
edit_format: diff
commit_hash: 0c383df-dirty
pass_rate_1: 29.8
@@ -138,7 +138,7 @@
- dirname: 2025-04-30-04-08-41--Qwen3-32B-whole-nothink
test_cases: 225
- model: Qwen3-32B with VLLM, bfloat16, recommended /no_think settings
+ model: Qwen3-32B whole with VLLM, bfloat16, recommended /no_think settings
edit_format: whole
commit_hash: 0c383df-dirty
pass_rate_1: 20.4
@@ -164,7 +164,7 @@
- dirname: 2025-04-30-04-08-51--Qwen3-32B-diff-nothink
test_cases: 225
- model: Qwen3-32B with VLLM, bfloat16, recommended /no_think settings
+ model: Qwen3-32B diff with VLLM, bfloat16, recommended /no_think settings
edit_format: diff
commit_hash: 0c383df-dirty
pass_rate_1: 20.4
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index 01a544b25..79d53ea8d 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -14,10 +14,13 @@ Open source models are wonderful because anyone can serve them,
but API providers can use very different inference settings, quantizations, etc.
Below are collection of aider polyglot benchmark results for the new Qwen3 models.
-Results are presented with various settings against various API providers,
-with the hope of showcasing the strengths of these models and their providers.
+Results are presented using both "diff" and "whole"
+[edit formats](https://aider.chat/docs/more/edit-formats.html),
+with various models settings, against various API providers.
-See details for configuring Qwen3 after the results table.
+See details on the
+[model settings](https://aider.chat/docs/config/adv-model-settings.html#model-settings)
+used after the results table.
{: .note }
This article is being updated as new results become available.
From e4274aa4f66a404374f9939526948d74569927eb Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 12:08:05 -0700
Subject: [PATCH 258/482] copy
---
HISTORY.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/HISTORY.md b/HISTORY.md
index 48738aa73..132b84e59 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -2,9 +2,9 @@
### main branch
-- Added support for `qwen3-235b` models, including `openrouter/qwen/qwen3-235b-a22b`.
+- Added support for `qwen3-235b` models.
- Added support for `gemini-2.5-pro-preview-05-06` models.
-- Added repomap support for OCaml and OCaml interface files, by Andrey Popp.
+- Added repo-map support for OCaml and OCaml interface files, by Andrey Popp.
- Introduced `--attribute-co-authored-by` option to add co-author trailer to commit messages, by Andrew Grigorev.
- Updated Gemini model aliases (e.g., `gemini`, `gemini-2.5-pro`) to point to the `05-06` preview versions.
- Marked Gemini 2.5 Pro preview models as `overeager` by default.
From cd7567fcf603857b6abc762bc4d4593502e31105 Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 12:08:14 -0700
Subject: [PATCH 259/482] chore: Refine ask mode prompt instructions
---
aider/coders/ask_prompts.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/aider/coders/ask_prompts.py b/aider/coders/ask_prompts.py
index 855806592..93106380a 100644
--- a/aider/coders/ask_prompts.py
+++ b/aider/coders/ask_prompts.py
@@ -8,7 +8,9 @@ class AskPrompts(CoderPrompts):
Answer questions about the supplied code.
Always reply to the user in {language}.
-Describe code changes however you like. Don't use SEARCH/REPLACE blocks!
+Describe code changes however you like.
+Don't use SEARCH/REPLACE blocks!
+Don't return entire updated source files.
"""
example_messages = []
From 82f33c12206d1ab7a19d4b5369a40c3016b255ee Mon Sep 17 00:00:00 2001
From: Paul Gauthier
Date: Thu, 8 May 2025 12:14:41 -0700
Subject: [PATCH 260/482] copy
---
aider/website/_posts/2025-05-08-qwen3.md | 1 +
aider/website/assets/2025-05-08-qwen3.jpg | Bin 0 -> 226001 bytes
2 files changed, 1 insertion(+)
create mode 100644 aider/website/assets/2025-05-08-qwen3.jpg
diff --git a/aider/website/_posts/2025-05-08-qwen3.md b/aider/website/_posts/2025-05-08-qwen3.md
index 79d53ea8d..21716c725 100644
--- a/aider/website/_posts/2025-05-08-qwen3.md
+++ b/aider/website/_posts/2025-05-08-qwen3.md
@@ -2,6 +2,7 @@
layout: post
title: Qwen3 benchmark results
excerpt: "Benchmark results for Qwen3 models using the Aider polyglot coding benchmark."
+highlight_image: /assets/2025-05-08-qwen3.jpg
date: 2025-05-08
---
diff --git a/aider/website/assets/2025-05-08-qwen3.jpg b/aider/website/assets/2025-05-08-qwen3.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..69934518c22eae9c8df019aacd6a856499ad6701
GIT binary patch
literal 226001
zcmdSAWmH_vmoMC;(cnpNO|TFo!5u;f?(UG_jk`NRf;5ug?hXMOcX#)0+^um7di(j$
z+<9l-4|lD*=F6SktIw%*PRTx1d+*xyt6k3v&uaiY83}0#01^@sAO`URJg)=%#oa+>
z0D!za-~#{vKnEZrkpfTVpZ(h^AT0lo<{+3|A!E@{j1Es
z-GNz1|DGFBPu7e7og3vT3-}-DAO944h5^I?z!(3}KUW}vkWrEUA#_w!6jTiKmoG8U
zF)&_Y;bOhS#KFYCz{bbM!NtSF$9swO>h&wU*N8OUKb0W;Qxb@bjwpzSiGhiD`hQ8!
z9RPfElpiQhKqP#?3w$IXKGJg!fCBMRNGShw*nbcTf7*EV6=&Cg
z8VCosxRFa>P*s;xCowJGSIr;6@!8XK^kP~GJu@Vd8pgHVy$ohKXC}F)h~~%;jQkt@
z2RBIn)*Rxc5I&-9BqS6RMArck3jT;g~fisB0B8%H{lS&*Y%q-AAk2t!=~N4HdW`%;&3;hiedwE0>;zH
z!wyns#4Rlz4y*pcWEnQFTiR+M*~g^c&M|}SN*z1mufwP*ckSSsX4L`=KQg({VJsgPk|0ge$e51y)D{FHQ
zTWJ9Rp0BL~_N`L&_XM@I2VQLphJrvRDHz;Tpv1I1(N}-}8!{(PYOZYea3?ZXn{TWl
z3F%OK)W(ItZt4b|Zki`nd0uKbQ&y_Y{^8V`NA0EYm6u6I;6h*Zo
zR?8-|oOIQBOETgx$PX-`_G0>+O|-MjPHdNC3dB;t?+IFEQJybsCys@Lx$h3Gd_{yO(xo~Jwm2-I_8YvU=|b4^&-
z8rOq<*GbyC(G-fC)sXj{{})T=6rUSSf!AuqHc`T_mtk9Swd
zGc3QVD=H&UKLTS~f8v!J%(7DC00`L7G`YFx)*4a!{wVur`u-Q;j@n>vGK7zeN0R!m
z4e8KUYMPm7cA>5u*ydtw}{`PTzJ)MXfCd%|Vk;_-v8O8O+a*2dLpu+7$2NoVBFt6!Eb59#cv
z$zov#gYnge$+(SOfrG}9ieC~U6;R>-rDJ^E9OnCMTP!ph??a|bAKSvGm}lbC)2Say5&a3VUK9FYSNn4xg|;9DGQod7rFA
z5Wd(vM<$2oc)M97wC+OgT!N-dCYLQiJH^JOdoP0qTdX
znI|r;8{$n-D2K%W%jCxBFiS!vs!KJI^x8B(5{=gvzWR5PE~^erOB&pcA`)}|SuXLO
z@QxX4BSO=nvFi4HcEUq2M+x+aa`lSNOJ+6HoFxSo96x8JuV
zbfSu2WX-wm$3eVsEr{@A3FoDC?%5+=hK`vulp7;uSCaWV47=OJxbGfkJ2_GTjm`n(
zR<0D{q|Hvj{%1cQBiyZrCkrfO&@K
zP_N69DV|gP_Z04SFAZ?v1ddD)(3c```-PptWP=-Z1abt60?-W#hq;@5C5fqsy7H*2v(C?&6A8=dNi>t*Zwt)}N0m2;GOK+umE0
z6qR%S(sGQj)^D|mD^aFtX6b-u#{lRe`8xBC=3hv_0g$v&GgPuZLo&?@LdP;M^4hgG
z+CV#vzf6WK;$CZP2nielYQgX8mzngl3tgyAA)+?*+Qkr9SlHu^e=4jYFI
zKH9JlJch<$AAc*tlE%C10u6}UhVa?+cl5GUJ_B;@kv{JVc+lB#tZpaxPpnrVjZ+Qj
z)K>EwtFmel6e6|FTl$DMk!wR#xc6+y3(!8VR~ZMj;k(|WUeU$?XoHie;+_FP68&zC
zXCTWaE$Skdig8iLqRQCO+c)C@XA+c>pXK7jr>AhUUE1H?Q#N8@>R++uN;-$WpMlEC
zx$#xqeSB$38<&*Iwrl0e3Wz;zr8G6-;3by^J+Pb&hprxLrZW|UJOdP2n7MV(Srwht
z--)uNXlEFsL`Kv^U9g=He*m
zgnWF5Itn^HX~{UlS$JC8ukTY>d&rum3bVOrtr~Q$9;JC8bE8lVZc>{)BqliXR)!5_0?o{$I%`GcRM4#wuz%0ds|
zCEMods#ogJR<
zx63!Hqi~JcMGEcMW&Q8{6^VVH>0O$_J*!CE-g`s^FE#(IhuO?Y(w+wN=imGsRVtr8
z%t)KiGRm(WcOg*HqY_Bl+X)d?&}7RsqG#}V7p()BA1mgCKX@regX!hd5W4PQApPvH)!%T^aUU7}DrW^p{bl44M#k)eZ1r*PNo)
zppAPJ>*vE+poJl}xM~)D$N<#{rVjkR4rbb{Y2n+X#rw0*XuWH;MJJf(khM>SOc=Z`(WfJ$b670T-~n5twkz20
z0;HBWU#!z7Z3)bN!*hs!^$hrti#nMWSC2G(q0wbTdtU+@wp9c{|ET?lb$n|)AR_*k=IBR!{g**_;J7I=`)~5
zBK?di#H*sCl+J2DW5HJApde&sLQY~m4j@JCFKaNRvxb|-izWBXsh+^_$A@P?cR{5(
zD85;){HB4?qPXON)#}%}S7g}^%Qk)t_wk8Nxf2QLy_N_jN4YkaeyYSLOrNPmNtzs+
zl?zUP^%&P(F#52p_Qa9i;{bI+eWO;Pa?0uGt=ti`HdXiXP}TmHEj50}Oa*59Mx9oiX21REDzN^Jkk^MTSuV?#ISsvnlZ^>;b@Q?XCD9E3$hIXAfhs=hp;Rg^=sQCBzK%yz+tdE}3p|
z3VNAH9Jn|p3p)64K$n>~f>q99`?NBCPv~Y`%d4?5jl8T}zXF=Z
z!ov2fG{;e0taIiYjX!@*iHgxl+9(>#K@yYbwm~}pBH|?^SP|=D55n>txWr0SR3ro@
zSRNdN?e7=oI@icE1!*LoDpZbITMeG4Gldena7dTO!3<6p3#w+N-<;O_R#-a`aeqNW
zI0AQ_|Cq%LlysxJ4~!p3(U+TJbk;m;N9~>Trf2x_D6^fm_%LNe
z&{*6STP$f#a1ti-w6?gjE+7P4
zHN#5UJ1ZLJ5ULx(8)N)Uric-SaC!V5L(6)3}!k
zP!u-#r~p5!S>V3G6t}${lj#146bm6^Y@S197d)fWIdaES@_R`=-;=IQt&{5592GA+
z3F(ILXI$6KR(){LC9ZgFDR91pFi~XsFrwtWxkHFMy&dhP3pSt)L$`6;eTSka5S=tRK|*Yss{V6j}FWOo_DLZn^DHy<%b(ntrRvyzrROEnC
zA#`xBYmrmgEUm1yGclnysxW9MOJcE`JlVJnW{7z)#h-p%C5o9Z5?pmve`jS@wLeOM
zQk@S6%jU;{$U$xbPE8nm5m26`^Y$cwD~=FBiZfM?MnrA(qh)TJwpDg{{SxD5Nq%u~
z=j13Rl)N7TKGhLLgEoQ%Hw;gIe}i(wX{_=4fFt{<>!tRXc3l*|i%D`QjD1QPF$aq)cgGKa}W6({$
zKI4FEJt4Wy_5;(ReK^b@ZPJ9hEHLU!xWw|N<6F_s*o={os_r4H8#LdRic4mVW-&Ya
z<#M$&QH!f+HAeUuY`5WhQbU
zcx(%80g!0@G4wXrMMNAkyH3*NoqjDT#Ay|?z9VXpfEj
zYY(%`E7#jHdfm1-zkLRF=_g-w$f9<#6~5`6^7$@3TC)x@t&@7gTGE?ha7EvxOZ2U$
zo+cUHH76*8jte$UH{4S5$_wi?RcDedO3WRQVj6hSzTUj9k!A%6@gVz~Oap5wHB%M%
z%*)$XZSjaz-`3+usAtpD%;c%^~1TTtpt*id8_PuNO29qtv6BCt%xnpm9o
zt$5*xe8~OUNyn?7<8K&^E96rDUAmZzAEutmJk-medcRkwZdCwAo+!&aCDK_hKqQnYpKaqH`9;$WAJQsmcmrv5{oviWRJh?fQ%xC)T-y
z5{B?6D2<*0!4;Fjbg}y9a5ht+gK!zCvV!%g=x%O;?f6oUir&RJ`N7PF4C7I!=xo
zKU3@M@;1lwLjpkmO+X%am#ZVF$|}Xv?oUr2FBVz2Fgs*3DdJsyTutr;4V
zFVX77u!6{9BJPQi&NP*p;g1SfZj(?U6jab)O+o-2jf8=YU9K*g_@zFe2=HYa6Z7S<
z2$3I~`HKQmTe|CB$;ugA@A}x#$vgK9ORoS655)9JXeFFhLjsPJ_t7y(0%aEWT?m
z#PpYbDFoHlwyS}ETg*w8T$jA`8vkjt(S$DGD^()uB<4pv;fV*o0hE0;v*&H6d|;{j
zTSXpn_-o%;$&isYFJ#yzx1n*Q4369fqKlt=VvN0ZxIrT#`3%5b;`zg7t$NyQCfC+`
zyeVB)y_os_)on?E)S@t`;sArCewj+;>ASt|(j5WNZT-77U1+UD%1Q
znSx}7F3RZ9!N!0|-kTHF(^-$CS%b_xg07jY2=HOpv?Rx-k93_HuPJ^6PWF*)k8HrB
zUf6WRp7PHVp_OUMqpHbd2|Qw&*o%8?MK_1S%wgIH+Z|cLt3UZ?d-$5YNp-{
zS-~4io)=nl_0({|bZhIWND2&mBZqb87Om
zUd^^bRm-K<-SS3rOS)zu=0$K^_~He-`C!>
zt{y)F&X!#(n?yjJ$Soe6xi+3i?hP4wAm%R=CBj-1uluV#
zhy!#iDf@l$BoiX#O_RD?hj1i}62UYV>$e)ZWeeA(XJ~8=rs3Q2j*U@`jav<~Efmpr
zdB;9TcDy~fQ#e$$C!OtR;u@ZJ%N6dzBKFm2PTns|T$A=-?X__#PqSmjhuS}
z0?hGRKbm!Qq48+J9w%|f9h`KQYcz0acBU-+&anYhL>nLXbyxR89{%8K=qbfkKht7!
zs7lB7lrh%^PyM>v)9X`_YpiF$#>=s!LrUb!*C^9qsw%y3a@TOHCqv7?3e<*Cr_v
zGoPf%MSE-)U}Q;rX!17x1my
zXmZ380H;(MzPb~Z)s{Fn>48V8^>Dbl_xiNlaeM`9hPBE9t%E>fBV+{RaGhR{=s%AL
z1x5!U)zQl@&wwb4){T<+M0IHi3(I0#g{=4}Q#pm-7*J8Ov)Z+*0}M*%$ggKqNuGmU
zh7?tc^z8@Y!qUmQdt}g|_1IKMEGO=dx6TzYM?6clh2NUQOZa(CZO`8373=JHts!|+lEjC)^{l1Qj;Yq3!E?W>u{GFki+H*mbbqJJnXns(0VS0>y2EdIq
zTKa*$n2(s9SGr2;v`Rn1p{3T__
z(7yP-A-f_>+vBRi>@HX1cHPko%W80cgB4Vlmmf9dYKsMQfD$*~0njhXrX!;mI(%#G
z1G3yr8tHQl$d|t~s>?#<4q3!yix_o0jKdkpNUS{kKRSSxEqbT~K-x@3YIUp0*;-3pfTS9V|&Yi0DB{r)l4YATB78lL$vO>i$
zRn9r>gJy{fnT7oA#SXT~=28RTa^0g29Lk;Rf844z$V<0bJ#5iWKZog3@K;=I(ZVwC
zTUJ9MqtXIS4oKFlPHaV
z4v1U}2taCqWybf)?KtxKok~3eaJ3DuzSx~XO5L_Z6l-xGItJSpuG*J`90UFu-ZDG`
zBJ(%zGIgI=qYx-3*{upfhVY*%lzcCX6~r$6!cso)g9&Q>?&gI^8+Ecu@U(r>>t6dP
zgmHY(*w5A_5-1Z6u2-u`m{SqswF!JTi9p%?HnESF?UbBP);YSW$#aAEeTF6#ncW|E
z;tur{W$_(Oxg|O61k0afvC2GzIzIiHcvYidoFIaBLUc!!MclfIIg?7EUedPj$d$2I
zZ1F%Vi)+?bM-n7LI?**x7!t~J1{UBv)^FA@k6HPexkuT6(%q#h}U^9}ldi$jjrM-?b22WT8yL#Mk@@n+2oy
zDpkX-(bvZ&Gu%gJTM}hIFevt!@^AaZ>(}|8xaJM7g_`g43g6y&WeW=L
zUq^tVN>L$3b59G({hO9QznR3%s}lw>ZF`WlINALK9jjoNI`k4Krk`BK+!
zonO?VsX}B84e25!A!}u3ZxjB$Yr8qttm6Q@+Ejy($z5qGGF=|uhe374g~;~zG6~47
zecBXMXcAtaZ7g+HkvZ>IAtM%>X}H7foe{1Li@fD|5OJnW)2VTXoYHSXpI
zb(#!g!Zz!9%yJ!qJ!(yfk}az4QB3Iqs%t9}JBqaj*I#k@zfu&~@$Inn#A#+Sz!OkK
z-_-Tj7wBfZded|-(dfpF3OifEyWo9D2;u$UNKn`e`P!5r@vnMh(1{%kYk
zSm3AB8t=4Bl>)GVafEdq^BMxH#!3oNt(uL&{BfPrb?jR8JGQ+hw#R?NJBt*sKxEel
z{WH`4gDA{^pmr6tRwLm&RCcrtpM-DUzA+4~9vbw#0tt;S+wkA6J((Sag?3
zKCWwxvGR=i)qPh;U-{U_Y@f8gLzk12Jr*a;eetRj(^mpH&z>qv@YCs`zePdZLK%d(
z6{%$omX&d1$i+dStgd#ACPjXZv1RqsO1rHCSDN-Bd0_1s&=t_#M^!)~!B^ZskdiPd
z9-k7f8;?zE#7m-$XO+rC%+CWcULGL@tO(sN$?QvyBegZyjvYeAPfZllpm|4!aE<1}
zy{%Q-vFzDdte>k3HxPuoGty_xTNt>M8)_}4%5V|@mz4rxtDY-S7l@o%uxQYEYguih#m(2oU4c
zzB#5kjZmO4pLw8m%n
z;?SBW)s{jYTh`(L1{D`_5nFlZT<*FKw+PpC%m`k}JE`l}O#A%EJNt+|U2fTNXwTeD
znG=^`Y2GWY0(JdaJ_X;B1=cNtK?_Ixc$iYuF&;f@zIwhmBL$BIf(EMJ2wtCy`q*@J
zI)w>dn`zO+Y4GA~tTQ8J-2~9I(mA&i50wAc*|LRqYRb@O?6vLOos2E?Fj}cI2KJe(
zxwarWMFQd$w$w3X+GdSi7r87i3?zZE}qi1UmwX-4Ch
zi(p*47#1x_Xmh4?P-!@XzkhFB5P59qQ0`>nBnkO5Rlkj*BSAxBdG`1Pj=FXu4|z?M
zCaI{bibChLN&7Ne9zVfIGW+VIbs_Y{sQcL0)wTBZ3$zHC==x0cpp9kLp)%t`EW+
zbl>OZ1urLm3VlI(Bem#}!G8oG!@e<3)GG#AaMuHpOH@B?hNZiXjiPpU(g`}?L^
z^JT;?mG1bl+p-H}O&D+8x{rBMW7p|$d4o3c*
zx9#-z9Ge}>_j#>Lax5Hk>U{pgBj-F@IJ8`;N2F+(jvgaBlIXr~%8|M+?+{MRK?S~P
zKBWJba85W}R+c!NNL_;TcE<|s^Dd-Cz$Sn#sP5Q7Anz7uYz@YqsotQ_RryzdrlPW-
ze%v}kx+8v!vwBcrzM;9;DK`qt(2__HAwlcw{DgI9Y1ziad^)Sz%jx@}Aw!#(oaaa}
zsUmSp#AL0oFh5L89@)NcWk+ISF8T;FrYPu)EK-)hR=KYN6bbY2W<7~fQ4$?phRVKS
zwtX61BCA#yM+Lmy7?D=x8EBnIOWr
zn8nW7al#yv59NXK0ej@4CqOHY4mhijvlGgwyWOx|ZPIp|z}Uynwh6Ew&POJv#1VSe
zXaVgs3*=KPn-e$w5=^|YV}1d5aP@VaY$K4@7{zruM%}U}%>VD!$
zO7jGJ|N4|;GqrA?K|jbCt|IrTs>gPq$21k<*3gjgl#EzbzJDSRBI&lrn#UXeb5F-o
zylBn!XK8=`owZV1PWmK156x$!6YDKr@YBfa8N{-Z?6~AcH^%p6Ch-!zcMT7=4Fd;w
ztNLXCriihzh4xeSxL;tu#HUt?8LWElk+R>34xuWObs-5AY_u#zB^)+v-_P}Q7RXWW
z{S6z){3R-R$@))=KoYno99AVP|e?d|)#5xz(IpdLVp@SN!RkHC&RbnX>_d76oQ2`JVRZRUE%v
z2)W=P8lYhe#idOHw$Z*|31^>ENl4BO>MDqcZ|R6Wx7k|w8$NRSXZB7#+@7LS;k#>t
zVQs;3j7blBI=IYVkD->3$f-6mFX}N3OpEq<8!&;|(d;FlL7I3Pc!t?k*St1Yd^xtc
zDFf(j2wHuRA$h^>XPPpN@I%~L8Zd4rZ
zHb;i*tCd~UBRAxr<}qsD!G+TYNs{dwo(LTl!B|)9Q&Qrr?Pz-sG#ZJ~C1Aaqc#kjB
zCV#5=WE_n%YiC(nwoDUU-9_moOMO_PQ4g~5`0k5?N8?_xysIT5ifXB4bGEDfyK
zW+97awO`*A2C_X?c%`rGHXQHrUeU&BvKqhpZw1AR?t1$wxLt8h
z@o!1G-q`y1cswVnzC^aH7M@c5(FsmS8nhucry+mCDw2}WrH@pgKvUMc^O(zk4Z^M~
zL~C7^gNrI7IW!Oiqe0qYMN2j6e+Dp_mh|YLv7ZT**N<_y>@0HQgXilqw2I5L;3Z0{
z=pIf#o$|09EWGk#VKJ^)R&GKVI$?_ecbicbwF#r$+w_4m34@=PzHQE`AhlZz2H937`V&;9e%WaHDimORH|X5W>pmk)
zb*L@KVZw(}U0OvQfagD88PtlF@sh3n&mG}e^1$Qg2Xa!6W8C0oZ0A!~mt<3U@jIV>
z18s7e(8{cCECs4EO#uZHUt6)CYotznHnwDygc@oaoF4L~1XGOk34|}TBLiOs-Y(6D
za7tq>qc7)D2Gjz|YesvA*7wYc$1w%x~QY
zmzp5nd_;OATzxlv5#K&eFpGf&OfF*KAjV^vP~2F
z`o)9H*B<(6iC$K#EFUjC5!hCM`mYJ=k2M_xyg%=ZtZD54X4K-|`mS
zs+Xft**kkMyZidFs#lh2VK_{%ODoiJv!#6T2Pef6W*w!p#%#x7>f_U3_@Wg%a~xdO
zx)!$Ke5D?*61EY-wzA86iS*5vX+KJz(5gQ@;UXV04xV+Gad50>=au!ac_KIS*a8k(
z_zRw2Zrdrc!v&doe3w{h{{K+gdtWp^g!pCN1D^pan4Up`56lZTKAYlIX?LbvU~Z#%0%`JQQ|NN(+Z1=Ix8ASA
za+Axqu-zkE>)V7|6?ULzv^GNS>o=!vr|_t06VKTE$6rjAx{A`0l5P#Mno7s#+El?j
zuAJCQ8=uJnR@Sh7Le5DFaY>#5n74%frYZe7S}af9!LWnvl>Ilc@+|USV3%JMb0Q-4D{&dAPfKCUM81GCZ;T*4)Wu(+|wYBBnY5bL>&
z=_H=?bpFz-628Q!V`O_uia(Y(#aK
zY39gW8Y0Ouc&?lFruVv}LRS;0i9Z_3SqmByzzg?w}3Rb!8txm?@n|JVi&phD1D*97b;Za=ZlOk%Dkzpoaw8$7L
zh~+>g=s}@#oyk9EV*vco(6D|^iSJ@IZq>#0vZ7^1h5bxS_%XO^WoKxoK7BHVXE|-u
z%fsz(E2>_g3@(X(kCfeLIxjdGNyOP!+qLQ4Z*z5J0>SafD>TkHMf*%HZGVl|sEC1=
zrm~)hExNv{UjX85ZnI_bYh;wnT@2J=l_HT`SG(Sdh8j{satxxgI3Z=h!nT<
zEz8zUS_X!A
zsj$E8wFJzwr<9XJTbH`1(V3iyd$B#@E8~lM&$X(0J6>-F&ZmfPypaQMNo-gBq=}7M
zcm}}KB!uPXb?u8TPSgEJ4=e8}mmjB8V;*DmLbq_&m7X}x{4^{?TGCw*VB2EkGaxmg
za_^I$>+FCu^@CAY$=iD0S3J`CG~X;{Wo`#!&i!{ahvvX-acd&AE}720ojdJ2HusOo
z>W|ZjZ~uzlGPXyK`dz6sKZvs*`ifmGJ5oih2IbyvLq&2C`?TEyO{+1Hn^YwApc68;
zp_ZM2g9q1juk3a;Rjy<6P~9E2Hdn6Ex808P(e|P!g~q!YEtVo**fP*~DM!lQkSMSe
zaNnmF>;f$rKkQf56ZJFO9#e-$AJMeni7o_>TS^4Zq)>Ib74V0u7SyvaG%cT~Rf{Wr
zs?nIA{j#{ajP4d3wT05b%SrKbTSyeBT+0@FM`M?hUpJwuTlDP+RQ%lpufI_+((1F7
z=hYqnGig_`izsvJ&Z8Su)V`*qRlvKB5@&>4YZ=bq8x6Lo)>LWBUEmcIWTvOx+P#2=o+7#
zOtyNe=tnr*f7Mn0Ku4Om!}|;fp?b)HP|XeB+^9!r+7nffeFDfvA=
zh2-w@c{e|)vIU;a09;n>y
zaG>!;Zs~&a-i`^Inyv+bat>EKFT*vi&l(@gu-T->%m?PHIt2XAzv2`cm+tU(oG{M^
zwxL{}5Hy-4ha^qFYzR}_W@ct&y&C*UC)-9T@wa(zxN=K>0&HdaX7h{$N%d~2hg?|e
ze91Yxo&jb9<=n}1DQ%6j3O|33dlB#0(aDwXI?&kkZE^Kb2J4#lIO3vY{uM3rgGWX@
zU^~vXPTs$3e1SV`*LCv1u;zD!m>GHqrsZ7v0no|FgG^lFR&dBRTD1M4Goe5_8ZZ32
zHTKc^uSB0=Dl#px=K38wFPYKYSDfwZhO@nXKa3cGu23Bg_ok)Mvv?_(k!$X%)23E^vt1xFt2c)mT_WUBS`etN!%*QLmqi
zN{=OJjL|h@Q#w=^8(VEcQ24DrZH4oQRj8yR-HisjDuLb~=uX{(2Fup`;+OW@S+aJM5&nxJ|8a7DmI%;V*y
zZL*vt$Ybxi#B0;Q*l!iq-41Mj2E>m)20Q~!P+ZWyJ9s^4af#g3=sqrLfsMnT0SNc^
zZ-4RXgpJ>d8p{DTMz}$8*D6KdZo=0CPi8CT^1$Ntyz_~fpGNSG6PiCouaH(Gh7GPH
z;n)Nl(~h-bzV%D{mNvC`FN>_+C0B+>$$I>Vau>|cb6NGN)03pq^}}El_+@oP`E%{g
zROk-ehB!(Xm-2|RT@KbD0n!#*>;GKg{%cEV_)G{-9sWgjX%`+ZKe8M86aGFEg{7NV#77JXTW*mGvJTN<61@5
zl3_5@ZH2&HujqYs*>qC$!yA#_lEX*4a)gU5RsJ{1=k}Y(=qTG$s`Jxvx;~pkyU5_>
z#i@$1CYDT{=LcA>KFCK8hb0c3zG22SxPn4QZ!W=Zh40SV^=;&WCBm&b>!OT4!!#Z^
zf0S!fU!tqgBM~D2$CXW=S51b7|4bY2BWy|JYRS)a&s+6P)zvYMNq?Zeqv-+%e&ddG
zl4sNLvh{Fo=;bxGops?5x3i*!(|XY*!>#n5BDn3kcXmgVHo<=;j`oXAF=ULh4MDxLhQ|Ti(vzZucq4egM@&
zb@-#|aO|xbDfykaM(wwE$lkf;hCS*`2-)@A22RVG95X=mFw9CzhXZhXb}^&oQyEi*aGIwyndp%bRIn)xz;S
zSGUnT#9wD8Mida37P^aC{DcvCyy_a)EWvT8KLp(;zuo_6>%*eXyE;Xt
zmq@BzIjH-VtpPHyYoZA&;80j_vvypviyN8?dRQ6bBS*Vtst1y-lYNAo=Ju*32-)>A
zf-I@ybP2>=RNdkR1qQH7A~P9koD`WdMDE|DjSAS3*Uy20*QU`Xk=C&dd=-G&j$`!8
z-~nIzGqPKbT3uC_8s-@m!9n{HCVDa5P2&Aybr)qdb`bHj2#0Zjm**&y*LriZ+b4XV
zC@d0p0$aFy&-os?-(J^j1v47DZxf5hy<^SBmDUgSa1)+tj2>rkdLSmP&9EZWPFeGi
zcrE^|ec7~8wbM`&ai&+o7%DS0u%FR^4F2^Sjfx?$xxqQ2=kp_RFWayyMa1G6nHb-D
z>)(hC3p04#q!^j;x5p@itBLcmfv~qBDTBOg(8G);MWqAkhwV%+W4Wi>PV4jsPb{^q
zOXB$Ro|wNKYpFHP*U(c3hiv(;N9?Ie%&}Vf&2r3xmas3Pt3K=ac2!F!TOM=QYc4$K
zdVtL|0sZ76zW8ITL{4kg@Z{4jZAt50lxkv+mSW1CxRuGyHfd^3Tj}2NSfYMSRQ~Lq
zW8=szUV?kVtil>yx||}@jglOO#^c{Dgy>l@_*EA%plFhgT-X9WxEcj_1%m@S&)$XV>Dp4+KMvA2>z6=njGPoD+NAC=io
z6p|~ts&V&0CYj<>l>rqEncRlkc3^gt1Iyu7
zEgTtXcH8#jjOEEQfN-8TnPVT$M=56d<`dq+s$tBq;HP@u>#8yjDryT&TQqa~=#DnB
z?yuFR^|D2SPBKYysB7Pk*0Q5kF@7Hj#OU$!OHvGw0VWVO$r_xcO}ZOa&f9u${Bs*>
z16H4y);qbR#FS@oS{WdIa&2~NjB@fnS9DSwC{v&XQNC!9nXx78b2N`fGKQj+>
z&nWQl5G3nryjPebzFw_2gV`;?ulHMP>q6ysctZp-jppS(veb#&*Q|gtrM2bh@1@B?
z`i=M@;2*r!2(3fMq`9yYejwCo4%`0NZb6x+G%B%3c_*r?$%4`sU)UI^m7-1Go$Y(H
z`ZwDd7L70a=7EUxFwNx8^3}Ln`GoR~nk%r6E4@HhO$n@`3O!`{xes
zkh{~2r&h5xM?r3QU7aOaFwXr^pW4?cT7dHoU8wD;*VxA6S0RzLrHyX2%9&cy#Zu@0
z#ok*7wb^#-;!vzDR!Y&J#fr8Rf(2+P#flX#1X|oeLTGR+(n4{!04c@YCAhn^xCM82
zE714k{q`ScpL6y%v-j`azd7fdc{4*ML%8pGo||>AXRUQ#>$+f>Ig;7MO(!}o1!14V
zVZ9LmrzywhqG(Qx0_!j4bfjpYwR9@jarT~{jLb_$_KE@7?1J1+`kayBUxuW^eQ<_L
zarjhL;Z_fr{rdTf26>ND37V$Aq_4dF_1&^o<(J!&_sfQ60rFLYp2jy!FwNo8)8Fj
ziX>j9z6aw!c!=D`X7;O}yn$+xeP
zyY9?a)ld$YOMJNGuOem}VC#2{8j~=nGZV5Z$V@9lmRC1pF+c`M^z#D`LObhE&wvqiDy(Jc`sY7!Ie(z>h9|^nWTplIaO)N*f&k5*Qy)!wiH?M}
zlTS2M&ckYgR;i~s8dTp;u{u2qC9@&iWtelePf}J*Rf^m6E<6D7Y%!*pY||^LWWn(`+mX1Nmm&TSV$wHE;S=
zsb}(m5y|jANU;~-i{_V-*N`>f+aGTJDeU4Ql)3VdT;%ar|umGBWC0^
z8>92ALq&ak-#kWf9>epSRM|UvO`ATdkdCyOt!XBUiuxLg$7F4jV>1_1r-b)GXvV$r
zqcE_A`H62e)br36(~tLHyiuSF_)YD=z$Q_aZ7(4g#MSf|KeA_%sGIlRCPQ~sG2rx1
zKowO`%guDb4eiZaWBu3T5;}R*S}M280c)y`dDYs9O8ar4Hf#I%0gX$Jvq9_6-Ah{4
zzfEkdIXR7L6iz}F(Yi0s`}K6RXTA7AZuK9!oni5AMyqy4fR{L75wEfrD8^GL4zH5n
zlbKGJWC%q0B!;JCoJL;B2B~jCp@dHn5X0wCpX{27UYj+Q_$6dB5JsMng1bY8IxEVIp1uPz9TiLu
z8*GtL?|l^RwgF0LEaEaLg>}%?bT|jzbC-(V6!Bk~`H-Lo<`t;Umk5${Ckvdcc
z7@FayUO#WcU9b|i8_sPK4^vxct?43k00L`Xj1`DgYc_r_Mt{iPsplk1?xbM__^7qS
zyIg!JLi^4e3c?%x;jMw{5i3GUAL|Y0r(u)Guk9R#9xkia)?5`~DcIe=fkpl(u@_@6
zWxRa>$GtuCMiYEi^B8OH$yAJ9*wfKdojCOZzWnUm;Aix|oGaj#HZBQ2@v3h{$7VR6
zfwqhvc!RxZJ}te#CUnL>ezO!KO~2nT=m+TKydx~yBy>==Mt?ZsRdwo{GtvPHLSI)3
zN?5gOJaCv%h+gi-!R4}oR>(ra*|kPrv})vE+@N@~t1aUToHF}33oV-R&f?CDToAID
zmM$9dwdiBfOAgMX#TTj$o|c_oR^kVg>1yO;Y$`^&&<{`MZA!$9rS@*?
z3AWw*zv5XpyoJR`$M+wfB`i?h?S1x(*Cp5{*MqmnNL%YXDj|U}JtwN6>Fv~s{lc(q
z^;h3H>KUtHaGv!l0$ay3SL5I3D8kvhrY2gaSwd7VKiC!_bxte%x>_X?{8d1EU^c0;
ztdCSU{Pf`#554FC$vMG@zt?Z#Fb-$(v@-)=hfG03MBR!O9m3hgN9#lZ=LPS;0aJWq
zmhzCfBMiNUlnb`O9(;ZAVie)PCb65yAH)IrYzbA6>d>!9!+WI8Ljb#%EdJ#KRxRG}
zk>BK!lwht}^9DW#JoCnt(=&NGZdm1Lw-j;DIz{cCl~6bLv7s64nqtgPPqj82E>I=v
z%Ruzy_HMrun+^i~oB`#oPQ5brOm<4Myxf$Y;pg%P;V^saqeEF);_OtLW@gg
z{&6UMjzp=t)^4utHR!w2=^gp>p_WGm^v_Yn@X
zt4<(&Y=<-ku`2?i9CZ^3HFi>`V31sFP%>6;Lx?D=vp=LyhW4e9%?D(}`kWsO53=m8
zGletx(J%e!AZ!;}<2vO@o%1b|ZK_|+QDv*-4XZzObd-Tw`_J_#0c!$bjfE(U>705r
zpMj~B59U7k4==MDMv2t?6jjXG`}C`T-aw;+*tjZ3p-G)?eGW=|Riw18R(xP>p({WU
z)Ez518}eG7kocQ7@!ZGG64AS-3Yt$K4t0|cXWaWgj{!|`K0Veg%jSMb1oJj&{=kvn
zxzb@JDdQh_Ug>e;L7hF?|b
zZ5|=>gbr$)=7Ic`?*U=!vGDs2h9-O5J0`HTvY{3kjD3Z<{ac9#i}V0qJ2DAof2&Yi
z32s4pm9ExhaR#@gkjHsY${H!9z;eJZZ=zIt7}2{!uNLVS?O_8O(@y&&5kN-)Kh(R&
ze3{i{i&eJ~qOljXnUy_@3+(X$VZF}$b|GXSw8YpD*TH4nByQ8nBZ_y{+j-ky*Sy@I
zA;${Z(9Qy@{bFTt4KR#;6@oD@MWH&Vp
zu$Uji7-S7{^TX!0>0-xA3U4pdzqf6b5>J5ay~X)Gwi_HYBxRNzaO}CTIrH8$$m{%o
zaeHF+v28>^!}2#j8u-|C)z{UoLH_2pjuTfR+wFum|QJkB&|e6z^U4F
zGvL)i-#m%uMd9M2A(E6GXF~nGi}O@JW}HjAt8eQ?X1zD;Yg8wyfBrxZ{S2-DT14lZ
zx}?V|N7^%I1NmH|WD!oL*xnu}?9j7!^SvgfrjlE~W7Pnz+`ezoZW%eTC_XqeXylOB
zG-d?g$hNWgEXV%rnQ)R>7-qI(?czugtDeR
z6=la{wPgpOcUqQn)!E9c<$!SuY-}On)wTz6#n$Bd3n+&t;(z{7)z^Z=?VEqB%U4>C
zr|IdcPYOpch$9L2So}bvk_f!ud@TIp#Uom34WL?_tz7Kr3)k8G6CMc^Q^tpquKBjZ
zl`!F{tAEDb@Io@eks(}QAkp#&ze~M2+7W%@M%A}(v$eyM`pzVG?+Vbf4IeU@sd4yG
zI<>3*4Pl+wvctq8EK0ddqq1+{5+~2L*KKcK48g;uX4X5J$I;X+|rf9o7KhI?+TiO)=grExa_V66=y*_bSXz&a11ttqtI-+m5TdS
zK7R!PCA0L8qT-)*Men1WDKc5Zozy>Y?v@%BFyR?#=-UO@7~)Lb*{F=hIZs1{i!Ftf
zwga$~81z_@7)+OURPJ|d%I^9`&cllvPLi4B(
z0PqDcznQ}px-t|Tlu<;PuJYs_o@D41^jh_}?k1BF1ril6hI+S*%fD_i6)EwL?V9j!
z#a19QmBgn!_tf-B&lidZ>x0qb>Pj5IcO~%=aZy9vJ)n23@VT_G`UnSILCOvXLflK9
zDlL|N?gRIY-18`yW1GP`I6tSbB;Q&}e?}Q#(6%)C&1LUqq((FX_ZQf#+@P!gNGN5R
z792clmmMA+j%2N14G;+^3uE&6Npvn?iliYR3Ee62%)P~Hw
z4DH`{E=Gh`#wfz#CsQWIoIKgwTGc5KYhLkQm|4>}|I2Lo{XXK#2@ju$=J=O)?FS?M
zH;FwQBs&XV_*aA)88wgUK;*w`b(1j37L&)tY)i=^WnHBFJS%|20w>?0*e@(G0Rqx^4=hW?8U_{^LyB{wDa6teKD
z?f?Gydky~eZJ>%Nmig67&rNB6UztbPuZ*3`TW7xKEDcaluBrWRA-)#IkSvyO
zzj0X5W;J(t@YZFv$sf351v8eq(}{^=`fcXQcFOMw|4$)=f2B{yW}9xkF;Pmp5Z?(&&-WWOcdMv^UUoNvbnMn=k6!>0g2H
zuW??1rMlc-mRCvZf;fRx_iB!U4G}la@uwEyxG>}fF^`9m$f}jO(cr+o<*o?kgtUIV
zD`gaCK0Z$b
zsqUQBQJYd#2f${7`)*SGM{e)`@gP=nb_s&{jw?QsKn
z=31?M8k9AVX_dJ(Yb>{s$2sQIV6LP4-ZKotD+liIO_-2fo$RZp3A~4hqS)a9I>0h+
z=D>xIv+)LOmK39|8n9|wHKXv%_JHb2I?KB8fMUq8tAttfa?7#;V``p`EU3s2P!K%|
z1BA1A!edktzGSEdx^oalqCRSghM|<#Vv)58k3f2(;REivtd*T^(xxhBCQ`cLm+
zuxV6T(M@<$9N+w)^_c3OO(ihm3p|RABXzVm0*#i!S;9X*@Vw^hu$z6zhK1Kp9#ZMt
z8W;TD#vi)~a_npS%XTR)bcpTYA{6^^?ePar9hZJ{9e1K}_INcfRVuApIY_0I0p
zsQuGCFD)bWS!c!q|0(cr^1j4_mnU&WwIRlR7rtR8sPXKiDrpx_4?zrfWtHQ}ka7b(
z_h-zo=#YZ2>YDLMgYWzuWZViZ#~Bxcdycn7KUd4Cfcx&7akejVc7ATkw8OQ}l>lyR
zlJ#N{ys=D~;aT-xH#h+q)XREILzS{DM9|uCT5kB`BRW?mEyn6S
zS4M@z2QND&DTCxAs~xVB%$-Z{J5Qk(l0Jj1j*rS!B{j4NE8^A)O+11eT-nlaGx8Qp
z8ZipNOBKL^kUGZ4b7TNcB8Y2DIjqC>GO!D(%+0qbuJgOdG{17^mGBf(3K&>^8cZw@
zcppGjKDu&~zB$Yx)mR=c@+64gF8aYe$sv584{R?&qedS)HDtgl%&@#Y5qy;DInsN$
z4KD7Y-%ya03Q?MpI_jIl44#uA)MF;$9$%2~Usx$42j)&W=g$`BeD2?stUJxe
zA8OZz2Q}uItU(N1HbpfnXF{XsAR*W_o38RZQi7wc