Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aider companion support #2067

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions aider/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,21 @@ def get_parser(default_config_files, git_root):
default=False,
)

##########
group = parser.add_argument_group("Companion")
group.add_argument(
"--enable-companion",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable use of Aider Companion (default: False)",
)
group.add_argument(
"--companion-base-url",
metavar="COMPANION_BASE_URL",
default="http://localhost:24337",
help="Base URL for Aider Companion (default: http://localhost:24337)",
)

##########
group = parser.add_argument_group("Other Settings")
group.add_argument(
Expand Down
27 changes: 25 additions & 2 deletions aider/coders/base_coder.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@
from aider.run_cmd import run_cmd
from aider.sendchat import retry_exceptions, send_completion
from aider.utils import format_content, format_messages, format_tokens, is_image_file

from ..dump import dump # noqa: F401
from .chat_chunks import ChatChunks
from ..dump import dump # noqa: F401


class MissingAPIKeyError(ValueError):
Expand Down Expand Up @@ -90,6 +89,8 @@ class Coder:
suggest_shell_commands = True
ignore_mentions = None
chat_language = None
companion = None
companion_files = None

@classmethod
def create(
Expand Down Expand Up @@ -263,7 +264,9 @@ def __init__(
num_cache_warming_pings=0,
suggest_shell_commands=True,
chat_language=None,
companion=None,
):

self.chat_language = chat_language
self.commit_before_message = []
self.aider_commit_hashes = set()
Expand Down Expand Up @@ -416,6 +419,11 @@ def __init__(
self.done_messages = utils.split_chat_history_markdown(history_md)
self.summarize_start()

self.companion = companion
self.companion_files = set()

self.update_inchat_files()

# Linting and testing
self.linter = Linter(root=self.root, encoding=io.encoding)
self.auto_lint = auto_lint
Expand Down Expand Up @@ -726,6 +734,7 @@ def run(self, with_message=None, preproc=True):

while True:
try:
self.update_inchat_files()
user_message = self.get_input()
self.run_one(user_message, preproc)
self.show_undo_hint()
Expand All @@ -734,6 +743,20 @@ def run(self, with_message=None, preproc=True):
except EOFError:
return

def update_inchat_files(self):
if self.companion:
companion_files = self.companion.get_open_files()

to_add = set(companion_files) - self.companion_files
for companion_file in to_add:
self.add_rel_fname(companion_file)

to_remove = self.companion_files - set(companion_files)
for companion_file in to_remove:
self.drop_rel_fname(companion_file)

self.companion_files = set(companion_files)

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]
Expand Down
21 changes: 17 additions & 4 deletions aider/commands.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import glob
import os
import pyperclip
import re
import subprocess
import sys
import tempfile
from PIL import Image, ImageGrab
from collections import OrderedDict
from os.path import expanduser
from pathlib import Path

import pyperclip
from PIL import Image, ImageGrab
from prompt_toolkit.completion import Completion, PathCompleter
from prompt_toolkit.document import Document

Expand All @@ -21,7 +20,6 @@
from aider.run_cmd import run_cmd
from aider.scrape import Scraper, install_playwright
from aider.utils import is_image_file

from .dump import dump # noqa: F401


Expand Down Expand Up @@ -1276,6 +1274,21 @@ def cmd_report(self, args):

report_github_issue(issue_text, title=title, confirm=False)

def cmd_companion(self, args):
"Start or stop the companion functionality"
action = args.strip().lower()
if action not in ["start", "stop"]:
self.io.tool_error("Invalid argument. Use 'start' or 'stop'.")
return

enabled = (action == "start")
if self.coder.companion:
self.coder.companion.set_enabled(enabled)
status = "enabled" if enabled else "disabled"
self.io.tool_output(f"Companion functionality is now {status}.")
else:
self.io.tool_error("Companion functionality is not enabled. Make sure you are running aider with/in a git repo.")


def expand_subdir(file_path):
if file_path.is_file():
Expand Down
48 changes: 48 additions & 0 deletions aider/companion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import requests

from aider.io import InputOutput


class Companion:
base_dir = ""
io: InputOutput = None
base_url = "http://localhost:24337"
enabled = False

def __init__(
self,
base_dir,
io=None,
base_url="http://localhost:24337",
enabled=False,
):
self.base_dir = base_dir
self.io = io
self.base_url = base_url
self.enabled = enabled

def set_enabled(self, enabled):
self.enabled = enabled

def get_open_files(self, use_absolute_paths=False):
if not self.enabled:
return []

try:
url = f"{self.base_url}/open-files"
response = requests.post(url, json={"projectBase": self.base_dir.replace("\\", "/")})

if response.status_code == 200:
files = response.json()
if use_absolute_paths:
files = [os.path.abspath(os.path.join(self.base_dir, file)) for file in files]
return files
else:
if self.io:
self.io.tool_error(f"Error: {response.status_code} - {response.text}")
return []
except requests.exceptions.RequestException as e:
if self.io:
self.io.tool_error(f"An error occurred while trying to connect to Aider Companion:\n{e}")
return []
14 changes: 10 additions & 4 deletions aider/main.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import configparser
import git
import json
import os
import re
import sys
import threading
import traceback
from pathlib import Path

import git
from dotenv import load_dotenv
from pathlib import Path
from prompt_toolkit.enums import EditingMode

from aider import __version__, models, urls, utils
from aider.args import get_parser
from aider.coders import Coder
from aider.commands import Commands, SwitchCoder
from aider.companion import Companion
from aider.format_settings import format_settings, scrub_sensitive_info
from aider.history import ChatSummary
from aider.io import InputOutput
from aider.llm import litellm # noqa: F401; properly init litellm on launch
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.report import report_uncaught_exceptions
from aider.versioncheck import check_version, install_from_main_branch, install_upgrade

from .dump import dump # noqa: F401


Expand Down Expand Up @@ -645,6 +644,12 @@ def get_io(pretty):
)
args.stream = False

companion = None
if git_dname:
companion = Companion(git_dname, io, args.companion_base_url, args.enable_companion)
elif args.enable_companion:
io.tool_warning("Companion functionality is not enabled. Make sure you are running aider in/with git repo.")

try:
coder = Coder.create(
main_model=main_model,
Expand Down Expand Up @@ -674,6 +679,7 @@ def get_io(pretty):
num_cache_warming_pings=args.cache_keepalive_pings,
suggest_shell_commands=args.suggest_shell_commands,
chat_language=args.chat_language,
companion=companion,
)
except ValueError as err:
io.tool_error(str(err))
Expand Down