Saltar al contenido principal

Sistema de plugins: integraciones con el core y entre plugins

Además del contrato básico (manifiesto, router, NopalPluginRegistry), hay acoplamientos que funcionan hoy pero no están declarados en ningún manifiesto ni formalizados. Esta página los describe con su estado.

IntegraciónEstado
NopalCameraCard (core → camera-viewer)convention
AI_TOOLS (plugin → NOPAL Intelligence)experimental
Hooks de proyecto NopalPluginContext y NopalProject.addElement (consumidos por font-library)experimental
Material compartido spoolman:<id> (spoolman → cotizador)convention
Imports directos del core desde un pluginconvention

NopalCameraCard: el core monta un widget del plugin​

Estado: convention. camera-viewer expone, además de su sección, el widget window.NopalCameraCard (frontend/camera-card.js). El propio core lo monta en las fichas de dispositivo de Klipper, láser, CNC y Marlin.

window.NopalCameraCard?.mount(contenedor, {
deviceType: 'klipper', // 'klipper' | 'laser' | 'cnc' | 'marlin'
deviceId: 'mi-impresora',
compact: true // opcional
});

window.NopalCameraCard?.unmount(contenedor);

El core lo invoca con encadenamiento opcional (?.): si camera-viewer no está instalado, la ficha simplemente no muestra cámara. Es la forma en que el core usa una función de un plugin sin dependerse de él. No hay contrato formal: la firma de mount y unmount es lo que hoy usa el core.

AI_TOOLS: un plugin ofrece herramientas a NOPAL Intelligence​

Estado: experimental. Si el módulo de entrada del backend de un plugin (backend/router.py) define una variable AI_TOOLS, NOPAL Intelligence la recoge y expone esas herramientas.

  • Cada elemento debe ser un Tool de backend.services.ai_tools. Se importa de forma perezosa.
  • Un valor inválido (no iterable, o un elemento que no es un Tool) se omite con una advertencia; nunca rompe la capa de IA.
  • Cada Tool debe declarar policy_action (Action.USE_PLUGIN o Action.CONFIGURE_PLUGIN) e indicar si es read_only. Las herramientas que no cumplen se omiten con una advertencia en el log.
  • No hay flujo de autoconfirmación: la identidad sale siempre de la sesión de quien conversa.
  • Solo se consideran módulos de plugins instalados.
  • Las herramientas respetan la autorización de quien conversa: existe una prueba específica de ello en el core.

Ningún plugin oficial lo declara hoy. Puede cambiar sin aviso.

NopalPluginContext: contexto de proyecto opcional​

Estado: experimental. font-library consulta, de forma opcional, window.NopalPluginContext (con getCurrentProject() o una propiedad currentProject) y window.__NOPAL_PROJECT_CONTEXT__ para saber el proyecto activo y su material. Ningún repositorio revisado define ese proveedor: el plugin funciona sin él.

NopalProject.addElement: un gancho que el core no implementa​

font-library entrega su resultado con window.NopalProject.addElement(detalle) y, si no existe, dispara el evento cancelable nopal:add-project-element en window. El core no define ni uno ni otro: hoy el botón Agregar al proyecto muestra un aviso de éxito pero los datos no se guardan en ningún sitio (así lo indica el README del plugin). Queda a la espera de que el core lo implemente.

Material compartido entre spoolman y cotizador​

Estado: convention. Un material_id con la forma spoolman:<id_de_carrete> enviado a POST /api/pricing/quote toma el costo desde spoolman en lugar de pricing_config.json. Spoolman sigue siendo la fuente de verdad del inventario; el plugin solo guarda identificadores de referencia. Ninguno de los dos manifiestos lo declara.

Imports directos del core​

Estado: convention. Los plugins con backend importan módulos del core con imports absolutos, por ejemplo backend.auth_deps. arduino-accessories importa además backend.services.laser_service y backend.services.marlin_printer_service para saltarse los puertos USB que ya usa un láser/CNC o una impresora Marlin.

Es un acoplamiento duro: si el core renombra o mueve esos módulos, el plugin se rompe, y ningún mecanismo versiona esa interfaz. Por eso las pruebas de un plugin necesitan un checkout del core (NOPAL_CORE_ROOT).