Desenvolvimento de Plugins DSH — Padrão Oficial
Esta skill é o padrão único para o desenvolvimento de plugins DeepSeek Harness (DSH): ela converge as convenções espalhadas em tutoriais, manuais de referência e diretórios gerados em fluxos de trabalho executáveis, regras rígidas e listas de verificação. Tudo no DSH é um plugin — adaptadores de modelo, registros de ferramentas, logs de sessão e até o próprio agent loop — portanto, agir de acordo com esta skill é estender o DSH da maneira como ele próprio é arquitetado.
Escopo
- Desenvolvimento de plugins DSH no estilo repositório interno e baseado em arquivos: escrever pacotes de plugin, registrar linhas
cordis.yml, patch overlay, desenvolver ferramentas, conectar modelos, empacotar e instalar. - O desenvolvimento de pacotes workspace dentro do monorepo DSH (
packages/<group>/<pkg>) também está no escopo desta skill (references/workspace-package.md). - Esta skill não cobre: plugins dinâmicos em sessão (fluxos
cordis_define/cordis_run) e edição combinada de agent presets — esses são cobertos por skills especializadas ou ferramentas oficiais de cada implantação.
Regras Rígidas (obrigatórias em qualquer cenário)
- A interface é a referência gerada. Nomes de serviço, métodos públicos, assinaturas de eventos, chaves
ctxdevem seguir as páginas de subsistema geradas automaticamente e as interfaces TypeScript do repositório; não deduza a API completa a partir de nomes de serviço, exemplos ou código antigo, nem mantenha uma lista estática separada. - Todas as contribuições são efeitos colaterais. Todo registro feito via
ctx(escuta de eventos, ferramentas, adaptadores,ctx.effect) é automaticamente desfeito ao desinstalar o plugin; não crie efeitos colaterais em nível de processo/página no escopo do módulo; assinaturas de terceiros que não retornam um disposer devem ter seu mecanismo de limpeza investigado ativamente. - Listeners waterfall devem chamar
next(). Não chamarnext()significa intencionalmente curto-circuitar os listeners downstream (usado para interceptação/gateway), não é opcional. - Falhe ruidosamente. Se
applylançar exceção, o processo é encerrado; se a validação de configuração falhar, relate o erro explicitamente; o schema deve expressar restrições completas por si só, não engula erros silenciosamente em tempo de execução. - Dependências obrigatórias com
inject, dependências opcionais comctx.get()e verificação de nulidade. Não useinjectpara evitar a verificação deundefined; também não acesse diretamentectx.xxxsem declarar a injeção — serviços não declarados, quando avaliados pelo resolvedor de serviços, podem resultar emundefined. - Configuração sempre com Schemastery. Exporte
interface Confige umSchemade mesmo nome; valores padrão devem estar no schema; não exporte objetos comuns comoConfig; todo parâmetro que possa ser alterado em diferentes implantações deve entrar na configuração. executede ferramentas retorna valores JSON padrão, não blocos de conteúdo. Texto voltado para humanos deve ficar emoutput.render; estratégias de implantação/hooks não devem ser embutidos no corpo da ferramenta.- Visível ao modelo é o mesmo que registrado. Qualquer nova entrada visível ao modelo deve cair em um mecanismo que possa ser reconstruído a partir dos logs de sessão (novo evento persistente ou via
agent.inject()), com uma asserção de invariante em tempo de execução. - Painéis de configuração do npm devem priorizar
ctx.connection.rpc. Métodos do processo principal chamados por painéis de configuração no navegador devem, prioritariamente, usar RPC de Conexão (ctx.connection.rpc.handle+ctx.connection.rpc.call); o modelo está em references/connection-rpc.md. São proibidos:@Remotepuro, manifest typert escrito à mão,createRequirependurado no código-fonte do harness. O caminho completo com saída do gerador Typert e exportação viapackage.jsonde./typert+./remote, consumido porctx.remote.$mount(), ainda é válido.
Fluxos de Trabalho Padrão
Cenário A: Criar um novo plugin
- Determine o que o plugin vai contribuir (serviço? ferramenta? escuta de eventos?) e use a tabela "Local de Pertencimento de Novos Comportamentos" em references/seams.md para escolher o mecanismo.
- Crie
src/<nome>.ts, exportandoname,inject(opcional),apply(ctx, config?). Comece com a forma de função; troque para a forma de classeServicequando precisar expor um serviço. - Loop de desenvolvimento local (código-fonte checkout):
mkdir -p scratch-plugin/src
# scratch-plugin/cordis.yml — patch overlay; caminho do plugin deve ser absoluto
- insert:
- id: hello
name: '/caminho/absoluto/para/deepseek-harness/scratch-plugin/src/meu-plugin.ts'
pnpm dsh web --patch ./scratch-plugin/cordis.yml # abre http://127.0.0.1:3080
- Verifique o carregamento e descarregamento: o log de inicialização deve aparecer e, ao parar, os recursos devem ser realmente limpos (references/plugin-anatomy.md).
Cenário B: Adicionar uma ferramenta a um modelo
inject: ['tools'], usedefineToolpara definir (name/description/parameters/output/execute).- Implemente de acordo com a convenção
executeem references/tools.md: DSL de schema para declarar parâmetros e saída,executeretornando valor JSON padrão, respeitarexec.signal, opcionalmentepresentationMeta/cartão UI. - Quando precisar de estratégia, use eventos
tools/*(pre-execute/guard/execute/post-execute/result); não embute a estratégia no corpo da ferramenta (exemplo de controle de acesso em references/plugin-forms.md). - Reinicie e faça o modelo realmente chamar a ferramenta para verificar.
Cenário C: Capacidade substituível (múltiplos provedores)
- Siga references/three-roles.md para dividir em três pacotes: Definição / Provedor / Consumidor (mescle papéis conforme necessário; não faça divisão preventiva).
- A Definição possui os tipos Request/Result e o Service abstrato; o Provedor implementa; o Consumidor expõe como ferramenta ou consumidor de serviço.
- No
cordis.yml, liste apenas as linhas do Provedor e do Consumidor; para trocar de provedor, mude apenas uma linha.
Cenário D: Conectar um novo provedor de modelo
- Estenda
LlmAdapterimplementandostream(), emitindo fragmentos conforme o protocoloStreamChunk; erros useLlmErrorcom código estável (ou termine in-band comfinish { kind: 'error' | 'aborted' }); cada requisição HTTP deve agregarattributionHeaders()e passar osignal. ctx.llm.registerAdapter(['<provedor>'], adapter); opcionalmente sobrescrevaresolveModel()/listModels().- Na composição, configure
provider/modeldoagent-looppara verificação. Veja references/llm-adapter.md (inclui 7 obrigações de protocolo).
Cenário E: Empacotar e instalar para entrega
- Crie um pacote de composição:
package.jsondeclarandodsh.bundle(apontando paracordis.patch.yml); linhas de patch referenciam o plugin pelo nome do pacote; pacotes de biblioteca apenas para importação não declaramdsh.bundle. - Instalação:
dsh plugin --profile <nome> add <pkg>; primeiro executedsh --profile <nome> --dump-configpara verificar as camadas, depois inicie. - Lembre-se da ordem das camadas e da semântica de substituição de linha inteira (references/packaging.md).
Cenário F: Criar um novo pacote no monorepo DSH
Siga a lista passo a passo de references/workspace-package.md: criar o pacote (package.json invariants/tsconfig/src/README) → registrar na configuração raiz → topologia e nomenclatura do pacote (tabela de papéis) → estrutura README Model Experience → comandos de verificação.
Consulta Rápida de Decisão
| Eu quero... | Mecanismo | Detalhes |
|---|---|---|
| Expor capacidades para outros plugins | Service (forma de classe) | references/services.md |
| Consumir capacidades existentes | inject ou ctx.get() | references/services.md |
| Comunicação entre plugins / pontos de extensão | ctx.on / ctx.emit etc. (cinco modos de distribuição) | references/events.md |
| Tornar algo configurável para o usuário | Config + Schemastery | references/config.md |
| Adicionar capacidade ao modelo | defineTool → ctx.tools.register (ou JSON Schema puro) | references/tools.md |
| Conectar novo provedor de modelo | LlmAdapter + ctx.llm.registerAdapter | references/llm-adapter.md |
| Dividir em capacidade substituível | Três papéis (Definition/Provider/Consumer) | references/three-roles.md |
| Distribuir um plugin | Pacote de composição + profile | references/packaging.md |
| Consultar serviços internos / local de pertencimento | Diretório seam, mapeamento de arquitetura | references/seams.md |
| Escopo / armazenamento de serviço / API Fiber | ctx.extend/isolate/provide/mixin, fiber.* | references/context-api.md |
| Hooks / UI / Painéis / Plugin de ponte de protocolo | Cinco formas de extensão + mapeamento funcionalidade→mecanismo | references/plugin-forms.md |
| Painel de configuração no navegador chamando processo principal | ctx.connection.rpc.handle/call, endpoint + envelope | references/connection-rpc.md |
| Criar novo pacote no repositório / nomenclatura | Lista de pacotes workspace + tabela de papéis | references/workspace-package.md |
Lista de Verificação Antes de Concluir
- Interface verificada com referência gerada (serviço/evento/chave ctx baseados na geração), não adivinhou API pelo nome.
- Todos os registros usam
ctx(evento/ferramenta/adaptador/effect); podem ser limpos ao desinstalar; limpeza sensível à ordem colocada no mesmoctx.effect. - Injeção de dependências obrigatórias declarada corretamente; dependências opcionais têm tratamento para
undefined. - Plugins com configuração:
Configusa Schemastery, valores padrão no schema, configuração inválida falha ruidosamente no carregamento. - Com ferramenta:
executeretorna valor JSON padrão;rendercuida da legibilidade humana; estratégia via eventostools/*; respeitaexec.signal; segurança de concorrência declarada (isConcurrencySafe— se não declarado,exclusive). - Com listener waterfall: chama e retorna
next()(a menos que haja curto-circuito intencional). - Com adaptador LLM: protocolo
StreamChunkcompleto (pares de bloco,indexna primeira ocorrência,usageantes definish,argumentscomo string JSON pura durante todo o processo); erros seguem um dos dois caminhos legais; campo não suportado lançaUNSUPPORTED; se precisar de replay nativo, emitefinish.replayState; passouattributionHeadersesignal. - Linhas de composição e ordem de camadas corretas; novas linhas visíveis em
--dump-config; sem registros residuais após HMR/reinicialização. - Se o conteúdo visível ao modelo mudou: caiu em mecanismo reconstruível a partir de logs.
- Painéis de configuração no navegador: priorizou
ctx.connection.rpc.handle/call; proibido@Remotepuro, manifest typert escrito à mão,createRequirependurado no código-fonte do harness; saída completa do gerador Typert +./typert+./remoteainda é válida. - Novo pacote workspace: invariantes do
package.json, exatamente um aggregate, nomenclatura conforme tabela de papéis, README com estrutura Model Experience, e constraints/typecheck/lint/build/hygiene tudo verde.
Arquivos de Referência (carregar sob demanda, não ler todos de uma vez)
Índice completo e tabela "quando ler" em references/README.md.
- references/plugin-anatomy.md — Leia ao escrever/modificar plugins, lidar com ciclo de vida ou HMR.
- references/services.md — Leia ao definir ou consumir serviços, injetar dependências.
- references/events.md — Leia ao usar eventos para comunicação, escutar pontos de extensão.
- references/config.md — Leia ao tornar um plugin configurável.
- references/context-api.md — Leia ao usar escopo, armazenamento de serviço ou API Fiber.
- references/three-roles.md — Leia ao dividir capacidades substituíveis.
- references/tools.md — Leia ao desenvolver ferramentas para modelo.
- references/llm-adapter.md — Leia ao conectar um novo provedor de modelo.
- references/plugin-forms.md — Leia ao escrever hooks/UI/plugins de ponte de protocolo.
- references/connection-rpc.md — Leia quando um painel de configuração npm precisar chamar métodos do processo principal; leia também ao encontrar
@Remotepuro / manifest escrito à mão /createRequirecomo ponte de código-fonte. - references/packaging.md — Leia ao empacotar, instalar e entregar plugins.
- references/workspace-package.md — Leia ao criar um novo pacote no monorepo.
- references/seams.md — Leia ao consultar serviços internos, local de pertencimento ou mapeamento de arquitetura.
Verificação
- Auto-checagem de formato:
nameem kebab-case e idêntico ao nome do diretório;descriptionnão vazio e conciso (esta skill deve ter no máximo 500 caracteres); corpo em Markdown padrão; todos os arquivos de referência mencionados existem de fato. - Nomenclatura do diretório: O nome desta skill (
name) édsh-plugin-dev, diferente do nome do repositório hospedadodsh-plugin-dev-skills— ao clonar/descompactar, a pasta deve ser renomeada paradsh-plugin-dev(igual aoname), caso contrário, carregadores que endereçam pelo nome do diretório podem não encontrar esta skill. - Em ambientes com CLI
skills-ref, execute:skills-ref validate ./dsh-plugin-dev - Disparar regressão: após modificar
description, execute o conjunto de avaliaçãoevals/trigger-queries.json(método no repositório evals/README.md). - Verificação de comportamento: Siga o Cenário A para criar um plugin mínimo (log de carregamento + limpeza ao descarregar) e depois o Cenário B para criar uma ferramenta
greet.