Skip to content
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This project aims to be compatible with upstream Aider, but with priority commit
* [Map Cache Location Config: #2911](https://github.com/Aider-AI/aider/pull/2911)
* [Enhanced System Prompts: #3804](https://github.com/Aider-AI/aider/pull/3804)
* [Repo Map File Name Truncation Fix: #4320](https://github.com/Aider-AI/aider/pull/4320)
* [Read Only Stub Files For Context Window Management : #3056](https://github.com/Aider-AI/aider/pull/3056)

### Other Updates

Expand All @@ -28,6 +29,7 @@ This project aims to be compatible with upstream Aider, but with priority commit
* [Edit Before Adding Files and Reflecting](https://github.com/dwash96/aider-ce/pull/22)
* [Fix Deepseek model configurations](https://github.com/Aider-AI/aider/commit/c839a6dd8964d702172cae007375e299732d3823)
* [Relax Version Pinning For Easier Distribution](https://github.com/dwash96/aider-ce/issues/18)
* [Remove Confirm Responses from History](https://github.com/Aider-AI/aider/pull/3958)

### Other Notes
* [MCP Configuration](https://github.com/dwash96/aider-ce/blob/main/aider/website/docs/config/mcp.md)
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.87.6.dev"
__version__ = "0.87.7.dev"
safe_version = __version__

try:
Expand Down
66 changes: 57 additions & 9 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def wrap_fence(name):
class Coder:
abs_fnames = None
abs_read_only_fnames = None
abs_read_only_stubs_fnames = None
repo = None
last_aider_commit_hash = None
aider_edited_files = None
Expand Down Expand Up @@ -184,8 +185,10 @@ def create(
# Bring along context from the old Coder
update = dict(
fnames=list(from_coder.abs_fnames),
# Copy read-only files
read_only_fnames=list(from_coder.abs_read_only_fnames),
read_only_fnames=list(from_coder.abs_read_only_fnames), # Copy read-only files
read_only_stubs_fnames=list(
from_coder.abs_read_only_stubs_fnames
), # Copy read-only stubs
done_messages=done_messages,
cur_messages=from_coder.cur_messages,
aider_commit_hashes=from_coder.aider_commit_hashes,
Expand Down Expand Up @@ -301,6 +304,10 @@ def get_announcements(self):
rel_fname = self.get_rel_fname(fname)
lines.append(f"Added {rel_fname} to the chat (read-only).")

for fname in self.abs_read_only_stubs_fnames:
rel_fname = self.get_rel_fname(fname)
lines.append(f"Added {rel_fname} to the chat (read-only stub).")

if self.done_messages:
lines.append("Restored previous conversation history.")

Expand All @@ -319,6 +326,7 @@ def __init__(
fnames=None,
add_gitignore_files=False,
read_only_fnames=None,
read_only_stubs_fnames=None,
show_diffs=False,
auto_commits=True,
dirty_commits=True,
Expand Down Expand Up @@ -420,6 +428,7 @@ def __init__(
self.abs_fnames = set()
self.abs_read_only_fnames = set()
self.add_gitignore_files = add_gitignore_files
self.abs_read_only_stubs_fnames = set()

if cur_messages:
self.cur_messages = cur_messages
Expand Down Expand Up @@ -513,6 +522,17 @@ def __init__(
else:
self.io.tool_warning(f"Error: Read-only file {fname} does not exist. Skipping.")

if read_only_stubs_fnames:
self.abs_read_only_stubs_fnames = set()
for fname in read_only_stubs_fnames:
abs_fname = self.abs_root_path(fname)
if os.path.exists(abs_fname):
self.abs_read_only_stubs_fnames.add(abs_fname)
else:
self.io.tool_warning(
f"Error: Read-only (stub) file {fname} does not exist. Skipping."
)

if map_tokens is None:
use_repo_map = main_model.use_repo_map
map_tokens = 1024
Expand Down Expand Up @@ -647,6 +667,10 @@ def choose_fence(self):
content = self.io.read_text(_fname)
if content is not None:
all_content += content + "\n"
for _fname in self.abs_read_only_stubs_fnames:
content = self.io.read_text(_fname)
if content is not None:
all_content += content + "\n"

lines = all_content.splitlines()
good = False
Expand Down Expand Up @@ -720,6 +744,7 @@ def get_files_content(self, fnames=None):

def get_read_only_files_content(self):
prompt = ""
# Handle regular read-only files
for fname in self.abs_read_only_fnames:
content = self.io.read_text(fname)
if content is not None and not is_image_file(fname):
Expand Down Expand Up @@ -764,6 +789,17 @@ def get_read_only_files_content(self):
prompt += content

prompt += f"{self.fence[1]}\n"

# Handle stub files
for fname in self.abs_read_only_stubs_fnames:
if not is_image_file(fname):
relative_fname = self.get_rel_fname(fname)
prompt += "\n"
prompt += f"{relative_fname} (stub)"
prompt += f"\n{self.fence[0]}\n"
stub = self.get_file_stub(fname)
prompt += stub
prompt += f"{self.fence[1]}\n"
return prompt

def get_cur_message_text(self):
Expand Down Expand Up @@ -818,7 +854,10 @@ def get_repo_map(self, force_refresh=False):

all_abs_files = set(self.get_all_abs_files())
repo_abs_read_only_fnames = set(self.abs_read_only_fnames) & all_abs_files
chat_files = set(self.abs_fnames) | repo_abs_read_only_fnames
repo_abs_read_only_stubs_fnames = set(self.abs_read_only_stubs_fnames) & all_abs_files
chat_files = (
set(self.abs_fnames) | repo_abs_read_only_fnames | repo_abs_read_only_stubs_fnames
)
other_files = all_abs_files - chat_files

repo_content = self.repo_map.get_repo_map(
Expand Down Expand Up @@ -877,7 +916,9 @@ def get_readonly_files_messages(self):
]

# Handle image files
images_message = self.get_images_message(self.abs_read_only_fnames)
images_message = self.get_images_message(
list(self.abs_read_only_fnames) + list(self.abs_read_only_stubs_fnames)
)
if images_message is not None:
readonly_messages += [
images_message,
Expand Down Expand Up @@ -998,15 +1039,17 @@ def copy_context(self):

def get_input(self):
inchat_files = self.get_inchat_relative_files()
read_only_files = [self.get_rel_fname(fname) for fname in self.abs_read_only_fnames]
all_files = sorted(set(inchat_files + read_only_files))
all_read_only_fnames = self.abs_read_only_fnames | self.abs_read_only_stubs_fnames
all_read_only_files = [self.get_rel_fname(fname) for fname in all_read_only_fnames]
all_files = sorted(set(inchat_files + all_read_only_files))
edit_format = "" if self.edit_format == self.main_model.edit_format else self.edit_format
return self.io.get_input(
self.root,
all_files,
self.get_addable_relative_files(),
self.commands,
self.abs_read_only_fnames,
abs_read_only_fnames=self.abs_read_only_fnames,
abs_read_only_stubs_fnames=self.abs_read_only_stubs_fnames,
edit_format=edit_format,
)

Expand Down Expand Up @@ -2220,7 +2263,8 @@ def get_file_mentions(self, content, ignore_current=False):

# Get basenames of files already in chat or read-only
existing_basenames = {os.path.basename(f) for f in self.get_inchat_relative_files()} | {
os.path.basename(self.get_rel_fname(f)) for f in self.abs_read_only_fnames
os.path.basename(self.get_rel_fname(f))
for f in self.abs_read_only_fnames | self.abs_read_only_stubs_fnames
}

mentioned_rel_fnames = set()
Expand Down Expand Up @@ -2639,6 +2683,9 @@ def get_multi_response_content_in_progress(self, final=False):

return cur + new

def get_file_stub(self, fname):
return RepoMap.get_file_stub(fname, self.io)

def get_rel_fname(self, fname):
try:
return os.path.relpath(fname, self.root)
Expand Down Expand Up @@ -2675,7 +2722,8 @@ def get_addable_relative_files(self):
all_files = set(self.get_all_relative_files())
inchat_files = set(self.get_inchat_relative_files())
read_only_files = set(self.get_rel_fname(fname) for fname in self.abs_read_only_fnames)
return all_files - inchat_files - read_only_files
stub_files = set(self.get_rel_fname(fname) for fname in self.abs_read_only_stubs_fnames)
return all_files - inchat_files - read_only_files - stub_files

def check_for_dirty_commit(self, path):
if not self.repo:
Expand Down
Loading
Loading