Documentos para desenvolvedores de plug-ins
Crie plug-ins para o aplicativo de desktop AnBoWork: adicione novas ferramentas para a IA, encaixe seu próprio painel próximo a uma sessão, envie notificações do sistema, analise novos formatos de arquivo. Um manifest.json mais um script de entrada são suficientes para começar.
01Visão geral
Um plugin AnBoWork é um programa Node.js simples. Após a instalação, o aplicativo o bifurca como um processo filho autônomo (Nó puro, sem API Electron) e se comunica com ele por meio de mensagens entre processos. Nenhum pacote SDK é necessário; tudo que você precisa é process.on('message') e process.send().
Tudo o que um plugin pode fazer é declarado estaticamente em manifest.json: a página de consentimento de pré-instalação e a revisão do mercado podem informar quais ferramentas ele adiciona e quais permissões são necessárias sem executar nenhum código de plugin. Toda a UI (ícones da barra de ferramentas, configurações, paleta de comandos, menus de contexto) é renderizada pelo host a partir da declaração; o código do plugin nunca é executado dentro da janela principal. Somente visualizações encaixadas e painéis flutuantes são seu próprio HTML e são executados em páginas isoladas em área restrita.
Visão geral das capacidades
| Campo de manifesto | Capacidade | Onde os usuários veem |
|---|---|---|
tools | Adicione ferramentas que podem ser chamadas para a IA | A IA os chama automaticamente durante uma conversa; chamadas de ferramenta são mostradas na sessão |
views | Visualização persistente ancorada na barra lateral direita da sessão | Um ícone extra na barra de ferramentas da sessão abre sua página à direita |
ui | Janela flutuante independente | Aberto no menu "⋯" na lista de plugins |
sessionAction | Ícone de ação persistente na barra de ferramentas da sessão | Um clique executa a ferramenta que você especifica |
configuration | Entradas na página de configurações | Configurações → Configuração do plugin; valores são passados com cada chamada |
commands | Entradas da paleta de comandos Ctrl/Cmd+K | Paleta de comandos |
keybindings | Atalhos de teclado globais | Uma combinação de teclas aciona um comando |
menus | Itens do menu de contexto da sessão | O menu "⋯"/clique com o botão direito em uma linha da sessão |
documentParsers | Analisar arquivos colocados na caixa de entrada | Chamado automaticamente quando o usuário descarta um arquivo correspondente |
activationEvents | Comece junto com o aplicativo | Invisível; para plug-ins que precisam de temporizadores em segundo plano |
permissions | Declarar as permissões necessárias | Página de consentimento de pré-instalação |
02Início rápido
Um plugin mínimo precisa de apenas dois arquivos.
1. Escreva manifesto.json
2. Escreva o script de entrada
3. Instale no aplicativo
Abra AnBoWork → barra superior "Ferramentas" → "Plugins" → "Instalar localmente" no canto superior direito e escolha a pasta do plugin (ou um zip dela). Uma página de consentimento lista as permissões declaradas e todas as ferramentas antes da instalação; confirme para ativar.
4. Experimente
Em qualquer sessão, diga à IA "peça ao plugin para dizer olá para Alice". Com base na descrição da ferramenta a IA decide chamar say_hello, e a chamada e seu resultado aparecem na sessão.
03Campos de manifesto
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id | string | Sim | Estilo de domínio reverso, por ex. com.example.my-plugin. Somente letras, dígitos, pontos e hifens. Imutável uma vez criado; instalar o mesmo ID novamente é tratado como uma reinstalação. |
name | string | Sim | Nome do plug-in. Junto com description ele é inserido no modelo como contexto, portanto o inglês é recomendado. |
version | string | Sim | Versão semântica; o mercado o utiliza para detectar atualizações. |
description | string | Sim | Uma frase descrevendo o que o plugin faz (Inglês). |
author | string | Não | Autor. |
readme | string | Não | A descrição longa mostrada na página de detalhes do mercado suporta Markdown. As imagens dentro dele devem ser https URLs — caminhos relativos para arquivos agrupados no zip não são suportados. |
icon | string | Não | Ícone mostrado na lista do mercado e na página de detalhes — um caminho relativo para um arquivo compactado no zip (por exemplo, icon.png). Deve ser PNG, não SVG, pelo menos 128×128. |
main | string | Sim | Script de entrada, relativo à pasta do plugin. .. escapar da pasta não é permitido. |
permissions | string[] | Sim | network / filesystem / notifications; pode ser uma matriz vazia. Consulte "Modelo de permissão". |
tools | object[] | Sim | Declarações de ferramentas; pode ser uma matriz vazia. Consulte "Ferramentas e protocolo de chamada". |
documentParsers | object[] | Não | Capacidade de análise de arquivos. |
ui | object | Não | Painel flutuante:{ entry, title } |
views | object[] | Não | Visualizações encaixadas:{ id, title, icon, entry, width? } |
sessionAction | object | Não | Ícone da barra de ferramentas, no máximo um por plugin. |
configuration | object[] | Não | Lista de entradas de configurações. |
commands | object[] | Não | Entradas da paleta de comandos. |
keybindings | object[] | Não | Atalhos. command deve fazer referência ao tool de uma entrada em commands[], caso contrário a instalação será rejeitada. |
menus | object | Não | Apenas a localização session/context está disponível por enquanto. |
activationEvents | string[] | Não | Apenas onStartupFinished por enquanto. |
Convenções de idioma para texto
O texto do manifesto tem dois públicos. Para o modelo: name, description, tools[].description, tools[].parameters.*.description. Escreva-os em inglês; os modelos entendem as descrições das ferramentas em inglês e preenchem os parâmetros de maneira mais confiável. Para pessoas: tools[].summary (resumo de uma linha na página de consentimento), ui.title, views[].title, sessionAction.tooltip, configuration[].label, commands[].title e title dentro de menus. Escreva-os no idioma dos usuários-alvo.
04Modelo de permissão
permissions deve refletir honestamente o que o código realmente faz. A página de consentimento de pré-instalação lista cada um para que os usuários possam decidir se desejam instalar; a revisão do mercado também verifica a declaração em relação ao código.
| Permissão | Quando deve ser declarado | Como o anfitrião trata isso |
|---|---|---|
filesystem | Ler ou gravar arquivos do usuário (ler código do projeto, gerar documentos, armazenar dados na pasta inicial) | Consentimento informado, mostrado ao usuário. |
network | Fazendo qualquer solicitação de rede (APIs de terceiros, downloads) | Consentimento informado, mostrado ao usuário. |
notifications | Mostrando notificações do sistema por meio do RPC reverso show_notification | Enforced: chamá-lo sem a declaração retorna host_error e nenhuma notificação é mostrada. |
filesystem e network são atualmente declarações de nível de consentimento, não uma sandbox de tempo de execução: o host não intercepta fs ou fetch. É exactamente por isso que as declarações devem ser honestas. Plugins que não são declarados são rejeitados na análise do mercado e perdem a confiança do usuário quando descobertos. Não declare demais (permissões não utilizadas fazem os usuários hesitarem).Privacidade e dados
context.cwd é a pasta do projeto do usuário e pode conter código-fonte e configurações confidenciais; os argumentos da ferramenta podem conter a conversa do usuário. Não envie esses dados pela rede, a menos que o recurso exija e, quando o fizer, indique em description e summary o que é enviado e para quem. Mantenha os próprios dados persistentes do plug-in em um arquivo na pasta inicial do usuário com o nome do ID do plug-in, para que seja fácil encontrá-los durante a desinstalação.
05Ferramentas e protocolo de chamada
Declaração
| Campo | Descrição |
|---|---|
name | Nome da ferramenta em letras minúsculas e sublinhados, exclusivo em todo o aplicativo (é registrado com o modelo junto com ferramentas integradas e ferramentas de outros plug-ins). |
description | Descrição do modelo (inglês). Indique três coisas: o que a ferramenta faz, o que o usuário diz quando deve ser chamada e quando não deve ser chamada. Este é o campo mais importante para saber se a IA usa seu plugin. |
summary | Resumo legível de uma linha mostrado na página de consentimento. Opcional, mas fortemente recomendado; caso contrário, uma descrição truncada será mostrada. |
parameters | Objeto JSON Schema padrão com description em cada propriedade. O modelo preenche os argumentos dele e o host os transmite sem validação extra, portanto, verifique os campos obrigatórios em seu código. |
renderAs | Opcional; atualmente apenas checklist: o host renderiza o array todos dos argumentos de chamada como um cartão de lista de verificação, veja abaixo. |
tools[] aqui — sessionAction.tool, commands[].tool e o campo tool dentro de menus são verificados apenas como strings não vazias no momento da instalação; o host não verifica se o nome foi declarado em tools[] e ainda despacha uma chamada com esse nome quando o botão, atalho ou item de menu é acionado. Portanto, uma ação puramente acionada pela IU pode ser realizada inteiramente em seu próprio index.js sem nunca aparecer em tools[] - mas a IA nunca poderá vê-la ou chamá-la. Se você deseja que a mesma ação seja acionada tanto pelo clique quanto pela IA agindo em uma solicitação de chat, declare o mesmo nome em tools[] também, para que ambos os pontos de entrada compartilhem um manipulador; se for para permanecer apenas na interface do usuário, deixe-o não declarado - não há necessidade de adicionar uma entrada apenas para parecer completo.Protocolo de mensagem
O host envia call_tool; o plugin deve responder com tool_result ou tool_error carregando o mesmo requestId. Uma chamada sem resposta em 30 segundos expira e o modelo recebe um erro.
content aceita apenas blocos text e image (imagem como base64 data mais mimeType); outros tipos são descartados. details são dados estruturados arbitrários que nunca são alimentados no modelo; é para renderização da interface do usuário do host e suas próprias visualizações encaixadas.
Resultados do arquivo: cartões de arquivo
Renderização da lista de verificação: lista de verificação renderAs
Escrevendo uma boa descrição
Descreva o gatilho no imperativo ("Chame isso quando o usuário pedir…") e exclusões de estado ("Não chame isso para…"). Se o resultado for um arquivo, peça ao modelo para fazer referência ao link do arquivo retornado em vez de afirmar que ele foi gerado. Se os argumentos forem encaminhados para uma API de geração externa, diga em qual idioma eles devem estar. Evite frases simples como "gerenciar todos"; o modelo não saberá quando usar a ferramenta.
06Visualizações ancoradas (visualizações)
Uma visualização encaixada é uma página persistente na barra lateral direita da sessão: um ícone extra aparece na barra de ferramentas da sessão e seu HTML aparece à direita quando aberto. O estado da página (posição de rolagem, rascunhos) sobrevive à troca de sessões e ao colapso/expansão, a mesma semântica de uma visualização da barra lateral do VS Code.
| Campo | Descrição |
|---|---|
id | Único dentro do plugin. |
title | Texto da dica de ferramenta para o ícone (legível por humanos). |
icon | Escolha na lista de permissões de hosts: git-branch, checklist. Mantém os ícones consistentes em todo o aplicativo; imagens personalizadas não são aceitas. |
entry | Arquivo HTML, relativo à pasta do plugin. |
width | Largura do painel padrão opcional em pixels, 240 a 640, padrão 360. Os usuários podem arrastar para redimensionar e o tamanho é lembrado. |
Tempo de execução da página
A página é executada em uma sandbox (sandbox + contextIsolation, sem Node, sem acesso aos dados do aplicativo host) e só pode se comunicar com seu próprio processo de plugin através dos poucos métodos em window.pluginHost. Traga seus próprios estilos; é recomendado seguir o esquema claro/escuro do aplicativo, como no exemplo abaixo.
Padrão recomendado: no primeiro carregamento, chame uma de suas próprias ferramentas de consulta com invoke() e faça com que ela retorne dados estruturados em details; depois, envie todas as alterações do processo do plugin com ui_push em vez de polling. Quando a IA altera os dados da conversa, o painel é atualizado imediatamente.
07Painel flutuante (ui)
ui: { entry, title } declara uma janela flutuante independente (900×700) que os usuários abrem no menu “⋯” na lista de plugins; ele é destruído de perto. O ambiente da página e a API window.pluginHost são idênticos às visualizações encaixadas, e ui_push é entregue tanto ao painel flutuante quanto às visualizações encaixadas. Adequado para grandes painéis abertos ocasionalmente; use views para conteúdo que deve ficar próximo à sessão.
08Ícone da barra de ferramentas da sessão (sessionAction)
No máximo um ícone persistente por plugin. Clicar nele chama tool com argumentos vazios, então essa ferramenta deve fazer algo significativo sem parâmetros.
| Campo | Descrição |
|---|---|
tool | Ferramenta para ligar ao clicar. |
icon | Nome do ícone permitido. |
tooltip | Passe o texto. |
visibleTool | Opcional. Quando definido, ele é chamado com argumentos vazios antes da renderização e o booleano details.visible no resultado decide se o ícone será exibido. Útil para verificações de tempo de execução como "a pasta atual é um repositório git". |
09Configurações (configuração)
As entradas declaradas aparecem na configuração do plugin na página de configurações. O host armazena valores alterados pelo usuário e os passa como context.config em cada call_tool (digitado por id, voltando para defaultValue), quer a chamada venha da IA, do ícone da barra de ferramentas ou do seu painel. Você nunca precisa pedir por eles.
| type | Renderizado como | tipo de valor padrão |
|---|---|---|
select | Lista de escolha única; as opções vêm de optionsTool | string |
boolean | Alternar interruptor | boolean |
string | Entrada de texto, confirmada em desfoque | string |
number | Entrada de número | number |
10Paleta de comandos/atalhos/menu de contexto
Todos os três são pontos de entrada diferentes para "chamar uma ferramenta com argumentos vazios"; um plugin pode declarar vários.
| Campo | Forma | Descrição |
|---|---|---|
commands | { tool, icon, title }[] | Mostrado na paleta de comandos Ctrl/Cmd+K e acionado após o usuário pesquisá-lo. |
keybindings | { command, key }[] | command deve ser igual a tool de uma entrada em commands[]. key usa a notação mod+shift+g, onde mod é Cmd em macOS e Ctrl em outro lugar. Os conflitos com outros atalhos não são verificados estaticamente, portanto escolha combinações incomuns. |
menus | { "session/context": { tool, icon, title }[] } | Adicionado ao menu em uma linha da sessão. Apenas este local está disponível por enquanto. |
11Analisadores de documentos (documentParsers)
Quando o usuário coloca um arquivo na caixa de entrada, o host procura analisadores declarados por plug-ins habilitados por tipo MIME e passa o conteúdo do arquivo como base64 para o toolName correspondente. Esta não é uma ferramenta que a IA decide chamar, então não liste também a ferramenta do analisador em tools, ou ela será exposta como uma ferramenta que pode ser chamada pela IA.
12RPC reverso (host_request)
O processo do plugin não possui API Electron. Quando precisa de uma capacidade real do sistema, ele envia host_request para o host, que responde com host_response ou host_error. Este canal é totalmente independente de call_tool; você pode usá-lo ao lidar com uma chamada de ferramenta ou com um temporizador.
| capability | params | result | Condição prévia |
|---|---|---|---|
show_notification | { title, body?, viewId? } | { shown: true } / { shown: false, reason: "disabled" | "unsupported" } | Requer a permissão notifications. Retorna desativado em vez de um erro quando o usuário desativou as notificações da área de trabalho nas configurações. Quando viewId aponta para uma de suas visualizações encaixadas, clicar na notificação traz o aplicativo para frente e expande essa visualização. |
render_pdf | { outputPath, title, content } | {} | o conteúdo é Markdown; o host renderiza um PDF em outputPath com seu renderizador integrado. |
13Vida útil
| Estágio | Comportamento |
|---|---|
| Começar | Preguiçoso por padrão: não iniciado com o aplicativo, bifurcado na primeira chamada para uma de suas ferramentas (IA, ícone da barra de ferramentas, painel, comando, análise de documento). Os plug-ins que declaram activationEvents: ["onStartupFinished"] iniciam logo após a inicialização do aplicativo; use isso apenas para plug-ins que precisam de temporizadores de fundo (lembretes, pesquisas), não para plug-ins de ferramentas comuns. |
| Residente | Uma vez iniciado, o processo permanece ativo e é reutilizado nas chamadas de ferramenta. Você pode armazenar em cache o estado na memória, mas suponha que ele possa ser reiniciado a qualquer momento. |
| Colidir | Se o processo for encerrado inesperadamente, o host o reinicia: imediatamente e depois de 5 e 15 segundos. Após 3 falhas consecutivas, ele será marcado como "travado" e não será mais tentado; os usuários veem o status na página do plugin. Todas as chamadas em voo retornam erros. |
| Desativar/desinstalar/reinstalar | O processo é encerrado e as visualizações encaixadas e os painéis flutuantes são destruídos; uma reinstalação substitui a pasta inteira. |
| Registros | Seus stdout/stderr são gravados no arquivo de log do aplicativo prefixado com o ID do plugin. Simples console.log é suficiente para depuração; consulte "Depuração e perguntas frequentes". |
ELECTRON_RUN_AS_NODE=1, cwd é a pasta de instalação do plugin e a versão do Node corresponde ao Electron fornecido com o aplicativo. Não dependa de nenhum pacote instalado globalmente e não presuma que npx existe.14Embalagem e publicação
Embalagem
Compacte a pasta do plugin com manifest.json na raiz do arquivo. Se você tiver dependências de terceiros, agrupe-as primeiro em um único arquivo com esbuild/webpack, em vez de enviar o node_modules inteiro.
Publicação no mercado
AnBoWork → Ferramentas → Plugins → guia "Marketplace" → "Publicar plugin" no canto superior direito e, em seguida, carregue o zip. Os envios passam por revisão, que verifica se a declaração do manifesto corresponde ao código (especialmente as permissões). Uma vez aprovado, outros usuários podem encontrá-lo e instalá-lo no mercado, e a IA pode instalar plug-ins verificados para usuários automaticamente quando considerar necessário.
Atualizações
Clique em version e publique novamente. O aplicativo compara a versão instalada com a versão do marketplace e solicita a atualização; a reinstalação mantém o estado ativado e os valores de configurações do usuário.
15Exemplo completo: Todo Quadrante
Um plugin real e funcional (cortado): a IA pode adicionar e remover todos, a barra lateral direita mostra um quadro que é atualizado em tempo real e pode enviar lembretes de notificação do sistema. O encadeamento desses três abrange o protocolo da ferramenta, pushes de visualização encaixada e RPC reverso.
16Depuração e perguntas frequentes
| Sintoma | Causa e correção |
|---|---|
| A validação do manifesto falha na instalação | Verifique cada campo na tabela "Campos de manifesto", conforme a mensagem indica: formato de id, principal/entrada não deve conter .., o ícone deve estar na lista de permissões, o comando de atalhos de teclado deve apontar para uma ferramenta existente nos comandos, largura entre 240 e 640. |
| A IA nunca liga para minha ferramenta | Quase sempre um problema description: o gatilho não está claro ou não está escrito em inglês. Consulte "Escrevendo uma boa descrição". Verifique também se o nome da ferramenta não colide com outra ferramenta. |
| A chamada expira (30 s) | O script de entrada não respondeu com tool_result. Normalmente requestId não foi ecoado de volta, a mensagem type está escrita incorretamente ou o script foi lançado na inicialização e encerrado. Procure linhas prefixadas com [plugin:your-id] no log do aplicativo. |
| O status do plug-in mostra "travado" | 3 partidas consecutivas com falha. Geralmente um require de um pacote ausente; executar node index.js na pasta do plugin o reproduz. Após a correção, desative e ligue o plugin novamente na página do plugin. |
| Painel abre em branco | Caminho entry errado ou um erro JS na página. A página roda em um sandbox sem o require do Node; apenas window.pluginHost está disponível. |
| A notificação não aparece | Verifique em ordem: o manifesto declara notifications; o resultado não é shown:false (o usuário desativou as notificações da área de trabalho); o sistema operacional permite notificações de AnBoWork. |
| Os valores das configurações não são legíveis | Os valores estão em message.context.config[id], não em params. |
Localização do arquivo de log
| SO | Caminho |
|---|---|
| macOS | ~/Library/Logs/AnBoWork/main.log |
| Windows | %USERPROFILE%\AppData\Roaming\AnBoWork\logs\main.log |