@hostwebhook/node-types 1.86.0 → 1.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/calendar-toolkit.d.ts +3 -0
- package/dist/calendar-toolkit.js +3 -2
- package/dist/clase-de-herramienta.d.ts +61 -0
- package/dist/clase-de-herramienta.js +153 -0
- package/dist/discord-toolkit.d.ts +2 -3
- package/dist/discord-toolkit.js +3 -6
- package/dist/docs-toolkit.d.ts +2 -1
- package/dist/docs-toolkit.js +3 -6
- package/dist/drive-toolkit.d.ts +9 -4
- package/dist/drive-toolkit.js +3 -4
- package/dist/esm/calendar-toolkit.d.ts +3 -0
- package/dist/esm/calendar-toolkit.js +3 -2
- package/dist/esm/clase-de-herramienta.d.ts +61 -0
- package/dist/esm/clase-de-herramienta.js +148 -0
- package/dist/esm/discord-toolkit.d.ts +2 -3
- package/dist/esm/discord-toolkit.js +3 -6
- package/dist/esm/docs-toolkit.d.ts +2 -1
- package/dist/esm/docs-toolkit.js +3 -6
- package/dist/esm/drive-toolkit.d.ts +9 -4
- package/dist/esm/drive-toolkit.js +3 -4
- package/dist/esm/gmail-operations.d.ts +2 -0
- package/dist/esm/gmail-operations.js +7 -6
- package/dist/esm/google-contacts-toolkit.d.ts +46 -0
- package/dist/esm/google-contacts-toolkit.js +180 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/mongo-toolkit.d.ts +47 -0
- package/dist/esm/mongo-toolkit.js +98 -0
- package/dist/esm/postgres-toolkit.d.ts +52 -0
- package/dist/esm/postgres-toolkit.js +85 -0
- package/dist/esm/registry.js +10 -0
- package/dist/esm/sheets-toolkit.d.ts +2 -1
- package/dist/esm/sheets-toolkit.js +3 -6
- package/dist/esm/slack-toolkit.d.ts +2 -3
- package/dist/esm/slack-toolkit.js +3 -4
- package/dist/esm/telegram-toolkit.d.ts +3 -0
- package/dist/esm/telegram-toolkit.js +3 -2
- package/dist/esm/toolkits.d.ts +111 -0
- package/dist/esm/toolkits.js +178 -0
- package/dist/gmail-operations.d.ts +2 -0
- package/dist/gmail-operations.js +11 -10
- package/dist/google-contacts-toolkit.d.ts +46 -0
- package/dist/google-contacts-toolkit.js +183 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +32 -1
- package/dist/mongo-toolkit.d.ts +47 -0
- package/dist/mongo-toolkit.js +101 -0
- package/dist/postgres-toolkit.d.ts +52 -0
- package/dist/postgres-toolkit.js +88 -0
- package/dist/registry.js +10 -0
- package/dist/sheets-toolkit.d.ts +2 -1
- package/dist/sheets-toolkit.js +3 -6
- package/dist/slack-toolkit.d.ts +2 -3
- package/dist/slack-toolkit.js +3 -4
- package/dist/telegram-toolkit.d.ts +3 -0
- package/dist/telegram-toolkit.js +3 -2
- package/dist/toolkits.d.ts +111 -0
- package/dist/toolkits.js +190 -0
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PostgreSQL AI Toolkit — las herramientas que un postgresAction expone cuando
|
|
4
|
+
* `aiEnabled` está encendido.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué las escrituras NO reciben SQL (2026-09-24, decisión de Ariel)
|
|
7
|
+
*
|
|
8
|
+
* El nodo, en modo de una operación, ejecuta el SQL que se le escribe: sus
|
|
9
|
+
* cinco operaciones son una etiqueta encima del mismo SQL crudo. Si el toolkit
|
|
10
|
+
* hiciera lo mismo, bloquear una herramienta no bloquearía nada — un
|
|
11
|
+
* `insert_rows` puede llevar un `DELETE` dentro de un `WITH`, y quien bloqueó
|
|
12
|
+
* `delete_rows` seguiría viendo desaparecer filas.
|
|
13
|
+
*
|
|
14
|
+
* Así que las tres escrituras reciben la tabla del nodo y JSON, y el SQL lo
|
|
15
|
+
* genera el handler, parametrizado y con los identificadores entrecomillados:
|
|
16
|
+
* el modelo no escribe SQL que se ejecute como escritura.
|
|
17
|
+
*
|
|
18
|
+
* ## Lo que queda con SQL, y cómo se contiene
|
|
19
|
+
*
|
|
20
|
+
* - `query_rows` recibe SQL, y corre dentro de una transacción **READ ONLY**:
|
|
21
|
+
* un `DELETE`, un `UPDATE` o un `CREATE` los rechaza el propio Postgres, no
|
|
22
|
+
* una expresión regular nuestra. Puede leer otras tablas —un JOIN hace
|
|
23
|
+
* falta a menudo—; el límite ahí lo pone el usuario de base de datos de la
|
|
24
|
+
* credencial.
|
|
25
|
+
* - `execute_sql` recibe SQL cualquiera, DDL incluido. Es la excepción
|
|
26
|
+
* consciente a «sólo la tabla del nodo»: SQL crudo no se puede vallar a una
|
|
27
|
+
* tabla. La contienen tres cosas: es siempre destructiva (el gate del AI
|
|
28
|
+
* Node la para si está encendido), se puede bloquear en el nodo, y el
|
|
29
|
+
* usuario de base de datos.
|
|
30
|
+
*
|
|
31
|
+
* Los textos van en inglés porque los lee el modelo.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.POSTGRES_TOOLKIT_BY_TOOL_NAME = exports.POSTGRES_TOOLKIT_SPECS = void 0;
|
|
35
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
36
|
+
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
37
|
+
const donde = (que) => p('where', `JSON object selecting the rows ${que}: each key is a column and each value the value it must equal, all of them at once, e.g. {"id": 42} or {"status": "pending", "customer_id": 7}. It cannot be empty — an empty condition would touch every row.`);
|
|
38
|
+
const parametros = () => p('params', 'Optional JSON array with the values for the $1, $2… placeholders in the SQL, e.g. ["paid", 100]. Always pass values this way instead of writing them into the SQL.', false);
|
|
39
|
+
exports.POSTGRES_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
40
|
+
{
|
|
41
|
+
operation: 'query',
|
|
42
|
+
label: 'Query rows',
|
|
43
|
+
toolName: 'query_rows',
|
|
44
|
+
description: 'Run a read-only SQL query (SELECT, WITH … SELECT) and return its rows, at most 200. It runs inside a READ ONLY transaction: a statement that writes is rejected by the database. Use it for lookups, counts, sums and joins.',
|
|
45
|
+
parameters: [
|
|
46
|
+
p('sql', 'The SELECT statement, with $1, $2… placeholders for values, e.g. SELECT * FROM orders WHERE status = $1 LIMIT 20.'),
|
|
47
|
+
parametros(),
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
operation: 'insertOne',
|
|
52
|
+
label: 'Insert rows',
|
|
53
|
+
toolName: 'insert_rows',
|
|
54
|
+
description: "Insert one or more rows into this node's table and return them as stored, with the values the database filled in (ids, defaults). It does not check for duplicates.",
|
|
55
|
+
parameters: [
|
|
56
|
+
p('rows', 'JSON object with one row, or a JSON array of rows. Keys are column names, e.g. {"name": "Ariel", "email": "a@b.c"}. A key that is not a column makes the call fail.'),
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
operation: 'update',
|
|
61
|
+
label: 'Update rows',
|
|
62
|
+
toolName: 'update_rows',
|
|
63
|
+
description: "Update the rows of this node's table that match a condition, overwriting the columns you set, and return them after the update. When no row matches it changes nothing.",
|
|
64
|
+
parameters: [
|
|
65
|
+
p('set', 'JSON object with the columns to overwrite and their new values, e.g. {"status": "shipped"}.'),
|
|
66
|
+
donde('to update'),
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
operation: 'delete',
|
|
71
|
+
label: 'Delete rows',
|
|
72
|
+
toolName: 'delete_rows',
|
|
73
|
+
description: "Delete the rows of this node's table that match a condition and return them as they were. This cannot be undone: when you are not sure which rows match, check with query_rows first.",
|
|
74
|
+
parameters: [donde('to delete')],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
operation: 'execute',
|
|
78
|
+
label: 'Execute SQL',
|
|
79
|
+
toolName: 'execute_sql',
|
|
80
|
+
description: 'Run any SQL statement — including ones that change the schema (CREATE, ALTER, DROP) — and return what it produces. It is not limited to this node\'s table. Prefer query_rows, insert_rows, update_rows or delete_rows whenever one of them can do the job.',
|
|
81
|
+
parameters: [
|
|
82
|
+
p('sql', 'The SQL statement, with $1, $2… placeholders for values.'),
|
|
83
|
+
parametros(),
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
]);
|
|
87
|
+
/** Las herramientas por nombre, para despachar una llamada del modelo. */
|
|
88
|
+
exports.POSTGRES_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.POSTGRES_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
package/dist/registry.js
CHANGED
|
@@ -412,6 +412,11 @@ exports.NODE_REGISTRY = {
|
|
|
412
412
|
allStateKey: "allMongoActions",
|
|
413
413
|
color: "#34d399",
|
|
414
414
|
testable: true,
|
|
415
|
+
/* Modo AI toolkit (2026-09-24): con `aiEnabled` el nodo sólo lo llama un
|
|
416
|
+
AI Node —como el resto de toolkits—, y una arista del lienzo no le
|
|
417
|
+
llevaría nada. Hasta que la api y el dashboard le den `aiEnabled`, el
|
|
418
|
+
campo no existe y esto devuelve `false`: no cambia nada. */
|
|
419
|
+
isToolOnly: (e) => e.aiEnabled === true,
|
|
415
420
|
},
|
|
416
421
|
postgresAction: {
|
|
417
422
|
type: "postgresAction",
|
|
@@ -424,6 +429,11 @@ exports.NODE_REGISTRY = {
|
|
|
424
429
|
allStateKey: "allPostgresActions",
|
|
425
430
|
color: "#336791",
|
|
426
431
|
testable: true,
|
|
432
|
+
/* Modo AI toolkit (2026-09-24): con `aiEnabled` el nodo sólo lo llama un
|
|
433
|
+
AI Node —como el resto de toolkits—, y una arista del lienzo no le
|
|
434
|
+
llevaría nada. Hasta que la api y el dashboard le den `aiEnabled`, el
|
|
435
|
+
campo no existe y esto devuelve `false`: no cambia nada. */
|
|
436
|
+
isToolOnly: (e) => e.aiEnabled === true,
|
|
427
437
|
},
|
|
428
438
|
notificationAction: {
|
|
429
439
|
type: "notificationAction",
|
package/dist/sheets-toolkit.d.ts
CHANGED
|
@@ -34,7 +34,8 @@ export interface SheetsToolkitSpec {
|
|
|
34
34
|
toolName: string;
|
|
35
35
|
description: string;
|
|
36
36
|
parameters: SheetsToolkitParameter[];
|
|
37
|
-
/**
|
|
37
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
38
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
38
39
|
destructive?: boolean;
|
|
39
40
|
}
|
|
40
41
|
export declare const SHEETS_TOOLKIT_SPECS: SheetsToolkitSpec[];
|
package/dist/sheets-toolkit.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.SHEETS_TOOLKIT_DEFAULTABLE = exports.SHEETS_TOOLKIT_BY_TOOL_NAME = exports.SHEETS_TOOLKIT_SPECS = void 0;
|
|
25
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
25
26
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
26
27
|
/*
|
|
27
28
|
* La hoja y la pestaña del nodo van como **defecto**, y el modelo puede
|
|
@@ -44,14 +45,13 @@ const p = (name, description, required = true, type = 'string') => ({ name, type
|
|
|
44
45
|
const hoja = () => p('spreadsheetId', "Id of the Google Sheets document — the long chunk of its URL, between /d/ and /edit.");
|
|
45
46
|
const pestana = () => p('sheetName', 'Name of the tab inside the document, exactly as it reads on its tab strip.');
|
|
46
47
|
const fila = (que) => p('row', `JSON object holding ${que}. Keys are the sheet's **header names**, spelled exactly as they appear in its title row: {"Name": "Ariel", "Email": "a@b.c"}. A key that is not a header makes the call fail, so when you do not know the headers, call get_rows first.`);
|
|
47
|
-
exports.SHEETS_TOOLKIT_SPECS = [
|
|
48
|
+
exports.SHEETS_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
48
49
|
{
|
|
49
50
|
operation: 'appendRow',
|
|
50
51
|
label: 'Append row',
|
|
51
52
|
toolName: 'append_row',
|
|
52
53
|
description: 'Add a new row at the bottom of the tab. It does not check whether the row already exists — when it might, use append_or_update_row instead so you do not duplicate it.',
|
|
53
54
|
parameters: [fila('the values of the new row'), hoja(), pestana()],
|
|
54
|
-
destructive: true,
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
operation: 'updateRow',
|
|
@@ -65,7 +65,6 @@ exports.SHEETS_TOOLKIT_SPECS = [
|
|
|
65
65
|
hoja(),
|
|
66
66
|
pestana(),
|
|
67
67
|
],
|
|
68
|
-
destructive: true,
|
|
69
68
|
},
|
|
70
69
|
{
|
|
71
70
|
operation: 'appendOrUpdateRow',
|
|
@@ -79,7 +78,6 @@ exports.SHEETS_TOOLKIT_SPECS = [
|
|
|
79
78
|
hoja(),
|
|
80
79
|
pestana(),
|
|
81
80
|
],
|
|
82
|
-
destructive: true,
|
|
83
81
|
},
|
|
84
82
|
{
|
|
85
83
|
operation: 'readRange',
|
|
@@ -116,9 +114,8 @@ exports.SHEETS_TOOLKIT_SPECS = [
|
|
|
116
114
|
* en el nodo, y la api la aplica.
|
|
117
115
|
*/
|
|
118
116
|
parameters: [p('title', 'Name of the new document.')],
|
|
119
|
-
destructive: true,
|
|
120
117
|
},
|
|
121
|
-
];
|
|
118
|
+
]);
|
|
122
119
|
/** Las herramientas por nombre, para despachar una llamada del modelo. */
|
|
123
120
|
exports.SHEETS_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.SHEETS_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
124
121
|
/**
|
package/dist/slack-toolkit.d.ts
CHANGED
|
@@ -38,9 +38,8 @@ export interface SlackToolkitSpec {
|
|
|
38
38
|
/** Descripción (más reglas de uso) que ve el LLM. */
|
|
39
39
|
description: string;
|
|
40
40
|
parameters: SlackToolkitParameter[];
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* salvo que la llamada traiga confirmación explícita. */
|
|
41
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
42
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
44
43
|
destructive?: boolean;
|
|
45
44
|
}
|
|
46
45
|
export declare const SLACK_TOOLKIT_SPECS: SlackToolkitSpec[];
|
package/dist/slack-toolkit.js
CHANGED
|
@@ -27,8 +27,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
27
27
|
exports.SLACK_TOOLKIT_BY_TOOL_NAME = exports.SLACK_TOOLKIT_SPECS = void 0;
|
|
28
28
|
exports.herramientasDeSlackPara = herramientasDeSlackPara;
|
|
29
29
|
const slack_operations_js_1 = require("./slack-operations.js");
|
|
30
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
30
31
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
31
|
-
exports.SLACK_TOOLKIT_SPECS = [
|
|
32
|
+
exports.SLACK_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
32
33
|
// ── Messages ─────────────────────────────────────────────────────
|
|
33
34
|
{
|
|
34
35
|
operation: 'sendMessage',
|
|
@@ -67,7 +68,6 @@ exports.SLACK_TOOLKIT_SPECS = [
|
|
|
67
68
|
p('channel', 'Channel where the message lives.'),
|
|
68
69
|
p('ts', 'Timestamp of the message to delete.'),
|
|
69
70
|
],
|
|
70
|
-
destructive: true,
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
operation: 'sendEphemeral',
|
|
@@ -146,7 +146,6 @@ exports.SLACK_TOOLKIT_SPECS = [
|
|
|
146
146
|
p('name', 'Channel name — lowercase, no spaces, max 80 chars.'),
|
|
147
147
|
p('isPrivate', 'Create a private channel instead of public. Default false.', false, 'boolean'),
|
|
148
148
|
],
|
|
149
|
-
destructive: true,
|
|
150
149
|
},
|
|
151
150
|
{
|
|
152
151
|
operation: 'inviteToChannel',
|
|
@@ -216,7 +215,7 @@ exports.SLACK_TOOLKIT_SPECS = [
|
|
|
216
215
|
p('threadTs', 'Thread to attach the file to.', false),
|
|
217
216
|
],
|
|
218
217
|
},
|
|
219
|
-
];
|
|
218
|
+
]);
|
|
220
219
|
exports.SLACK_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.SLACK_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
221
220
|
/**
|
|
222
221
|
* Las herramientas que ofrecerle al modelo con ESTA credencial.
|
|
@@ -39,6 +39,9 @@ export interface TelegramToolkitSpec {
|
|
|
39
39
|
/** Descripción (más reglas de uso) que ve el LLM. */
|
|
40
40
|
description: string;
|
|
41
41
|
parameters: TelegramToolkitParameter[];
|
|
42
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
43
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
44
|
+
destructive?: boolean;
|
|
42
45
|
/**
|
|
43
46
|
* Encabezado de grupo para la lista de la página de detalle. Las filas
|
|
44
47
|
* consecutivas que comparten grupo se pintan bajo un único título, así que el
|
package/dist/telegram-toolkit.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.TELEGRAM_TOOLKIT_BY_TOOL_NAME = exports.TELEGRAM_TOOLKIT_SPECS = void 0;
|
|
25
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
25
26
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
26
27
|
/*
|
|
27
28
|
* `sendAndWaitForResponse` NO está aquí, y es una decisión, no un olvido: la op
|
|
@@ -36,7 +37,7 @@ const p = (name, description, required = true, type = 'string') => ({ name, type
|
|
|
36
37
|
* campo en ninguna de las dos capas, y añadirlo cambiaría cuándo el AI Node pide
|
|
37
38
|
* confirmación. Eso es otra decisión, no parte de mudar el esquema de sitio.
|
|
38
39
|
*/
|
|
39
|
-
exports.TELEGRAM_TOOLKIT_SPECS = [
|
|
40
|
+
exports.TELEGRAM_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
40
41
|
{
|
|
41
42
|
operation: 'sendMessage',
|
|
42
43
|
label: 'Send message',
|
|
@@ -181,6 +182,6 @@ exports.TELEGRAM_TOOLKIT_SPECS = [
|
|
|
181
182
|
p('showAlert', 'Optional. true = modal alert; false (default) = toast notification.', false, 'boolean'),
|
|
182
183
|
],
|
|
183
184
|
},
|
|
184
|
-
];
|
|
185
|
+
]);
|
|
185
186
|
/** Las herramientas por nombre, para despachar una llamada del modelo. */
|
|
186
187
|
exports.TELEGRAM_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.TELEGRAM_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Los toolkits por tipo de nodo: qué herramientas expone cada nodo en modo
|
|
3
|
+
* AI toolkit, en un solo sitio.
|
|
4
|
+
*
|
|
5
|
+
* ## Para qué (2026-09-24)
|
|
6
|
+
*
|
|
7
|
+
* Para que el gate «Block destructive tool calls» del AI Node pueda preguntar
|
|
8
|
+
* por la OPERACIÓN y no sólo por el nombre. Hasta hoy sólo miraba el nombre
|
|
9
|
+
* contra unos patrones (`delete_*`, `drop_*`…), así que `update_row` de Sheets
|
|
10
|
+
* —que pisa una fila— pasaba con el gate encendido. Con esto, la herramienta
|
|
11
|
+
* que el AI Node guardó al conectar (`nodeRefType` + `operationOverride`) se
|
|
12
|
+
* resuelve aquí a su operación, y su `destructive` —que sale del verbo, ver
|
|
13
|
+
* `clase-de-herramienta.ts`— decide.
|
|
14
|
+
*
|
|
15
|
+
* ## Lo que falta aquí, a propósito
|
|
16
|
+
*
|
|
17
|
+
* WhatsApp y Social siguen con sus specs fuera de este paquete (WhatsApp
|
|
18
|
+
* escrito a mano en la api y el dashboard; Social armado por entidad desde el
|
|
19
|
+
* registro de proveedores). Quien consulte este registro tiene que componerlos
|
|
20
|
+
* por su lado — {@link esOperacionDestructiva} devuelve `null` para ellos, que
|
|
21
|
+
* significa «no lo sé», no «no es destructiva». Contacts se mudó el
|
|
22
|
+
* 2026-09-24.
|
|
23
|
+
*
|
|
24
|
+
* ## El bloqueo por nodo y la puerta sin herramienta (2026-09-24)
|
|
25
|
+
*
|
|
26
|
+
* Abajo viven también las dos reglas que se aplican a TODA llamada a un nodo en
|
|
27
|
+
* modo toolkit, en un solo sitio para que la api, hw-nodes, node-sdk y el
|
|
28
|
+
* dashboard pregunten lo mismo:
|
|
29
|
+
*
|
|
30
|
+
* - «Block these tool calls»: el dueño bloquea herramientas en el nodo
|
|
31
|
+
* (`blockedTools`, por nombre). Vale para todo tipo de este registro
|
|
32
|
+
* ({@link admiteBloqueo}).
|
|
33
|
+
* - Sin herramienta no se corre: en modo toolkit un nodo sólo ejecuta la
|
|
34
|
+
* herramienta que le nombran en `operation`. Un evento sin ella —una arista
|
|
35
|
+
* vieja del lienzo— ya no corre la operación de «Single operation», que en
|
|
36
|
+
* ese modo no se ve. Decisión de Ariel para los catorce toolkits
|
|
37
|
+
* ({@link TIPOS_CON_TOOLKIT}), no sólo los de este registro.
|
|
38
|
+
*
|
|
39
|
+
* {@link motivoParaNoCorrer} junta las dos y la llama node-sdk al registrar
|
|
40
|
+
* cada handler, así que cubre todo camino que acabe en `handler.execute`.
|
|
41
|
+
*/
|
|
42
|
+
/** Lo mínimo de una herramienta de toolkit que hace falta para decidir. */
|
|
43
|
+
export interface OperacionDeToolkit {
|
|
44
|
+
operation: string;
|
|
45
|
+
toolName: string;
|
|
46
|
+
label: string;
|
|
47
|
+
destructive?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export declare const TOOLKITS_POR_TIPO: Readonly<Record<string, readonly OperacionDeToolkit[]>>;
|
|
50
|
+
/**
|
|
51
|
+
* La operación de un toolkit, buscada por su nombre interno (`updateRow`) O
|
|
52
|
+
* por el nombre de su herramienta (`update_row`).
|
|
53
|
+
*
|
|
54
|
+
* Las dos formas porque las dos llegan: el AI Node guarda `operationOverride`
|
|
55
|
+
* con el nombre interno, y el servidor MCP recibe el nombre de la herramienta.
|
|
56
|
+
*/
|
|
57
|
+
export declare function operacionDeToolkit(nodeType: string | undefined | null, operacionONombre: string | undefined | null): OperacionDeToolkit | null;
|
|
58
|
+
/**
|
|
59
|
+
* ¿Es destructiva esta operación de toolkit?
|
|
60
|
+
*
|
|
61
|
+
* `null` cuando no se sabe —el tipo no es un toolkit de este paquete, o la
|
|
62
|
+
* operación no existe en él—. Quien llama decide qué hace con el «no sé»; el
|
|
63
|
+
* gate del AI Node lo combina con los patrones de nombre, que siguen ahí para
|
|
64
|
+
* las herramientas que no son de toolkit (MCP, HTTP…).
|
|
65
|
+
*/
|
|
66
|
+
export declare function esOperacionDestructiva(nodeType: string | undefined | null, operacionONombre: string | undefined | null): boolean | null;
|
|
67
|
+
/**
|
|
68
|
+
* Los tipos con modo AI toolkit de VARIAS herramientas: los de este registro
|
|
69
|
+
* más WhatsApp y Social, cuyas herramientas aún no viven aquí. Es la lista de
|
|
70
|
+
* quién se niega a correr sin herramienta pedida.
|
|
71
|
+
*
|
|
72
|
+
* RSS, Mailchimp o Shopify también tienen `aiEnabled`, pero exponen el nodo
|
|
73
|
+
* como UNA herramienta sin `operation`: no están aquí a propósito.
|
|
74
|
+
*/
|
|
75
|
+
export declare const TIPOS_CON_TOOLKIT: readonly string[];
|
|
76
|
+
export declare function tieneModoToolkit(nodeType: string | undefined | null): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* ¿Admite «Block these tool calls»? Los de este registro: para bloquear hay
|
|
79
|
+
* que saber traducir la operación que guarda el AI Node al nombre de la
|
|
80
|
+
* herramienta que guarda el nodo, y eso sólo se sabe aquí.
|
|
81
|
+
*/
|
|
82
|
+
export declare function admiteBloqueo(nodeType: string | undefined | null): boolean;
|
|
83
|
+
/** Los nombres de herramienta de un toolkit: lo único que `blockedTools` acepta. */
|
|
84
|
+
export declare function nombresDeHerramientas(nodeType: string | undefined | null): string[];
|
|
85
|
+
/** Los nombres bloqueados de un nodo, tolerando documentos sin el campo. */
|
|
86
|
+
export declare function bloqueadasDe(entidad: unknown): string[];
|
|
87
|
+
/**
|
|
88
|
+
* ¿Está bloqueada en este nodo? Acepta la operación (`deleteOne`, lo que guarda
|
|
89
|
+
* el AI Node en `operationOverride`) o el nombre (`delete_document`, lo que
|
|
90
|
+
* recibe el servidor MCP).
|
|
91
|
+
*/
|
|
92
|
+
export declare function herramientaBloqueadaEn(entidad: unknown, nodeType: string | undefined | null, operacionONombre: string | undefined | null): boolean;
|
|
93
|
+
/** Lo que se contesta a una llamada sin herramienta. Lo lee una persona en el
|
|
94
|
+
* historial —una arista vieja— o el modelo, así que dice qué hacer. */
|
|
95
|
+
export declare const MENSAJE_SIN_HERRAMIENTA = "This node is an AI toolkit: it only runs the tool an AI Node or an MCP client names, and this call named none. If a connection in the flow leads here, remove it \u2014 in toolkit mode the node is not part of the pipeline.";
|
|
96
|
+
export declare function mensajeDeHerramientaBloqueada(toolName: string): string;
|
|
97
|
+
/**
|
|
98
|
+
* Por qué una llamada NO debe correr en este nodo, o `null` si puede.
|
|
99
|
+
*
|
|
100
|
+
* Sólo mira nodos en modo toolkit (`aiEnabled` y un tipo de
|
|
101
|
+
* {@link TIPOS_CON_TOOLKIT}); cualquier otro nodo corre como siempre. En modo
|
|
102
|
+
* toolkit:
|
|
103
|
+
* - sin `operation` → {@link MENSAJE_SIN_HERRAMIENTA};
|
|
104
|
+
* - con una herramienta bloqueada en el nodo → su mensaje.
|
|
105
|
+
*
|
|
106
|
+
* Una operación que el registro no conoce NO se rechaza aquí: cada servicio
|
|
107
|
+
* sabe qué operaciones acepta (Mongo y Postgres las validan con más detalle),
|
|
108
|
+
* y rechazar lo desconocido aquí rompería operaciones legítimas que no son
|
|
109
|
+
* herramientas.
|
|
110
|
+
*/
|
|
111
|
+
export declare function motivoParaNoCorrer(nodeType: string | undefined | null, entidad: unknown, payload: unknown): string | null;
|
package/dist/toolkits.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Los toolkits por tipo de nodo: qué herramientas expone cada nodo en modo
|
|
4
|
+
* AI toolkit, en un solo sitio.
|
|
5
|
+
*
|
|
6
|
+
* ## Para qué (2026-09-24)
|
|
7
|
+
*
|
|
8
|
+
* Para que el gate «Block destructive tool calls» del AI Node pueda preguntar
|
|
9
|
+
* por la OPERACIÓN y no sólo por el nombre. Hasta hoy sólo miraba el nombre
|
|
10
|
+
* contra unos patrones (`delete_*`, `drop_*`…), así que `update_row` de Sheets
|
|
11
|
+
* —que pisa una fila— pasaba con el gate encendido. Con esto, la herramienta
|
|
12
|
+
* que el AI Node guardó al conectar (`nodeRefType` + `operationOverride`) se
|
|
13
|
+
* resuelve aquí a su operación, y su `destructive` —que sale del verbo, ver
|
|
14
|
+
* `clase-de-herramienta.ts`— decide.
|
|
15
|
+
*
|
|
16
|
+
* ## Lo que falta aquí, a propósito
|
|
17
|
+
*
|
|
18
|
+
* WhatsApp y Social siguen con sus specs fuera de este paquete (WhatsApp
|
|
19
|
+
* escrito a mano en la api y el dashboard; Social armado por entidad desde el
|
|
20
|
+
* registro de proveedores). Quien consulte este registro tiene que componerlos
|
|
21
|
+
* por su lado — {@link esOperacionDestructiva} devuelve `null` para ellos, que
|
|
22
|
+
* significa «no lo sé», no «no es destructiva». Contacts se mudó el
|
|
23
|
+
* 2026-09-24.
|
|
24
|
+
*
|
|
25
|
+
* ## El bloqueo por nodo y la puerta sin herramienta (2026-09-24)
|
|
26
|
+
*
|
|
27
|
+
* Abajo viven también las dos reglas que se aplican a TODA llamada a un nodo en
|
|
28
|
+
* modo toolkit, en un solo sitio para que la api, hw-nodes, node-sdk y el
|
|
29
|
+
* dashboard pregunten lo mismo:
|
|
30
|
+
*
|
|
31
|
+
* - «Block these tool calls»: el dueño bloquea herramientas en el nodo
|
|
32
|
+
* (`blockedTools`, por nombre). Vale para todo tipo de este registro
|
|
33
|
+
* ({@link admiteBloqueo}).
|
|
34
|
+
* - Sin herramienta no se corre: en modo toolkit un nodo sólo ejecuta la
|
|
35
|
+
* herramienta que le nombran en `operation`. Un evento sin ella —una arista
|
|
36
|
+
* vieja del lienzo— ya no corre la operación de «Single operation», que en
|
|
37
|
+
* ese modo no se ve. Decisión de Ariel para los catorce toolkits
|
|
38
|
+
* ({@link TIPOS_CON_TOOLKIT}), no sólo los de este registro.
|
|
39
|
+
*
|
|
40
|
+
* {@link motivoParaNoCorrer} junta las dos y la llama node-sdk al registrar
|
|
41
|
+
* cada handler, así que cubre todo camino que acabe en `handler.execute`.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.MENSAJE_SIN_HERRAMIENTA = exports.TIPOS_CON_TOOLKIT = exports.TOOLKITS_POR_TIPO = void 0;
|
|
45
|
+
exports.operacionDeToolkit = operacionDeToolkit;
|
|
46
|
+
exports.esOperacionDestructiva = esOperacionDestructiva;
|
|
47
|
+
exports.tieneModoToolkit = tieneModoToolkit;
|
|
48
|
+
exports.admiteBloqueo = admiteBloqueo;
|
|
49
|
+
exports.nombresDeHerramientas = nombresDeHerramientas;
|
|
50
|
+
exports.bloqueadasDe = bloqueadasDe;
|
|
51
|
+
exports.herramientaBloqueadaEn = herramientaBloqueadaEn;
|
|
52
|
+
exports.mensajeDeHerramientaBloqueada = mensajeDeHerramientaBloqueada;
|
|
53
|
+
exports.motivoParaNoCorrer = motivoParaNoCorrer;
|
|
54
|
+
const gmail_operations_js_1 = require("./gmail-operations.js");
|
|
55
|
+
const calendar_toolkit_js_1 = require("./calendar-toolkit.js");
|
|
56
|
+
const drive_toolkit_js_1 = require("./drive-toolkit.js");
|
|
57
|
+
const telegram_toolkit_js_1 = require("./telegram-toolkit.js");
|
|
58
|
+
const discord_toolkit_js_1 = require("./discord-toolkit.js");
|
|
59
|
+
const slack_toolkit_js_1 = require("./slack-toolkit.js");
|
|
60
|
+
const sheets_toolkit_js_1 = require("./sheets-toolkit.js");
|
|
61
|
+
const docs_toolkit_js_1 = require("./docs-toolkit.js");
|
|
62
|
+
const mongo_toolkit_js_1 = require("./mongo-toolkit.js");
|
|
63
|
+
const postgres_toolkit_js_1 = require("./postgres-toolkit.js");
|
|
64
|
+
const google_contacts_toolkit_js_1 = require("./google-contacts-toolkit.js");
|
|
65
|
+
exports.TOOLKITS_POR_TIPO = Object.freeze({
|
|
66
|
+
gmailAction: gmail_operations_js_1.GMAIL_ALL_TOOLKIT_SPECS,
|
|
67
|
+
emailAction: gmail_operations_js_1.NATIVE_EMAIL_TOOLKIT_SPECS,
|
|
68
|
+
calendarAction: calendar_toolkit_js_1.GOOGLE_CALENDAR_TOOLKIT_SPECS,
|
|
69
|
+
driveAction: drive_toolkit_js_1.DRIVE_TOOLKIT_SPECS,
|
|
70
|
+
telegramAction: telegram_toolkit_js_1.TELEGRAM_TOOLKIT_SPECS,
|
|
71
|
+
discordAction: discord_toolkit_js_1.DISCORD_TOOLKIT_SPECS,
|
|
72
|
+
slackAction: slack_toolkit_js_1.SLACK_TOOLKIT_SPECS,
|
|
73
|
+
sheetsAction: sheets_toolkit_js_1.SHEETS_TOOLKIT_SPECS,
|
|
74
|
+
docsAction: docs_toolkit_js_1.DOCS_TOOLKIT_SPECS,
|
|
75
|
+
mongoAction: mongo_toolkit_js_1.MONGO_TOOLKIT_SPECS,
|
|
76
|
+
postgresAction: postgres_toolkit_js_1.POSTGRES_TOOLKIT_SPECS,
|
|
77
|
+
googleContactsAction: google_contacts_toolkit_js_1.GOOGLE_CONTACTS_TOOLKIT_SPECS,
|
|
78
|
+
});
|
|
79
|
+
/**
|
|
80
|
+
* La operación de un toolkit, buscada por su nombre interno (`updateRow`) O
|
|
81
|
+
* por el nombre de su herramienta (`update_row`).
|
|
82
|
+
*
|
|
83
|
+
* Las dos formas porque las dos llegan: el AI Node guarda `operationOverride`
|
|
84
|
+
* con el nombre interno, y el servidor MCP recibe el nombre de la herramienta.
|
|
85
|
+
*/
|
|
86
|
+
function operacionDeToolkit(nodeType, operacionONombre) {
|
|
87
|
+
if (!nodeType || !operacionONombre)
|
|
88
|
+
return null;
|
|
89
|
+
const toolkit = exports.TOOLKITS_POR_TIPO[nodeType];
|
|
90
|
+
if (!toolkit)
|
|
91
|
+
return null;
|
|
92
|
+
return (toolkit.find((s) => s.operation === operacionONombre) ??
|
|
93
|
+
toolkit.find((s) => s.toolName === operacionONombre) ??
|
|
94
|
+
null);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* ¿Es destructiva esta operación de toolkit?
|
|
98
|
+
*
|
|
99
|
+
* `null` cuando no se sabe —el tipo no es un toolkit de este paquete, o la
|
|
100
|
+
* operación no existe en él—. Quien llama decide qué hace con el «no sé»; el
|
|
101
|
+
* gate del AI Node lo combina con los patrones de nombre, que siguen ahí para
|
|
102
|
+
* las herramientas que no son de toolkit (MCP, HTTP…).
|
|
103
|
+
*/
|
|
104
|
+
function esOperacionDestructiva(nodeType, operacionONombre) {
|
|
105
|
+
const op = operacionDeToolkit(nodeType, operacionONombre);
|
|
106
|
+
return op ? op.destructive === true : null;
|
|
107
|
+
}
|
|
108
|
+
/* ── Quién tiene toolkit, el bloqueo por nodo y la puerta ───────────────── */
|
|
109
|
+
/**
|
|
110
|
+
* Los tipos con modo AI toolkit de VARIAS herramientas: los de este registro
|
|
111
|
+
* más WhatsApp y Social, cuyas herramientas aún no viven aquí. Es la lista de
|
|
112
|
+
* quién se niega a correr sin herramienta pedida.
|
|
113
|
+
*
|
|
114
|
+
* RSS, Mailchimp o Shopify también tienen `aiEnabled`, pero exponen el nodo
|
|
115
|
+
* como UNA herramienta sin `operation`: no están aquí a propósito.
|
|
116
|
+
*/
|
|
117
|
+
exports.TIPOS_CON_TOOLKIT = Object.freeze([
|
|
118
|
+
...Object.keys(exports.TOOLKITS_POR_TIPO),
|
|
119
|
+
'whatsappAction',
|
|
120
|
+
'socialMediaAction',
|
|
121
|
+
]);
|
|
122
|
+
function tieneModoToolkit(nodeType) {
|
|
123
|
+
return !!nodeType && exports.TIPOS_CON_TOOLKIT.includes(nodeType);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* ¿Admite «Block these tool calls»? Los de este registro: para bloquear hay
|
|
127
|
+
* que saber traducir la operación que guarda el AI Node al nombre de la
|
|
128
|
+
* herramienta que guarda el nodo, y eso sólo se sabe aquí.
|
|
129
|
+
*/
|
|
130
|
+
function admiteBloqueo(nodeType) {
|
|
131
|
+
return !!nodeType && Object.prototype.hasOwnProperty.call(exports.TOOLKITS_POR_TIPO, nodeType);
|
|
132
|
+
}
|
|
133
|
+
/** Los nombres de herramienta de un toolkit: lo único que `blockedTools` acepta. */
|
|
134
|
+
function nombresDeHerramientas(nodeType) {
|
|
135
|
+
if (!admiteBloqueo(nodeType))
|
|
136
|
+
return [];
|
|
137
|
+
return exports.TOOLKITS_POR_TIPO[nodeType].map((s) => s.toolName);
|
|
138
|
+
}
|
|
139
|
+
/** Los nombres bloqueados de un nodo, tolerando documentos sin el campo. */
|
|
140
|
+
function bloqueadasDe(entidad) {
|
|
141
|
+
const lista = entidad?.blockedTools;
|
|
142
|
+
return Array.isArray(lista) ? lista.filter((x) => typeof x === 'string') : [];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* ¿Está bloqueada en este nodo? Acepta la operación (`deleteOne`, lo que guarda
|
|
146
|
+
* el AI Node en `operationOverride`) o el nombre (`delete_document`, lo que
|
|
147
|
+
* recibe el servidor MCP).
|
|
148
|
+
*/
|
|
149
|
+
function herramientaBloqueadaEn(entidad, nodeType, operacionONombre) {
|
|
150
|
+
if (!operacionONombre)
|
|
151
|
+
return false;
|
|
152
|
+
const bloqueadas = bloqueadasDe(entidad);
|
|
153
|
+
if (bloqueadas.length === 0)
|
|
154
|
+
return false;
|
|
155
|
+
const op = operacionDeToolkit(nodeType, operacionONombre);
|
|
156
|
+
return bloqueadas.includes(op?.toolName ?? operacionONombre);
|
|
157
|
+
}
|
|
158
|
+
/** Lo que se contesta a una llamada sin herramienta. Lo lee una persona en el
|
|
159
|
+
* historial —una arista vieja— o el modelo, así que dice qué hacer. */
|
|
160
|
+
exports.MENSAJE_SIN_HERRAMIENTA = 'This node is an AI toolkit: it only runs the tool an AI Node or an MCP client names, and this call named none. If a connection in the flow leads here, remove it — in toolkit mode the node is not part of the pipeline.';
|
|
161
|
+
function mensajeDeHerramientaBloqueada(toolName) {
|
|
162
|
+
return `The tool "${toolName}" is blocked on this node by its owner. Do not retry it; tell the user it is not allowed here.`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Por qué una llamada NO debe correr en este nodo, o `null` si puede.
|
|
166
|
+
*
|
|
167
|
+
* Sólo mira nodos en modo toolkit (`aiEnabled` y un tipo de
|
|
168
|
+
* {@link TIPOS_CON_TOOLKIT}); cualquier otro nodo corre como siempre. En modo
|
|
169
|
+
* toolkit:
|
|
170
|
+
* - sin `operation` → {@link MENSAJE_SIN_HERRAMIENTA};
|
|
171
|
+
* - con una herramienta bloqueada en el nodo → su mensaje.
|
|
172
|
+
*
|
|
173
|
+
* Una operación que el registro no conoce NO se rechaza aquí: cada servicio
|
|
174
|
+
* sabe qué operaciones acepta (Mongo y Postgres las validan con más detalle),
|
|
175
|
+
* y rechazar lo desconocido aquí rompería operaciones legítimas que no son
|
|
176
|
+
* herramientas.
|
|
177
|
+
*/
|
|
178
|
+
function motivoParaNoCorrer(nodeType, entidad, payload) {
|
|
179
|
+
const e = entidad;
|
|
180
|
+
if (!e || e.aiEnabled !== true || !tieneModoToolkit(nodeType))
|
|
181
|
+
return null;
|
|
182
|
+
const pedida = payload?.operation;
|
|
183
|
+
if (typeof pedida !== 'string' || !pedida.trim())
|
|
184
|
+
return exports.MENSAJE_SIN_HERRAMIENTA;
|
|
185
|
+
if (herramientaBloqueadaEn(entidad, nodeType, pedida)) {
|
|
186
|
+
const op = operacionDeToolkit(nodeType, pedida);
|
|
187
|
+
return mensajeDeHerramientaBloqueada(op?.toolName ?? pedida);
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
package/package.json
CHANGED