/** * Los toolkits por tipo de nodo: qué herramientas expone cada nodo en modo * AI toolkit, en un solo sitio. * * ## Para qué (2026-09-24) * * Para que el gate «Block destructive tool calls» del AI Node pueda preguntar * por la OPERACIÓN y no sólo por el nombre. Hasta hoy sólo miraba el nombre * contra unos patrones (`delete_*`, `drop_*`…), así que `update_row` de Sheets * —que pisa una fila— pasaba con el gate encendido. Con esto, la herramienta * que el AI Node guardó al conectar (`nodeRefType` + `operationOverride`) se * resuelve aquí a su operación, y su `destructive` —que sale del verbo, ver * `clase-de-herramienta.ts`— decide. * * ## Lo que falta aquí, a propósito * * Social sigue con sus specs fuera de este paquete (armado por entidad desde * el registro de proveedores); WhatsApp se mudó el 2026-09-29. Quien consulte este registro tiene que componerlos * por su lado — {@link esOperacionDestructiva} devuelve `null` para ellos, que * significa «no lo sé», no «no es destructiva». Contacts se mudó el * 2026-09-24. De Social sí viven aquí sus NOMBRES desde el 2026-10-06, para el * bloqueo: ver `social-toolkit.ts`. * * ## El bloqueo por nodo y la puerta sin herramienta (2026-09-24) * * Abajo viven también las dos reglas que se aplican a TODA llamada a un nodo en * modo toolkit, en un solo sitio para que la api, hw-nodes, node-sdk y el * dashboard pregunten lo mismo: * * - «Block these tool calls»: el dueño bloquea herramientas en el nodo * (`blockedTools`, por nombre). Vale para todo tipo con toolkit * ({@link admiteBloqueo}); Social, desde el 2026-10-06. * - Sin herramienta no se corre: en modo toolkit un nodo sólo ejecuta la * herramienta que le nombran en `operation`. Un evento sin ella —una arista * vieja del lienzo— ya no corre la operación de «Single operation», que en * ese modo no se ve. Decisión de Ariel para los catorce toolkits * ({@link TIPOS_CON_TOOLKIT}), no sólo los de este registro. * * `motivoParaNoCorrer` junta las dos y la llama node-sdk al registrar * cada handler, así que cubre todo camino que acabe en `handler.execute`. * * ## Dónde viven ahora las reglas [2026-10-12] * * En `toolkits-ligero.ts`, sobre un resumen generado de este registro: aquí * sólo queda el registro completo y lo que necesita las descripciones * (`herramientasQueLlegaronDespues`). Importar una regla desde aquí arrastraba * los ~40 toolkits a cada página del dashboard que preguntaba por el bloqueo. */ import { type HerramientaDelAgente, type OperacionDeToolkit } from './toolkits-ligero.js'; export { MENSAJE_SIN_HERRAMIENTA, MENSAJE_HERRAMIENTA_SIN_MARCA, NECESITAN_CUENTA, RESUMEN_DE_TOOLKITS, TIPOS_CON_TOOLKIT, admiteBloqueo, bloqueadasDe, bloqueadasPorDefecto, claveDeHerramientaDeToolkit, esOperacionDestructiva, herramientaBloqueadaEn, mensajeDeHerramientaBloqueada, motivoParaNoCorrer, nombresDeHerramientas, operacionDelResumen, tieneModoToolkit, } from './toolkits-ligero.js'; export type { HerramientaDelAgente, OperacionDeToolkit } from './toolkits-ligero.js'; /** * El registro COMPLETO: cada toolkit con sus descripciones y parámetros. Lo * necesitan la api y hw-nodes (para dárselo al modelo); para decidir basta el * resumen de `toolkits-ligero.ts`, que no carga ninguno. */ export declare const TOOLKITS_POR_TIPO: Readonly>; /** * La herramienta de un toolkit, ENTERA —con su descripción y sus parámetros, * aunque el tipo sólo publique lo de {@link OperacionDeToolkit}—, buscada por * su nombre interno (`updateRow`) O por el de la herramienta (`update_row`). * * Entera a propósito: la api lee sus `parameters` (el agente de voz sólo pasa * al nodo los argumentos declarados, `entradaDelNodo`). Para decidir —bloqueo, * destructiva— basta `operacionDelResumen`, que no carga ningún toolkit; por * eso las pantallas no importan ésta [2026-10-12]. */ export declare function operacionDeToolkit(nodeType: string | undefined | null, operacionONombre: string | undefined | null): OperacionDeToolkit | null; /** * Las herramientas que un toolkit ganó DESPUÉS de que el agente eligiera las * suyas de ese nodo, y que por eso le llegan solas. * * ## Por qué (2026-10-10) * * El panel guarda en el AI Node una COPIA de cada herramienta elegida, así * que una operación nueva de un toolkit no le llegaba a ningún agente que ya * lo usaba: había que abrir cada AI Node y añadirla a mano (pasó con * `list_hubspot_lists`). Ariel decidió que lleguen solas, salvo las que el * dueño del toolkit tenga bloqueadas. * * ## Qué cuenta como nueva * * Una herramienta con `desde` posterior a la PRIMERA vez que el agente eligió * herramientas de ESE nodo (`elegidaEl`, la más antigua de las suyas; las * guardadas antes de que existiera el campo cuentan como «nunca»), que el * agente no tiene, que no quitó a propósito (`descartadas`, claves de * {@link claveDeHerramientaDeToolkit}) y que no está bloqueada en el nodo. * Sólo para nodos que el agente ya usa: un toolkit que no tiene no le llega. * * 🔥 La primera y no la última: con la última, añadir HOY otra herramienta * de ese nodo movía la referencia a hoy y le quitaba en silencio todas las * que le habían llegado solas. Con la primera, una que el agente no quiera * se quita a mano y queda en `descartadas`. * * `desde` es un día y `elegidaEl` un instante: «2026-10-11» es MENOR que * «2026-10-11T09:00…», así que lo elegido ese mismo día ya la vio en el * selector y no se le añade. */ export declare function herramientasQueLlegaronDespues(p: { nodeType: string; nodeId: string; herramientas: ReadonlyArray; /** El nodo del toolkit, para saber qué tiene bloqueado. */ entidad: unknown; descartadas?: ReadonlyArray | null; }): OperacionDeToolkit[];