FileGenerator
ARFA Generator работает итеративно emit → write → cleanup, что позволяет нескольким плагинам последовательно изменять файлы, пока кодовая база не стабилизируется, а затем выполняются чекеры для проверки корректности и остальной жизненный цикл.
ts | Режим CI, по умолчанию |
ts | Корневая директория для glob-паттернов плагинов и watch-режима. Генератор не меняет файлы за её пределами |
ts | Плагины, которые предлагают файлы для записи. Выполняются в порядке объявления на каждой итерации |
ts | Проверки, которые запускаются после завершения работы плагинов и каскадных изменений |
ts | Функция форматирования содержимого файлов, предложенных плагинами. Вызывается перед сравнением с содержимым на диске и записью |
ts | Общий текст, добавляемый в начало каждого сгенерированного файла, если плагин не указал |
ts | Абсолютный путь к файлу с результатами запусков в формате JSONL, при Размещайте файл за пределами |
API
runFullCycle
Запускает один полный проход генерации с проверками и жизненным циклом.
runFullCycle(params?: {
onStart?: () => void;
afterCheckers?: (args: TypeAfterCheckersArgs) => void | Promise<void>;
afterFinish?: (args: TypeAfterFinishArgs) => void | Promise<void>;
}): Promise<void>
type TypeAfterCheckersArgs = {
changedFiles: Array<{ relativePath: string; absolutePath: string }>;
deletedFiles: Array<{ relativePath: string; absolutePath: string }>;
isFullGeneration: boolean;
};
type TypeAfterFinishArgs = TypeAfterCheckersArgs & { logs: TypeLogs };onStart — синхронный колбэк перед запуском плагинов.
afterCheckers — синхронный или асинхронный колбэк после завершения работы плагинов и чекеров. Может использоваться для запуска бандлера и других не изменяющих код операций.
afterFinish — синхронный или асинхронный колбэк после afterCheckers. Получает те же данные и logs, включая ошибки из предыдущего колбэка. Подходит для вывода логов и произвольной логики, например отправки сигнала браузеру обновить страницу или запуска LLM-агента (то есть допускаются изменяющие код операции, они запустят новый цикл генерации, но только в watch-режиме). Ошибки из этого колбэка выводятся в консоль в обход logs и сохраняются в JSONL.
changedFiles содержит существующие файлы, изменённые плагинами или пользователем в рамках watch-процесса, а deletedFiles — удалённые файлы.
isFullGeneration для данного метода равен true.
startWatch
Начинает следить за изменениями в rootDir, не запуская первоначальную генерацию. При ci: true сразу возвращает завершённый Promise.
startWatch(params?: {
onStart?: () => void;
afterCheckers?: (args: TypeAfterCheckersArgs) => void | Promise<void>;
afterFinish?: (args: TypeAfterFinishArgs) => void | Promise<void>;
aggregationTimeout?: number;
}): Promise<void>onStart — синхронный колбэк, вызываемый после накопления изменений за aggregationTimeout, перед запуском плагинов.
isFullGeneration в данном методе равен false, а изменения файлов во время afterFinish вызовут новый полный цикл генерации.
aggregationTimeout (в миллисекундах, 0 по умолчанию) полезен в качестве debounce — для предотвращения лишних срабатываний при быстрых изменениях или настроенных File Watchers в IDE (например, переформатирование при сохранении файла).
startWatch следит за изменениями только в rootDir. Изменение внешних файлов вроде tsconfig, .env или зависимостей не перезапускает генерацию, как и изменение конфигурации самого генератора — в этом случае нужен ручной перезапуск процесса.
Дополнительно
Это долгоживущий процесс, который практически никогда не выбрасывает исключений, а сохраняет ошибки в логи для вывода в консоль и в JSONL. Таким образом, ошибки кода можно исправлять "на лету"
stopWatch
Останавливает наблюдение, но не отменяет уже выполняющийся цикл генерации.
stopWatch(): Promise<void>getControlledFiles
Возвращает список существующих файлов, контролируемых генератором, включая устаревшие файлы, которые плагины планируют удалить в cleanup фазе.
getControlledFiles(): Promise<Array<{
relativePath: string;
absolutePath: string;
}>>const files = await generator.getControlledFiles();
console.log(files.map(({relativePath}) => relativePath));removeGeneratedFiles
Вызывает настроенные плагины, но вместо создания файлов — удаляет их. Полезен при изменении конфигурации. Пустые папки, созданные плагинами, могут остаться: рекурсивное удаление папок не выполняется.
removeGeneratedFiles(): Promise<void>Пример: Codex в afterFinish
В watch-режиме при наличии // AGENT в изменённых файлах запускается Codex, который выполняет задачу и удаляет маркер для избежания бесконечного цикла
async afterFinish({ changedFiles }) {
const codex = new Codex();
const thread = codex.startThread();
for (const { absolutePath } of changedFiles || []) {
const content = fs.readFileSync(absolutePath, 'utf8');
const prompt = content.match(/\/\/ AGENT (.+)/)?.[1];
if (!prompt) continue;
await thread.run(`
File: ${absolutePath}
Task: ${prompt}
Edit the file directly and remove the completed // AGENT command.
`);
}
},
Запустить Sandbox
[ARFA-GEN] finished in 0ms