Skip to content

CH 22 · Plugins de UI: Troque a Skin, Adicione Painéis, Injete Conteúdo no dsh

Número de palavras~2.420 palavrasTempo~20 minPré-requisitosCH 17 (Instalação de Plugins)NívelReproduzível

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:

PluginO que faz
dsh-themeTroca a skin da Web UI (um cartão de tema aparece em Configurações → Aparência)
dsh-oil-sticky-promptFixa a mensagem mais recente do usuário no topo ao rolar
dsh-better-sidebarBancada 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:

js
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:

powershell
New-Item -ItemType Directory -Path "ui-demo\src" -Force

Crie ui-demo\src\event-watch.js:

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):

yaml
- insert:
    - id: event-watch
      name: 'file:///E:/seu-workspace/ui-demo/src/event-watch.js'

Passo 3: Execute o headless Uma Vez

powershell
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:

text
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

ProblemaO que está acontecendoComo lidar
Observador de eventos não imprimesession/event inscrito errado, ou plugin não carregadoConfirme o caminho de cordis.yml, sintaxe ctx.on
Tantos eventos que você não consegue lê-losUma conversa naturalmente tem dezenas de eventosPrimeiro olhe entre turn/start e turn/end, essa é a tronco principal
Quer desenhar conteúdo diretamente na conversaIsso requer um renderizador React, avançadoPrimeiro se familiarize com o fluxo de eventos e configurações, avançado depois
Reporta Cannot find packagePlugin usa dependências externas que não estão instaladasnpm 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

Open Source · MIT · Community Driven