DeepSeek Harness: Configuração de Plugin
Última atualização: 2026-08-31
Configuração é o "botão de controle" de um plugin — chaves de API, timeouts, toggles de funcionalidade, esses parâmetros específicos do ambiente não devem ser hardcoded mas externalizados através de um sistema de configuração. Schemastery é o framework de configuração declarativa do Cordis: defina uma vez, automaticamente obtenha segurança de tipo, formulários UI, validação e documentação.
📋 Pré-requisitos: Ter completado 15-define-tool.md, capaz de escrever ferramentas básicas
1. O Que Você Vai Aprender
- Sistema de configuração declarativa Schemastery
- Schema.string/number/boolean/object/array
- .required()/.default()/.description()
- Configuração aninhada com Schema.object
- Exibição de configuração na página de configurações da Web UI
- Validação de configuração e mensagens de erro
- Atualizações dinâmicas de configuração
2. Configuração Declarativa Schemastery
(1) Conceito Básico
▶ Exemplo 1: Config com Schemastery
Schemastery é a biblioteca de definição de Schema built-in do Cordis, inspirada em Zod e JSON Schema, mas projetada especificamente para configuração interativa.
import { Schema } from '@deepseek-ai/cordis'
export const Config = Schema.object({
apiKey: Schema.string().required().description('Chave de API para o serviço'),
maxRetries: Schema.number().default(3).description('Número máximo de tentativas'),
debug: Schema.boolean().default(false).description('Habilitar logging de depuração')
})
(2) Comparação com JSON Schema
| Dimensão | Schemastery | JSON Schema |
|---|---|---|
| Sintaxe | API encadeável | Objeto JSON |
| Inferência de tipo | ✅ Automática | ❌ Manual |
| Formulários UI | ✅ Auto-gerados | ❌ Ferramentas extras necessárias |
| Valores padrão | .default() |
Campo default |
| Descrições | .description() |
Campo description |
| Validação | Validadores encadeáveis | pattern/min/max etc. |
(3) Uso em Plugin
▶ Exemplo 2: Config em um Plugin
export const Config = Schema.object({
apiKey: Schema.string().required(),
maxRetries: Schema.number().default(3)
})
export const name = 'my-plugin'
export function apply(ctx: Context) {
// Tipo de ctx.config é automaticamente inferido
ctx.logger.info(`Chave de API: ${ctx.config.apiKey}`)
ctx.logger.info(`Máx. tentativas: ${ctx.config.maxRetries}`)
}
O framework valida os valores de configuração fornecidos pelo usuário e os injeta em ctx.config.
3. Tipos de Schema
(1) Schema.string
Schema.string() // Qualquer string
Schema.string().required() // Obrigatório
Schema.string().default('hello') // Valor padrão
Schema.string().description('Seu nome') // Descrição
Schema.string().pattern(/^[a-z]+$/) // Validação regex
Schema.string().min(1).max(100) // Limites de comprimento
(2) Schema.number
Schema.number() // Qualquer número
Schema.number().default(0) // Valor padrão
Schema.number().min(0).max(100) // Limites de faixa
Schema.number().step(1) // Passo (para sliders UI)
Schema.integer() // Inteiro
(3) Schema.boolean
Schema.boolean() // Booleano
Schema.boolean().default(false) // Padrão false
(4) Schema.object
Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
ssl: Schema.boolean().default(false)
})
(5) Schema.array
Schema.array(Schema.string()) // Array de strings
Schema.array(Schema.string()).default([]) // Padrão array vazio
Schema.array(Schema.object({ // Array de objetos
name: Schema.string().required(),
url: Schema.string().required()
}))
(6) Schema.union / Schema.const
// Valores enum
Schema.union(['read', 'write', 'execute'])
// Constante
Schema.const('fixed-value')
// Enum com descrições
Schema.union([
Schema.const('read').description('Acesso somente leitura'),
Schema.const('write').description('Acesso de leitura e escrita'),
Schema.const('execute').description('Acesso total')
])
(7) Schema.dict
// Tipo dicionário
Schema.dict(
Schema.string(), // Tipo do valor
Schema.string() // Tipo da chave (opcional)
)
4. Modificadores Encadeáveis
(1) .required()
Marca como obrigatório. Quando o usuário não fornece, o framework reporta erro e bloqueia o carregamento.
apiKey: Schema.string().required()
(2) .default(value)
Define um valor padrão. Quando o usuário não fornece, o padrão é usado sem erro.
maxRetries: Schema.number().default(3)
timeout: Schema.number().default(30000)
(3) .description(text)
Adiciona uma descrição a um item de configuração, exibida na Web UI como texto de dica para rótulos de formulário.
apiKey: Schema.string().required()
.description('Chave de API obtida no painel do serviço')
(4) .min() / .max()
Limites de faixa numérica ou comprimento de string:
port: Schema.number().min(1).max(65535).default(8080)
name: Schema.string().min(1).max(50)
(5) .pattern()
Validação regex:
email: Schema.string().pattern(/^[^@]+@[^@]+\.[^@]+$/)
.description('Endereço de email válido')
(6) .step()
Passo numérico, afeta a precisão do slider na UI:
timeout: Schema.number().min(1000).max(300000).step(1000).default(30000)
(7) Uso Combinado
▶ Exemplo 3: Config Completa com Múltiplos Modificadores
const Config = Schema.object({
apiKey: Schema.string()
.required()
.pattern(/^sk-[a-zA-Z0-9]+$/)
.description('Chave de API DeepSeek (começa com sk-)'),
maxTokens: Schema.number()
.min(1).max(32768)
.default(4096)
.description('Máximo de tokens por requisição'),
model: Schema.union(['deepseek-chat', 'deepseek-reasoner'])
.default('deepseek-chat')
.description('Modelo a usar'),
temperature: Schema.number()
.min(0).max(2).step(0.1)
.default(0.7)
.description('Temperatura de amostragem')
})
5. Configuração Aninhada
(1) Objetos Aninhados
const Config = Schema.object({
database: Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
name: Schema.string().required(),
ssl: Schema.boolean().default(false)
}).default({ host: 'localhost', port: 5432, ssl: false }),
cache: Schema.object({
enabled: Schema.boolean().default(true),
ttl: Schema.number().default(3600).description('TTL do cache em segundos')
}).default({ enabled: true, ttl: 3600 })
})
(2) Aninhamento Profundo
const Config = Schema.object({
llm: Schema.object({
provider: Schema.union(['deepseek', 'openai']).default('deepseek'),
deepseek: Schema.object({
apiKey: Schema.string().required(),
model: Schema.string().default('deepseek-chat')
}),
openai: Schema.object({
apiKey: Schema.string(),
endpoint: Schema.string().default('https://api.openai.com/v1')
})
})
})
(3) Schema Reutilizável
const ConnectionSchema = Schema.object({
host: Schema.string().default('localhost'),
port: Schema.number().default(5432),
timeout: Schema.number().default(5000)
})
const Config = Schema.object({
primary: ConnectionSchema.description('Conexão primária'),
replica: ConnectionSchema.description('Conexão réplica')
})
6. Exibição de Configuração na Página de Configurações da Web UI
(1) Geração Automática de Formulários
Config definida com Schemastery automaticamente gera formulários na página de configurações da Web UI:
| Tipo Schema | Controle UI |
|---|---|
Schema.string() |
Campo de texto |
Schema.number() |
Campo numérico / slider |
Schema.boolean() |
Switch toggle |
Schema.union() |
Select dropdown |
Schema.array() |
Editor de lista |
Schema.object() |
Painel agrupado |
Schema.dict() |
Editor chave-valor |
(2) Exibição de Descrição
A .description() de cada campo aparece como texto de dica abaixo do input:
┌─────────────────────────────────────────┐
│ Chave de API │
│ [sk-xxxxxxxxxxxxxxx ] │
│ Chave de API DeepSeek (começa com sk-) │
├─────────────────────────────────────────┤
│ Máx. Tokens │
│ [4096 ] │
│ Máximo de tokens por requisição │
└─────────────────────────────────────────┘
(3) Feedback de Validação
Quando o input do usuário não corresponde ao Schema, a UI mostra feedback imediato:
┌─────────────────────────────────────────┐
│ Chave de API │
│ [invalid-key ] │
│ ❌ Deve corresponder ao padrão: /^sk-[a-zA-Z0-9]+$/ │
└─────────────────────────────────────────┘
7. Validação de Configuração e Mensagens de Erro
(1) Validação na Inicialização
Quando um plugin carrega, o framework automaticamente valida sua configuração:
const Config = Schema.object({
port: Schema.number().min(1).max(65535)
})
// Config do usuário: port: -1
// → Erro: Config inválida para plugin my-plugin:
// port: deve ser >= 1
Quando a validação falha, o plugin não é carregado e o erro é exibido no terminal.
(2) Segurança de Tipo
TypeScript automaticamente infere o tipo de ctx.config a partir da definição Config:
const Config = Schema.object({
apiKey: Schema.string().required(),
maxRetries: Schema.number().default(3)
})
export function apply(ctx: Context) {
ctx.config.apiKey // string ✅
ctx.config.maxRetries // number ✅
ctx.config.unknown // Erro de tipo ❌
}
(3) Validação Customizada
const Config = Schema.object({
startDate: Schema.string().required(),
endDate: Schema.string().required()
}).validate((value) => {
if (new Date(value.startDate) > new Date(value.endDate)) {
throw new Error('startDate deve ser anterior a endDate')
}
return value
})
8. Atualizações Dinâmicas de Configuração
(1) Escuta de Mudanças de Configuração
export function apply(ctx: Context) {
ctx.on('config/updated', (newConfig) => {
ctx.logger.info('config atualizada:', newConfig)
// Ajustar comportamento com base na nova config
})
}
(2) Fluxo de Atualização a Quente
graph LR
UI[Usuário modifica config] --> VALID[Validação Schema]
VALID --> APPLY[Aplicar nova config]
APPLY --> EMIT[Emitir config/updated]
EMIT --> RELOAD[Plugin responde à atualização]
(3) Configs Que Requerem Reinicialização
Algumas mudanças de configuração (como números de porta ou injeção de dependência) requerem reinicialização:
export function apply(ctx: Context) {
ctx.on('config/updated', (config) => {
if (config.port !== ctx.config.port) {
ctx.logger.warn('mudança de porta requer reinicialização')
}
})
}
❓ Perguntas Frequentes
Config?export const Config. Outros nomes não serão reconhecidos.ctx.on('config/updated') para responder a mudanças de configuração..hidden(), que exibe um campo de senha na UI: typescript apiKey: Schema.string().required().hidden() plugins.plugin-name.config, isolado entre si.📖 Resumo
- Schemastery é o framework de configuração declarativa do Cordis: defina uma vez, automaticamente obtenha segurança de tipo, formulários UI e validação
- Suporta Schema.string/number/boolean/object/array/union/dict
- Modificadores encadeáveis: .required()/.default()/.description()/.min()/.max()/.pattern()
- Schema.object aninhado organiza configurações complexas; definições Schema reutilizáveis
- Web UI auto-gera formulários; descrição mostra como dicas; falhas de validação dão feedback imediato
- Mudanças de configuração são monitoradas via eventos config/updated; algumas mudanças requerem reinicialização
📝 Exercícios
1. ⭐ Básico: Adicione Config à ferramenta file_count com defaultPath (string, padrão diretório atual) e maxDepth (number, padrão 10). Verifique a geração do formulário na página de configurações da Web UI.
2. ⭐⭐ Intermediário: Escreva um plugin de configuração de múltiplas conexões. Config contém connections (array de objetos, cada um com host/port/username/password), definido com Schema.object aninhado. Verifique: erros quando campos obrigatórios estão ausentes, valores padrão preenchem corretamente.
3. ⭐⭐⭐ Desafio: Crie uma configuração com validação customizada: startDate e endDate devem satisfazer startDate < endDate; maxRetries deve ser um inteiro positivo. Teste: insira valores inválidos e confirme que as mensagens de erro de validação são exibidas corretamente na Web UI.