Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Language Server Protocol (LSP)

O Hermes roda language servers completos — pyright, gopls, rust-analyzer, typescript-language-server, clangd e uns 20 outros — como subprocessos em segundo plano e injeta os diagnósticos semânticos deles na verificação de lint pós-escrita usada por write_file e patch. Quando o agente edita um arquivo, ele vê exatamente os erros que aquela edição introduziu — não só erros de sintaxe, mas erros de tipo, nomes não definidos, imports faltando e problemas semânticos de todo o projeto que o language server detecta.

É a mesma arquitetura que os melhores agentes de programação usam. O Hermes entrega isso autocontido: sem precisar de um editor hospedeiro, sem plugins para instalar, sem daemon separado para administrar.

Quando o LSP roda​

O LSP depende da detecção de espaço de trabalho git. Quando o diretório de trabalho do agente (ou o arquivo em edição) está dentro de um repositório git, o LSP roda contra esse espaço de trabalho. Quando nenhum dos dois está em um repositório git, o LSP fica dormente — útil para gateways de mensagem, em que o cwd é o diretório home do usuário e não há projeto nenhum para diagnosticar.

A verificação é em camadas: primeiro a checagem de sintaxe no próprio processo (microssegundos), depois os diagnósticos do LSP quando a sintaxe está limpa. Um language server instável ou ausente nunca consegue quebrar uma escrita — todo caminho de falha do LSP cai silenciosamente no resultado só de sintaxe.

Na prática, em cada write_file ou patch bem-sucedido:

  1. O Hermes captura uma linha de base dos diagnósticos atuais do arquivo.
  2. Realiza a escrita.
  3. Consulta o language server de novo, filtra os diagnósticos que já estavam na linha de base e mostra apenas os novos.

O agente vê uma saída assim:

{
"bytes_written": 42,
"dirs_created": false,
"lint": {"status": "ok", "output": ""},
"lsp_diagnostics": "LSP diagnostics introduced by this edit:\n<diagnostics file=\"/caminho/do/foo.py\">\nERROR [42:5] Cannot find name 'foo' [reportUndefinedVariable] (Pyright)\nERROR [50:1] Argument of type \"str\" is not assignable to \"int\" [reportArgumentType] (Pyright)\n</diagnostics>"
}

O campo lint carrega o resultado da checagem de sintaxe (parse no próprio processo, em microssegundos, via ast.parse, json.loads etc.); o campo lsp_diagnostics carrega os diagnósticos semânticos do language server de verdade. Dois canais, sinais independentes — o agente vê um arquivo com sintaxe limpa e problemas semânticos como lint: ok mais um lsp_diagnostics preenchido.

Linguagens suportadas​

LinguagemServidorInstalação automática
Pythonpyright-langservernpm
TypeScript / JavaScript / JSX / TSXtypescript-language-servernpm
Vue@vue/language-servernpm
Sveltesvelte-language-servernpm
Astro@astrojs/language-servernpm
Gogoplsgo install
Rustrust-analyzermanual (rustup)
C / C++clangdmanual (LLVM)
Bash / Zshbash-language-servernpm
YAMLyaml-language-servernpm
Lualua-language-servermanual (releases do GitHub)
PHPintelephensenpm
OCamlocaml-lspmanual (opam)
Dockerfiledockerfile-language-server-nodejsnpm
Terraformterraform-lsmanual
Dartdart language-servermanual (SDK do dart)
Haskellhaskell-language-servermanual (ghcup)
Juliajulia + LanguageServer.jlmanual
Clojureclojure-lspmanual
Nixnixdmanual
Zigzlsmanual
Gleamgleam lspmanual (gleam install)
Elixirelixir-lsmanual
Prismaprisma language-servermanual
Kotlinkotlin-language-servermanual
Javajdtlsmanual
PowerShellPowerShellEditorServices (host pwsh)manual (zip da release)

Nos casos marcados como "manual", instale o servidor pelo gerenciador de toolchain que fizer sentido para aquela linguagem (rustup, ghcup, opam, brew…). O Hermes detecta o binário sozinho, no PATH ou em <HERMES_HOME>/lsp/bin/.

PowerShell​

