Aider

Каждый, кто пытался автоматизировать локальный рефакторинг кода с помощью больших языковых моделей (LLM), неизбежно наступал на одни и те же грабли. Вы просите локальную модель (например, крутейшую qwen2.5-coder) выдать изменения в формате Git Unified Diff. Модель соглашается, начинает стримить дифф в ваш терминал... и тут начинается ад.

Локальная LLM «плывет» в математике и выдает случайные числа в метаданных @@ -1,3 +1,4 @@. Эмулятор терминала принудительно переносит длинные строки (Word Wrap), намертво ломая синтаксис префиксов + и -. А сама модель внезапно решает прокомментировать свои действия человеческим языком прямо внутри патча, превращая каноничный файл изменений в мусор. В итоге git apply захлебывается ошибками вида error: патч поврежден на строке N...

Но индустрия уже нашла решение. Aider — консольный AI-агент, который кардинально меняет подход к генерации патчей и рефакторингу. Попробуем получить от него кристально чистый .patch файл в Ubuntu.

Что под капотом: Как Aider решает проблему контекста

Главная фишка Aider — он не просто слепо скармливает файлы модели. Он строит семантическую карту репозитория на базе абстрактного синтаксического дерева (AST).

1. Парсинг через Tree-sitter

Вместо капризного текстового поиска Regex, Aider использует мощную open-source утилиту grep-coder, развернутую на движке Tree-sitter. Он рекурсивно обходит ваш проект (например, директорию src/) и строит граф вызовов:

  • Извлекает сигнатуры всех классов, интерфейсов, методов и функций.
  • Фиксирует точные связи и зависимости (какой модуль импортирует конкретную утилиту и где вызывается ядро движка).

2. Умное сжатие контекста

Если скормить LLM весь проект целиком, вы мгновенно сожжете лимит токенов (контекстное окно), а модель начнет путаться в деталях. Aider решает это элегантно. На основе построенного графа вызовов он создает компактную карту зависимостей репозитория.

Когда вы добавляете конкретный файл в работу, ИИ получает не только его код, но и высокоуровневую выжимку: какие внешние компоненты зависят от этого файла. Это позволяет локальной qwen2.5-coder-long «видеть» архитектуру всего проекта, тратя на это минимум токенов.

3. Отказ от сырых диффов: SEARCH/REPLACE блоки

Чтобы локальная модель не сходила с ума, высчитывая байты и номера строк для Unified Diff, Aider заставляет её общаться в формате SEARCH/REPLACE блоков. Модель присылает строго изолированный кусок:

<<<<<<< SEARCH
      destroy() {
        performCleanup()
      }
=======
      destroy() {
        unsubscribeEffect()
        performCleanup()
      }
>>>>>>> REPLACE

Aider сам находит этот фрагмент в файле на диске, сопоставляет его с AST-деревом и вносит изменения. Никаких слепых зон и поломок синтаксиса.

Лабораторный воркшоп: Генерируем идеальный многофайловый патч в Ubuntu

Давайте применим Aider на практике для генерации патча для двух файлов в репозитории reactive-engine под управлением Ubuntu. Изменения должны остаться в виде .patch файла, без автоматического засорения истории Git (без автокоммитов).

Шаг 1. Разворачиваем изолированное окружение через uv

Современные дистрибутивы Linux защищают системный Python (особенно новые версии вроде 3.14) от захламления сторонними пакетами. Чтобы обойти это, используем ультрабыстрый менеджер пакетов на Rust — uv от Astral.

Устанавливаем uv в систему:

curl -LsSf https://astral.sh/uv/install.sh | sh

Применяем новые пути окружения в текущей консоли:

source $HOME/.local/bin/env

Шаг 2. Запускаем локальный ИИ-сервер

В соседней вкладке терминала поднимаем нашу локальную модель, которая будет крутиться на мощностях CPU/VRAM:

ollama run qwen2.5-coder-long

Шаг 3. Запуск Aider в режиме генератора патчей

Возвращаемся в исходную вкладку с проектом reactive-engine. Запускаем Aider через uv, принудительно заставив его использовать стабильный Python 3.12, а также передаем флаг --no-auto-commits (запрет на автокоммиты) и выставляем формат диффа:

uv run --python 3.12 --with aider-chat aider --model ollama/qwen2.5-coder-long --edit-format diff --no-auto-commits

