Plugins são a forma de estender o Koris sem tocar no core. Há duas famílias de plugin —
canais e ferramentas — que compartilham o
mesmo formato e o mesmo kernel, descritos abaixo. A pasta plugins/ também abriga
skills, mas skills são um tipo diferente de extensão: Markdown
puro, sincronizado pelo SkillSyncService em vez do kernel descrito nesta página.
plugins/registry.ts contém o núcleo agnóstico de família: ExtensionPoint,
PluginRegistry e buildRegistry. As duas famílias se apoiam nele. Na inicialização,
core/src/app.ts monta um único PluginRegistry compartilhado a partir dos plugins de
canal e de ferramenta juntos.
Um plugin importa somente do contracts.ts da sua própria família e do
plugins/registry.ts compartilhado. Ele nunca importa de core/src/, nem do
contracts.ts da outra família.
O core depende dos SDKs e injeta serviços concretos no sentido contrário, por um
PluginContext (canais) ou ToolPluginContext (ferramentas) montado na raiz de
composição, core/src/app.ts. Cada pasta de plugin expõe uma função create(context)
que recebe esse contexto.
A única exceção documentada é plugins/tools/create-tool/, que acessa
scripts/scaffold-tool.ts para gerar novas pastas de ferramenta.
O scanner carrega todo subdiretório da pasta de uma família — plugins/channels/ e
plugins/tools/. Arquivos soltos nessas pastas, como o contracts.ts, são ignorados.
Adicionar um plugin significa adicionar uma pasta; para ferramentas, o
pnpm scaffold:tool <nome> cria uma para você. Nenhuma alteração no core é necessária.
(plugins/skills/ fica ao lado dessas duas, mas não é varrida aqui — veja
Skills para como é sincronizada.)
A ativação fica no banco, na tabela plugin_settings: family, name e enabled, com
chave primária (family, name). O resolvePluginEnabled lê a linha e recorre a um
padrão definido em código quando ainda não existe registro.
A alternância vale ao vivo — sem reiniciar. O PluginCatalogSingleton mantém cada par
{ family, name } registrado para que a API administrativa liste os plugins sem
revarrer o disco. Veja o dashboard administrativo para o
painel de Plugins.
Plugins de canal continuam guardando seus segredos e a flag de confiança
allow_unlisted_senders no config.yml de cada pasta; somente a flag enabled foi para
o banco.