Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ analytics: false
auto-commits: true
auto-save: true
auto-load: true
cache-prompts: true
check-update: true
debug: false
enable-context-compaction: true
Expand Down Expand Up @@ -86,8 +87,8 @@ The current priorities are to improve core capabilities and user experience of t

2. **Repo Map Accuracy** - [Discussion](https://github.com/dwash96/aider-ce/issues/45)
* [x] [Bias page ranking toward active/editable files in repo map parsing](https://github.com/Aider-AI/aider/issues/2405)
* [ ] [Include import information in repo map for richer context](https://github.com/Aider-AI/aider/issues/2688)
* [ ] [Handle non-unique symbols that break down in large codebases](https://github.com/Aider-AI/aider/issues/2341)
* [x] [Include import information in repo map for richer context](https://github.com/Aider-AI/aider/issues/2688)
* [x] [Handle non-unique symbols that break down in large codebases](https://github.com/Aider-AI/aider/issues/2341)

3. **Context Discovery** - [Discussion](https://github.com/dwash96/aider-ce/issues/46)
* [ ] Develop AST-based search capabilities
Expand Down
2 changes: 1 addition & 1 deletion aider/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from packaging import version

__version__ = "0.88.26.dev"
__version__ = "0.88.27.dev"
safe_version = __version__

try:
Expand Down
103 changes: 56 additions & 47 deletions aider/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,58 @@ def get_parser(default_config_files, git_root):
),
)

#########
group = parser.add_argument_group("Agent settings")
group.add_argument(
"--agent-config",
metavar="AGENT_CONFIG_JSON",
help="Specify Agent Mode configuration as a JSON string",
default=None,
)
group.add_argument(
"--auto-save",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable automatic saving of sessions as 'auto-save' (default: False)",
)
group.add_argument(
"--auto-load",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable automatic loading of 'auto-save' session on startup (default: False)",
)
group.add_argument(
"--mcp-servers",
metavar="MCP_CONFIG_JSON",
help="Specify MCP server configurations as a JSON string",
default=None,
)
group.add_argument(
"--mcp-servers-file",
metavar="MCP_CONFIG_FILE",
help="Specify a file path with MCP server configurations",
default=None,
)
group.add_argument(
"--mcp-transport",
metavar="MCP_TRANSPORT",
help="Specify the transport for MCP servers (default: stdio)",
default="stdio",
choices=["stdio", "http", "sse"],
)
group.add_argument(
"--preserve-todo-list",
action="store_true",
help="Preserve the existing .aider.todo.txt file on startup (default: False)",
default=False,
)
group.add_argument(
"--use-enhanced-map",
action="store_true",
help="Use enhanced Repo Map that takes into account imports (default: False)",
default=False,
)

##########
group = parser.add_argument_group("Context Compaction")
group.add_argument(
Expand All @@ -248,7 +300,7 @@ def get_parser(default_config_files, git_root):
default=None,
help=(
"The maximum number of tokens in the conversation before context compaction is"
" triggered. (default: 80% of model's context window)"
" triggered. (default: 80%% of model's context window)"
),
)
group.add_argument(
Expand Down Expand Up @@ -789,22 +841,10 @@ def get_parser(default_config_files, git_root):
######
group = parser.add_argument_group("Other settings")
group.add_argument(
"--preserve-todo-list",
"--yes-always",
action="store_true",
help="Preserve the existing .aider.todo.txt file on startup (default: False)",
default=False,
)
group.add_argument(
"--auto-save",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable automatic saving of sessions as 'auto-save' (default: False)",
)
group.add_argument(
"--auto-load",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable automatic loading of 'auto-save' session on startup (default: False)",
help="Always say yes to every confirmation",
default=None,
)
group.add_argument(
"--disable-playwright",
Expand Down Expand Up @@ -842,12 +882,6 @@ def get_parser(default_config_files, git_root):
default=None,
help="Specify the language to use in the commit message (default: None, user language)",
)
group.add_argument(
"--yes-always",
action="store_true",
help="Always say yes to every confirmation",
default=None,
)
group.add_argument(
"-v",
"--verbose",
Expand All @@ -871,25 +905,6 @@ def get_parser(default_config_files, git_root):
default="platform",
help="Line endings to use when writing files (default: platform)",
)
group.add_argument(
"--mcp-servers",
metavar="MCP_CONFIG_JSON",
help="Specify MCP server configurations as a JSON string",
default=None,
)
group.add_argument(
"--mcp-servers-file",
metavar="MCP_CONFIG_FILE",
help="Specify a file path with MCP server configurations",
default=None,
)
group.add_argument(
"--mcp-transport",
metavar="MCP_TRANSPORT",
help="Specify the transport for MCP servers (default: stdio)",
default="stdio",
choices=["stdio", "http"],
)
group.add_argument(
"-c",
"--config",
Expand All @@ -900,12 +915,6 @@ def get_parser(default_config_files, git_root):
" or home directory)"
),
).complete = shtab.FILE
group.add_argument(
"--agent-config",
metavar="AGENT_CONFIG_JSON",
help="Specify Agent Mode configuration as a JSON string",
default=None,
)
# This is a duplicate of the argument in the preparser and is a no-op by this time of
# argument parsing, but it's here so that the help is displayed as expected.
group.add_argument(
Expand Down
2 changes: 1 addition & 1 deletion aider/coders/agent_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ async def process_tool_calls(self, tool_call_response):
Track tool usage before calling the base implementation.
"""
self.agent_finished = False
self.auto_save_session()
await self.auto_save_session()

if self.partial_response_tool_calls:
for tool_call in self.partial_response_tool_calls:
Expand Down
36 changes: 24 additions & 12 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ def __init__(
max_code_line_length=map_max_line_length,
repo_root=self.root,
use_memory_cache=repomap_in_memory,
use_enhanced_map=False if not self.args or self.args.use_enhanced_map else True,
)

self.summarizer = summarizer or ChatSummary(
Expand Down Expand Up @@ -892,7 +893,8 @@ def get_repo_map(self, force_refresh=False):
)
except ANY_GIT_ERROR as err:
# Handle git errors gracefully - use a fallback hash
self.io.tool_warning(f"Git error while checking staged files for repo map: {err}")
if self.verbose:
self.io.tool_warning(f"Git error while checking staged files for repo map: {err}")
staged_files_hash = hash(str(time.time())) # Use timestamp as fallback

read_only_count = len(set(self.abs_read_only_fnames)) + len(
Expand Down Expand Up @@ -1145,7 +1147,7 @@ async def _run_linear(self, with_message=None, preproc=True):
self.io.tool_output("Finished.")
self.io.ring_bell()
user_message = None
self.auto_save_session()
await self.auto_save_session()

except KeyboardInterrupt:
if self.io.input_task:
Expand Down Expand Up @@ -1221,7 +1223,7 @@ async def _run_parallel(self, with_message=None, preproc=True):
# Ensure IO tasks are properly cancelled
await self.io.cancel_task_streams()

self.auto_save_session()
await self.auto_save_session()
except EOFError:
return
finally:
Expand All @@ -1248,7 +1250,7 @@ async def input_task(self, preproc):
if not self.io.acknowledge_confirmation():
if user_message:
self.user_message = user_message
self.auto_save_session()
await self.auto_save_session()
else:
self.user_message = ""
await self.io.cancel_task_streams()
Expand Down Expand Up @@ -1325,7 +1327,7 @@ async def output_task(self, preproc):
# Stop spinner when processing task completes
self.io.stop_spinner()

self.auto_save_session()
await self.auto_save_session()
await asyncio.sleep(0.01) # Small yield to prevent tight loop

except KeyboardInterrupt:
Expand Down Expand Up @@ -2007,7 +2009,7 @@ async def check_tokens(self, messages):
" the context limit is exceeded."
)

if not await self.io.confirm_ask("Try to proceed anyway?"):
if not await self.io.confirm_ask("Try to proceed anyway?", explicit_yes_required=True):
return False
return True

Expand Down Expand Up @@ -3382,7 +3384,8 @@ def get_all_relative_files(self):
return self.data_cache["relative_files"]
except ANY_GIT_ERROR as err:
# Handle git errors gracefully - fall back to getting tracked files
self.io.tool_warning(f"Git error while checking staged files: {err}")
if self.verbose:
self.io.tool_warning(f"Git error while checking staged files: {err}")
# Continue to get tracked files normally

if self.repo:
Expand Down Expand Up @@ -3691,7 +3694,7 @@ def apply_edits(self, edits):
def apply_edits_dry_run(self, edits):
return edits

def auto_save_session(self):
async def auto_save_session(self):
"""Automatically save the current session as 'auto-save'."""
if not getattr(self.args, "auto_save", False):
return
Expand All @@ -3700,13 +3703,22 @@ def auto_save_session(self):
if not hasattr(self, "_last_autosave_time"):
self._last_autosave_time = 0

# Throttle autosave to run at most once per second
if not hasattr(self, "_autosave_future"):
self._autosave_future = None

if self._autosave_future and self._autosave_future.done():
return

# Throttle autosave to run at most once every 15 seconds
current_time = time.time()
if current_time - self._last_autosave_time >= 1.0:
if current_time - self._last_autosave_time >= 15.0:
try:
session_manager = SessionManager(self, self.io)
session_manager.save_session("auto-save", False)
self._last_autosave_time = current_time
session_manager = SessionManager(self, self.io)
loop = asyncio.get_running_loop()
self._autosave_future = loop.run_in_executor(
None, session_manager.save_session, "auto-save", False
)
except Exception:
# Don't show errors for auto-save to avoid interrupting the user experience
pass
Expand Down
14 changes: 12 additions & 2 deletions aider/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,13 @@ def reject_outstanding_confirmations(self):
# This method is now a no-op since we removed the confirmation_future logic
pass

def get_coder(self):
coder = self.coder() if self.coder else None
return coder

async def recreate_input(self, future=None):
if not coroutines.is_active(self.input_task):
coder = self.coder() if self.coder else None
coder = self.get_coder()

if coder:
self.input_task = asyncio.create_task(coder.get_input())
Expand Down Expand Up @@ -889,7 +893,13 @@ def get_continuation(width, line_number, is_soft_wrap):
return cmd

except EOFError:
raise
coder = self.get_coder()

if coder:
await coder.commands.cmd_exit(None)
else:
raise SystemExit

except KeyboardInterrupt:
self.console.print()
return ""
Expand Down
3 changes: 3 additions & 0 deletions aider/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,9 @@ def load_slow_imports(swallow=True):

async def graceful_exit(coder=None, exit_code=0):
if coder:
if hasattr(coder, "_autosave_future"):
await coder._autosave_future

for server in coder.mcp_servers:
try:
await server.exit_stack.aclose()
Expand Down
8 changes: 8 additions & 0 deletions aider/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,14 @@ async def send_completion(
dump(kwargs)
kwargs["messages"] = messages

# Cache System Prompts When Possible
kwargs["cache_control_injection_points"] = [
{
"location": "message",
"role": "system",
}
]

# Are we using github copilot?
if "GITHUB_COPILOT_TOKEN" in os.environ or self.name.startswith("github_copilot/"):
if "extra_headers" not in kwargs:
Expand Down
3 changes: 3 additions & 0 deletions aider/queries/tree-sitter-language-pack/c-tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
(type_definition declarator: (type_identifier) @name.definition.type) @definition.type

(enum_specifier name: (type_identifier) @name.definition.type) @definition.type

(preproc_include
path: (_) @name.reference.import) @reference.import
5 changes: 5 additions & 0 deletions aider/queries/tree-sitter-language-pack/clojure-tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
(#match? @ignore "^def.*"))

(sym_lit name: (sym_name) @name.reference.call)

(list_lit
. (sym_lit name: (sym_name) @import_call)
. (sym_lit name: (sym_name) @name.reference.import)
(#match? @import_call "^(require|use)$")) @reference.import
5 changes: 5 additions & 0 deletions aider/queries/tree-sitter-language-pack/commonlisp-tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
;; first element
(list_lit . [(sym_lit) (package_lit)] @name.reference.call) @reference.call

(list_lit
. (sym_lit) @import_call
. (sym_lit) @name.reference.import
(#match? @import_call "^(require|load)$")) @reference.import

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; classes

Expand Down
3 changes: 3 additions & 0 deletions aider/queries/tree-sitter-language-pack/cpp-tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
(enum_specifier name: (type_identifier) @name.definition.type) @definition.type

(class_specifier name: (type_identifier) @name.definition.class) @definition.class

(preproc_include
path: (_) @name.reference.import) @reference.import
6 changes: 6 additions & 0 deletions aider/queries/tree-sitter-language-pack/csharp-tags.scm
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@
(namespace_declaration name: (identifier) @name.definition.module) @definition.module

(namespace_declaration name: (identifier) @name.definition.module) @module

(using_directive
(qualified_name) @name.reference.import) @reference.import

(using_directive
(identifier) @name.reference.import) @reference.import
Loading
Loading