CH 22 · Plugins de UI: Troque a Skin, Adicione Painéis, Injete Conteúdo no dsh
Objetivo do Capítulo
Os plugins nos capítulos anteriores trabalharam em lugares "que você não pode ver": registrar ferramentas, interceptar chamadas, fornecer dependências. Este capítulo muda para a camada visível — plugins podem diretamente mudar a aparência e capacidades da Web UI. Este capítulo deixa claro o que plugins de UI podem fazer, como funcionam, e na prática ver um fluxo de eventos real.
Você Já Está Usando Plugins de UI
Olhando de volta para o CH 17, instalamos três plugins, e todos eram plugins de UI:
| Plugin | O que faz |
|---|---|
| dsh-theme | Troca a skin da Web UI (um cartão de tema aparece em Configurações → Aparência) |
| dsh-oil-sticky-prompt | Fixa a mensagem mais recente do usuário no topo ao rolar |
| dsh-better-sidebar | Bancada de barra lateral, veja o diretório diretamente do painel de arquivos |
Você pode ter apenas "instalado um plugin" na época, mas agora você entende: todos eles modificam a UI. Esse é o primeiro nível de compreensão dos plugins de UI — eles são responsáveis por toda a personalização que você "pode ver".
O Que Plugins de UI Podem Fazer
Aproximadamente três categorias de capacidades:
- Troca de skin: mude cores, fontes, estilo de layout. A categoria mais leve, dsh-theme é um.
- Modificar layout / adicionar painéis / adicionar recursos: mova a barra lateral, barra superior, área de entrada, e também adicione diretamente um módulo de recurso completo ou painel de visualização à interface. dsh-better-sidebar, dsh-oil-sticky-prompt estão nesta categoria; o DSH Skill & MCP Panel que você instalou no CH 12 também é um — ele adiciona diretamente uma entrada "Gerenciamento MCP" às Configurações, o status de cada servidor e contagem de ferramentas visíveis de relance, equivalente a adicionar um painel de O&M de visualização à Web UI.
- Contribua conteúdo para a conversa: renderize linhas personalizadas na sessão (por exemplo, desenhe um cartão para um certo tipo de resultado de ferramenta, insira nós especiais). Esta é a categoria mais profunda, oficialmente chamada de "contribua linhas de negócio para o Web Client".
As duas primeiras categorias são em sua maioria trabalho puramente front-end; a terceira realmente precisa "se conectar ao" pipeline de renderização de conversa.
Como Plugins de UI Funcionam: Tudo Começa com o Fluxo de Eventos
Plugins de UI não manipulam diretamente o DOM na página, eles se inscrevem no fluxo de eventos. Este é o ponto mais crítico em entender plugins de UI.
Ao longo de uma sessão, cada evento se torna um evento padrão: usuário enviou uma mensagem, modelo começou a transmitir saída, um step começou, uma chamada de ferramenta aconteceu... esses eventos fluem pelo canal session/event como água. A interface integrada renderiza bolhas de conversa, trajetória e status a partir deles; plugins de UI fazem o mesmo, se inscrevendo no mesmo fluxo via ctx.on('session/event', ...).
O exemplo mínimo oficial para um plugin de UI faz exatamente isto:
export const name = 'my-ui'
export const inject = ['agents']
export function apply(ctx) {
ctx.on('session/event', (_session, event) => {
if (event.type === 'assistant/chunk' && event.data.chunk.type === 'text-delta') {
console.log(event.data.chunk.text) // Cada pedaço da saída streaming do modelo
}
})
}O esqueleto de todo o mecanismo:
Você insere, o modelo responde, o controlador de sessão traduz tudo em um fluxo de eventos; plugins de UI e a interface integrada se inscrevem no mesmo fluxo, cada um pega o que precisa. A interface é um "consumidor" do fluxo de eventos, não um manipulador direto do DOM — isso também explica por que "tudo é plugin" pode cobrir a UI: mesmo a interface é "ouvida" por plugins a partir do fluxo de eventos.
Prática: Instale um "Observador de Eventos" para Ver o Fluxo de Eventos
Apenas olhar o mecanismo não é divertido o suficiente, vamos escrever um plugin minimalista que imprime cada evento de sessão — veja quanto realmente acontece por trás de uma única conversa.
Passo 1: Crie Diretório, Escreva Plugin
Em um workspace onde você quer colocar plugins:
New-Item -ItemType Directory -Path "ui-demo\src" -ForceCrie ui-demo\src\event-watch.js:
export const name = 'event-watch'
export function apply(ctx) {
ctx.on('session/event', (_session, event) => {
console.log(`[event] ${event.type}${event.data?.type ? ' / ' + event.data.type : ''}`)
})
}Apenas inscreva-se em session/event e imprima o tipo de cada evento.
Passo 2: Declare o Plugin
Crie ui-demo\cordis.yml (substitua o caminho pelo seu, lembre-se de %20 para espaços):
- insert:
- id: event-watch
name: 'file:///E:/seu-workspace/ui-demo/src/event-watch.js'Passo 3: Execute o headless Uma Vez
cd seu-diretório-de-workspace
dsh --profile headless --patch "./ui-demo/cordis.yml" "Just reply: hi"Minha saída real do terminal:

