Commit graph

1365 commits

Author SHA1 Message Date
paul-gauthier
23f972fb2e
Merge pull request #12 from paul-gauthier/handle-openai-exceptions 2023-06-03 06:31:00 -07:00
Paul Gauthier
5263367af0 added import 2023-06-03 06:23:07 -07:00
Paul Gauthier
2d1fc9f6da aider: Added a new test case test_send_with_retries_connection_error to ensure that send_with_retries handles the ConnectionError correctly and calls time.sleep once before retrying.
# Context:
USER: make another test like that, but raise requests.exceptions.ConnectionError
ASSISTANT: To add another test case for `coder.send_with_retries(model, messages)` that raises `requests.exceptions.ConnectionError`, we will modify the `tests/test_coder.py` file. We will create a new test method called `test_send_with_retries_connection_error` and use `patch` to mock the `openai.ChatCompletion.create` and `time.sleep` methods.

Here's the code change for the new test case:

```python
tests/test_coder.py
<<<<<<< ORIGINAL
if __name__ == "__main__":
    unittest.main()
=======
    @patch("aider.coder.openai.ChatCompletion.create")
    @patch("aider.coder.time.sleep")
    def test_send_with_retries_connection_error(self, mock_sleep, mock_chat_completion_create):
        # Mock the IO object
        mock_io = MagicMock()

        # Initialize the Coder object with the mocked IO and mocked repo
        coder = Coder(io=mock_io, openai_api_key="fake_key")

        # Set up the mock to raise ConnectionError on the first call and return None on the second call
        mock_chat_completion_create.side_effect = [requests.exceptions.ConnectionError("Connection error"), None]

        # Call the send_with_retries method
        coder.send_with_retries("model", ["message"])

        # Assert that time.sleep was called once
        mock_sleep.assert_called_once()

if __name__ == "__main__":
    unittest.main()
>>>>>>> UPDATED
```

This test case will ensure that `send_with_retries` handles the `ConnectionError` correctly and calls `time.sleep` once before retrying.
2023-06-03 06:22:33 -07:00
Paul Gauthier
3bdddf4b36 added import 2023-06-03 06:21:33 -07:00
Paul Gauthier
2a8e5a727c aider: Added a test case for coder.send_with_retries(model, messages) to handle RateLimitError and call time.sleep once.
# Context:
USER: add a test case for coder.send_with_retries(model, messages). it should patch openai.ChatCompletion.create so that on the first call it raises openai.error import RateLimitError. and on the 2nd call it returns None. the test should confirm that time.sleep is called 1 time.
ASSISTANT: To add the test case for `coder.send_with_retries(model, messages)`, we will modify the `tests/test_coder.py` file. We will create a new test method called `test_send_with_retries_rate_limit_error` and use `patch` to mock the `openai.ChatCompletion.create` and `time.sleep` methods.

Here's the code change for the new test case:

```python
tests/test_coder.py
<<<<<<< ORIGINAL
if __name__ == "__main__":
    unittest.main()
=======
    @patch("aider.coder.openai.ChatCompletion.create")
    @patch("aider.coder.time.sleep")
    def test_send_with_retries_rate_limit_error(self, mock_sleep, mock_chat_completion_create):
        # Mock the IO object
        mock_io = MagicMock()

        # Initialize the Coder object with the mocked IO and mocked repo
        coder = Coder(io=mock_io, openai_api_key="fake_key")

        # Set up the mock to raise RateLimitError on the first call and return None on the second call
        mock_chat_completion_create.side_effect = [openai.error.RateLimitError("Rate limit exceeded"), None]

        # Call the send_with_retries method
        coder.send_with_retries("model", ["message"])

        # Assert that time.sleep was called once
        mock_sleep.assert_called_once()

if __name__ == "__main__":
    unittest.main()
>>>>>>> UPDATED
```

