aider-ce 0.88.20__py3-none-any.whl → 0.88.38__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. aider/__init__.py +1 -1
  2. aider/_version.py +2 -2
  3. aider/args.py +63 -43
  4. aider/coders/agent_coder.py +331 -79
  5. aider/coders/agent_prompts.py +3 -15
  6. aider/coders/architect_coder.py +21 -5
  7. aider/coders/base_coder.py +661 -413
  8. aider/coders/base_prompts.py +6 -3
  9. aider/coders/chat_chunks.py +39 -17
  10. aider/commands.py +79 -15
  11. aider/diffs.py +10 -9
  12. aider/exceptions.py +1 -1
  13. aider/helpers/coroutines.py +8 -0
  14. aider/helpers/requests.py +45 -0
  15. aider/history.py +5 -0
  16. aider/io.py +179 -25
  17. aider/main.py +86 -35
  18. aider/models.py +16 -8
  19. aider/queries/tree-sitter-language-pack/c-tags.scm +3 -0
  20. aider/queries/tree-sitter-language-pack/clojure-tags.scm +5 -0
  21. aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +5 -0
  22. aider/queries/tree-sitter-language-pack/cpp-tags.scm +3 -0
  23. aider/queries/tree-sitter-language-pack/csharp-tags.scm +6 -0
  24. aider/queries/tree-sitter-language-pack/dart-tags.scm +5 -0
  25. aider/queries/tree-sitter-language-pack/elixir-tags.scm +5 -0
  26. aider/queries/tree-sitter-language-pack/elm-tags.scm +3 -0
  27. aider/queries/tree-sitter-language-pack/go-tags.scm +7 -0
  28. aider/queries/tree-sitter-language-pack/java-tags.scm +6 -0
  29. aider/queries/tree-sitter-language-pack/javascript-tags.scm +8 -0
  30. aider/queries/tree-sitter-language-pack/lua-tags.scm +5 -0
  31. aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +3 -0
  32. aider/queries/tree-sitter-language-pack/python-tags.scm +10 -0
  33. aider/queries/tree-sitter-language-pack/r-tags.scm +6 -0
  34. aider/queries/tree-sitter-language-pack/ruby-tags.scm +5 -0
  35. aider/queries/tree-sitter-language-pack/rust-tags.scm +3 -0
  36. aider/queries/tree-sitter-language-pack/solidity-tags.scm +1 -1
  37. aider/queries/tree-sitter-language-pack/swift-tags.scm +4 -1
  38. aider/queries/tree-sitter-languages/c-tags.scm +3 -0
  39. aider/queries/tree-sitter-languages/c_sharp-tags.scm +6 -0
  40. aider/queries/tree-sitter-languages/cpp-tags.scm +3 -0
  41. aider/queries/tree-sitter-languages/dart-tags.scm +2 -1
  42. aider/queries/tree-sitter-languages/elixir-tags.scm +5 -0
  43. aider/queries/tree-sitter-languages/elm-tags.scm +3 -0
  44. aider/queries/tree-sitter-languages/fortran-tags.scm +3 -0
  45. aider/queries/tree-sitter-languages/go-tags.scm +6 -0
  46. aider/queries/tree-sitter-languages/haskell-tags.scm +2 -0
  47. aider/queries/tree-sitter-languages/java-tags.scm +6 -0
  48. aider/queries/tree-sitter-languages/javascript-tags.scm +8 -0
  49. aider/queries/tree-sitter-languages/julia-tags.scm +2 -2
  50. aider/queries/tree-sitter-languages/kotlin-tags.scm +3 -0
  51. aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +6 -0
  52. aider/queries/tree-sitter-languages/php-tags.scm +6 -0
  53. aider/queries/tree-sitter-languages/python-tags.scm +10 -0
  54. aider/queries/tree-sitter-languages/ruby-tags.scm +5 -0
  55. aider/queries/tree-sitter-languages/rust-tags.scm +3 -0
  56. aider/queries/tree-sitter-languages/scala-tags.scm +2 -3
  57. aider/queries/tree-sitter-languages/typescript-tags.scm +3 -0
  58. aider/queries/tree-sitter-languages/zig-tags.scm +20 -3
  59. aider/repomap.py +71 -11
  60. aider/resources/model-metadata.json +27335 -635
  61. aider/resources/model-settings.yml +190 -0
  62. aider/scrape.py +2 -0
  63. aider/tools/__init__.py +2 -0
  64. aider/tools/command.py +84 -94
  65. aider/tools/command_interactive.py +95 -110
  66. aider/tools/delete_block.py +131 -159
  67. aider/tools/delete_line.py +97 -132
  68. aider/tools/delete_lines.py +120 -160
  69. aider/tools/extract_lines.py +288 -312
  70. aider/tools/finished.py +30 -43
  71. aider/tools/git_branch.py +107 -109
  72. aider/tools/git_diff.py +44 -56
  73. aider/tools/git_log.py +39 -53
  74. aider/tools/git_remote.py +37 -51
  75. aider/tools/git_show.py +33 -47
  76. aider/tools/git_status.py +30 -44
  77. aider/tools/grep.py +214 -242
  78. aider/tools/indent_lines.py +175 -201
  79. aider/tools/insert_block.py +220 -253
  80. aider/tools/list_changes.py +65 -80
  81. aider/tools/ls.py +64 -80
  82. aider/tools/make_editable.py +57 -73
  83. aider/tools/make_readonly.py +50 -66
  84. aider/tools/remove.py +64 -80
  85. aider/tools/replace_all.py +96 -109
  86. aider/tools/replace_line.py +118 -156
  87. aider/tools/replace_lines.py +160 -197
  88. aider/tools/replace_text.py +159 -160
  89. aider/tools/show_numbered_context.py +115 -141
  90. aider/tools/thinking.py +52 -0
  91. aider/tools/undo_change.py +78 -91
  92. aider/tools/update_todo_list.py +130 -138
  93. aider/tools/utils/base_tool.py +64 -0
  94. aider/tools/utils/output.py +118 -0
  95. aider/tools/view.py +38 -54
  96. aider/tools/view_files_matching.py +131 -134
  97. aider/tools/view_files_with_symbol.py +108 -120
  98. aider/urls.py +1 -1
  99. aider/versioncheck.py +4 -3
  100. aider/website/docs/config/adv-model-settings.md +237 -0
  101. aider/website/docs/config/agent-mode.md +36 -3
  102. aider/website/docs/config/model-aliases.md +2 -1
  103. aider/website/docs/faq.md +6 -11
  104. aider/website/docs/languages.md +2 -2
  105. aider/website/docs/more/infinite-output.md +27 -0
  106. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/METADATA +112 -70
  107. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/RECORD +112 -107
  108. aider_ce-0.88.38.dist-info/entry_points.txt +6 -0
  109. aider_ce-0.88.20.dist-info/entry_points.txt +0 -2
  110. /aider/tools/{tool_utils.py → utils/helpers.py} +0 -0
  111. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/WHEEL +0 -0
  112. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/licenses/LICENSE.txt +0 -0
  113. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/top_level.txt +0 -0