Шаг 4. Интерактивная сессия рефакторинга

Aider загрузится, просканирует проект и выдаст строку приглашения diff>. Действуем строго по шагам:

  1. Добавляем в контекст графа вызовов первый файл (утилиты)
diff> /add src/utils/index.ts
  1. Добавляем второй файл (ядро)
diff> /add src/core/core.ts
  1. Когда файлы подсветились зеленым, отправляем нашу архитектурную задачу на русском языке:
diff> Оптимизируй метод .destroy() в файле src/core/core.ts для предотвращения утечек памяти в подписках сигналов. Также добавь в самый конец файла src/utils/index.ts новую отдельную строку комментария: // Тестовый комментарий от ИИ для проверки Word Wrap.

Aider отправляет пакет, локальная Ollama думает, стримит блоки изменений, и утилита мгновенно применяет их к коду на диске. Пишем в чат /exit (или жмем Ctrl+D) для выхода.

Шаг 5. Экспорт кристально чистого патча

В вашем репозитории файлы физически изменились, но Git-история чиста — коммитов нет. Теперь мы заставляем родной, локальный движок Git вашей Ubuntu сгенерировать патч:

git diff > qwen_refactoring_changes.patch

Резюме

Парсить экраны терминала через мультиплексоры PTY — веселое хакерское приключение, но для построения надежного конвейера автоматизации ИИ-разработки нужен контроль на уровне синтаксических деревьев и Git API. Связка uv + Aider + Ollama под управлением Ubuntu превращает капризные локальные LLM в хирургически точный инструмент рефакторинга, генерирующий патчи высокого качества.

Автоматизация Aider средствами Bash

Мы напишем автоматический Bash-скрипт ai_generate_patch.sh, который будет принимать файлы и промпт как аргументы командной строки, сам передавать их ИИ-агенту через встроенный неинтерактивный флаг Aider --message, а на выходе сразу выплевывать готовый, кристально чистый .patch файл.

Шаг 1: Создание автоматического скрипта ai_generate_patch.sh

Создайте новый файл ai_generate_patch.sh прямо в корне вашего проекта и вставьте в него этот промышленный код:

#!/bin/bash

# --- ЦВЕТА ДЛЯ ЛОГИРОВАНИЯ ---
GREEN='\033[32m'
BLUE='\033[34m'
YELLOW='\033[33m'
RED='\033[31m'
RESET='\033[0m'

echo -e "${BLUE}=== ЗАПУСК АВТОНОМНОГО ИИ-ГЕНЕРАТОРА ПАТЧЕЙ ===${RESET}"

# Переменные окружения для локальной Ollama
export OLLAMA_API_BASE="http://127.0.0.1:11434"
export AIDER_MODEL="ollama/qwen2.5-coder-long"

# Проверяем, запущен ли сервер Ollama
if ! curl -s http://127.0.0 > /dev/null; then
    echo -e "${RED}[Ошибка] Локальный сервер Ollama не запущен! Выполните 'ollama run qwen2.5-coder-long' в другой вкладке.${RESET}"
    exit 1
fi

# Жестко прописываем наши целевые файлы для отладки (или можно принимать из аргументов)
FILE1="src/utils/index.ts"
FILE2="src/core/core.ts"
OUTPUT_PATCH="qwen_refactoring_changes.patch"

# Проверяем наличие файлов в текущем каталоге
if [ ! -f "$FILE1" ] || [ ! -f "$FILE2" ]; then
    echo -e "${RED}[Ошибка] Запуск должен происходить из корня репозитория, где лежат $FILE1 и $FILE2!${RESET}"
    exit 1
fi

# Формируем четкое текстовое задание для ИИ
AI_TASK="Оптимизируй метод .destroy() в файле src/core/core.ts для предотвращения утечек памяти в подписках сигналов. Также добавь в самый конец файла src/utils/index.ts новую строку комментария: // Тестовый комментарий от ИИ для проверки Word Wrap. Выведи только патч, без лишних слов."

echo -e "${YELLOW}[Пайплайн] Сбрасываем старые незакоммиченные тесты в Git...${RESET}"
git checkout -- "$FILE1" "$FILE2" &>/dev/null

echo -e "${YELLOW}[Пайплайн] Инициализация Aider. Построение графа вызовов через Tree-sitter...${RESET}"

