Add Reference Spec

This commit is contained in:
dimitrievgs 2025-09-25 01:40:16 +03:00
parent 24ac848ab9
commit 8e54a65fa9

View File

@ -0,0 +1,127 @@
# Техническое Задание: Система Ссылок и Раскрытия Контента в LLM Agent Plugin Obsidian
## 1. Введение
Данный документ описывает функциональность системы ссылок и механизм раскрытия контента в плагине LLM Agent для Obsidian. Целью является предоставление пользователю возможности динамически включать содержимое файлов (заметок, документов, кода) и шаблонов (специальных промптов) в свои запросы к LLM-агенту, используя удобный синтаксис ссылок, автодополнение и визуальное представление.
Система вдохновлена подходом таких инструментов, как Continue.dev, но адаптирована под экосистему Obsidian и требования пользователя.
## 2. Терминология
* **Ссылка:** Специальный синтаксис в сообщении пользователя, указывающий на файл или промпт в хранилище Obsidian.
* **Одинарная ссылка:** Ссылка, содержимое которой раскрывается только один раз, при отправке текущего сообщения на сервер. В последующих сообщениях эта ссылка остаётся в своём исходном виде. Имеет префикс `@` (для файлов) или `#` (для промптов).
* **Постоянная ссылка (Persistent Reference):** Ссылка, содержимое которой раскрывается при отправке *любого* сообщения пользователя, если она присутствовала в предыдущих сообщениях. Предназначена для поддержания постоянного контекста. Имеет префикс `@@` (для файлов) или `##` (для промптов).
* **Промпт:** Markdown-файл, содержащий шаблон запроса или часть запроса для LLM. Хранится в специально выделенной папке.
* **Шаблонная ссылка (Template Reference):** Ссылка внутри *промпта* на другой промпт. Использует синтаксис `@{prompt_name}`. Поддерживает только один уровень вложенности (нет рекурсии).
* **Бокс ссылки (Reference Box):** Визуальное представление ссылки в поле ввода (contenteditable div) после её выбора пользователем через автодополнение. Содержит иконку и имя.
* **Раскрытие контента (Content Expansion):** Процесс замены ссылки её фактическим содержимым файла или промпта перед отправкой запроса LLM-агенту.
* **Снапшот (Snapshot):** Сохранённое содержимое файла на момент его раскрытия. (**TODO**: будет реализовано позднее в отдельной таблице БД.)
## 3. Требования к Функциональности
### 3.1. Синтаксис Ссылок в Поле Ввода
Система должна распознавать следующие типы ссылок:
* **Ссылки на файлы:**
* `@<имя_файла>`: Одинарная ссылка на файл.
* `@@<имя_файла>`: Постоянная ссылка на файл.
* **Ссылки на промпты:**
* `#<имя_промпта>`: Одинарная ссылка на промпт.
* `##<имя_промпта>`: Постоянная ссылка на промпт.
**Правила именования:**
* `<имя_файла>` и `<имя_промпта>` должны соответствовать `basename` файла (название файла без расширения и пути).
* Ссылки могут содержать пробелы, если имя файла/промпта заключено в кавычки, например, `@ "My Awesome File"`. В противном случае пробелы являются разделителями.
### 3.2. Автодополнение Ссылок (Autocomplete)
При вводе пользователем символов `@`, `@@`, `#`, `##` в поле ввода сообщения (ChatPanel), система должна показывать выпадающий список (autocomplete) релевантных файлов или промптов.
* **Триггеры:** Ввод `@` или `#`. Автодополнение должно появляться, как только пользователь начинает вводить имя после префикса.
* **Фильтрация:** Список должен фильтроваться по мере ввода имени файла/промпта.
* **Опции:** Каждая опция в списке автодополнения должна включать:
* Иконку (соответствующую типу файла или промпту).
* Имя файла/промпта.
* Путь к файлу (относительно корня хранилища Obsidian, может быть сокращён).
* **Навигация:** Пользователь должен иметь возможность навигировать по списку с помощью клавиш `ArrowUp`/`ArrowDown`.
* **Выбор:** Выбор элемента осуществляется по `Enter` или `Tab` (или кликом).
* **Позиционирование:** Выпадающий список должен позиционироваться динамически:
* Если есть место, он появляется под курсором.
* Если места снизу недостаточно, он появляется над курсором.
* Должен учитывать границы экрана.
### 3.3. Визуальное Представление Ссылок (Reference Boxes)
После выбора элемента из списка автодополнения, текстовое представление ссылки в поле ввода должно заменяться на визуальный "бокс ссылки".
* **Состав бокса:** Иконка ( Obsidian icon, соответствующая типу) и имя файла/промпта.
* **Стилизация:**
* Боксы для файлов (`@`/`@@`) и промптов (`#`/`##`) должны иметь отличающиеся цветовые схемы (фон, рамка).
* Боксы для одинарных ссылок (`@`/`#`) и постоянных ссылок (`@@`/`##`) должны иметь отличающиеся стили (например, более яркий фон/толстая рамка для постоянных).
* **Интерактивность:** При клике на бокс, должна быть предусмотрена возможность предпросмотра содержимого файла/промпта (функциональность **TODO** для будущих итераций).
* **Редактирование:** Пользователь должен иметь возможность удалять или редактировать боксы (например, нажать Delete/Backspace).
* **Сохранение информации:** Бокс должен содержать данные, достаточные для восстановления исходной ссылки (тип, имя, путь, признак постоянной ссылки).
### 3.4. Раскрытие Контента перед Отправкой на Сервер
Перед отправкой сообщения пользователя на backend LLM-агента, все ссылки в сообщении должны быть раскрыты.
* **Одинарные ссылки (`@`/`#`):** Содержимое файла/промпта раскрывается и вставляется *только* в текущее отправляемое сообщение. В истории чата (в поле ввода) ссылка остаётся как бокс или текстовое представление.
* **Постоянные ссылки (`@@`/`##`):** Содержимое файла/промпта раскрывается и вставляется в текущее отправляемое сообщение. Более того, при загрузке истории для любого узла, если в этой истории есть сообщения пользователя с *постоянными* ссылками, их содержимое также должно быть раскрыто. Это обеспечивает поддержание постоянного контекста для LLM.
* **Форматирование раскрытого контента:** Раскрытое содержимое должно быть обернуто специальными маркерами для ясности, например:
```
--- Содержимое файла: my-file.md ---
(текст файла)
--- Конец файла: my-file.md ---
```
* **Размер файла:** Нет явных ограничений на размер файла для раскрытия. В случае превышения разумного размера, пользователь и/или LLM-агент могут обрабатывать это (например, через суммаризацию, но это вне рамок данной задачи).
* **Обработка ошибок:** Если файл/промпт не найден, вместо содержимого вставляется сообщение об ошибке (например, `[Ошибка: Файл "filename" не найден]`).
* **TODO: Снапшоты:** В будущем будет реализована функция сохранения "снимка" содержимого файла на момент его раскрытия. Это позволит гарантировать воспроизводимость диалога, даже если исходный файл изменится.
### 3.5. Система Промптов и Шаблонные Ссылки
* **Папка для промптов:** Пользователь должен указать путь к папке в настройках плагина, где хранятся все промпты. Все промпты являются Markdown-файлами (`.md`).
* **Шаблонные ссылки ВНУТРИ промптов (`@{prompt_name}`):**
* Промпты могут содержать ссылки на другие промпты. Синтаксис: `@{prompt_name}`.
* **Ограничение:** Поддерживается только один уровень вложенности. То есть, промпт C не может ссылаться на промпт B, который в свою очередь ссылается на промпт A. (A -> B -> C -> LLM is OK, but A -> B -> C -> B -> LLM is not).
* **Пример:** `prompts/base-personality.md` может содержать текст, а `prompts/game-master.md` может начинаться с `@{base-personality}`.
* **Наследование типа подстановки:** Если промпт `master-prompt` ссылается на `sub-prompt` через `@{sub-prompt}`, и `master-prompt` был вызван как `##master-prompt` (постоянная ссылка), то содержимое `sub-prompt` также должно раскрыться как часть постоянного контекста. То есть, тип (одинарный/постоянный) определяется префиксом (`#`/`##`) корневой ссылки пользователем в ChatPanel.
* **Валидация промптов:** При сохранении промпта (или при попытке его раскрытия), система должна проверять корректность синтаксиса `@{...}` и наличие файлов, на которые ссылаются шаблонные ссылки. Ошибки должны быть зарегистрированы.
### 3.6. Настройки Плагина
В настройках плагина должны быть добавлены следующие опции:
* **`promptsFolder`**: (Строка) Путь к папке, где хранятся Markdown-файлы промптов. По умолчанию: "prompts".
* **`enableFileReferences`**: (Boolean) Включить/выключить функцию ссылок на файлы (@/@@). По умолчанию: `true`.
* **`enablePromptReferences`**: (Boolean) Включить/выключить функцию ссылок на промпты (#/##). По умолчанию: `true`.
### 3.7. Интеграция с Backend
* Frontend должен отправлять на backend *полностью раскрытый* текст сообщения.
* Backend не должен знать о системе ссылок, он работает только с конечным текстом.
* **TODO: Снапшоты (Backend):** Позднее, при реализации снапшотов, в модель данных `AgentState` и в базу данных (`graph_history_manager`) будут добавлены поля для хранения информации о раскрытых файлах и их содержимом.
### 3.8. Технические Требования
* **Производительность:** Автодополнение и раскрытие контента должны работать быстро, не вызывая заметных задержек в UI.
* **Совместимость:** Должна быть сохранена совместимость с существующей функциональностью плагина (слеш-команды, граф диалогов).
* **Иконки:** Использовать стандартные иконки Obsidian.
* **CSS:** Все новые стили должны быть аккуратно добавлены в `styles.css`.
## 4. Ограничения
* **Отсутствие рекурсии в шаблонных ссылках (`@{...}`):** Промпт не может ссылаться на себя или на промпт, который явно или косвенно ссылается на него. Система должна обнаружить подобные попытки и выдать ошибку. (Текущее требование - только 1 уровень вложенности, что фактически исключает рекурсию)
* **Снапшоты:** Отложенная функциональность.
* **Предпросмотр контента:** Отложенная функциональность для клика по Reference Box.
---
**TODO:** (Для будущих итераций)
* Реализовать сохранение снапшотов файлов в базе данных.
* Добавить UI для предпросмотра содержимого Reference Box при клике.
* Улучшить обработку ошибок (уведомления пользователю).
* Оптимизация производительности для очень больших хранилищ с множеством файлов.
* Поддержка других типов файлов (изображения, PDF) - раскрытие метаданных или ссылки на файл.
* Управление версиями промптов, история изменений.