@@ -77,11 +77,14 @@ The user is going to provide you with a conversation.
77
77
  This conversation is getting too long to fit in the context window of a language model.
78
78
  You need to summarize the conversation to reduce its length, while retaining all the important information.
79
79
 
80
- The summary should contain three parts:
80
+ The summary should contain four parts:
81
81
  - Overall Goal: What is the user trying to achieve with this conversation?
82
82
  - Next Steps: What are the next steps for the language model to take to help the user?
83
- Create a checklist of what has been done and what is left to do.
84
- - Active files: What files are currently in the context window?
83
+ Describe the current investigation path and intention.
84
+ - Key Findings: Keep information most important to prevent having to search for it again
85
+ This should be quite specific (e/g. relevant files, method names, relevant lines of code, and code structure)
86
+ - Active files: What files are currently most relevant to the discussion?
87
+ Be confident in proceeding with any in progress edits.
85
88
 
86
89
  Here is the conversation so far:
87
90
  """
@@ -10,20 +10,34 @@ class ChatChunks:
10
10
  repo: List = field(default_factory=list)
11
11
  readonly_files: List = field(default_factory=list)
12
12
  chat_files: List = field(default_factory=list)
13
+ edit_files: List = field(default_factory=list)
13
14
  cur: List = field(default_factory=list)
14
15
  reminder: List = field(default_factory=list)
16
+ chunk_ordering: List = field(default_factory=list)
17
+
18
+ def __init__(self, chunk_ordering=None):
19
+ self.chunk_ordering = chunk_ordering
15
20
 
16
21
  def all_messages(self):
17
- return (
18
- self.system
19
- + self.examples
20
- + self.readonly_files
21
- + self.repo
22
- + self.done
23
- + self.chat_files
24
- + self.cur
25
- + self.reminder
26
- )
22
+ if self.chunk_ordering:
23
+ messages = []
24
+ for chunk_name in self.chunk_ordering:
25
+ chunk = getattr(self, chunk_name, [])
26
+ if chunk:
27
+ messages.extend(chunk)
28
+ return messages
29
+ else:
30
+ return (
31
+ self.format_list(self.system)
32
+ + self.format_list(self.examples)
33
+ + self.format_list(self.readonly_files)
34
+ + self.format_list(self.chat_files)
35
+ + self.format_list(self.repo)
36
+ + self.format_list(self.done)
37
+ + self.format_list(self.edit_files)
38
+ + self.format_list(self.cur)
39
+ + self.format_list(self.reminder)
40
+ )
27
41
 
28
42
  def add_cache_control_headers(self):
29
43
  if self.examples:
@@ -31,15 +45,17 @@ class ChatChunks:
31
45
  else:
32
46
  self.add_cache_control(self.system)
33
47
 
34
- if self.repo:
35
- # this will mark both the readonly_files and repomap chunk as cacheable
36
- self.add_cache_control(self.repo)
37
- else:
38
- # otherwise, just cache readonly_files if there are any
39
- self.add_cache_control(self.readonly_files)
40
-
48
+ # The files form a cacheable block.
49
+ # The block starts with readonly_files and ends with chat_files.
50
+ # So we mark the end of chat_files.
41
51
  self.add_cache_control(self.chat_files)
42
52
 
53
+ # The repo map is its own cacheable block.
54
+ self.add_cache_control(self.repo)
55
+
56
+ # The history is ephemeral on its own.
57
+ self.add_cache_control(self.done)
58
+
43
59
  def add_cache_control(self, messages):
44
60
  if not messages:
45
61
  return
@@ -62,3 +78,9 @@ class ChatChunks:
62
78
  ):
63
79
  return messages[: len(messages) - i]
64
80
  return messages
81
+
82
+ def format_list(self, chunk):
83
+ if type(chunk) is not list:
84
+ return []
85
+
86
+ return chunk
aider/commands.py CHANGED
@@ -89,7 +89,8 @@ class Commands:
89
89
  async def cmd_model(self, args):
90
90
  "Switch the Main Model to a new LLM"
91
91
 
92
- model_name = args.strip()
92
+ arg_split = args.split(" ", 1)
93
+ model_name = arg_split[0].strip()
93
94
  if not model_name:
94
95
  announcements = "\n".join(self.coder.get_announcements())
95
96
  self.io.tool_output(announcements)
@@ -111,19 +112,57 @@ class Commands:
111
112
  # If the user was using the old model's default, switch to the new model's default
112
113
  new_edit_format = model.edit_format
113
114
 
114
- raise SwitchCoder(main_model=model, edit_format=new_edit_format)
115
+ if len(arg_split) > 1:
116
+ # implement architect coder-like generation call for model
117
+ message = arg_split[1].strip()
115
118
 
116
- async def cmd_editor_model(self, args):
117
- "Switch the Editor Model to a new LLM"
119
+ # Store the original model configuration
120
+ original_main_model = self.coder.main_model
121
+ original_edit_format = self.coder.edit_format
118
122
 
119
- model_name = args.strip()
120
- model = models.Model(
121
- self.coder.main_model.name,
122
- editor_model=model_name,
123
- weak_model=self.coder.main_model.weak_model.name,
124
- )
125
- await models.sanity_check_models(self.io, model)
126
- raise SwitchCoder(main_model=model)
123
+ # Create a temporary coder with the new model
124
+ from aider.coders import Coder
125
+
126
+ kwargs = dict()
127
+ kwargs["main_model"] = model
128
+ kwargs["edit_format"] = new_edit_format
129
+ kwargs["suggest_shell_commands"] = False
130
+ kwargs["total_cost"] = self.coder.total_cost
131
+ kwargs["num_cache_warming_pings"] = 0
132
+ kwargs["summarize_from_coder"] = False
133
+
134
+ new_kwargs = dict(io=self.io, from_coder=self.coder)
135
+ new_kwargs.update(kwargs)
136
+
137
+ temp_coder = await Coder.create(**new_kwargs)
138
+ temp_coder.cur_messages = []
139
+ temp_coder.done_messages = []
140
+
141
+ if self.verbose:
142
+ temp_coder.show_announcements()
143
+
144
+ try:
145
+ await temp_coder.generate(user_message=message, preproc=False)
146
+ self.coder.move_back_cur_messages(
147
+ f"Model {model_name} made those changes to the files."
148
+ )
149
+ self.coder.total_cost = temp_coder.total_cost
150
+ self.coder.aider_commit_hashes = temp_coder.aider_commit_hashes
151
+
152
+ # Restore the original model configuration
153
+ raise SwitchCoder(main_model=original_main_model, edit_format=original_edit_format)
154
+ except Exception as e:
155
+ # If there's an error, still restore the original model
156
+ if not isinstance(e, SwitchCoder):
157
+ self.io.tool_error(e)
158
+ raise SwitchCoder(
159
+ main_model=original_main_model, edit_format=original_edit_format
160
+ )
161
+ else:
162
+ # Re-raise SwitchCoder if that's what was thrown
163
+ raise
164
+ else:
165
+ raise SwitchCoder(main_model=model, edit_format=new_edit_format)
127
166
 
128
167
  async def cmd_weak_model(self, args):
129
168
  "Switch the Weak Model to a new LLM"
@@ -414,7 +453,6 @@ class Commands:
414
453
  )
415
454
 
416
455
  lint_coder.add_rel_fname(fname)
417
- await self.coder.io.recreate_input()
418
456
  await lint_coder.run_one(errors, preproc=False)
419
457
  lint_coder.abs_fnames = set()
420
458
 
@@ -999,6 +1037,22 @@ class Commands:
999
1037
  if hasattr(self.coder, "_calculate_context_block_tokens"):
1000
1038
  self.coder._calculate_context_block_tokens()
1001
1039
 
1040
+ if self.coder.repo_map:
1041
+ map_tokens = self.coder.repo_map.max_map_tokens
1042
+ map_mul_no_files = self.coder.repo_map.map_mul_no_files
1043
+ else:
1044
+ map_tokens = 0
1045
+ map_mul_no_files = 1
1046
+
1047
+ raise SwitchCoder(
1048
+ edit_format=self.coder.edit_format,
1049
+ summarize_from_coder=False,
1050
+ from_coder=self.coder,
1051
+ map_tokens=map_tokens,
1052
+ map_mul_no_files=map_mul_no_files,
1053
+ show_announcements=False,
1054
+ )
1055
+
1002
1056
  def completions_drop(self):
1003
1057
  files = self.coder.get_inchat_relative_files()
1004
1058
  read_only_files = [
@@ -1095,7 +1149,7 @@ class Commands:
1095
1149
  matched_files = [
1096
1150
  self.coder.get_rel_fname(f)
1097
1151
  for f in self.coder.abs_fnames
1098
- if expanded_word in f
1152
+ if self.coder.abs_root_path(expanded_word) in f
1099
1153
  ]
1100
1154
 
1101
1155
  if not matched_files:
@@ -1498,6 +1552,9 @@ class Commands:
1498
1552
 
1499
1553
  from aider.coders.base_coder import Coder
1500
1554
 
1555
+ original_main_model = self.coder.main_model
1556
+ original_edit_format = self.coder.edit_format
1557
+
1501
1558
  coder = await Coder.create(
1502
1559
  io=self.io,
1503
1560
  from_coder=self.coder,
@@ -1508,9 +1565,16 @@ class Commands:
1508
1565
  )
1509
1566
 
1510
1567
  user_msg = args
1511
- await coder.run(user_msg, False)
1568
+ await coder.generate(user_message=user_msg, preproc=False)
1512
1569
  self.coder.aider_commit_hashes = coder.aider_commit_hashes
1513
1570
 
1571
+ raise SwitchCoder(
1572
+ main_model=original_main_model,
1573
+ edit_format=original_edit_format,
1574
+ done_messages=coder.done_messages,
1575
+ cur_messages=coder.cur_messages,
1576
+ )
1577
+
1514
1578
  def get_help_md(self):
1515
1579
  "Show help about all commands in markdown"
1516
1580
 
aider/diffs.py CHANGED
@@ -63,17 +63,18 @@ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None):
63
63
  if last_non_deleted is None:
64
64
  return ""
65
65
 
66
- if num_orig_lines:
67
- pct = last_non_deleted * 100 / num_orig_lines
68
- else:
69
- pct = 50
70
- bar = create_progress_bar(pct)
71
- bar = f" {last_non_deleted:3d} / {num_orig_lines:3d} lines [{bar}] {pct:3.0f}%\n"
66
+ # if num_orig_lines:
67
+ # pct = last_non_deleted * 100 / num_orig_lines
68
+ # else:
69
+ # pct = 50
70
+ # bar = create_progress_bar(pct)
71
+ # bar = f" {last_non_deleted:3d} / {num_orig_lines:3d} lines [{bar}] {pct:3.0f}%\n"
72
72
 
73
73
  lines_orig = lines_orig[:last_non_deleted]
74
74
 
75
75
  if not final:
76
- lines_updated = lines_updated[:-1] + [bar]
76
+ # lines_updated = lines_updated[:-1] + [bar]
77
+ lines_updated = lines_updated[:-1]
77
78
 
78
79
  diff = difflib.unified_diff(lines_orig, lines_updated, n=5)
79
80
 
@@ -88,14 +89,14 @@ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None):
88
89
  if backticks not in diff:
89
90
  break
90
91
 
91
- show = f"{backticks}diff\n"
92
+ show = "diff\n"
92
93
  if fname:
93
94
  show += f"--- {fname} original\n"
94
95
  show += f"+++ {fname} updated\n"
95
96
 
96
97
  show += diff
97
98
 
98
- show += f"{backticks}\n\n"
99
+ show += "\n\n"
99
100
 
100
101
  # print(diff)
101
102
 
aider/exceptions.py CHANGED
@@ -20,7 +20,7 @@ EXCEPTIONS = [
20
20
  "The API provider is not able to authenticate you. Check your API key.",
21
21
  ),
22
22
  ExInfo("AzureOpenAIError", True, None),
23
- ExInfo("BadGatewayError", False, None),
23
+ ExInfo("BadGatewayError", True, None),
24
24
  ExInfo("BadRequestError", False, None),
25
25
  ExInfo("BudgetExceededError", True, None),
26
26
  ExInfo(
@@ -0,0 +1,8 @@
1
+ import asyncio # noqa: F401
2
+
3
+
4
+ def is_active(coroutine):
5
+ if not coroutine or coroutine.done() or coroutine.cancelled():
6
+ return False
7
+
8
+ return True
@@ -0,0 +1,45 @@
1
+ from ..sendchat import ensure_alternating_roles
2
+
3
+
4
+ def thought_signature(model, messages):
5
+ # Add thought signatures for Vertex AI and Gemini models
6
+ if model.name.startswith("vertex_ai/") or model.name.startswith("gemini/"):
7
+ for msg in messages:
8
+ if "tool_calls" in msg:
9
+ tool_calls = msg["tool_calls"]
10
+
11
+ if tool_calls:
12
+ for call in tool_calls:
13
+ if not call:
14
+ continue
15
+
16
+ # Check if thought signature is missing in extra_content.google.thought_signature
17
+ if "provider_specific_fields" not in call:
18
+ call["provider_specific_fields"] = {}
19
+ if "thought_signature" not in call["provider_specific_fields"]:
20
+ call["provider_specific_fields"][
21
+ "thought_signature"
22
+ ] = "skip_thought_signature_validator"
23
+
24
+ if "function_call" in msg:
25
+ call = msg["function_call"]
26
+
27
+ if not call:
28
+ continue
29
+
30
+ # Check if thought signature is missing in extra_content.google.thought_signature
31
+ if "provider_specific_fields" not in call:
32
+ call["provider_specific_fields"] = {}
33
+ if "thought_signature" not in call["provider_specific_fields"]:
34
+ call["provider_specific_fields"][
35
+ "thought_signature"
36
+ ] = "skip_thought_signature_validator"
37
+
38
+ return messages
39
+
40
+
41
+ def model_request_parser(model, messages):
42
+ messages = thought_signature(model, messages)
43
+ messages = ensure_alternating_roles(messages)
44
+
45
+ return messages
aider/history.py CHANGED
@@ -30,6 +30,11 @@ class ChatSummary:
30
30
  sized.append((tokens, msg))
31
31
  return sized
32
32
 
33
+ def count_tokens(self, messages):
34
+ sized = self.tokenize(messages)
35
+ total = sum(tokens for tokens, _msg in sized)
36
+ return total
37
+
33
38
  async def summarize(self, messages, depth=0):
34
39
  messages = await self.summarize_real(messages)
35
40
  if messages and messages[-1]["role"] != "assistant":