# 🚀 ОДНОРАЗОВЫЙ ЗАПУСК AIDER (Флаг --message выполняет команду без входа в интерактивный чат)
uv run --python 3.12 --with aider-chat aider \
    --model "$AIDER_MODEL" \
    --edit-format diff \
    --no-auto-commits \
    --message "$AI_TASK" \
    "$FILE1" "$FILE2"

if [ $? -eq 0 ]; then
    echo -e "\n${YELLOW}[Пайплайн] Изменения успешно внесены в код на диске.${RESET}"
    echo -e "${YELLOW}[Пайплайн] Выгружаем легитимный патч через системный git diff...${RESET}"

    # Генерируем патч силами локального Git
    git diff > "$OUTPUT_PATCH"

    if [ -s "$OUTPUT_PATCH" ]; then
        echo -e "${GREEN}[УСПЕХ] Кристально чистый патч успешно создан и сохранен:${RESET}"
        echo -e "        ${GREEN}$PWD/$OUTPUT_PATCH${RESET}"

        # ВРЕМЕННО: Откатываем изменения в кодовой базе, оставляя только готовый чистый патч на диске
        git checkout -- "$FILE1" "$FILE2" &>/dev/null
    else
        echo -e "${RED}[Ошибка] Патч-файл оказался пустым. Возможно, ИИ не внес изменений.${RESET}"
        exit 1
    fi
else
    echo -e "${RED}[Ошибка] Сбой во время работы ИИ-агента Aider.${RESET}"
    exit 1
fi

Шаг 2: Выдача прав и контрольный запуск

  1. Сделайте скрипт исполняемым в терминале Ubuntu:
chmod +x ai_generate_patch.sh
  1. Убедитесь, что в соседней вкладке запущена модель (ollama run qwen2.5-coder-long)
  2. Запускайте конвейер одной командой прямо из корня проекта:
./ai_generate_patch.sh

Системные и программные требования для ИИ-агента генерации патчей

Документ содержит полный перечень спецификаций, необходимых для стабильной локальной работы пайплайна автоматического рефакторинга на базе uv, Aider и Ollama.

1. Аппаратные требования (Hardware)

  • Процессор (CPU): AMD Ryzen AI 9 (или любой современный CPU с аналогичной многопоточной производительностью и обязательной аппаратной поддержкой инструкций AVX2). Необходим для быстрой локальной квантизации и прогрева контекста языковой модели.
  • Оперативная память (RAM): Минимум 32 ГБ (настоятельно рекомендуется 64 ГБ). Тяжелые многофайловые рефакторинги разворачивают семантическую карту проекта (Repo Map) объемом 22k+ токенов, что лавинообразно расширяет размер KV-кэша в памяти.

2. Требования к операционной системе (OS)

  • Дистрибутив Linux: Ubuntu Linux (стабильные версии 22.04 LTS / 24.04 LTS или новее).
  • Командная оболочка (Shell): Bash (скрипты автоматизации используют специфичный синтаксис подстановки массивов, утилиты обработки строк и парсинга переменных).

3. Программные зависимости (Software)

Для успешного выполнения неинтерактивного ИИ-конвейера в операционной системе должны быть глобально доступны следующие инструменты:

  1. Git CLI:
    • Целевой проект автоматизации должен быть инициализирован как Git-репозиторий (git init).
    • Используется для сквозного сброса незакоммиченных изменений на диске и выгрузки эталонного артефакта патча силами локального движка git diff.
  2. Ollama:
    • Локальный ИИ-сервер, обслуживающий запросы на порту 127.0.0.1:11434.
    • В локальном кэше сервера должна быть загружена весовая модель qwen2.5-coder-long (или её легковесные альтернативы для быстрых тестов: qwen2.5-coder:7b/14b).
  3. Astral uv:
    • Высокопроизводительный менеджер пакетов, написанный на Rust.
    • Используется для нативного скачивания, изоляции и запуска чистого окружения Python 3.12 на лету, полностью изолируя конвейер от системных ограничений вашего нового Python 3.14.
  4. Базовые системные утилиты Linux (POSIX):
    • curl — для пинга и верификации сокетов API локальной Ollama.
    • sed и tr — для очистки строки файлов из конфига от запятых и лишних пробелов.
    • grep и xargs — для неинтерактивного парсинга параметров из .env.development.