Usar un plugin
config lo tipa el plugin (definePlugin<MiConfig>()): una opción
desconocida es un error de compilación, y una configuración declarada con la
interfaz de configuración del plugin se pasa tal cual.
bot.plug(plugin, config?) devuelve una función unplug (no el bot, así
que las llamadas a plug() no se encadenan). Al llamarla, primero ejecuta el
uninstall(ctx) del plugin, si lo tiene, y después revierte, de lo más nuevo
a lo más antiguo, lo que el plugin registró vía ctx.bot:
- comandos (
command()), matchers (when(),onMessage(),onType()), conversaciones y disparadores de flows (conversation(),use(flow)); - hooks (
before(),after(),onError(),hook()); - plugins anidados (
ctx.bot.plug()); - flows registrados en caliente con
ctx.bot.registerFlow(), o creados (no reemplazados) conctx.bot.replaceFlow(); - cada callback de
ctx.onDispose(fn).
ctx.bot.on() / once()),
herramientas inyectadas (ctx.bot.provide() / ctx.tools), mensajes de
idioma (ctx.bot.locale()), tareas programadas (schedule(), every(),
delay()), handlers de inactividad (onIdle()), un flow que replaceFlow()
sobrescribió (no se restaura), el estado de handoff, escrituras en el store ni
timers o conexiones propios. Deshazlos en ctx.onDispose() (o en
uninstall()). Llamar a unplug dos veces no hace nada. Si install() lanza de
forma síncrona, lo que alcanzó a registrar se revierte antes de que el error te
llegue; si devuelve una promesa que rechaza, el rechazo va al evento 'error'
y no se revierte nada.
Dependencias entre plugins (requires)
Un plugin puede listar por nombre los plugins que necesita. bot.plug() los
comprueba antes de ejecutar install() y lanza un error descriptivo si falta
alguno:
inbox después no
desenchufa crm. Un plugin anidado dentro de otro (ctx.bot.plug() desde
install()) puede requerir a su padre.
Una instancia por nombre (multiple)
bot.plug() rechaza un plugin cuyo name ya está enchufado en el bot, así un
plugin registrado dos veces por error nunca ejecuta sus handlers dos veces:
multiple: true en su spec (todas las instancias deben ponerlo). Cada
instancia se desenchufa por separado y cualquiera de ellas cumple requires.
Incluido: slashCommands
Config:{ greeting?: string; unknownMessage?: string }. El prefijo de
comandos es una opción del bot (new Bot({ commandPrefix })), no del
plugin. Las respuestas son textos internos en el
idioma del bot.
Los
/comandos desconocidos reciben automáticamente una respuesta de
“comando desconocido” (unknownMessage).
Crear un plugin
Plugin simple
Plugin configurable con cleanup
Estructura de un plugin
definePlugin(spec) devuelve el spec sin cambios, tipado. Un plugin también
puede ser una función (config) => spec.
El
ctx que recibe install:
Compartir herramientas (inyección de dependencias)
Comparte herramientas entre handlers, hooks y plugins sin usar globales.El problema que resuelve
Cómo funciona
1. Registrar una herramienta
bot.provide(name, value) devuelve this, así que las llamadas se pueden
encadenar:
2. Tiparla
ctx.tools se tipa con la interfaz DefaultTools, que está vacía hasta que la
amplías (declaration merging). Declara cada herramienta una vez, junto al código
que la registra, y todos los handlers la ven tipada:
@botmesh/ai tipa ctx.tools.ai, e importar @botmesh/nlu tipa
ctx.tools.nlu. En JavaScript no hay nada que declarar.
3. Usarla en cualquier handler
4. También disponible en hooks y plugins
install(ctx) de un plugin también recibe ctx.tools, así que los
plugins pueden consumir herramientas registradas en otro lugar (o
registrar las suyas con ctx.bot.provide). Fuera de los handlers (una tarea
programada, un webhook), léelas de bot.injectTools.
Quitar una herramienta
bot.unprovide(name) quita una herramienta y devuelve true si existía.
Desenchufar un plugin no deshace sus provide(), así que hazlo en
ctx.onDispose():
Múltiples herramientas
DefaultTools como arriba.
Paquetes de plugins
Además deslashCommandsPlugin, estos paquetes traen plugins listos:
- IA —
@botmesh/ai: respuestas con LLM (aiPlugin), con herramientas, memoria y RAG y streaming. - Voz —
@botmesh/voice(voicePlugin): voz a texto para las notas de voz entrantes y respuestas con texto a voz. - Integraciones —
@botmesh/chatwoot,@botmesh/tickets,@botmesh/moderation,@botmesh/dialogflowy@botmesh/nlu(intenciones locales). - Trazas —
@botmesh/otel(otelMetricsPlugin):bot.metrics()y los spans del bot en OpenTelemetry.
@botmesh/rag (recuperación para aiPlugin) se
explica en memoria y RAG.
Siguientes pasos
- Scheduler — tareas programadas, que leen las herramientas de
bot.injectTools - Ejemplo: rate limiter — plugin completo