O PowerShellEditorServices não é um binário único — é um pacote de módulos do PowerShell iniciado por um host pwsh (PowerShell 7+) ou powershell. Configuração:

  1. Instale o PowerShell para que pwsh (ou o powershell do Windows) fique no PATH.
  2. Baixe o zip da release mais recente em releases do PowerShellEditorServices e extraia.
  3. Aponte o Hermes para o pacote extraído — o diretório que contém PowerShellEditorServices/Start-EditorServices.ps1. Faça de um destes jeitos:
    • defina lsp.servers.powershell.command: ["/caminho/do/pacote"] no config.yaml, ou
    • extraia para <HERMES_HOME>/lsp/PowerShellEditorServices, ou
    • exporte PSES_BUNDLE_PATH=/caminho/do/pacote.

O hermes lsp status reporta installed quando encontra o pwsh; se o pacote estiver faltando, você vê um aviso único nos logs com o link de download.

Alguns servidores são instalados junto com uma dependência par que o npm não baixa sozinho. O caso atual é o typescript-language-server, que precisa que o SDK typescript seja importável da mesma árvore node_modules — o Hermes instala os dois pacotes juntos quando você roda hermes lsp install typescript ou quando a instalação automática dispara no primeiro uso.

CLI​

hermes lsp status # estado do serviço + status de instalação de cada servidor
hermes lsp list # registro, opcionalmente com --installed-only
hermes lsp install <id> # instala um servidor de imediato
hermes lsp install-all # tenta todo servidor que tenha receita conhecida
hermes lsp restart # derruba os clientes em execução
hermes lsp which <id> # imprime o caminho resolvido do binário

O hermes lsp status é o melhor ponto de partida — ele mostra quais linguagens vão ter diagnósticos semânticos hoje e quais precisam de um binário instalado.

Configuração​

Os padrões funcionam para instalações típicas; não há nada para definir se os binários estão no PATH.

# config.yaml
lsp:
# Chave-mestra. Desligar pula o subsistema inteiro — nenhum servidor
# sobe, nenhum laço de eventos em segundo plano roda.
enabled: true

# Quanto esperar por diagnósticos depois de cada escrita.
wait_mode: document # "document" ou "full"
# Máximo de segundos a esperar até o servidor re-checar o arquivo
# depois de uma edição. Só diagnósticos *frescos* (produzidos para o
# conteúdo pós-edição) são reportados; se o servidor não terminar
# dentro desse orçamento, a edição reporta "no LSP data" em vez de
# erros velhos de antes da edição. Aumente para servidores lentos em
# projetos grandes (tsserver, rust-analyzer indexando).
wait_timeout: 5.0

# O que fazer quando falta o binário do servidor.
# auto — instala via npm/pip/go install em <HERMES_HOME>/lsp/bin
# manual — usa só binários que já estão no PATH
install_strategy: auto

# Quanto tempo um cliente de language server sem uso fica vivo (segundos).
# Servidores ociosos são desligados automaticamente e sobem de novo na
# próxima operação de arquivo relevante. Defina 0 para desligar a coleta
# por ociosidade e manter os servidores vivos por toda a vida do
# processo. Valores abaixo de 30s são elevados a 30, para que uma
# varredura nunca colete um cliente no meio de uma operação.
idle_timeout: 600

# Sobrescritas por servidor (todas opcionais).
servers:
pyright:
disabled: false
command: ["/caminho/absoluto/do/pyright-langserver", "--stdio"]
env: { PYRIGHT_LOG_LEVEL: "info" }
initialization_options:
python:
analysis:
typeCheckingMode: "strict"
typescript:
disabled: true # pula o TS mesmo quando as extensões batem

Chaves por servidor​

  • disabled: true — pula este servidor por completo, mesmo quando as extensões dele batem com um arquivo.
  • command: [bin, ...args] — fixa um caminho de binário personalizado. Ignora a instalação automática.
  • env: {KEY: value} — variáveis de ambiente extras passadas ao processo criado.
  • initialization_options: {...} — mesclado no payload initializationOptions do LSP, enviado no aperto de mão do initialize. É específico de cada servidor; consulte a documentação do language server.

Locais de instalação​

Com install_strategy: auto, o Hermes instala os binários em <HERMES_HOME>/lsp/bin/. Pacotes NPM caem em <HERMES_HOME>/lsp/node_modules/, com links simbólicos dos binários um nível acima. Os binários Go vêm de go install, com o GOBIN apontado para o diretório de preparo.