This test case will ensure that `send_with_retries` handles the `RateLimitError` correctly and calls `time.sleep` once before retrying.
2023-06-03 06:20:56 -07:00
Paul Gauthier
c27483193b refac 2023-06-03 06:18:45 -07:00
Paul Gauthier
1882cf55db Handle ConnectionError 2023-06-03 06:16:33 -07:00
Paul Gauthier
4f1e1181c4 Tweaked prompt 2023-06-02 16:30:19 -07:00
Paul Gauthier
bd81ef6201 added newline to prompt 2023-06-02 12:54:28 -07:00
Paul Gauthier
d1f05ca18a Handle io=none 2023-06-01 10:55:39 -07:00
Paul Gauthier
7bc26e6762 Added --verbose support to repomap 2023-06-01 09:04:08 -07:00
Paul Gauthier
e43a48ee10 patch check_model_availability in tests 2023-06-01 08:58:35 -07:00
Paul Gauthier
2cc87a4afe aider: Added patch to setUp method and stored mock object as an instance variable.
# Context:
USER: how can i move the patch to setUp so that it is active for all tests?
ASSISTANT: To move the patch to the `setUp` method and make it active for all tests, you can use the `patch` as a context manager in the `setUp` method and store the mock object as an instance variable. Then, in the `tearDown` method, you can stop the patch. Here's how to do it:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

    def tearDown(self):
        os.chdir(self.original_cwd)
        shutil.rmtree(self.tempdir)
=======
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)
        self.patcher = patch("aider.main.Coder.check_model_availability")
        self.mock_check = self.patcher.start()
        self.mock_check.return_value = True

    def tearDown(self):
        os.chdir(self.original_cwd)
        shutil.rmtree(self.tempdir)
        self.patcher.stop()
>>>>>>> UPDATED
```

Now the patch is active for all tests, and you can remove the `with` statement from the `test_main_with_empty_dir_no_files_on_command` method:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def test_main_with_empty_dir_no_files_on_command(self):
        with patch("aider.main.Coder.check_model_availability") as mock_check:
            mock_check.return_value = True

            pipe_input = create_input(StringIO(""))
            main([], input=pipe_input, output=DummyOutput())
            pipe_input.close()
=======
    def test_main_with_empty_dir_no_files_on_command(self):
        pipe_input = create_input(StringIO(""))
        main([], input=pipe_input, output=DummyOutput())
        pipe_input.close()
>>>>>>> UPDATED
```
2023-06-01 08:54:15 -07:00
Paul Gauthier
a5414473d9 wip 2023-06-01 08:52:21 -07:00
Paul Gauthier
99693fe614 aider: Modified setUp method to patch check_model_availability with MagicMock object that always returns True.
# Context:
USER: the patch in `setUp` is not correcting forcing a return of true
ASSISTANT: To ensure that the patch in `setUp` correctly forces a return of `True`, you need to modify the `setUp` method in the `TestMain` class in the `tests/test_main.py` file. Here's the change:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        with patch("aider.main.Coder.check_model_availability") as self.mock_check:
            self.mock_check.return_value = True
        super().setUp()
=======
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        self.mock_check = MagicMock(return_value=True)
        with patch("aider.main.Coder.check_model_availability", new=self.mock_check):
            super().setUp()
>>>>>>> UPDATED
```

This change ensures that the `check_model_availability` method is patched with a `MagicMock` object that always returns `True`.
2023-06-01 08:50:55 -07:00
Paul Gauthier
4774f0518c wip 2023-06-01 08:49:55 -07:00
Paul Gauthier
2b07a334cc aider: Set return value of check_model_availability to True during test setup.
# Context:
USER: the patch in `setUp` is not correcting forcing a return of true
ASSISTANT: To fix the patch in `setUp`, you need to start the patch and set the return value to `True`. Here's the change you need to make in the `tests/test_main.py` file:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    self.mock_check = patch("aider.main.Coder.check_model_availability")
    self.mock_check.return_value = True
=======
    with patch("aider.main.Coder.check_model_availability") as self.mock_check:
        self.mock_check.return_value = True
        super().setUp()
>>>>>>> UPDATED
```

This change will ensure that the `check_model_availability` method returns `True` during the test setup.
2023-06-01 08:49:39 -07:00
Paul Gauthier
c97a0ce30a wip 2023-06-01 08:48:55 -07:00
Paul Gauthier
f4bc22e4fc wip 2023-06-01 08:46:42 -07:00
Paul Gauthier
1b49ba6e91 aider: Fixed the setUp method in the TestMain class to correctly mock the check_for_model_availability method.
# Context:
USER: E           AttributeError: <class 'aider.coder.Coder'> does not have the attribute 'check_for_model_availability'
ASSISTANT: It seems like you are trying to access the `check_for_model_availability` method of the `Coder` class, but it is not defined as an instance method. To fix this issue, you need to move the `check_model_availability` method inside the `Coder` class and update the tests accordingly.

