Diffs
diffs — это опциональный инструмент-плагин с кратким встроенным системным руководством и вспомогательным навыком, который превращает контент с изменениями в артефакт diff только для чтения для агентов. Он принимает либо:
- текст
beforeиafter - унифицированный
patch
Он может возвращать:
- URL просмотрщика шлюза для презентации на canvas
- путь к отрендеренному файлу (PNG или PDF) для отправки в сообщении
- оба вывода за один вызов
Когда плагин включен, он добавляет краткое руководство по использованию в пространство системного промпта, а также предоставляет подробный навык для случаев, когда агенту требуются полные инструкции.
Быстрый старт
- Включите плагин.
- Вызовите
diffsсmode: "view"для потоков, ориентированных на canvas. - Вызовите
diffsсmode: "file"для потоков доставки файлов в чате. - Вызовите
diffsсmode: "both", когда нужны оба артефакта.
Включение плагина
{
plugins: {
entries: {
diffs: {
enabled: true,
},
},
},
}
Отключение встроенного системного руководства
Если вы хотите оставить инструмент diffs включенным, но отключить его встроенное руководство в системном промпте, установите plugins.entries.diffs.hooks.allowPromptInjection в false:
{
plugins: {
entries: {
diffs: {
enabled: true,
hooks: {
allowPromptInjection: false,
},
},
},
},
}
Это блокирует хук before_prompt_build плагина diffs, оставляя сам плагин, инструмент и вспомогательный навык доступными. Если вы хотите отключить и руководство, и инструмент, отключите плагин полностью.
Типичный рабочий процесс агента
- Агент вызывает
diffs. - Агент читает поля
details. - Агент либо:
- открывает
details.viewerUrlс помощьюcanvas present - отправляет
details.filePathс помощьюmessage, используяpathилиfilePath - делает и то, и другое
- открывает
Примеры входных данных
Before и after:
{
"before": "# Hello\n\nOne",
"after": "# Hello\n\nTwo",
"path": "docs/example.md",
"mode": "view"
}
Patch:
{
"patch": "diff --git a/src/example.ts b/src/example.ts\n--- a/src/example.ts\n+++ b/src/example.ts\n@@ -1 +1 @@\n-const x = 1;\n+const x = 2;\n",
"mode": "both"
}
Справочник по входным данным инструмента
Все поля необязательны, если не указано иное:
before(string): исходный текст. Обязателен вместе сafter, когдаpatchопущен.after(string): обновленный текст. Обязателен вместе сbefore, когдаpatchопущен.patch(string): текст унифицированного diff. Взаимоисключается сbeforeиafter.path(string): отображаемое имя файла для режима before и after.lang(string): подсказка для переопределения языка в режиме before и after.title(string): переопределение заголовка просмотрщика.mode("view" | "file" | "both"): режим вывода. По умолчанию используется значение плагинаdefaults.mode.theme("light" | "dark"): тема просмотрщика. По умолчанию используется значение плагинаdefaults.theme.layout("unified" | "split"): макет diff. По умолчанию используется значение плагинаdefaults.layout.expandUnchanged(boolean): развернуть неизмененные секции, когда доступен полный контекст. Только опция для отдельного вызова (не ключ по умолчанию плагина).fileFormat("png" | "pdf"): формат рендеренного файла. По умолчанию используется значение плагинаdefaults.fileFormat.fileQuality("standard" | "hq" | "print"): пресет качества для рендеринга PNG или PDF.fileScale(number): переопределение масштаба устройства (1-4).fileMaxWidth(number): максимальная ширина рендера в CSS-пикселях (640-2400).ttlSeconds(number): TTL артефакта просмотрщика в секундах. По умолчанию 1800, максимум 21600.baseUrl(string): переопределение источника URL просмотрщика. Должен бытьhttpилиhttps, без query/hash.
Валидация и ограничения:
beforeиafterмаксимум по 512 КиБ каждый.patchмаксимум 2 МиБ.pathмаксимум 2048 байт.langмаксимум 128 байт.titleмаксимум 1024 байт.- Ограничение сложности патча: максимум 128 файлов и 120000 строк всего.
patchвместе сbeforeилиafterотклоняется.- Ограничения безопасности для рендеренных файлов (применяются к PNG и PDF):
fileQuality: "standard": максимум 8 МП (8 000 000 отрендеренных пикселей).fileQuality: "hq": максимум 14 МП (14 000 000 отрендеренных пикселей).fileQuality: "print": максимум 24 МП (24 000 000 отрендеренных пикселей).- PDF также имеет максимум 50 страниц.
Контракт деталей вывода
Инструмент возвращает структурированные метаданные в details. Общие поля для режимов, создающих просмотрщик:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmode
Поля файла, когда рендерится PNG или PDF:
filePathpath(то же значение, что иfilePath, для совместимости с инструментом message)fileBytesfileFormatfileQualityfileScalefileMaxWidth
Сводка поведения по режимам:
mode: "view": только поля просмотрщика.mode: "file": только поля файла, без артефакта просмотрщика.mode: "both": поля просмотрщика плюс поля файла. Если рендеринг файла не удался, просмотрщик все равно возвращается сfileError.
Свернутые неизмененные секции
- Просмотрщик может показывать строки вида
N unmodified lines. - Элементы управления развертыванием для этих строк условны и не гарантированы для каждого типа входных данных.
- Элементы управления развертыванием появляются, когда отрендеренный diff имеет расширяемые данные контекста, что типично для входных данных before и after.
- Для многих входных данных унифицированного патча опущенные тела контекста недоступны в разобранных блоках патча, поэтому строка может отображаться без элементов управления развертыванием. Это ожидаемое поведение.
expandUnchangedприменяется только когда существует расширяемый контекст.
Настройки плагина по умолчанию
Установите настройки по умолчанию для всего плагина в ~/.openclaw/openclaw.json:
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
defaults: {
fontFamily: "Fira Code",
fontSize: 15,
lineSpacing: 1.6,
layout: "unified",
showLineNumbers: true,
diffIndicators: "bars",
wordWrap: true,
background: true,
theme: "dark",
fileFormat: "png",
fileQuality: "standard",
fileScale: 2,
fileMaxWidth: 960,
mode: "both",
},
},
},
},
},
}
Поддерживаемые настройки по умолчанию:
fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmode
Явные параметры инструмента переопределяют эти настройки.
Конфигурация безопасности
security.allowRemoteViewer(boolean, по умолчаниюfalse)false: запросы не с loopback к маршрутам просмотрщика отклоняются.true: удаленные просмотрщики разрешены, если токенизированный путь валиден.
Пример:
{
plugins: {
entries: {
diffs: {
enabled: true,
config: {
security: {
allowRemoteViewer: false,
},
},
},
},
},
}
Жизненный цикл и хранение артефактов
- Артефакты хранятся во временной подпапке:
$TMPDIR/openclaw-diffs. - Метаданные артефакта просмотрщика содержат:
- случайный ID артефакта (20 hex символов)
- случайный токен (48 hex символов)
createdAtиexpiresAt- сохраненный путь
viewer.html
- TTL просмотрщика по умолчанию — 30 минут, если не указано иное.
- Максимально принимаемый TTL просмотрщика — 6 часов.
- Очистка выполняется оппортунистически после создания артефакта.
- Просроченные артефакты удаляются.
- Резервная очистка удаляет устаревшие папки старше 24 часов, когда метаданные отсутствуют.
URL просмотрщика и сетевое поведение
Маршрут просмотрщика:
/plugins/diffs/view/{artifactId}/{token}
Ресурсы просмотрщика:
/plugins/diffs/assets/viewer.js/plugins/diffs/assets/viewer-runtime.js
Поведение построения URL:
- Если предоставлен
baseUrl, он используется после строгой валидации. - Без
baseUrlURL просмотрщика по умолчанию использует loopback127.0.0.1. - Если режим привязки шлюза
customи установленgateway.customBindHost, используется этот хост.
Правила baseUrl:
- Должен быть
http://илиhttps://. - Query и hash отклоняются.
- Разрешен origin плюс опциональный базовый путь.
Модель безопасности
Усиление защиты просмотрщика:
- По умолчанию только loopback.
- Токенизированные пути просмотрщика со строгой валидацией ID и токена.
- CSP ответа просмотрщика:
default-src 'none'- скрипты и ресурсы только с собственного источника
- нет исходящих
connect-src
- Ограничение частоты удаленных ошибок при включенном удаленном доступе:
- 40 ошибок за 60 секунд
- блокировка на 60 секунд (
429 Too Many Requests)
Усиление защиты рендеринга файлов:
- Маршрутизация запросов браузера для скриншотов запрещена по умолчанию.
- Разрешены только локальные ресурсы просмотрщика с
http://127.0.0.1/plugins/diffs/assets/*. - Внешние сетевые запросы блокируются.
Требования к браузеру для режима file
mode: "file" и mode: "both" требуют браузер, совместимый с Chromium. Порядок определения:
browser.executablePathв конфиге OpenClaw.- Переменные окружения:
OPENCLAW_BROWSER_EXECUTABLE_PATHBROWSER_EXECUTABLE_PATHPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
- Резервное определение команды/пути для платформы.
Типичный текст ошибки:
Diff PNG/PDF rendering requires a Chromium-compatible browser...
Исправьте, установив Chrome, Chromium, Edge или Brave, или задав один из вариантов пути к исполняемому файлу выше.
Устранение неполадок
Ошибки валидации входных данных:
Provide patch or both before and after text.- Укажите и
before, иafter, или предоставьтеpatch.
- Укажите и
Provide either patch or before/after input, not both.- Не смешивайте режимы входных данных.
Invalid baseUrl: ...- Используйте origin
http(s)с опциональным путем, без query/hash.
- Используйте origin
{field} exceeds maximum size (...)- Уменьшите размер данных.
- Отклонение большого патча
- Уменьшите количество файлов или общее количество строк в патче.
Проблемы с доступностью просмотрщика:
- URL просмотрщика по умолчанию разрешается в
127.0.0.1. - Для сценариев удаленного доступа либо:
- передавайте
baseUrlпри каждом вызове инструмента, либо - используйте
gateway.bind=customиgateway.customBindHost
- передавайте
- Включайте
security.allowRemoteViewerтолько когда вам нужен внешний доступ к просмотрщику.
У строки с неизмененными строками нет кнопки развертывания:
- Это может происходить для входных данных патча, когда патч не содержит расширяемого контекста.
- Это ожидаемо и не указывает на сбой просмотрщика.
Артефакт не найден:
- Артефакт истек по TTL.
- Токен или путь изменились.
- Очистка удалила устаревшие данные.
Операционные рекомендации
- Предпочитайте
mode: "view"для локальных интерактивных проверок на canvas. - Предпочитайте
mode: "file"для исходящих каналов чата, которым требуется вложение. - Держите
allowRemoteViewerвыключенным, если ваше развертывание не требует удаленных URL просмотрщика. - Устанавливайте явный короткий
ttlSecondsдля чувствительных diff. - Избегайте отправки секретов во входных данных diff, когда это не требуется.
- Если ваш канал агрессивно сжимает изображения (например, Telegram или WhatsApp), предпочитайте вывод PDF (
fileFormat: "pdf").
Движок рендеринга diff: