Plugins

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.

O kernel

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.

Inversão de dependência

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.

Descoberta

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.)

Estado de liga/desliga

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.