11 KiB
Memory Import Processor
Memory Import Processor — это функция, которая позволяет модуляризовать ваши контекстные файлы (например, QWEN.md), импортируя содержимое из других файлов с помощью синтаксиса @file.md.
Обзор
Эта функция позволяет разбивать большие контекстные файлы (например, QWEN.md) на более мелкие и удобные в управлении компоненты, которые можно повторно использовать в разных контекстах. Import processor поддерживает как относительные, так и абсолютные пути, а также включает встроенные меры безопасности для предотвращения циклических импортов и обеспечения безопасности доступа к файлам.
Синтаксис
Используйте символ @, за которым следует путь к файлу, который вы хотите импортировать:
# Основной файл QWEN.md
Это основной контент.
@./components/instructions.md
Здесь еще контент.
@./shared/configuration.md
Поддерживаемые форматы путей
Относительные пути
@./file.md— Импорт из той же директории@../file.md— Импорт из родительской директории@./components/file.md— Импорт из поддиректории
Абсолютные пути
@/absolute/path/to/file.md— Импорт с использованием абсолютного пути
Примеры
Базовый импорт
# My QWEN.md
Добро пожаловать в мой проект!
@./getting-started.md
## Возможности
@./features/overview.md
Вложенные импорты
Импортируемые файлы могут сами содержать импорты, создавая вложенную структуру:
# main.md
@./header.md
@./content.md
@./footer.md
# header.md
# Заголовок проекта
@./shared/title.md
Функции безопасности
Обнаружение циклических импортов
Процессор автоматически обнаруживает и предотвращает циклические импорты:
# file-a.md
@./file-b.md
# file-b.md
@./file-a.md <!-- Это будет обнаружено и предотвращено -->
Безопасность доступа к файлам
Функция validateImportPath гарантирует, что импорт разрешен только из указанных директорий, предотвращая доступ к чувствительным файлам за пределами разрешенной области.
Максимальная глубина импорта
Чтобы предотвратить бесконечную рекурсию, можно настроить максимальную глубину импорта (по умолчанию: 5 уровней).
Обработка ошибок
Отсутствующие файлы
Если указанный файл не существует, импорт завершится с ошибкой, и в выводе появится комментарий с описанием ошибки.
Ошибки доступа к файлам
Проблемы с правами доступа или другие ошибки файловой системы обрабатываются корректно с выводом соответствующих сообщений об ошибках.
Определение областей кода
Процессор импорта использует библиотеку marked для определения блоков кода и встроенных фрагментов кода, чтобы корректно игнорировать @ импорты внутри этих областей. Это обеспечивает надежную обработку вложенных блоков кода и сложных структур Markdown.
Структура дерева импорта
Процессор возвращает дерево импорта, которое отображает иерархию импортированных файлов. Это помогает пользователям отлаживать проблемы с их контекстными файлами, показывая, какие файлы были прочитаны и каковы их отношения импорта.
Пример структуры дерева:
Memory Files
L project: QWEN.md
L a.md
L b.md
L c.md
L d.md
L e.md
L f.md
L included.md
Дерево сохраняет порядок, в котором файлы были импортированы, и показывает полную цепочку импорта для целей отладки.
Сравнение с подходом Claude Code /memory (claude.md)
Функция /memory в Claude Code (как показано в claude.md) создает плоский линейный документ путем объединения всех включенных файлов, всегда помечая границы файлов четкими комментариями и именами путей. Она не отображает явно иерархию импортов, но LLM получает все содержимое файлов и пути, что достаточно для восстановления иерархии при необходимости.
Примечание: Импортное дерево主要用于开发过程中的清晰度,对LLM消费的相关性有限。
Справочник API
processImports(content, basePath, debugMode?, importState?)
Обрабатывает import statements в содержимом файла контекста.
Параметры:
content(string): Содержимое для обработки импортовbasePath(string): Путь к директории, где находится текущий файлdebugMode(boolean, optional): Включить ли debug logging (по умолчанию: false)importState(ImportState, optional): Состояние для отслеживания и предотвращения циклических импортов
Возвращает: Promise - Объект, содержащий обработанное содержимое и дерево импортов
ProcessImportsResult
interface ProcessImportsResult {
content: string; // Обработанное содержимое с разрешенными импортами
importTree: MemoryFile; // Древовидная структура, показывающая иерархию импортов
}
MemoryFile
interface MemoryFile {
path: string; // Путь к файлу
imports?: MemoryFile[]; // Прямые импорты в порядке их импорта
}
validateImportPath(importPath, basePath, allowedDirectories)
Проверяет пути импорта, чтобы убедиться, что они безопасны и находятся в разрешенных директориях.
Параметры:
importPath(string): Путь импорта для проверкиbasePath(string): Базовая директория для разрешения относительных путейallowedDirectories(string[]): Массив разрешенных путей директорий
Возвращает: boolean - Допустим ли путь импорта
findProjectRoot(startDir)
Находит корень проекта, выполняя поиск директории .git вверх от указанной стартовой директории. Реализована как async функция с использованием неблокирующих API файловой системы, чтобы избежать блокировки event loop в Node.js.
Параметры:
startDir(string): Директория, с которой начинается поиск
Возвращает: Promise - Директория корня проекта (или стартовая директория, если .git не найдена)
Рекомендации
- Используйте понятные имена файлов для импортируемых компонентов
- Держите импорты поверхностными — избегайте глубоко вложенных цепочек импорта
- Документируйте структуру — поддерживайте четкую иерархию импортируемых файлов
- Тестируйте импорты — убедитесь, что все указанные файлы существуют и доступны
- Используйте относительные пути когда это возможно, для лучшей переносимости
Устранение неполадок
Частые проблемы
- Импорт не работает: Проверьте, что файл существует и путь указан верно
- Предупреждения о циклическом импорте: Пересмотрите структуру импортов на наличие циклических ссылок
- Ошибки доступа: Убедитесь, что файлы доступны для чтения и находятся в разрешённых директориях
- Проблемы с разрешением путей: Используйте абсолютные пути, если относительные не разрешаются корректно
Режим отладки
Включите режим отладки, чтобы видеть подробный лог процесса импорта:
const result = await processImports(content, basePath, true);