Встроенные инструменты

Diffs

diffs — это опциональный инструмент-плагин с кратким встроенным системным руководством и вспомогательным навыком, который превращает контент с изменениями в артефакт diff только для чтения для агентов. Он принимает либо:

  • текст before и after
  • унифицированный patch

Он может возвращать:

  • URL просмотрщика шлюза для презентации на canvas
  • путь к отрендеренному файлу (PNG или PDF) для отправки в сообщении
  • оба вывода за один вызов

Когда плагин включен, он добавляет краткое руководство по использованию в пространство системного промпта, а также предоставляет подробный навык для случаев, когда агенту требуются полные инструкции.

Быстрый старт

  1. Включите плагин.
  2. Вызовите diffs с mode: "view" для потоков, ориентированных на canvas.
  3. Вызовите diffs с mode: "file" для потоков доставки файлов в чате.
  4. Вызовите 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, оставляя сам плагин, инструмент и вспомогательный навык доступными. Если вы хотите отключить и руководство, и инструмент, отключите плагин полностью.

Типичный рабочий процесс агента

  1. Агент вызывает diffs.
  2. Агент читает поля details.
  3. Агент либо:
    • открывает 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. Общие поля для режимов, создающих просмотрщик:

  • artifactId
  • viewerUrl
  • viewerPath
  • title
  • expiresAt
  • inputKind
  • fileCount
  • mode

Поля файла, когда рендерится PNG или PDF:

  • filePath
  • path (то же значение, что и filePath, для совместимости с инструментом message)
  • fileBytes
  • fileFormat
  • fileQuality
  • fileScale
  • fileMaxWidth

Сводка поведения по режимам:

  • 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",
          },
        },
      },
    },
  },
}

Поддерживаемые настройки по умолчанию:

  • fontFamily
  • fontSize
  • lineSpacing
  • layout
  • showLineNumbers
  • diffIndicators
  • wordWrap
  • background
  • theme
  • fileFormat
  • fileQuality
  • fileScale
  • fileMaxWidth
  • mode

Явные параметры инструмента переопределяют эти настройки.

Конфигурация безопасности

  • 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, он используется после строгой валидации.
  • Без baseUrl URL просмотрщика по умолчанию использует loopback 127.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. Порядок определения:

  1. browser.executablePath в конфиге OpenClaw.
  2. Переменные окружения:
    • OPENCLAW_BROWSER_EXECUTABLE_PATH
    • BROWSER_EXECUTABLE_PATH
    • PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
  3. Резервное определение команды/пути для платформы.

Типичный текст ошибки:

  • 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.
  • {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:

Связанные документы

Perplexity SonarИнструмент PDF