Design de Capacidades Requeridas de Skills
Status: nota de design; este PR prossegue com a Opção B e deixa
required-capabilities como uma proposta futura.
Contexto
O Web Shell pode renderizar blocos de código delimitados personalizados por meio de seu renderizador de markdown. A proposta do renderizador de gráficos usa um bloco de código delimitado echarts-fulldata para que o modelo possa retornar uma opção completa do ECharts e um payload de dataset que o Web Shell renderiza como um gráfico interativo.
Esse contrato de saída só é útil em clientes que podem renderizá-lo. Na CLI, em clientes ACP ou em qualquer outra superfície sem um renderizador correspondente, a mesma resposta apareceria como um grande bloco de código em vez de um gráfico.
A proposta inicial da skill de gráfico integrada dependia de texto para informar ao modelo que o formato é para o Web Shell. Esta é uma proteção suave. Se a skill for exposta em uma sessão não-Web-Shell, o modelo ainda poderá escolher um formato de saída que o cliente não consegue renderizar.
Para o PR atual, o Qwen Code mantém o ponto de extensão do renderizador no Web Shell, mas não inclui o qwencode-viz no core. O pacote Web Shell inclui um modelo de skill copiável e não carregado automaticamente, e os hosts devem instalar ou injetar essa skill somente quando também registrarem um renderizador echarts-fulldata.
Problema
O Qwen Code precisa de uma maneira clara de decidir se uma skill específica de host deve ser mostrada ao modelo e aos usuários.
Para o qwencode-viz, a pergunta concreta é:
- O core deve suportar um campo de metadados de skill genérico
required-capabilities? - Ou o
qwencode-viznão deve ser uma skill integrada do core, e sim fornecido apenas por clientes Web Shell que a instalam ou injetam?
Objetivos
- Impedir que skills específicas de renderizador sejam expostas quando o cliente atual não puder satisfazer seu contrato de saída.
- Manter os lembretes de skill na inicialização, a ativação explícita de skills, a descoberta de comandos de barra e a validação de skills consistentes.
- Evitar codificar o
qwencode-vizcomo um caso especial. - Preservar o comportamento existente das skills quando nenhum requisito de capacidade for declarado.
- Manter o design extensível para capacidades futuras de host, não apenas para o ECharts.
Não Objetivos
- Implementar o próprio renderizador do ECharts.
- Redesenhar toda a negociação de capacidades entre cliente e servidor.
- Alterar a semântica do frontmatter de skills existentes.
- Resolver alterações de capacidade em sessões compartilhadas de múltiplos clientes na primeira versão.
Mecanismos Relacionados Atuais
A base de código já possui vários controles de visibilidade, mas nenhum representa capacidades de renderização do cliente:
disable-model-invocation: impede que uma skill seja invocada automaticamente pelo modelo.user-invocable: controla se uma skill integrada está disponível como um comando.paths: restringe a disponibilidade da skill aos caminhos de workspace correspondentes.skills.disabled: desativa skills configuradas.allowedTools: atualmente usado pelo carregamento de skills integradas para ocultar skills orientadas a cron quando as ferramentas de cron não estão disponíveis.supportedModesdo comando de barra: filtra comandos por modo de execução.- Objetos de capacidade do Daemon e ACP: descrevem o suporte ao protocolo ou ao cliente, mas atualmente não estão conectados à exposição de skills.
Não existe um frontmatter de skill required-capabilities ou equivalente. Adicioná-lo seria um novo contrato de skill.
Opção A: Adicionar required-capabilities
Adicionar um campo de frontmatter de skill genérico:
---
name: qwencode-viz
description: Render analytical charts in Web Shell using echarts-fulldata fenced code blocks.
required-capabilities:
- markdown.codeBlock.echarts-fulldata
---Quando o cliente/sessão atual não anuncia todas as capacidades listadas, a skill é tratada como indisponível.
Nomenclatura de Capacidades
Use capacidades de string com namespace:
markdown.codeBlock.echarts-fulldataIsso mantém o campo genérico, tornando o contrato preciso:
markdown: a capacidade pertence ao markdown renderizado.codeBlock: a capacidade se aplica à renderização de blocos de código delimitados.echarts-fulldata: a string de linguagem/info específica suportada pelo renderizador.
Exemplos futuros poderiam ser:
markdown.codeBlock.vega-litemarkdown.codeBlock.mermaid-interactiveartifact.openUrl
Metadados de Skill
Adicionar requiredCapabilities?: string[] à configuração da skill após analisar a chave de frontmatter required-capabilities.
Ambos os caminhos de análise de skill devem compreender o campo:
packages/core/src/skills/skill-load.tspackages/core/src/skills/skill-manager.ts
O campo deve ser opcional. Ausente ou vazio significa que a skill não tem requisito de capacidade do cliente.
Fonte de Capacidade em Runtime
Adicionar capacidades do cliente/sessão à configuração de runtime:
interface ConfigParameters {
clientCapabilitiesProvider?: () => ReadonlySet<string>;
}Expor um helper em Config, por exemplo:
config.getClientCapabilities(): ReadonlySet<string>Em seguida, centralizar a verificação:
function skillMeetsRequiredCapabilities(skill: Skill, config: Config): boolean {
return skill.config.requiredCapabilities.every((capability) =>
config.getClientCapabilities().has(capability),
);
}Pontos de Filtragem
O filtro de capacidade deve ser aplicado antes que as skills sejam expostas ao modelo ou ao usuário:
collectAvailableSkillEntriesempackages/core/src/tools/skill-utils.tsdeve ignorar skills cujas capacidades requeridas estão faltando. Isso mantém os lembretes de skill na inicialização, lembretes de delta, validação deSkillToole ativação invocável pelo modelo alinhados.BundledSkillLoaderdeve ignorar skills integradas indisponíveis ao criar comandos voltados para o usuário.SkillCommandLoaderdeve ignorar skills de sistema de arquivos indisponíveis ao criar comandos voltados para o usuário.
O invariante importante é que uma skill oculta do modelo não deve continuar aparecendo como um comando invocável, a menos que o projeto suporte intencionalmente uma substituição manual.
Registro no Web Shell
O Web Shell deve anunciar o suporte ao renderizador explicitamente, em vez de depender da presença de um callback opaco renderCodeBlock.
Por exemplo:
<WebShell
customization={{
markdown: {
renderableCodeBlockLanguages: ['echarts-fulldata'],
renderCodeBlock(info) {
// render custom blocks
},
},
}}
/>O cliente Web Shell pode mapear isso para:
markdown.codeBlock.echarts-fulldataIsso torna a declaração de capacidade estável, mesmo que o callback do renderizador contenha lógica personalizada, fallbacks ou múltiplos idiomas suportados.
Propagação no Daemon e ACP
Para sessões hospedadas ou baseadas em daemon, o conjunto de capacidades do cliente precisa chegar ao core antes que as skills sejam carregadas ou listadas. Uma versão mínima pode passar as capacidades ao criar uma sessão:
interface CreateSessionRequest {
clientCapabilities?: string[];
}O bridge do daemon, o SDK e o fluxo de criação de sessão ACP podem armazenar isso como uma configuração com escopo de sessão.
Para a primeira versão, as capacidades podem ter escopo de sessão. Se múltiplos clientes se conectarem à mesma sessão, o comportamento deve ser documentado como o uso das capacidades do momento da criação da sessão.
Prós
- Mantém o
qwencode-vizcomo uma skill integrada canônica. - Impede que contratos de saída específicos de host vazem para clientes não suportados.
- Cria um mecanismo reutilizável para skills futuras específicas de renderizador ou de host.
- Torna a dependência explícita e testável.
Contras
- Adiciona um novo campo de metadados de skill transversal.
- Requer a integração de capacidades de cliente/sessão nas superfícies Web Shell, daemon, SDK e ACP.
- Requer documentação cuidadosa para o comportamento de sessão compartilhada.
- Pode ser mais complexo do que o necessário se o
qwencode-vizfor a única skill esperada controlada por capacidade.
Opção B: Skill Fornecida pelo Cliente
Não adicionar um campo genérico required-capabilities. Em vez disso, evitar integrar o qwencode-viz no core. O cliente Web Shell, ou qualquer cliente que suporte o renderizador, fornece a própria skill.
Modelos de distribuição possíveis:
- O host do Web Shell instala
.qwen/skills/qwencode-viz/SKILL.md. - O pacote Web Shell distribui um modelo de skill opcional e não carregado automaticamente que um host pode copiar ou instalar quando a renderização de gráficos está habilitada.
- A integração do Web Shell distribui um pacote de skill de extensão.
- A integração do Web Shell injeta instruções de modelo equivalentes somente quando seu renderizador de gráficos está habilitado.
Neste modelo, a skill está disponível apenas porque o cliente de renderização escolheu fornecê-la.
Prós
- Alteração mínima no core.
- Nenhum novo contrato global de metadados de skill.
- A disponibilidade de capacidade é naturalmente de propriedade do cliente que implementa o renderizador.
- Evita a integração com daemon ou ACP, a menos que o cliente já tenha um mecanismo de injeção de skill.
Contras
- Nenhuma skill integrada canônica, a menos que todos os clientes copiem o mesmo conteúdo.
- Mais carga para cada integrador do Web Shell.
- Usuários que alternam entre clientes podem ver uma disponibilidade de skill inconsistente.
- Não cria uma salvaguarda geral para skills futuras específicas de host.
- Mais difícil de testar no core porque a disponibilidade depende de instalação ou injeção externa.
Recomendação
Para este PR, use a Opção B.
Isso mantém o sistema de skills do core inalterado e evita expor instruções echarts-fulldata em clientes não suportados. O hook do renderizador do Web Shell continua útil para qualquer renderizador de bloco de propriedade do host, enquanto as instruções de modelo específicas de gráficos se tornam um opt-in explícito do host.
A longo prazo, discuta isso como uma decisão de limite de produto/API.
Escolha a Opção A se os mantenedores esperam que o Qwen Code suporte mais contratos de saída renderizados pelo cliente ao longo do tempo. Nesse caso, required-capabilities é um pequeno contrato geral que garante que a exposição de skills seja correta entre CLI, Web Shell, ACP e clientes futuros.
Escolha a Opção B se for esperado que o qwencode-viz permaneça como uma extensão exclusiva do Web Shell e os mantenedores não queiram que as skills do core dependam de recursos de renderização do cliente. Nesse caso, a skill integrada atual deve ser removida do core e fornecida por clientes Web Shell que suportam echarts-fulldata.
O padrão futuro recomendado é a Opção A somente se os mantenedores estiverem confortáveis em tornar as capacidades de cliente/sessão parte do sistema de skills. Caso contrário, mantenha as skills de renderizador de host como propriedade do cliente.
Questões em Aberto
- As capacidades devem ter escopo de sessão, escopo de requisição ou escopo de cliente?
- Capacidades ausentes devem ocultar comandos invocáveis pelo usuário ou apenas ocultar a ativação de skills invocáveis pelo modelo?
- Os nomes das capacidades devem ser strings de forma livre ou validados em relação a um registro conhecido?
- Skills indisponíveis devem ser totalmente ocultadas de
/skillsou mostradas como desativadas com um motivo? - Deve haver uma substituição manual para usuários que desejam intencionalmente emitir blocos brutos
echarts-fulldataem clientes não suportados? - O nome do campo deve ser
required-capabilities,requires-capabilitiesouclient-capabilities?
Plano de Validação
Se a Opção A for implementada, adicione testes para:
- Análise de frontmatter em ambos os caminhos de análise de skill.
collectAvailableSkillEntriesocultando uma skill quando as capacidades estão ausentes.- A mesma skill aparecendo quando as capacidades estão presentes.
- Interação com
paths,skills.disablededisable-model-invocation. - Visibilidade de comandos de
BundledSkillLoadereSkillCommandLoader. - Mapeamento do Web Shell de linguagens de bloco de código suportadas para capacidades do cliente.
- Criação de sessão Daemon ou ACP preservando o conjunto de capacidades.
- Testes de integração de skills integradas existentes, para garantir que skills sem
required-capabilitiespermaneçam inalteradas.
Migração
Skills existentes não requerem migração porque o novo campo é opcional.
Para o caminho atual da Opção B, remova a skill de gráfico das skills integradas do core. O modelo do pacote Web Shell não deve ser carregado automaticamente pelo core; os hosts aderem instalando-o ou injetando-o.
Se a Opção A for aceita, adicione:
required-capabilities:
- markdown.codeBlock.echarts-fulldataa um futuro qwencode-viz integrado.
Se a Opção B for aceita, remova a skill de gráfico das skills integradas do core e documente como os clientes Web Shell podem instalá-la ou injetá-la quando registrarem um renderizador echarts-fulldata.