Tools
Diffs
diffs é uma ferramenta opcional de Plugin com orientação de sistema curta integrada e uma skill complementar que transforma conteúdo de alterações em um artefato diff somente leitura para agentes.
Ela aceita:
- texto
beforeeafter - um
patchunificado
Ela pode retornar:
- uma URL do visualizador do Gateway para apresentação em canvas
- um caminho de arquivo renderizado (PNG ou PDF) para entrega por mensagem
- ambas as saídas em uma única chamada
Quando habilitado, o Plugin acrescenta orientações concisas de uso ao espaço do prompt de sistema e também expõe uma skill detalhada para casos em que o agente precisa de instruções mais completas.
Início rápido
Install the plugin
openclaw plugins install diffsEnable the plugin
{ plugins: { entries: { diffs: { enabled: true, }, }, },}Pick a mode
view
Fluxos com canvas primeiro: agentes chamam diffs com mode: "view" e abrem details.viewerUrl com canvas present.
file
Entrega de arquivo no chat: agentes chamam diffs com mode: "file" e enviam details.filePath com message usando path ou filePath.
both
Combinado: agentes chamam diffs com mode: "both" para obter os dois artefatos em uma única chamada.
Desabilitar a orientação de sistema integrada
Se você quiser manter a ferramenta diffs habilitada, mas desabilitar sua orientação integrada de prompt de sistema, defina plugins.entries.diffs.hooks.allowPromptInjection como false:
{ plugins: { entries: { diffs: { enabled: true, hooks: { allowPromptInjection: false, }, }, }, },}Isso bloqueia o hook before_prompt_build do Plugin diffs, mantendo o Plugin, a ferramenta e a skill complementar disponíveis.
Se você quiser desabilitar tanto a orientação quanto a ferramenta, desabilite o Plugin em vez disso.
Fluxo de trabalho típico do agente
Call diffs
O agente chama a ferramenta diffs com entrada.
Read details
O agente lê os campos details da resposta.
Present
O agente abre details.viewerUrl com canvas present, envia details.filePath com message usando path ou filePath, ou faz ambos.
Exemplos de entrada
Before and 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"}Referência de entrada da ferramenta
Todos os campos são opcionais, salvo indicação em contrário.
beforestringTexto original. Obrigatório com after quando patch é omitido.
afterstringTexto atualizado. Obrigatório com before quando patch é omitido.
patchstringTexto de diff unificado. Mutuamente exclusivo com before e after.
pathstringNome de arquivo de exibição para o modo antes e depois.
langstringDica de substituição de linguagem para o modo antes e depois. Valores desconhecidos e linguagens fora do conjunto padrão do visualizador retornam para texto simples, a menos que o Plugin Diff Viewer Language Pack esteja instalado.
titlestringSubstituição do título do visualizador.
mode"view" | "file" | "both"Modo de saída. O padrão é o padrão do Plugin defaults.mode. Alias obsoleto: "image" se comporta como "file" e ainda é aceito para compatibilidade retroativa.
theme"light" | "dark"Tema do visualizador. O padrão é o padrão do Plugin defaults.theme.
layout"unified" | "split"Layout do diff. O padrão é o padrão do Plugin defaults.layout.
expandUnchangedbooleanExpande seções inalteradas quando o contexto completo está disponível. Opção apenas por chamada (não é uma chave padrão do Plugin).
fileFormat"png" | "pdf"Formato de arquivo renderizado. O padrão é o padrão do Plugin defaults.fileFormat.
fileQuality"standard" | "hq" | "print"Predefinição de qualidade para renderização PNG ou PDF.
fileScalenumberSubstituição de escala do dispositivo (1-4).
fileMaxWidthnumberLargura máxima de renderização em pixels CSS (640-2400).
ttlSecondsnumberdefault: 1800TTL do artefato em segundos para saídas do visualizador e de arquivo independente. Máximo de 21600.
baseUrlstringSubstituição da origem da URL do visualizador. Substitui viewerBaseUrl do Plugin. Deve ser http ou https, sem consulta/hash.
Legacy input aliases
Ainda aceitos para compatibilidade retroativa:
format->fileFormatimageFormat->fileFormatimageQuality->fileQualityimageScale->fileScaleimageMaxWidth->fileMaxWidth
Validation and limits
beforeeaftercom máximo de 512 KiB cada.patchcom máximo de 2 MiB.pathcom máximo de 2048 bytes.langcom máximo de 128 bytes.titlecom máximo de 1024 bytes.- Limite de complexidade do patch: máximo de 128 arquivos e 120000 linhas no total.
patchjunto combeforeouafteré rejeitado.- Limites de segurança de arquivo renderizado (aplicam-se a PNG e PDF):
fileQuality: "standard": máximo de 8 MP (8.000.000 pixels renderizados).fileQuality: "hq": máximo de 14 MP (14.000.000 pixels renderizados).fileQuality: "print": máximo de 24 MP (24.000.000 pixels renderizados).- PDF também tem um máximo de 50 páginas.
Realce de sintaxe
OpenClaw inclui realce de sintaxe para linguagens comuns de código-fonte, configuração e documentação:
javascript, typescript, tsx, jsx, json, markdown, yaml, css, html, sh, python, go, rust, java, c, cpp, csharp, php, sql, docker, ruby, swift, kotlin, r, dart, lua, powershell, xml e toml.
Aliases comuns como js, ts, bash, md, yml, c++, dockerfile, rb, kt e ps1 são normalizados para essas linguagens padrão.
Instale o Plugin Diff Viewer Language Pack para destacar outras linguagens:
openclaw plugins install clawhub:@openclaw/diffs-language-packCom o pacote de linguagens disponível, o OpenClaw consegue destacar muito mais linguagens. Se o pacote não estiver instalado, arquivos fora da lista padrão ainda serão renderizados como texto simples legível. Exemplos incluem Astro, Vue, Svelte, MDX, GraphQL, Terraform/HCL, Nix, Clojure, Elixir, Haskell, OCaml, Scala, Zig, Solidity, Verilog/VHDL, Fortran, MATLAB, LaTeX, Mermaid, Sass/Less/SCSS, Nginx, Apache, CSV, dotenv, INI e arquivos diff.
Veja o Plugin Diffs Language Pack para detalhes e linguagens do Shiki para o catálogo upstream de linguagens e aliases do Shiki.
Contrato de detalhes de saída
A ferramenta retorna metadados estruturados em details.
Campos do visualizador
Campos compartilhados para modos que criam um visualizador:
artifactIdviewerUrlviewerPathtitleexpiresAtinputKindfileCountmodecontext(agentId,sessionId,messageChannel,agentAccountIdquando disponível)
Campos de arquivo
Campos de arquivo quando PNG ou PDF é renderizado:
artifactIdexpiresAtfilePathpath(mesmo valor quefilePath, para compatibilidade com ferramentas de mensagem)fileBytesfileFormatfileQualityfileScalefileMaxWidth
Aliases de compatibilidade
Também retornados para chamadores existentes:
format(mesmo valor quefileFormat)imagePath(mesmo valor quefilePath)imageBytes(mesmo valor quefileBytes)imageQuality(mesmo valor quefileQuality)imageScale(mesmo valor quefileScale)imageMaxWidth(mesmo valor quefileMaxWidth)
Resumo do comportamento dos modos:
| Modo | O que é retornado |
|---|---|
"view" |
Apenas campos do visualizador. |
"file" |
Apenas campos de arquivo, sem artefato de visualizador. |
"both" |
Campos do visualizador mais campos de arquivo. Se a renderização do arquivo falhar, o visualizador ainda retorna com o alias fileError e imageError. |
Seções inalteradas recolhidas
- O visualizador pode mostrar linhas como
N unmodified lines. - Os controles de expansão nessas linhas são condicionais e não são garantidos para todo tipo de entrada.
- Os controles de expansão aparecem quando o diff renderizado tem dados de contexto expansíveis, o que é típico para entradas antes e depois.
- Para muitas entradas de patch unificado, os corpos de contexto omitidos não estão disponíveis nos hunks do patch analisado, então a linha pode aparecer sem controles de expansão. Esse é o comportamento esperado.
expandUnchangedse aplica apenas quando existe contexto expansível.
Padrões do Plugin
Defina padrões para todo o Plugin em ~/.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", ttlSeconds: 21600, }, }, }, }, },}Padrões compatíveis:
fontFamilyfontSizelineSpacinglayoutshowLineNumbersdiffIndicatorswordWrapbackgroundthemefileFormatfileQualityfileScalefileMaxWidthmodettlSeconds
Parâmetros explícitos da ferramenta substituem esses padrões.
Configuração persistente de URL do visualizador
viewerBaseUrlstringFallback pertencente ao Plugin para links de visualizador retornados quando uma chamada de ferramenta não passa baseUrl. Deve ser http ou https, sem consulta/hash.
{ plugins: { entries: { diffs: { enabled: true, config: { viewerBaseUrl: "https://gateway.example.com/openclaw", }, }, }, },}Configuração de segurança
security.allowRemoteViewerbooleandefault: falsefalse: solicitações não loopback para rotas do visualizador são negadas. true: visualizadores remotos são permitidos se o caminho tokenizado for válido.
{ plugins: { entries: { diffs: { enabled: true, config: { security: { allowRemoteViewer: false, }, }, }, }, },}Ciclo de vida e armazenamento de artefatos
- Os artefatos são armazenados na subpasta temporária:
$TMPDIR/openclaw-diffs. - Os metadados do artefato do visualizador contêm:
- ID aleatório do artefato (20 caracteres hexadecimais)
- token aleatório (48 caracteres hexadecimais)
createdAteexpiresAt- caminho armazenado de
viewer.html
- O TTL padrão do artefato é de 30 minutos quando não especificado.
- O TTL máximo aceito do visualizador é de 6 horas.
- A limpeza é executada oportunisticamente após a criação do artefato.
- Artefatos expirados são excluídos.
- A limpeza de fallback remove pastas obsoletas com mais de 24 horas quando os metadados estão ausentes.
URL do visualizador e comportamento de rede
Rota do visualizador:
/plugins/diffs/view/{artifactId}/{token}
Assets do visualizador:
/plugins/diffs/assets/viewer.js/plugins/diffs/assets/viewer-runtime.js/plugins/diffs-language-pack/assets/viewer.jsquando o diff usa uma linguagem do Diff Viewer Language Pack
O documento do visualizador resolve esses assets em relação à URL do visualizador, então um prefixo de caminho opcional baseUrl também é preservado para ambas as solicitações de assets.
Comportamento de construção de URL:
- Se
baseUrlda chamada de ferramenta for fornecido, ele será usado após validação rigorosa. - Caso contrário, se
viewerBaseUrldo Plugin estiver configurado, ele será usado. - Sem nenhuma das substituições, a URL do visualizador usa por padrão o loopback
127.0.0.1. - Se o modo de vinculação do Gateway for
customegateway.customBindHostestiver definido, esse host será usado.
Regras de baseUrl:
- Deve ser
http://ouhttps://. - Query e hash são rejeitados.
- Origem mais caminho base opcional são permitidos.
Modelo de segurança
Proteção do visualizador
- Apenas loopback por padrão.
- Caminhos de visualizador tokenizados com validação rigorosa de ID e token.
- CSP da resposta do visualizador:
default-src 'none'- scripts e assets apenas da própria origem
- nenhum
connect-srcde saída
- Limitação de erros remotos quando o acesso remoto está habilitado:
- 40 falhas a cada 60 segundos
- bloqueio de 60 segundos (
429 Too Many Requests)
Proteção da renderização de arquivos
- O roteamento de solicitações do navegador para capturas de tela é negar por padrão.
- Apenas assets locais do visualizador em
http://127.0.0.1/plugins/diffs/assets/*são permitidos. - Solicitações de rede externas são bloqueadas.
Requisitos de navegador para o modo de arquivo
mode: "file" e mode: "both" precisam de um navegador compatível com Chromium.
Ordem de resolução:
Configuração
browser.executablePath na configuração do OpenClaw.
Variáveis de ambiente
OPENCLAW_BROWSER_EXECUTABLE_PATHBROWSER_EXECUTABLE_PATHPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
Fallback da plataforma
Fallback de descoberta de comando/caminho da plataforma.
Texto comum de falha:
Diff PNG/PDF rendering requires a Chromium-compatible browser...
Corrija instalando Chrome, Chromium, Edge ou Brave, ou definindo uma das opções de caminho de executável acima.
Solução de problemas
Erros de validação de entrada
Provide patch or both before and after text.— incluabeforeeafter, ou forneçapatch.Provide either patch or before/after input, not both.— não misture modos de entrada.Invalid baseUrl: ...— use origemhttp(s)com caminho opcional, sem query/hash.{field} exceeds maximum size (...)— reduza o tamanho do payload.- Rejeição de patch grande — reduza a contagem de arquivos do patch ou o total de linhas.
Acessibilidade do visualizador
- A URL do visualizador resolve para
127.0.0.1por padrão. - Para cenários de acesso remoto:
- defina
viewerBaseUrldo Plugin, ou - passe
baseUrlpor chamada de ferramenta, ou - use
gateway.bind=customegateway.customBindHost
- defina
- Se
gateway.trustedProxiesincluir loopback para um proxy no mesmo host (por exemplo, Tailscale Serve), solicitações brutas do visualizador por loopback sem cabeçalhos de IP do cliente encaminhados falham fechadas por design. - Para essa topologia de proxy:
- prefira
mode: "file"oumode: "both"quando você precisar apenas de um anexo, ou - habilite intencionalmente
security.allowRemoteViewere definaviewerBaseUrldo Plugin ou passe umbaseUrlde proxy/público quando precisar de uma URL de visualizador compartilhável
- prefira
- Habilite
security.allowRemoteViewerapenas quando você pretende permitir acesso externo ao visualizador.
A linha de linhas não modificadas não tem botão de expandir
Isso pode acontecer para entrada de patch quando o patch não carrega contexto expansível. Isso é esperado e não indica falha do visualizador.
Artefato não encontrado
- O artefato expirou devido ao TTL.
- O token ou caminho mudou.
- A limpeza removeu dados obsoletos.
Orientação operacional
- Prefira
mode: "view"para revisões interativas locais no canvas. - Prefira
mode: "file"para canais de chat de saída que precisam de um anexo. - Mantenha
allowRemoteViewerdesabilitado, a menos que sua implantação exija URLs remotas do visualizador. - Defina
ttlSecondscurto explícito para diffs sensíveis. - Evite enviar segredos na entrada de diff quando não for necessário.
- Se seu canal comprime imagens de forma agressiva (por exemplo, Telegram ou WhatsApp), prefira saída em PDF (
fileFormat: "pdf").