Apenas respondendo "hi", nos bastidores passaram 22 eventos: inicialização de sessão (permission, sandbox, approval), turn/start, step/start, três user/messages, headers de requisição, assistant/chunk transmitindo texto um por um, assistant/message assentando, step/end, turn/end...
A conversa que você vê na Web UI é esta cadeia de eventos sendo renderizada após consumo. O observador de eventos nos deixou "ver" a matéria-prima por trás da UI pela primeira vez.
Deixe o dsh Fazer: Desenvolva um Plugin de UI Visível
O observador de eventos acima apenas "observa eventos" e ainda não mudou realmente a interface. Faça o dsh diretamente desenvolver um plugin de UI onde o efeito é visível na página de configurações, ele pode fazer isso.
Envie este prompt diretamente na caixa de entrada da Web UI:
In my current workspace, help me develop a simple UI plugin visible in the Web UI: add a custom tab to the settings page (e.g. called "My Plugins", with some placeholder content on the page, no complex functionality needed). First read the dsh official docs to understand the UI plugin mechanism and how to add tabs to the settings page, implement per the official spec, tell me which profile to install to, how to see it in the interface (and tell me if you need to restart dsh or change config).Ele vai ler a documentação sozinho, julgar o stack tecnológico (tais plugins de interface geralmente precisam de TypeScript e build front-end, ele vai lidar com isso sozinho), implementar, e dizer como verificar. Siga as instruções dele para reiniciar o dsh, e você verá a nova aba na página de configurações.
Isto é eu realmente executando uma vez — ele foi de ler a documentação, escrever o plugin, instalar no profile, até me dizer como ver na interface, como sair, tudo feito sozinho, até destacando os caminhos-chave:

Após reiniciar, vá para Configurações → Plugins, e o topo tem uma nova aba "My Plugins":

Um detalhe: este plugin é puro UI, sem comportamento do lado Host, então sem mudanças em settings.yaml / cordis.yml — tudo é carregado através dos bundles do profile. Reverter também é simples: apenas remova do array de bundles. Esta é outra manifestação de "tudo é plugin": até adicionar uma aba na interface é "instalar um plugin".
Armadilhas Comuns
| Problema | O que está acontecendo | Como lidar |
|---|---|---|
| Observador de eventos não imprime | session/event inscrito errado, ou plugin não carregado | Confirme o caminho de cordis.yml, sintaxe ctx.on |
| Tantos eventos que você não consegue lê-los | Uma conversa naturalmente tem dezenas de eventos | Primeiro olhe entre turn/start e turn/end, essa é a tronco principal |
| Quer desenhar conteúdo diretamente na conversa | Isso requer um renderizador React, avançado | Primeiro se familiarize com o fluxo de eventos e configurações, avançado depois |
Reporta Cannot find package | Plugin usa dependências externas que não estão instaladas | npm install o pacote correspondente no diretório do plugin |
O que você aprendeu neste capítulo
- [ ] Indique as três categorias de capacidades de plugin de UI: troca de skin / layout e painel / contribuição de conteúdo de sessão
- [ ] Entenda o mecanismo central de que "a interface é um consumidor do fluxo de eventos"
- [ ] Use
ctx.on('session/event', ...)para se inscrever em eventos de sessão - [ ] Use o observador de eventos para ver o fluxo de eventos por trás de uma única conversa
- [ ] Saiba que plugins de UI podem adicionar abas personalizadas à página de configurações
