@hostwebhook/node-types 1.86.0 → 1.87.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/index.d.ts +8 -0
- package/dist/esm/index.js +5 -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 +47 -0
- package/dist/esm/toolkits.js +74 -0
- package/dist/gmail-operations.d.ts +2 -0
- package/dist/gmail-operations.js +11 -10
- package/dist/index.d.ts +8 -0
- package/dist/index.js +16 -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 +47 -0
- package/dist/toolkits.js +79 -0
- package/package.json +1 -1
|
@@ -44,6 +44,9 @@ export interface GoogleCalendarToolkitSpec {
|
|
|
44
44
|
/** Descripción y reglas de uso que ve el LLM. */
|
|
45
45
|
description: string;
|
|
46
46
|
parameters: GoogleCalendarToolkitParameter[];
|
|
47
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
48
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
49
|
+
destructive?: boolean;
|
|
47
50
|
}
|
|
48
51
|
export declare const GOOGLE_CALENDAR_TOOLKIT_SPECS: GoogleCalendarToolkitSpec[];
|
|
49
52
|
/** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
|
package/dist/calendar-toolkit.js
CHANGED
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
*/
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
33
|
exports.GOOGLE_CALENDAR_TOOLKIT_BY_TOOL_NAME = exports.GOOGLE_CALENDAR_TOOLKIT_SPECS = void 0;
|
|
34
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
34
35
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
35
|
-
exports.GOOGLE_CALENDAR_TOOLKIT_SPECS = [
|
|
36
|
+
exports.GOOGLE_CALENDAR_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
36
37
|
{
|
|
37
38
|
operation: "createEvent",
|
|
38
39
|
label: "Create event",
|
|
@@ -150,6 +151,6 @@ exports.GOOGLE_CALENDAR_TOOLKIT_SPECS = [
|
|
|
150
151
|
p("calendarId", "Optional calendar id. Defaults to the configured calendar (usually 'primary'). Use list_my_calendars to discover ids.", false),
|
|
151
152
|
],
|
|
152
153
|
},
|
|
153
|
-
];
|
|
154
|
+
]);
|
|
154
155
|
/** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
|
|
155
156
|
exports.GOOGLE_CALENDAR_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.GOOGLE_CALENDAR_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qué le hace al mundo una herramienta, leído de su nombre: la ÚNICA
|
|
3
|
+
* definición de «destructiva» que comparten el AI Node, el servidor MCP y el
|
|
4
|
+
* dashboard.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué vive aquí (2026-09-24)
|
|
7
|
+
*
|
|
8
|
+
* Había tres definiciones y ninguna coincidía con otra:
|
|
9
|
+
*
|
|
10
|
+
* 1. los patrones de nombre del gate del AI Node (`delete_*`, `drop_*`…),
|
|
11
|
+
* que es lo ÚNICO que el gate miraba al ejecutar;
|
|
12
|
+
* 2. el `destructive: true` escrito a mano en cada operación de toolkit, que
|
|
13
|
+
* los comentarios decían que usaba el gate y que no leía nadie — y que
|
|
14
|
+
* además estaba puesto sin criterio: Docs marcaba `create_doc`, Slack
|
|
15
|
+
* `create_slack_channel`, y Gmail no marcaba ni `delete_email`;
|
|
16
|
+
* 3. la tabla de verbos de las anotaciones MCP de la api, la única con un
|
|
17
|
+
* criterio escrito.
|
|
18
|
+
*
|
|
19
|
+
* Se queda la tercera, y se sube aquí para que las otras dos la usen. El flag
|
|
20
|
+
* de cada operación ya no se escribe a mano: lo pone {@link marcarDestructivas}
|
|
21
|
+
* al cargar el módulo, así que no hay nada que se pueda separar del verbo.
|
|
22
|
+
*
|
|
23
|
+
* ## El criterio
|
|
24
|
+
*
|
|
25
|
+
* lectura no toca nada
|
|
26
|
+
* escritura añade, no pisa (crear, añadir, enviar…)
|
|
27
|
+
* destructiva pisa o borra algo que ya existía
|
|
28
|
+
*
|
|
29
|
+
* Por VERBO —el primer segmento del nombre— y no una lista de cien nombres,
|
|
30
|
+
* porque los nombres ya son regulares y una lista se queda vieja en cuanto
|
|
31
|
+
* alguien añade una operación. Las excepciones son los nombres cuyo verbo
|
|
32
|
+
* miente, cada una con su porqué.
|
|
33
|
+
*/
|
|
34
|
+
export type ClaseDeHerramienta = 'lectura' | 'escritura' | 'destructiva';
|
|
35
|
+
/**
|
|
36
|
+
* La clase de una herramienta, o `null` si ningún verbo la reconoce.
|
|
37
|
+
*
|
|
38
|
+
* El `null` es para las pruebas: una herramienta nueva con un verbo que nadie
|
|
39
|
+
* conoce tiene que ponerlas en rojo, no colarse clasificada por descuido.
|
|
40
|
+
*/
|
|
41
|
+
export declare function claseDeHerramienta(toolName: string): ClaseDeHerramienta | null;
|
|
42
|
+
/**
|
|
43
|
+
* ¿Es destructiva? Lo que no se reconoce SE TRATA COMO DESTRUCTIVO: ante una
|
|
44
|
+
* herramienta que no sabemos qué hace, la respuesta segura para un gate es
|
|
45
|
+
* pararla, no dejarla pasar.
|
|
46
|
+
*/
|
|
47
|
+
export declare function esHerramientaDestructiva(toolName: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Pone el `destructive` de cada operación de un toolkit a partir de su nombre.
|
|
50
|
+
*
|
|
51
|
+
* Se llama UNA vez, al cargar el módulo de cada toolkit, sobre su propio
|
|
52
|
+
* array. Muta en sitio a propósito: los `*_BY_TOOL_NAME` y cualquier otro
|
|
53
|
+
* índice apuntan a los MISMOS objetos, así que ven el flag sin tener que
|
|
54
|
+
* reconstruirse. `true` cuando es destructiva; cuando no, la clave desaparece
|
|
55
|
+
* — un `destructive: false` explícito se leería como una decisión que nadie
|
|
56
|
+
* tomó.
|
|
57
|
+
*/
|
|
58
|
+
export declare function marcarDestructivas<T extends {
|
|
59
|
+
toolName: string;
|
|
60
|
+
destructive?: boolean;
|
|
61
|
+
}>(specs: T[]): T[];
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Qué le hace al mundo una herramienta, leído de su nombre: la ÚNICA
|
|
4
|
+
* definición de «destructiva» que comparten el AI Node, el servidor MCP y el
|
|
5
|
+
* dashboard.
|
|
6
|
+
*
|
|
7
|
+
* ## Por qué vive aquí (2026-09-24)
|
|
8
|
+
*
|
|
9
|
+
* Había tres definiciones y ninguna coincidía con otra:
|
|
10
|
+
*
|
|
11
|
+
* 1. los patrones de nombre del gate del AI Node (`delete_*`, `drop_*`…),
|
|
12
|
+
* que es lo ÚNICO que el gate miraba al ejecutar;
|
|
13
|
+
* 2. el `destructive: true` escrito a mano en cada operación de toolkit, que
|
|
14
|
+
* los comentarios decían que usaba el gate y que no leía nadie — y que
|
|
15
|
+
* además estaba puesto sin criterio: Docs marcaba `create_doc`, Slack
|
|
16
|
+
* `create_slack_channel`, y Gmail no marcaba ni `delete_email`;
|
|
17
|
+
* 3. la tabla de verbos de las anotaciones MCP de la api, la única con un
|
|
18
|
+
* criterio escrito.
|
|
19
|
+
*
|
|
20
|
+
* Se queda la tercera, y se sube aquí para que las otras dos la usen. El flag
|
|
21
|
+
* de cada operación ya no se escribe a mano: lo pone {@link marcarDestructivas}
|
|
22
|
+
* al cargar el módulo, así que no hay nada que se pueda separar del verbo.
|
|
23
|
+
*
|
|
24
|
+
* ## El criterio
|
|
25
|
+
*
|
|
26
|
+
* lectura no toca nada
|
|
27
|
+
* escritura añade, no pisa (crear, añadir, enviar…)
|
|
28
|
+
* destructiva pisa o borra algo que ya existía
|
|
29
|
+
*
|
|
30
|
+
* Por VERBO —el primer segmento del nombre— y no una lista de cien nombres,
|
|
31
|
+
* porque los nombres ya son regulares y una lista se queda vieja en cuanto
|
|
32
|
+
* alguien añade una operación. Las excepciones son los nombres cuyo verbo
|
|
33
|
+
* miente, cada una con su porqué.
|
|
34
|
+
*/
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.claseDeHerramienta = claseDeHerramienta;
|
|
37
|
+
exports.esHerramientaDestructiva = esHerramientaDestructiva;
|
|
38
|
+
exports.marcarDestructivas = marcarDestructivas;
|
|
39
|
+
const POR_VERBO = Object.freeze({
|
|
40
|
+
// Lectura
|
|
41
|
+
get: 'lectura',
|
|
42
|
+
list: 'lectura',
|
|
43
|
+
search: 'lectura',
|
|
44
|
+
read: 'lectura',
|
|
45
|
+
download: 'lectura',
|
|
46
|
+
export: 'lectura',
|
|
47
|
+
find: 'lectura',
|
|
48
|
+
/* Los dos de las bases de datos. `query_rows` de Postgres corre dentro de
|
|
49
|
+
una transacción READ ONLY —no escribe aunque el SQL lo intente— y
|
|
50
|
+
`aggregate_documents` de Mongo rechaza `$out` y `$merge`, que son las dos
|
|
51
|
+
etapas que escriben. */
|
|
52
|
+
query: 'lectura',
|
|
53
|
+
aggregate: 'lectura',
|
|
54
|
+
// Escritura que sólo añade
|
|
55
|
+
send: 'escritura',
|
|
56
|
+
create: 'escritura',
|
|
57
|
+
add: 'escritura',
|
|
58
|
+
append: 'escritura',
|
|
59
|
+
insert: 'escritura',
|
|
60
|
+
upload: 'escritura',
|
|
61
|
+
draft: 'escritura',
|
|
62
|
+
schedule: 'escritura',
|
|
63
|
+
reply: 'escritura',
|
|
64
|
+
forward: 'escritura',
|
|
65
|
+
invite: 'escritura',
|
|
66
|
+
share: 'escritura',
|
|
67
|
+
copy: 'escritura',
|
|
68
|
+
pin: 'escritura',
|
|
69
|
+
untrash: 'escritura',
|
|
70
|
+
mark: 'escritura',
|
|
71
|
+
answer: 'escritura',
|
|
72
|
+
/* El par de Calendar: `propose_` crea un evento tentativo sin invitar a
|
|
73
|
+
nadie, `confirm_` lo promociona y manda las invitaciones. Ninguno pisa
|
|
74
|
+
nada; mandar invitaciones pesa lo mismo que un `send_email`. */
|
|
75
|
+
propose: 'escritura',
|
|
76
|
+
confirm: 'escritura',
|
|
77
|
+
// Escritura que pisa o borra
|
|
78
|
+
update: 'destructiva',
|
|
79
|
+
edit: 'destructiva',
|
|
80
|
+
replace: 'destructiva',
|
|
81
|
+
delete: 'destructiva',
|
|
82
|
+
remove: 'destructiva',
|
|
83
|
+
trash: 'destructiva',
|
|
84
|
+
move: 'destructiva',
|
|
85
|
+
/* `execute_sql` de Postgres: SQL cualquiera, DDL incluido. Siempre
|
|
86
|
+
destructiva, por decisión de Ariel (2026-09-24). */
|
|
87
|
+
execute: 'destructiva',
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* Los nombres cuyo verbo miente.
|
|
91
|
+
*
|
|
92
|
+
* Una entrada aquí es una decisión, y cada una lleva la suya: sin el porqué,
|
|
93
|
+
* la siguiente persona la quitaría por «incoherente».
|
|
94
|
+
*/
|
|
95
|
+
const EXCEPCIONES = Object.freeze({
|
|
96
|
+
/* Empieza por `append` y termina pisando la fila que encuentre. */
|
|
97
|
+
append_or_update_row: 'destructiva',
|
|
98
|
+
/* Los `batch_*` no dicen en el primer segmento qué hacen: hay que leer el
|
|
99
|
+
segundo. */
|
|
100
|
+
batch_create_contacts: 'escritura',
|
|
101
|
+
batch_update_contacts: 'destructiva',
|
|
102
|
+
batch_delete_contacts: 'destructiva',
|
|
103
|
+
/* Compartir no pisa nada, pero expone: un fichero compartido con quien no
|
|
104
|
+
debía ya ha salido, y eso no se deshace quitando el permiso después. Para
|
|
105
|
+
un agente que decide solo, pesa como un borrado. */
|
|
106
|
+
share_drive_file: 'destructiva',
|
|
107
|
+
/* Añadir un rol no borra nada, pero puede dar permisos de administrador. Es
|
|
108
|
+
el mismo peso que quitarlo, que ya era destructiva por su verbo. */
|
|
109
|
+
add_discord_role: 'destructiva',
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* La clase de una herramienta, o `null` si ningún verbo la reconoce.
|
|
113
|
+
*
|
|
114
|
+
* El `null` es para las pruebas: una herramienta nueva con un verbo que nadie
|
|
115
|
+
* conoce tiene que ponerlas en rojo, no colarse clasificada por descuido.
|
|
116
|
+
*/
|
|
117
|
+
function claseDeHerramienta(toolName) {
|
|
118
|
+
const nombre = (toolName ?? '').trim().toLowerCase();
|
|
119
|
+
if (!nombre)
|
|
120
|
+
return null;
|
|
121
|
+
const excepcion = EXCEPCIONES[nombre];
|
|
122
|
+
if (excepcion)
|
|
123
|
+
return excepcion;
|
|
124
|
+
return POR_VERBO[nombre.split('_')[0]] ?? null;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* ¿Es destructiva? Lo que no se reconoce SE TRATA COMO DESTRUCTIVO: ante una
|
|
128
|
+
* herramienta que no sabemos qué hace, la respuesta segura para un gate es
|
|
129
|
+
* pararla, no dejarla pasar.
|
|
130
|
+
*/
|
|
131
|
+
function esHerramientaDestructiva(toolName) {
|
|
132
|
+
const clase = claseDeHerramienta(toolName);
|
|
133
|
+
return clase === null || clase === 'destructiva';
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Pone el `destructive` de cada operación de un toolkit a partir de su nombre.
|
|
137
|
+
*
|
|
138
|
+
* Se llama UNA vez, al cargar el módulo de cada toolkit, sobre su propio
|
|
139
|
+
* array. Muta en sitio a propósito: los `*_BY_TOOL_NAME` y cualquier otro
|
|
140
|
+
* índice apuntan a los MISMOS objetos, así que ven el flag sin tener que
|
|
141
|
+
* reconstruirse. `true` cuando es destructiva; cuando no, la clave desaparece
|
|
142
|
+
* — un `destructive: false` explícito se leería como una decisión que nadie
|
|
143
|
+
* tomó.
|
|
144
|
+
*/
|
|
145
|
+
function marcarDestructivas(specs) {
|
|
146
|
+
for (const spec of specs) {
|
|
147
|
+
if (esHerramientaDestructiva(spec.toolName))
|
|
148
|
+
spec.destructive = true;
|
|
149
|
+
else
|
|
150
|
+
delete spec.destructive;
|
|
151
|
+
}
|
|
152
|
+
return specs;
|
|
153
|
+
}
|
|
@@ -38,9 +38,8 @@ export interface DiscordToolkitSpec {
|
|
|
38
38
|
/** Descripción (más reglas de uso) que ve el LLM. */
|
|
39
39
|
description: string;
|
|
40
40
|
parameters: DiscordToolkitParameter[];
|
|
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 DISCORD_TOOLKIT_SPECS: DiscordToolkitSpec[];
|
package/dist/discord-toolkit.js
CHANGED
|
@@ -27,8 +27,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
27
27
|
exports.DISCORD_TOOLKIT_BY_TOOL_NAME = exports.DISCORD_TOOLKIT_SPECS = void 0;
|
|
28
28
|
exports.herramientasDeDiscordPara = herramientasDeDiscordPara;
|
|
29
29
|
const discord_operations_js_1 = require("./discord-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.DISCORD_TOOLKIT_SPECS = [
|
|
32
|
+
exports.DISCORD_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
32
33
|
// ── Messages ───────────────────────────────────────────────────
|
|
33
34
|
{
|
|
34
35
|
operation: 'sendMessage',
|
|
@@ -67,7 +68,6 @@ exports.DISCORD_TOOLKIT_SPECS = [
|
|
|
67
68
|
p('channelId', 'Channel snowflake where the message lives.'),
|
|
68
69
|
p('messageId', 'Snowflake of the message to delete.'),
|
|
69
70
|
],
|
|
70
|
-
destructive: true,
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
operation: 'getMessage',
|
|
@@ -153,7 +153,6 @@ exports.DISCORD_TOOLKIT_SPECS = [
|
|
|
153
153
|
toolName: 'delete_discord_channel',
|
|
154
154
|
description: 'Permanently delete a Discord channel and ALL its messages. Irreversible. ALWAYS confirm with the user before calling — Discord does not provide a recovery window.',
|
|
155
155
|
parameters: [p('channelId', 'Channel snowflake to delete.')],
|
|
156
|
-
destructive: true,
|
|
157
156
|
},
|
|
158
157
|
{
|
|
159
158
|
operation: 'getChannel',
|
|
@@ -209,7 +208,6 @@ exports.DISCORD_TOOLKIT_SPECS = [
|
|
|
209
208
|
p('userId', 'Member snowflake.'),
|
|
210
209
|
p('roleId', 'Role snowflake to grant.'),
|
|
211
210
|
],
|
|
212
|
-
destructive: true,
|
|
213
211
|
},
|
|
214
212
|
{
|
|
215
213
|
operation: 'removeRole',
|
|
@@ -221,7 +219,6 @@ exports.DISCORD_TOOLKIT_SPECS = [
|
|
|
221
219
|
p('userId', 'Member snowflake.'),
|
|
222
220
|
p('roleId', 'Role snowflake to remove.'),
|
|
223
221
|
],
|
|
224
|
-
destructive: true,
|
|
225
222
|
},
|
|
226
223
|
{
|
|
227
224
|
operation: 'getMember',
|
|
@@ -233,7 +230,7 @@ exports.DISCORD_TOOLKIT_SPECS = [
|
|
|
233
230
|
p('userId', 'Member snowflake.'),
|
|
234
231
|
],
|
|
235
232
|
},
|
|
236
|
-
];
|
|
233
|
+
]);
|
|
237
234
|
exports.DISCORD_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.DISCORD_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
238
235
|
/**
|
|
239
236
|
* Las herramientas que ofrecerle al modelo con ESTA credencial.
|
package/dist/docs-toolkit.d.ts
CHANGED
|
@@ -27,7 +27,8 @@ export interface DocsToolkitSpec {
|
|
|
27
27
|
toolName: string;
|
|
28
28
|
description: string;
|
|
29
29
|
parameters: DocsToolkitParameter[];
|
|
30
|
-
/**
|
|
30
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
31
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
31
32
|
destructive?: boolean;
|
|
32
33
|
}
|
|
33
34
|
export declare const DOCS_TOOLKIT_SPECS: DocsToolkitSpec[];
|
package/dist/docs-toolkit.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.DOCS_TOOLKIT_DEFAULTABLE = exports.DOCS_TOOLKIT_BY_TOOL_NAME = exports.DOCS_TOOLKIT_SPECS = void 0;
|
|
19
|
+
const clase_de_herramienta_js_1 = require("./clase-de-herramienta.js");
|
|
19
20
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
20
21
|
/*
|
|
21
22
|
* El documento del nodo va como **defecto** y el modelo puede cambiarlo — la
|
|
@@ -34,7 +35,7 @@ const p = (name, description, required = true, type = 'string') => ({ name, type
|
|
|
34
35
|
* documento nuevo nacería con el id del viejo por título.
|
|
35
36
|
*/
|
|
36
37
|
const documento = () => p('documentId', 'Id of the Google Docs document — the long chunk of its URL, between /d/ and /edit.');
|
|
37
|
-
exports.DOCS_TOOLKIT_SPECS = [
|
|
38
|
+
exports.DOCS_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
38
39
|
{
|
|
39
40
|
operation: 'readDoc',
|
|
40
41
|
label: 'Read document',
|
|
@@ -51,7 +52,6 @@ exports.DOCS_TOOLKIT_SPECS = [
|
|
|
51
52
|
p('title', 'Name of the new document.'),
|
|
52
53
|
p('content', 'Initial body, as HTML. Basic tags work (<p>, <b>, <i>, <ul>, <li>, <h1>…). Plain text is fine too. Leave it out for an empty document.', false),
|
|
53
54
|
],
|
|
54
|
-
destructive: true,
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
operation: 'appendText',
|
|
@@ -62,7 +62,6 @@ exports.DOCS_TOOLKIT_SPECS = [
|
|
|
62
62
|
p('content', 'What to add, as HTML. Basic tags work (<p>, <b>, <i>, <ul>, <li>, <h1>…). Plain text is fine too.'),
|
|
63
63
|
documento(),
|
|
64
64
|
],
|
|
65
|
-
destructive: true,
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
operation: 'replaceText',
|
|
@@ -74,7 +73,6 @@ exports.DOCS_TOOLKIT_SPECS = [
|
|
|
74
73
|
p('replaceWith', 'Text to put in its place. An empty string deletes the matches.'),
|
|
75
74
|
documento(),
|
|
76
75
|
],
|
|
77
|
-
destructive: true,
|
|
78
76
|
},
|
|
79
77
|
{
|
|
80
78
|
operation: 'insertTable',
|
|
@@ -86,9 +84,8 @@ exports.DOCS_TOOLKIT_SPECS = [
|
|
|
86
84
|
p('cols', 'Number of columns.', true, 'number'),
|
|
87
85
|
documento(),
|
|
88
86
|
],
|
|
89
|
-
destructive: true,
|
|
90
87
|
},
|
|
91
|
-
];
|
|
88
|
+
]);
|
|
92
89
|
/** Las herramientas por nombre, para despachar una llamada del modelo. */
|
|
93
90
|
exports.DOCS_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.DOCS_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
94
91
|
/**
|
package/dist/drive-toolkit.d.ts
CHANGED
|
@@ -42,10 +42,15 @@ export interface DriveToolkitSpec {
|
|
|
42
42
|
/** Encabezado de grupo de la página de detalle. El orden es el que agrupa. */
|
|
43
43
|
group?: string;
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del nombre
|
|
46
|
+
* (ver `clase-de-herramienta.ts`), no se escribe a mano.
|
|
47
|
+
*
|
|
48
|
+
* ⚠️ Hasta el 2026-09-24 aquí se decía que `move` no lo llevaba —«deshacerlo
|
|
49
|
+
* es otro move»—, mientras la tabla de anotaciones MCP de la api decía lo
|
|
50
|
+
* contrario: sacar el fichero de su carpeta es quitarlo de donde estaba. Eran
|
|
51
|
+
* dos criterios para lo mismo; se queda el de la tabla, que es el único que
|
|
52
|
+
* estaba escrito como regla. `share_drive_file` sigue marcada, ahora como
|
|
53
|
+
* excepción explícita: compartir expone, y eso no se deshace.
|
|
49
54
|
*/
|
|
50
55
|
destructive?: boolean;
|
|
51
56
|
}
|
package/dist/drive-toolkit.js
CHANGED
|
@@ -22,11 +22,12 @@
|
|
|
22
22
|
*/
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.DRIVE_TOOLKIT_BY_TOOL_NAME = exports.DRIVE_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
|
const ENTRAN_Y_SALEN = 'Files in / out';
|
|
27
28
|
const DESCUBRIR = 'Discovery';
|
|
28
29
|
const MUTACIONES = 'Mutations (LLM confirms first)';
|
|
29
|
-
exports.DRIVE_TOOLKIT_SPECS = [
|
|
30
|
+
exports.DRIVE_TOOLKIT_SPECS = (0, clase_de_herramienta_js_1.marcarDestructivas)([
|
|
30
31
|
/* ── Files in / out ─────────────────────────────────────────────────── */
|
|
31
32
|
{
|
|
32
33
|
operation: 'upload',
|
|
@@ -157,7 +158,6 @@ exports.DRIVE_TOOLKIT_SPECS = [
|
|
|
157
158
|
p('fileId', 'The Drive file ID to delete.'),
|
|
158
159
|
p('permanent', 'Optional. true = bypass trash and erase forever (irreversible). Default false.', false, 'boolean'),
|
|
159
160
|
],
|
|
160
|
-
destructive: true,
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
operation: 'share',
|
|
@@ -173,8 +173,7 @@ exports.DRIVE_TOOLKIT_SPECS = [
|
|
|
173
173
|
p('domain', 'Required when type=domain.', false),
|
|
174
174
|
p('sendNotificationEmail', 'Optional. true = email the recipient about the share.', false, 'boolean'),
|
|
175
175
|
],
|
|
176
|
-
destructive: true,
|
|
177
176
|
},
|
|
178
|
-
];
|
|
177
|
+
]);
|
|
179
178
|
/** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
|
|
180
179
|
exports.DRIVE_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.DRIVE_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
@@ -44,6 +44,9 @@ export interface GoogleCalendarToolkitSpec {
|
|
|
44
44
|
/** Descripción y reglas de uso que ve el LLM. */
|
|
45
45
|
description: string;
|
|
46
46
|
parameters: GoogleCalendarToolkitParameter[];
|
|
47
|
+
/** Pisa o borra. Lo pone `marcarDestructivas` leyendo el verbo del
|
|
48
|
+
* nombre (ver `clase-de-herramienta.ts`), no se escribe a mano. */
|
|
49
|
+
destructive?: boolean;
|
|
47
50
|
}
|
|
48
51
|
export declare const GOOGLE_CALENDAR_TOOLKIT_SPECS: GoogleCalendarToolkitSpec[];
|
|
49
52
|
/** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
|
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
* El array se generó desde la copia de la api para que las descripciones largas
|
|
29
29
|
* salieran idénticas, no tecleadas.
|
|
30
30
|
*/
|
|
31
|
+
import { marcarDestructivas } from './clase-de-herramienta.js';
|
|
31
32
|
const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
|
|
32
|
-
export const GOOGLE_CALENDAR_TOOLKIT_SPECS = [
|
|
33
|
+
export const GOOGLE_CALENDAR_TOOLKIT_SPECS = marcarDestructivas([
|
|
33
34
|
{
|
|
34
35
|
operation: "createEvent",
|
|
35
36
|
label: "Create event",
|
|
@@ -147,6 +148,6 @@ export const GOOGLE_CALENDAR_TOOLKIT_SPECS = [
|
|
|
147
148
|
p("calendarId", "Optional calendar id. Defaults to the configured calendar (usually 'primary'). Use list_my_calendars to discover ids.", false),
|
|
148
149
|
],
|
|
149
150
|
},
|
|
150
|
-
];
|
|
151
|
+
]);
|
|
151
152
|
/** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
|
|
152
153
|
export const GOOGLE_CALENDAR_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(GOOGLE_CALENDAR_TOOLKIT_SPECS.map((s) => [s.toolName, s]));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qué le hace al mundo una herramienta, leído de su nombre: la ÚNICA
|
|
3
|
+
* definición de «destructiva» que comparten el AI Node, el servidor MCP y el
|
|
4
|
+
* dashboard.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué vive aquí (2026-09-24)
|
|
7
|
+
*
|
|
8
|
+
* Había tres definiciones y ninguna coincidía con otra:
|
|
9
|
+
*
|
|
10
|
+
* 1. los patrones de nombre del gate del AI Node (`delete_*`, `drop_*`…),
|
|
11
|
+
* que es lo ÚNICO que el gate miraba al ejecutar;
|
|
12
|
+
* 2. el `destructive: true` escrito a mano en cada operación de toolkit, que
|
|
13
|
+
* los comentarios decían que usaba el gate y que no leía nadie — y que
|
|
14
|
+
* además estaba puesto sin criterio: Docs marcaba `create_doc`, Slack
|
|
15
|
+
* `create_slack_channel`, y Gmail no marcaba ni `delete_email`;
|
|
16
|
+
* 3. la tabla de verbos de las anotaciones MCP de la api, la única con un
|
|
17
|
+
* criterio escrito.
|
|
18
|
+
*
|
|
19
|
+
* Se queda la tercera, y se sube aquí para que las otras dos la usen. El flag
|
|
20
|
+
* de cada operación ya no se escribe a mano: lo pone {@link marcarDestructivas}
|
|
21
|
+
* al cargar el módulo, así que no hay nada que se pueda separar del verbo.
|
|
22
|
+
*
|
|
23
|
+
* ## El criterio
|
|
24
|
+
*
|
|
25
|
+
* lectura no toca nada
|
|
26
|
+
* escritura añade, no pisa (crear, añadir, enviar…)
|
|
27
|
+
* destructiva pisa o borra algo que ya existía
|
|
28
|
+
*
|
|
29
|
+
* Por VERBO —el primer segmento del nombre— y no una lista de cien nombres,
|
|
30
|
+
* porque los nombres ya son regulares y una lista se queda vieja en cuanto
|
|
31
|
+
* alguien añade una operación. Las excepciones son los nombres cuyo verbo
|
|
32
|
+
* miente, cada una con su porqué.
|
|
33
|
+
*/
|
|
34
|
+
export type ClaseDeHerramienta = 'lectura' | 'escritura' | 'destructiva';
|
|
35
|
+
/**
|
|
36
|
+
* La clase de una herramienta, o `null` si ningún verbo la reconoce.
|
|
37
|
+
*
|
|
38
|
+
* El `null` es para las pruebas: una herramienta nueva con un verbo que nadie
|
|
39
|
+
* conoce tiene que ponerlas en rojo, no colarse clasificada por descuido.
|
|
40
|
+
*/
|
|
41
|
+
export declare function claseDeHerramienta(toolName: string): ClaseDeHerramienta | null;
|
|
42
|
+
/**
|
|
43
|
+
* ¿Es destructiva? Lo que no se reconoce SE TRATA COMO DESTRUCTIVO: ante una
|
|
44
|
+
* herramienta que no sabemos qué hace, la respuesta segura para un gate es
|
|
45
|
+
* pararla, no dejarla pasar.
|
|
46
|
+
*/
|
|
47
|
+
export declare function esHerramientaDestructiva(toolName: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Pone el `destructive` de cada operación de un toolkit a partir de su nombre.
|
|
50
|
+
*
|
|
51
|
+
* Se llama UNA vez, al cargar el módulo de cada toolkit, sobre su propio
|
|
52
|
+
* array. Muta en sitio a propósito: los `*_BY_TOOL_NAME` y cualquier otro
|
|
53
|
+
* índice apuntan a los MISMOS objetos, así que ven el flag sin tener que
|
|
54
|
+
* reconstruirse. `true` cuando es destructiva; cuando no, la clave desaparece
|
|
55
|
+
* — un `destructive: false` explícito se leería como una decisión que nadie
|
|
56
|
+
* tomó.
|
|
57
|
+
*/
|
|
58
|
+
export declare function marcarDestructivas<T extends {
|
|
59
|
+
toolName: string;
|
|
60
|
+
destructive?: boolean;
|
|
61
|
+
}>(specs: T[]): T[];
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qué le hace al mundo una herramienta, leído de su nombre: la ÚNICA
|
|
3
|
+
* definición de «destructiva» que comparten el AI Node, el servidor MCP y el
|
|
4
|
+
* dashboard.
|
|
5
|
+
*
|
|
6
|
+
* ## Por qué vive aquí (2026-09-24)
|
|
7
|
+
*
|
|
8
|
+
* Había tres definiciones y ninguna coincidía con otra:
|
|
9
|
+
*
|
|
10
|
+
* 1. los patrones de nombre del gate del AI Node (`delete_*`, `drop_*`…),
|
|
11
|
+
* que es lo ÚNICO que el gate miraba al ejecutar;
|
|
12
|
+
* 2. el `destructive: true` escrito a mano en cada operación de toolkit, que
|
|
13
|
+
* los comentarios decían que usaba el gate y que no leía nadie — y que
|
|
14
|
+
* además estaba puesto sin criterio: Docs marcaba `create_doc`, Slack
|
|
15
|
+
* `create_slack_channel`, y Gmail no marcaba ni `delete_email`;
|
|
16
|
+
* 3. la tabla de verbos de las anotaciones MCP de la api, la única con un
|
|
17
|
+
* criterio escrito.
|
|
18
|
+
*
|
|
19
|
+
* Se queda la tercera, y se sube aquí para que las otras dos la usen. El flag
|
|
20
|
+
* de cada operación ya no se escribe a mano: lo pone {@link marcarDestructivas}
|
|
21
|
+
* al cargar el módulo, así que no hay nada que se pueda separar del verbo.
|
|
22
|
+
*
|
|
23
|
+
* ## El criterio
|
|
24
|
+
*
|
|
25
|
+
* lectura no toca nada
|
|
26
|
+
* escritura añade, no pisa (crear, añadir, enviar…)
|
|
27
|
+
* destructiva pisa o borra algo que ya existía
|
|
28
|
+
*
|
|
29
|
+
* Por VERBO —el primer segmento del nombre— y no una lista de cien nombres,
|
|
30
|
+
* porque los nombres ya son regulares y una lista se queda vieja en cuanto
|
|
31
|
+
* alguien añade una operación. Las excepciones son los nombres cuyo verbo
|
|
32
|
+
* miente, cada una con su porqué.
|
|
33
|
+
*/
|
|
34
|
+
const POR_VERBO = Object.freeze({
|
|
35
|
+
// Lectura
|
|
36
|
+
get: 'lectura',
|
|
37
|
+
list: 'lectura',
|
|
38
|
+
search: 'lectura',
|
|
39
|
+
read: 'lectura',
|
|
40
|
+
download: 'lectura',
|
|
41
|
+
export: 'lectura',
|
|
42
|
+
find: 'lectura',
|
|
43
|
+
/* Los dos de las bases de datos. `query_rows` de Postgres corre dentro de
|
|
44
|
+
una transacción READ ONLY —no escribe aunque el SQL lo intente— y
|
|
45
|
+
`aggregate_documents` de Mongo rechaza `$out` y `$merge`, que son las dos
|
|
46
|
+
etapas que escriben. */
|
|
47
|
+
query: 'lectura',
|
|
48
|
+
aggregate: 'lectura',
|
|
49
|
+
// Escritura que sólo añade
|
|
50
|
+
send: 'escritura',
|
|
51
|
+
create: 'escritura',
|
|
52
|
+
add: 'escritura',
|
|
53
|
+
append: 'escritura',
|
|
54
|
+
insert: 'escritura',
|
|
55
|
+
upload: 'escritura',
|
|
56
|
+
draft: 'escritura',
|
|
57
|
+
schedule: 'escritura',
|
|
58
|
+
reply: 'escritura',
|
|
59
|
+
forward: 'escritura',
|
|
60
|
+
invite: 'escritura',
|
|
61
|
+
share: 'escritura',
|
|
62
|
+
copy: 'escritura',
|
|
63
|
+
pin: 'escritura',
|
|
64
|
+
untrash: 'escritura',
|
|
65
|
+
mark: 'escritura',
|
|
66
|
+
answer: 'escritura',
|
|
67
|
+
/* El par de Calendar: `propose_` crea un evento tentativo sin invitar a
|
|
68
|
+
nadie, `confirm_` lo promociona y manda las invitaciones. Ninguno pisa
|
|
69
|
+
nada; mandar invitaciones pesa lo mismo que un `send_email`. */
|
|
70
|
+
propose: 'escritura',
|
|
71
|
+
confirm: 'escritura',
|
|
72
|
+
// Escritura que pisa o borra
|
|
73
|
+
update: 'destructiva',
|
|
74
|
+
edit: 'destructiva',
|
|
75
|
+
replace: 'destructiva',
|
|
76
|
+
delete: 'destructiva',
|
|
77
|
+
remove: 'destructiva',
|
|
78
|
+
trash: 'destructiva',
|
|
79
|
+
move: 'destructiva',
|
|
80
|
+
/* `execute_sql` de Postgres: SQL cualquiera, DDL incluido. Siempre
|
|
81
|
+
destructiva, por decisión de Ariel (2026-09-24). */
|
|
82
|
+
execute: 'destructiva',
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* Los nombres cuyo verbo miente.
|
|
86
|
+
*
|
|
87
|
+
* Una entrada aquí es una decisión, y cada una lleva la suya: sin el porqué,
|
|
88
|
+
* la siguiente persona la quitaría por «incoherente».
|
|
89
|
+
*/
|
|
90
|
+
const EXCEPCIONES = Object.freeze({
|
|
91
|
+
/* Empieza por `append` y termina pisando la fila que encuentre. */
|
|
92
|
+
append_or_update_row: 'destructiva',
|
|
93
|
+
/* Los `batch_*` no dicen en el primer segmento qué hacen: hay que leer el
|
|
94
|
+
segundo. */
|
|
95
|
+
batch_create_contacts: 'escritura',
|
|
96
|
+
batch_update_contacts: 'destructiva',
|
|
97
|
+
batch_delete_contacts: 'destructiva',
|
|
98
|
+
/* Compartir no pisa nada, pero expone: un fichero compartido con quien no
|
|
99
|
+
debía ya ha salido, y eso no se deshace quitando el permiso después. Para
|
|
100
|
+
un agente que decide solo, pesa como un borrado. */
|
|
101
|
+
share_drive_file: 'destructiva',
|
|
102
|
+
/* Añadir un rol no borra nada, pero puede dar permisos de administrador. Es
|
|
103
|
+
el mismo peso que quitarlo, que ya era destructiva por su verbo. */
|
|
104
|
+
add_discord_role: 'destructiva',
|
|
105
|
+
});
|
|
106
|
+
/**
|
|
107
|
+
* La clase de una herramienta, o `null` si ningún verbo la reconoce.
|
|
108
|
+
*
|
|
109
|
+
* El `null` es para las pruebas: una herramienta nueva con un verbo que nadie
|
|
110
|
+
* conoce tiene que ponerlas en rojo, no colarse clasificada por descuido.
|
|
111
|
+
*/
|
|
112
|
+
export function claseDeHerramienta(toolName) {
|
|
113
|
+
const nombre = (toolName ?? '').trim().toLowerCase();
|
|
114
|
+
if (!nombre)
|
|
115
|
+
return null;
|
|
116
|
+
const excepcion = EXCEPCIONES[nombre];
|
|
117
|
+
if (excepcion)
|
|
118
|
+
return excepcion;
|
|
119
|
+
return POR_VERBO[nombre.split('_')[0]] ?? null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* ¿Es destructiva? Lo que no se reconoce SE TRATA COMO DESTRUCTIVO: ante una
|
|
123
|
+
* herramienta que no sabemos qué hace, la respuesta segura para un gate es
|
|
124
|
+
* pararla, no dejarla pasar.
|
|
125
|
+
*/
|
|
126
|
+
export function esHerramientaDestructiva(toolName) {
|
|
127
|
+
const clase = claseDeHerramienta(toolName);
|
|
128
|
+
return clase === null || clase === 'destructiva';
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Pone el `destructive` de cada operación de un toolkit a partir de su nombre.
|
|
132
|
+
*
|
|
133
|
+
* Se llama UNA vez, al cargar el módulo de cada toolkit, sobre su propio
|
|
134
|
+
* array. Muta en sitio a propósito: los `*_BY_TOOL_NAME` y cualquier otro
|
|
135
|
+
* índice apuntan a los MISMOS objetos, así que ven el flag sin tener que
|
|
136
|
+
* reconstruirse. `true` cuando es destructiva; cuando no, la clave desaparece
|
|
137
|
+
* — un `destructive: false` explícito se leería como una decisión que nadie
|
|
138
|
+
* tomó.
|
|
139
|
+
*/
|
|
140
|
+
export function marcarDestructivas(specs) {
|
|
141
|
+
for (const spec of specs) {
|
|
142
|
+
if (esHerramientaDestructiva(spec.toolName))
|
|
143
|
+
spec.destructive = true;
|
|
144
|
+
else
|
|
145
|
+
delete spec.destructive;
|
|
146
|
+
}
|
|
147
|
+
return specs;
|
|
148
|
+
}
|