Here are the changes you need to make:

1. Move the `
^C KeyboardInterrupt
USER: fix the `setUp`
ASSISTANT: To fix the `setUp` method in the `TestMain` class, you need to update the way you are mocking the `check_for_model_availability` method. Here are the changes you need to make:

1. Modify the `setUp` method in the `TestMain` class to correctly mock the `check_for_model_availability` method of the `Coder` class.

```python
tests/test_main.py
<<<<<<< ORIGINAL
    with patch("aider.coder.Coder.check_for_model_availability") as mock_check:
        mock_check.return_value = True
        self.mock_check = mock_check
=======
    with patch("aider.coder.Coder.check_model_availability") as mock_check:
        mock_check.return_value = True
        self.mock_check = mock_check
>>>>>>> UPDATED
```

This change will ensure that the `check_for_model_availability` method is correctly mocked during the tests.
2023-06-01 08:45:02 -07:00
Paul Gauthier
fd70d9d63b aider: Patched check_for_model_availability to always return True during setUp method execution.
# Context:
USER: in setup, patch coder.check_for_model_availability to return true
ASSISTANT: To patch the `check_for_model_availability` method in the `setUp` method of the `TestMain` class, you can use the `unittest.mock.patch` context manager. Here's the change you need to make in the `tests/test_main.py` file:

```python
tests/test_main.py
<<<<<<< ORIGINAL
    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)
=======
    from unittest.mock import MagicMock

    def setUp(self):
        os.environ["OPENAI_API_KEY"] = "deadbeef"
        self.original_cwd = os.getcwd()
        self.tempdir = tempfile.mkdtemp()
        os.chdir(self.tempdir)

        with patch("aider.coder.Coder.check_for_model_availability") as mock_check:
            mock_check.return_value = True
            self.mock_check = mock_check