Nada nunca é instalado em /usr/local/, ~/.local/ ou qualquer outro local compartilhado — o diretório de preparo é 100% do Hermes e é removido quando você reseta o perfil.

Características de desempenho​

Os servidores LSP sobem de forma preguiçosa, no primeiro uso. Editar um arquivo Python em um projeto que nunca viu tráfego de .py faz subir o pyright; a subida leva de 1 a 3 segundos na maioria dos servidores (o rust-analyzer pode levar mais de 10 em um projeto frio). As edições seguintes no mesmo espaço de trabalho reaproveitam o servidor em execução.

A camada de LSP acrescenta poucos milissegundos às escritas limpas, quando nenhum diagnóstico é emitido. Quando há diagnósticos, o orçamento de espera é de wait_timeout segundos — normalmente o servidor responde em dezenas de milissegundos no pyright/tsserver e em alguns segundos no rust-analyzer enquanto indexa.

Os diagnósticos têm controle de frescor: um resultado só conta quando o servidor o produziu para o conteúdo da edição atual (um push de publishDiagnostics no momento da mudança ou depois dela, ou uma consulta respondida depois dela). Servidores lentos que ainda não re-checaram resultam em "sem dados" para aquela edição — nunca nos erros de ontem sendo reportados como atuais.

Os servidores são mantidos vivos enquanto estão em uso e desligados depois de lsp.idle_timeout segundos (600 por padrão) sem atividade de arquivo — um gateway de vida longa que mexe em muitas worktrees não acumula mais um processo de language server por espaço de trabalho para sempre. Um servidor coletado sobe de novo automaticamente na próxima operação de arquivo relevante. Defina idle_timeout: 0 para desligar a coleta e manter o índice de todo servidor quente por toda a vida do processo.

Como desligar​

Defina lsp.enabled: false no config.yaml para desligar o subsistema inteiro. A verificação pós-escrita cai na checagem de sintaxe no próprio processo (ast.parse para Python, json.loads para JSON etc.), que vem inalterada das versões anteriores.

Para desligar uma única linguagem sem desligar a camada toda:

lsp:
servers:
rust-analyzer:
disabled: true

Resolução de problemas​

O hermes lsp status mostra um servidor como "missing"

O binário não está no PATH nem em <HERMES_HOME>/lsp/bin/. Rode hermes lsp install <server_id> para tentar a instalação automática, ou instale o binário na mão, pela toolchain normal da linguagem.

Seção Backend warnings no hermes lsp status

Alguns servidores vêm como cascas finas em volta de uma CLI externa que faz o diagnóstico de verdade — eles sobem limpos e aceitam requisições, mas nunca emitem erros quando o binário auxiliar está faltando. O caso mais comum é o bash-language-server, que delega os diagnósticos ao shellcheck. Quando o hermes lsp status mostra uma seção Backend warnings, instale a ferramenta indicada pelo gerenciador de pacotes do seu sistema:

apt install shellcheck # Debian / Ubuntu
brew install shellcheck # macOS
scoop install shellcheck # Windows

O mesmo aviso é registrado uma vez, na hora em que o servidor sobe, em ~/.hermes/logs/agent.log.

O servidor sobe, mas nunca devolve diagnósticos

Procure entradas [agent.lsp.client] em ~/.hermes/logs/agent.log — o stderr do language server e os erros de protocolo caem ali. Alguns servidores (o rust-analyzer em especial) precisam terminar um índice de todo o projeto antes de emitir diagnósticos por arquivo; a primeira edição depois de o servidor subir pode terminar sem diagnóstico nenhum, e as edições seguintes já pegam tudo.

O servidor quebrou

Um servidor que quebra entra no conjunto de defeituosos e não é tentado de novo pelo resto da sessão. Rode hermes lsp restart para limpar o conjunto; a próxima edição sobe o servidor outra vez.

Editar um arquivo fora de qualquer repositório git

Por decisão de projeto, o LSP só roda dentro de um repositório git. Se o projeto ainda não foi inicializado, rode git init para habilitar os diagnósticos do LSP. Fora disso, vale o fallback só de sintaxe no próprio processo.