>>>>>>> UPDATED
```

This will patch the `check_for_model_availability` method to always return `True` during the `setUp` method execution.
2023-06-01 08:42:18 -07:00
Paul Gauthier
1f2aa1a6c8 Auto fallback to 3.5 2023-06-01 08:39:27 -07:00
Paul Gauthier
1b046e8111 aider: Added a new method to check the availability of OpenAI models and called it in the __init__ method to ensure the main_model is available in the list of OpenAI models.
# Context:
USER: in init, call check the list of available openai models and make sure the `main_model` is in there. if not, print an err msg
ASSISTANT:
^C KeyboardInterrupt
USER: in init, call check the list of available openai models and make sure the `main_model` is in there. if not, print an err msg
ASSISTANT: To check the list of available OpenAI models and make sure the `main_model` is in there, you need to modify the `__init__` method in the `Coder` class. Here's how you can do it:

1. Add a new method `check_model_availability` to the `Coder` class that takes the `main_model` as an argument and checks if it's available in the list of OpenAI models.
2. Call this method in the `__init__` method of the `Coder` class.

Here are the changes you need to make:

```python
aider/coder.py
<<<<<<< ORIGINAL
class Coder:
    abs_fnames = None
    repo = None
    last_aider_commit_hash = None
    last_asked_for_commit_time = 0

    def __init__(
=======
class Coder:
    abs_fnames = None
    repo = None
    last_aider_commit_hash = None
    last_asked_for_commit_time = 0

    def check_model_availability(self, main_model):
        available_models = openai.Model.list()
        model_ids = [model.id for model in available_models['data']]
        if main_model not in model_ids:
            raise ValueError(f"Model {main_model} is not available. Please choose from the available models: {model_ids}")

    def __init__(
>>>>>>> UPDATED
```

```python
aider/coder.py
<<<<<<< ORIGINAL
        self.main_model = main_model
        if main_model == "gpt-3.5-turbo":
            self.io.tool_error(
                f"aider doesn't work well with {main_model}, use gpt-4 for best results."
            )

        self.set_repo(fnames)
=======
        self.check_model_availability(main_model)
        self.main_model = main_model
        if main_model == "gpt-3.5-turbo":
            self.io.tool_error(
                f"aider doesn't work well with {main_model}, use gpt-4 for best results."
            )

        self.set_repo(fnames)
>>>>>>> UPDATED
```

These changes will add a new method `check_model_availability` to the `Coder` class and call it in the `__init__` method to ensure the `main_model` is available in the list of OpenAI models. If not, it will raise a `ValueError` with an appropriate error message.
2023-06-01 08:36:48 -07:00
Paul Gauthier
d95d4d931d copy 2023-06-01 06:19:08 -07:00
Paul Gauthier
93dae2c108 copy 2023-06-01 06:16:16 -07:00
Paul Gauthier
354a29f6be copy 2023-06-01 06:14:54 -07:00
Paul Gauthier
3b2c8c81ca copy 2023-05-31 16:29:53 -07:00
Paul Gauthier
3e384dd35b copy 2023-05-31 16:26:51 -07:00
Paul Gauthier
755cabe54f Merge remote-tracking branch 'origin/main' 2023-05-31 15:34:29 -07:00
paul-gauthier
d07d72c2d6
Update README.md 2023-05-31 09:33:59 -07:00
paul-gauthier
1031320836
Merge pull request #9 from jevon/patch-1
Update README.md
2023-05-31 08:25:21 -07:00
Jevon MacDonald
e1df502f34
Update README.md
Disambiguating the format to include OpenAI API token in ~/.aider.config.yml
2023-05-31 11:46:25 -03:00
Paul Gauthier
5d4fd15a21 do isort first 2023-05-30 13:55:28 -07:00
Paul Gauthier
77d20b6819 Fixed TAGS_CACHE 2023-05-30 13:54:56 -07:00
Paul Gauthier
5801bd9ca4 aider: Moved TAGS_CACHE into the RepoMap class.
# Context:
USER: move `TAGS_CACHE` into the class
ASSISTANT: To move the `TAGS_CACHE` into the `RepoMap` class, I will make the following changes:

```python
aider/repomap.py
<<<<<<< ORIGINAL
# Global cache for tags
TAGS_CACHE = {}
=======
>>>>>>> UPDATED
```

```python
aider/repomap.py
<<<<<<< ORIGINAL
class RepoMap:
    ctags_cmd = ["ctags", "--fields=+S", "--extras=-F", "--output-format=json"]

    def __init__(self, use_ctags=None, root=None, main_model="gpt-4"):
=======
    class RepoMap:
        ctags_cmd = ["ctags", "--fields=+S", "--extras=-F", "--output-format=json"]
        TAGS_CACHE = {}

        def __init__(self, use_ctags=None, root=None, main_model="gpt-4"):
>>>>>>> UPDATED
```

Now, the `TAGS_CACHE` is a class attribute of the `RepoMap` class.
2023-05-30 13:53:31 -07:00
Paul Gauthier
ca74eee2f9 Allow GPT to omit the filename from edit blocks, if an earlier block provided it 2023-05-30 11:45:21 -07:00
Paul Gauthier
ef22abd8be copy 2023-05-30 08:01:49 -07:00
Paul Gauthier
9cb793c82d reverted c9ebbdf0 2023-05-30 07:58:54 -07:00
Paul Gauthier
b359134f86 reverted a4e57e17b5 2023-05-30 07:58:31 -07:00
Paul Gauthier
0d568e2b59 screencast.svg 2023-05-30 06:42:05 -07:00
Paul Gauthier
6b4ce832b3 screencast.svg 2023-05-30 06:39:19 -07:00
Paul Gauthier
eb6aba8726 screencast.svg 2023-05-30 06:25:52 -07:00
Paul Gauthier
a4e57e17b5 aider: Added completions_height parameter to InputOutput class and passed it from aider/main.py.
# Context:
USER: pass it to `InputOutput` and store as a self. var
ASSISTANT: I will modify the `InputOutput` class in `aider/io.py` to accept the `completions_height` parameter and store it as an instance variable.

Here's the change to add the `completions_height` parameter to the `InputOutput` class:

```python
aider/io.py

^C KeyboardInterrupt
USER: `aider/io.py`
ASSISTANT: I will modify the `InputOutput` class in `aider/io.py` to accept the `completions_height` parameter and store it as an instance variable.

Here's the change to add the `completions_height` parameter to the `InputOutput` class:

```python
aider/io.py
<<<<<<< ORIGINAL
    def __init__(
        self,
        pretty=True,
        yes=False,
        input_history_file=None,
        chat_history_file=None,
        input=None,
        output=None,
        user_input_color="blue",
        tool_output_color=None,
        tool_error_color="red",
    ):
=======
    def __init__(
        self,
        pretty=True,
        yes=False,
        input_history_file=None,
        chat_history_file=None,
        input=None,
        output=None,
        user_input_color="blue",
        tool_output_color=None,
        tool_error_color="red",
        completions_height=10,
    ):
        self.completions_height = completions_height
>>>>>>> UPDATED
```

Now, you need to pass the `completions_height` value from `aider/main.py` to the `InputOutput` class when creating an instance:

```python
aider/main.py
<<<<<<< ORIGINAL
    io = InputOutput(
        args.pretty,
        args.yes,
        args.input_history_file,
        args.chat_history_file,
        input=input,
        output=output,
        user_input_color=args.user_input_color,
        tool_output_color=args.tool_output_color,
        tool_error_color=args.tool_error_color,
    )
=======
    io = InputOutput(
        args.pretty,
        args.yes,
        args.input_history_file,
        args.chat_history_file,
        input=input,
        output=output,
        user_input_color=args.user_input_color,
        tool_output_color=args.tool_output_color,
        tool_error_color=args.tool_error_color,
        completions_height=args.completions_height,
    )
>>>>>>> UPDATED
```

Now, the `completions_height` value is passed to the `InputOutput` class and stored as an instance variable.
2023-05-29 17:33:39 -07:00
Paul Gauthier
c9ebbdf0c0 aider: Added a --completions-height command line parameter to aider/main.py.
# Context:
USER: add a --completions-height cmd line param to `aider/main.py`
ASSISTANT: I will add a `--completions-height` command line parameter to `aider/main.py`. This parameter will allow users to set the height of the completions displayed in the terminal.

Here's the change to add the `--completions-height` parameter:

```python
aider/main.py
<<<<<<< ORIGINAL
    parser.add_argument(
        "--no-dirty-commits",
        action="store_false",
        dest="dirty_commits",
        help="Disable dirty commit of changes",
    )
=======
    parser.add_argument(
        "--no-dirty-commits",
        action="store_false",
        dest="dirty_commits",
        help="Disable dirty commit of changes",
    )
    parser.add_argument(
        "--completions-height",
        type=int,
        default=10,
        metavar="COMPLETIONS_HEIGHT",
        help="Set the height of the completions displayed in the terminal (default: 10)",
    )
>>>>>>> UPDATED
```

This will add a new command line argument `--completions-height` with a default value of 10. Users can now set the height of the completions displayed in the terminal by providing a value for this argument.
2023-05-29 17:32:02 -07:00
Paul Gauthier
a7ab3d5d78 screencast.svg 2023-05-29 17:08:06 -07:00
Paul Gauthier
e25cf11aff stronger prompt against editing r/o files 2023-05-29 15:02:51 -07:00
Paul Gauthier
728d3f76a8 new gif 2023-05-29 14:55:04 -07:00
Paul Gauthier
765e0886f9 new gif 2023-05-29 12:21:43 -07:00
Paul Gauthier
2ff24a51dd bold italic 2023-05-29 12:13:28 -07:00
Paul Gauthier
fbb14b2823 aider: Changed pygments.literal.string to appear in inverse colors.
# Context:
USER: no. let's make pygments.literal.string be in inverse colors
ASSISTANT: To make `pygments.literal.string` appear in inverse colors, we need to modify the `aider/io.py` file. Update the `style` dictionary in the `get_input` method:

```python
aider/io.py
<<<<<<< ORIGINAL
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": f"underline {self.user_input_color}"})
=======
        if self.user_input_color:
            style = Style.from_dict({"": self.user_input_color, "pygments.literal.string": f"reverse {self.user_input_color}"})
>>>>>>> UPDATED
```

This change will apply the inverse color style to ticked words in the `PromptSession`.
2023-05-29 11:49:50 -07:00