@hostwebhook/node-types 1.68.0 → 1.70.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.
Files changed (94) hide show
  1. package/dist/calendar-toolkit.d.ts +1 -1
  2. package/dist/connections.d.ts +1 -1
  3. package/dist/credentials.d.ts +89 -2
  4. package/dist/credentials.js +31 -4
  5. package/dist/discord-operations.d.ts +1 -1
  6. package/dist/discord-operations.js +4 -4
  7. package/dist/discord-toolkit.d.ts +1 -1
  8. package/dist/discord-toolkit.js +3 -3
  9. package/dist/dispatch.d.ts +1 -1
  10. package/dist/docs-toolkit.d.ts +1 -1
  11. package/dist/drive-toolkit.d.ts +1 -1
  12. package/dist/esm/calendar-operations.d.ts +67 -0
  13. package/dist/esm/calendar-operations.js +176 -0
  14. package/dist/esm/calendar-toolkit.d.ts +50 -0
  15. package/dist/esm/calendar-toolkit.js +152 -0
  16. package/dist/esm/capacidad-de-credencial.d.ts +75 -0
  17. package/dist/esm/capacidad-de-credencial.js +68 -0
  18. package/dist/esm/connections.d.ts +17 -0
  19. package/dist/esm/connections.js +106 -0
  20. package/dist/esm/credentials.d.ts +144 -0
  21. package/dist/esm/credentials.js +199 -0
  22. package/dist/esm/discord-operations.d.ts +104 -0
  23. package/dist/esm/discord-operations.js +407 -0
  24. package/dist/esm/discord-toolkit.d.ts +64 -0
  25. package/dist/esm/discord-toolkit.js +260 -0
  26. package/dist/esm/dispatch.d.ts +16 -0
  27. package/dist/esm/dispatch.js +76 -0
  28. package/dist/esm/docs-operations.d.ts +99 -0
  29. package/dist/esm/docs-operations.js +127 -0
  30. package/dist/esm/docs-toolkit.d.ts +42 -0
  31. package/dist/esm/docs-toolkit.js +97 -0
  32. package/dist/esm/drive-operations.d.ts +103 -0
  33. package/dist/esm/drive-operations.js +319 -0
  34. package/dist/esm/drive-toolkit.d.ts +54 -0
  35. package/dist/esm/drive-toolkit.js +177 -0
  36. package/dist/esm/github-operations.d.ts +147 -0
  37. package/dist/esm/github-operations.js +551 -0
  38. package/dist/esm/gmail-operations.d.ts +190 -0
  39. package/dist/esm/gmail-operations.js +560 -0
  40. package/dist/esm/google-analytics-operations.d.ts +99 -0
  41. package/dist/esm/google-analytics-operations.js +222 -0
  42. package/dist/esm/google-contacts-operations.d.ts +93 -0
  43. package/dist/esm/google-contacts-operations.js +363 -0
  44. package/dist/esm/index.d.ts +66 -0
  45. package/dist/esm/index.js +50 -0
  46. package/dist/esm/jira-operations.d.ts +164 -0
  47. package/dist/esm/jira-operations.js +470 -0
  48. package/dist/esm/llm-models.d.ts +101 -0
  49. package/dist/esm/llm-models.js +230 -0
  50. package/dist/esm/mailchimp-operations.d.ts +56 -0
  51. package/dist/esm/mailchimp-operations.js +155 -0
  52. package/dist/esm/mongo-operations.d.ts +61 -0
  53. package/dist/esm/mongo-operations.js +120 -0
  54. package/dist/esm/notion-operations.d.ts +125 -0
  55. package/dist/esm/notion-operations.js +511 -0
  56. package/dist/esm/openrouter.d.ts +142 -0
  57. package/dist/esm/openrouter.js +99 -0
  58. package/dist/esm/package.json +4 -0
  59. package/dist/esm/postgres-operations.d.ts +60 -0
  60. package/dist/esm/postgres-operations.js +75 -0
  61. package/dist/esm/registry.d.ts +160 -0
  62. package/dist/esm/registry.js +555 -0
  63. package/dist/esm/sheets-operations.d.ts +78 -0
  64. package/dist/esm/sheets-operations.js +150 -0
  65. package/dist/esm/sheets-toolkit.d.ts +49 -0
  66. package/dist/esm/sheets-toolkit.js +127 -0
  67. package/dist/esm/shopify-operations.d.ts +95 -0
  68. package/dist/esm/shopify-operations.js +259 -0
  69. package/dist/esm/slack-operations.d.ts +81 -0
  70. package/dist/esm/slack-operations.js +244 -0
  71. package/dist/esm/slack-toolkit.d.ts +60 -0
  72. package/dist/esm/slack-toolkit.js +235 -0
  73. package/dist/esm/telegram-operations.d.ts +104 -0
  74. package/dist/esm/telegram-operations.js +351 -0
  75. package/dist/esm/telegram-toolkit.d.ts +52 -0
  76. package/dist/esm/telegram-toolkit.js +183 -0
  77. package/dist/esm/types.d.ts +149 -0
  78. package/dist/esm/types.js +8 -0
  79. package/dist/esm/ui.d.ts +13 -0
  80. package/dist/esm/ui.js +150 -0
  81. package/dist/esm/whatsapp-operations.d.ts +23 -0
  82. package/dist/esm/whatsapp-operations.js +36 -0
  83. package/dist/index.d.ts +66 -66
  84. package/dist/index.js +185 -185
  85. package/dist/openrouter.d.ts +1 -1
  86. package/dist/registry.d.ts +1 -1
  87. package/dist/sheets-toolkit.d.ts +1 -1
  88. package/dist/slack-operations.d.ts +1 -1
  89. package/dist/slack-operations.js +4 -4
  90. package/dist/slack-toolkit.d.ts +1 -1
  91. package/dist/slack-toolkit.js +3 -3
  92. package/dist/telegram-toolkit.d.ts +1 -1
  93. package/dist/ui.d.ts +1 -1
  94. package/package.json +21 -3
@@ -28,7 +28,7 @@
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 type { GoogleCalendarOperation } from './calendar-operations';
31
+ import type { GoogleCalendarOperation } from './calendar-operations.js';
32
32
  export interface GoogleCalendarToolkitParameter {
33
33
  name: string;
34
34
  type: 'string' | 'number' | 'boolean';
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Adding a new node type = add 1 entry here. All repos import from this package.
8
8
  */
9
- import type { NodeType, NodeConnectionConfig } from './types';
9
+ import type { NodeType, NodeConnectionConfig } from './types.js';
10
10
  export declare const NODE_CONNECTIONS: Record<NodeType, NodeConnectionConfig>;
11
11
  export declare function canReceiveFrom(targetType: NodeType, sourceType: NodeType): boolean;
12
12
  export declare function canReceiveFromNodes(nodeType: NodeType): boolean;
@@ -36,7 +36,89 @@ export interface CredentialTypeRegistration {
36
36
  * Registry — order matters for fallthrough behavior in pickers (most
37
37
  * common types first), but not for correctness.
38
38
  */
39
- export declare const CREDENTIAL_TYPES: readonly CredentialTypeRegistration[];
39
+ export declare const CREDENTIAL_TYPES: readonly [{
40
+ readonly type: "google_service_account";
41
+ }, {
42
+ readonly type: "oauth2_google";
43
+ }, {
44
+ readonly type: "oauth2_atlassian";
45
+ }, {
46
+ readonly type: "mongodb";
47
+ readonly ssrfValidated: true;
48
+ readonly tunnelable: true;
49
+ }, {
50
+ readonly type: "postgres";
51
+ readonly ssrfValidated: true;
52
+ readonly tunnelable: true;
53
+ }, {
54
+ readonly type: "slack_webhook";
55
+ }, {
56
+ readonly type: "slack_oauth";
57
+ }, {
58
+ readonly type: "discord_webhook";
59
+ }, {
60
+ readonly type: "llm_anthropic";
61
+ }, {
62
+ readonly type: "llm_openai";
63
+ }, {
64
+ readonly type: "llm_google";
65
+ }, {
66
+ readonly type: "llm_groq";
67
+ }, {
68
+ readonly type: "llm_openrouter";
69
+ }, {
70
+ readonly type: "llm_ollama";
71
+ }, {
72
+ readonly type: "firecrawl";
73
+ }, {
74
+ readonly type: "http_auth";
75
+ }, {
76
+ readonly type: "aws_s3";
77
+ }, {
78
+ readonly type: "memory_contextwindow";
79
+ }, {
80
+ readonly type: "memory_mongodb";
81
+ readonly ssrfValidated: true;
82
+ readonly tunnelable: true;
83
+ }, {
84
+ readonly type: "mcp_server";
85
+ }, {
86
+ readonly type: "voice_agent";
87
+ }, {
88
+ readonly type: "telegram_bot";
89
+ }, {
90
+ readonly type: "whatsapp_business";
91
+ }, {
92
+ readonly type: "discord_bot";
93
+ }, {
94
+ readonly type: "discord_oauth";
95
+ }, {
96
+ readonly type: "bluesky_app_password";
97
+ }, {
98
+ readonly type: "twitter_oauth2";
99
+ }, {
100
+ readonly type: "mastodon_oauth2";
101
+ }, {
102
+ readonly type: "linkedin_oauth2";
103
+ }, {
104
+ readonly type: "threads_oauth2";
105
+ }, {
106
+ readonly type: "instagram_oauth2";
107
+ }, {
108
+ readonly type: "facebook_oauth2";
109
+ }, {
110
+ readonly type: "notion_internal";
111
+ }, {
112
+ readonly type: "notion_oauth";
113
+ }, {
114
+ readonly type: "mailchimp_oauth2";
115
+ }, {
116
+ readonly type: "shopify_oauth2";
117
+ }, {
118
+ readonly type: "github_app";
119
+ }, {
120
+ readonly type: "github_pat";
121
+ }];
40
122
  /**
41
123
  * Plain string array — what the Mongoose `enum` field and the
42
124
  * class-validator `@IsIn(...)` decorator both consume. Keep it as a
@@ -51,7 +133,12 @@ export declare const credentialTypeValues: () => string[];
51
133
  * Discriminated union of every supported type. Use as the field type
52
134
  * on entities + DTOs so a typo at the call site fails at compile
53
135
  * time, not at runtime via a Mongoose validation error.
136
+ *
137
+ * ⚠️ Y ahora ES una unión. Hasta la 1.69.0 esto valía `string` —la anotación
138
+ * de `CREDENTIAL_TYPES` ensanchaba los literales— así que la frase de arriba
139
+ * describía una protección que no existía. Ver el comentario del `satisfies`
140
+ * al final del registro.
54
141
  */
55
- export type CredentialType = typeof CREDENTIAL_TYPES[number]['type'];
142
+ export type CredentialType = (typeof CREDENTIAL_TYPES)[number]['type'];
56
143
  export declare function getCredentialType(type: string): CredentialTypeRegistration | undefined;
57
144
  export declare function isCredentialType(type: string): type is CredentialType;
@@ -19,6 +19,23 @@ exports.CREDENTIAL_TYPES = [
19
19
  { type: 'llm_anthropic' },
20
20
  { type: 'llm_openai' },
21
21
  { type: 'llm_google' },
22
+ // La clave de API de Groq (`gsk_…`), que el usuario saca de
23
+ // https://console.groq.com/keys y pega. Un secreto suyo, sin OAuth de por
24
+ // medio, igual que los tres de arriba y que `llm_openrouter` de abajo.
25
+ //
26
+ // El sufijo es `groq` por la misma regla que explica el bloque de
27
+ // OpenRouter: de aquí salen `getModelsFor`/`getDefaultModel` quitando el
28
+ // prefijo `llm_`, así que lo que quede detrás tiene que ser LITERALMENTE el
29
+ // `LlmProvider`, y ése es `'groq'`.
30
+ //
31
+ // 🔥 Llega TARDE, y el agujero que tapa no era teórico: `groq` es un
32
+ // `LlmProvider` de pleno derecho desde hace tiempo —está en `LLM_PROVIDERS`,
33
+ // con sus cinco modelos en `LLM_MODELS.groq`— pero no tenía tipo de
34
+ // credencial. O sea que el proveedor se podía ELEGIR en el selector y no
35
+ // había dónde guardar su clave: una rama del catálogo inalcanzable, sin un
36
+ // solo error que lo dijera. El resto de la lista se anota antes de que la
37
+ // api exista precisamente para no llegar a esto.
38
+ { type: 'llm_groq' },
22
39
  // La clave de API de OpenRouter (`sk-or-v1-…`). Un secreto pegado por el
23
40
  // usuario, igual que los tres de arriba: no hay OAuth de por medio.
24
41
  //
@@ -31,10 +48,10 @@ exports.CREDENTIAL_TYPES = [
31
48
  // el validador del DTO, y un tipo que falte ahí no rompe al compilar — mata
32
49
  // el `create` de la credencial en runtime, con el usuario delante.
33
50
  //
34
- // ⚠️ Y falta un vecino, que no es cosa de este cambio pero conviene que esté
35
- // escrito: `groq` es un `LlmProvider` desde hace tiempo y NO tiene
36
- // `llm_groq` en esta lista. O sea que hoy se puede elegir Groq como
37
- // proveedor y no hay tipo de credencial con el que guardar su clave.
51
+ // ⚠️ El vecino que faltaba y que este bloque dejó escrito —`groq` sin su
52
+ // `llm_groq`— ya está arriba. Lo que queda de aquel aviso es la regla que lo
53
+ // hizo posible, y por eso la cubre ahora un test: cada `LlmProvider` de
54
+ // `LLM_PROVIDERS` tiene que tener su `llm_*` en esta lista.
38
55
  { type: 'llm_openrouter' },
39
56
  { type: 'llm_ollama' },
40
57
  { type: 'firecrawl' },
@@ -158,6 +175,16 @@ exports.CREDENTIAL_TYPES = [
158
175
  // que cambia es de dónde sale la lista de repositorios del formulario: los
159
176
  // del usuario, en vez de los que abarca una instalación.
160
177
  { type: 'github_pat' },
178
+ /* ⚠️ `as const satisfies …` y no `: readonly CredentialTypeRegistration[]`.
179
+ Los dos comprueban lo mismo —que cada entrada tenga la forma del registro—,
180
+ pero la ANOTACIÓN además ENSANCHA lo que se guarda: con ella cada `type` se
181
+ recuerda como `string`, y entonces `CredentialType` de más abajo es
182
+ literalmente `string`. O sea que la promesa de su comentario («un typo al
183
+ asignar falla al compilar») era falsa desde el primer día: `const t:
184
+ CredentialType = 'llm_openroutr'` compilaba sin rechistar.
185
+
186
+ `satisfies` comprueba y NO ensancha, así que los literales sobreviven y la
187
+ unión es de verdad. El control está en `tipos-de-credencial.test.ts`. */
161
188
  ];
162
189
  /**
163
190
  * Plain string array — what the Mongoose `enum` field and the
@@ -17,7 +17,7 @@
17
17
  * forum-post create) extend this list — bump the package and re-install
18
18
  * in consumers, same pattern as Gmail / Calendar / Drive / Telegram.
19
19
  */
20
- import { type CapacidadesPorCredencial } from './capacidad-de-credencial';
20
+ import { type CapacidadesPorCredencial } from './capacidad-de-credencial.js';
21
21
  export declare const DISCORD_OPERATIONS: readonly ["sendMessage", "editMessage", "deleteMessage", "getMessage", "addReaction", "removeReaction", "pinMessage", "createChannel", "editChannel", "deleteChannel", "getChannel", "listChannels", "createThread", "sendDM", "addRole", "removeRole", "getMember"];
22
22
  export type DiscordOperation = (typeof DISCORD_OPERATIONS)[number];
23
23
  /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
@@ -24,7 +24,7 @@ exports.camposDeDiscordNoDisponibles = camposDeDiscordNoDisponibles;
24
24
  * forum-post create) extend this list — bump the package and re-install
25
25
  * in consumers, same pattern as Gmail / Calendar / Drive / Telegram.
26
26
  */
27
- const capacidad_de_credencial_1 = require("./capacidad-de-credencial");
27
+ const capacidad_de_credencial_js_1 = require("./capacidad-de-credencial.js");
28
28
  exports.DISCORD_OPERATIONS = [
29
29
  // Messages
30
30
  'sendMessage',
@@ -402,13 +402,13 @@ exports.DISCORD_CAPACIDADES_POR_CREDENCIAL = {
402
402
  };
403
403
  /** Las operaciones que ofrecer para una credencial de Discord. */
404
404
  function operacionesDeDiscordPara(tipoDeCredencial) {
405
- return (0, capacidad_de_credencial_1.operacionesPara)(exports.DISCORD_OPERATIONS, exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial);
405
+ return (0, capacidad_de_credencial_js_1.operacionesPara)(exports.DISCORD_OPERATIONS, exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial);
406
406
  }
407
407
  /** Si esa credencial puede ejecutar esa operación de Discord. */
408
408
  function discordPuedeEjecutar(tipoDeCredencial, operacion) {
409
- return (0, capacidad_de_credencial_1.puedeEjecutar)(exports.DISCORD_OPERATIONS, exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial, operacion);
409
+ return (0, capacidad_de_credencial_js_1.puedeEjecutar)(exports.DISCORD_OPERATIONS, exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial, operacion);
410
410
  }
411
411
  /** Los campos que esa credencial de Discord no deja elegir. */
412
412
  function camposDeDiscordNoDisponibles(tipoDeCredencial) {
413
- return (0, capacidad_de_credencial_1.camposNoDisponiblesPara)(exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial);
413
+ return (0, capacidad_de_credencial_js_1.camposNoDisponiblesPara)(exports.DISCORD_CAPACIDADES_POR_CREDENCIAL, tipoDeCredencial);
414
414
  }
@@ -22,7 +22,7 @@
22
22
  * pueda usarse sin adaptador. Los textos van en inglés porque los lee el modelo
23
23
  * y quien mire la lista de herramientas del servidor MCP.
24
24
  */
25
- import type { DiscordOperation } from './discord-operations';
25
+ import type { DiscordOperation } from './discord-operations.js';
26
26
  export interface DiscordToolkitParameter {
27
27
  name: string;
28
28
  type: 'string' | 'number' | 'boolean';
@@ -26,7 +26,7 @@
26
26
  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
- const discord_operations_1 = require("./discord-operations");
29
+ const discord_operations_js_1 = require("./discord-operations.js");
30
30
  const p = (name, description, required = true, type = 'string') => ({ name, type, description, required });
31
31
  exports.DISCORD_TOOLKIT_SPECS = [
32
32
  // ── Messages ───────────────────────────────────────────────────
@@ -252,8 +252,8 @@ exports.DISCORD_TOOLKIT_BY_TOOL_NAME = Object.fromEntries(exports.DISCORD_TOOLKI
252
252
  * fallar, porque parece que funcionó.
253
253
  */
254
254
  function herramientasDeDiscordPara(tipoDeCredencial) {
255
- const permitidas = new Set((0, discord_operations_1.operacionesDeDiscordPara)(tipoDeCredencial));
256
- const fuera = (0, discord_operations_1.camposDeDiscordNoDisponibles)(tipoDeCredencial);
255
+ const permitidas = new Set((0, discord_operations_js_1.operacionesDeDiscordPara)(tipoDeCredencial));
256
+ const fuera = (0, discord_operations_js_1.camposDeDiscordNoDisponibles)(tipoDeCredencial);
257
257
  return exports.DISCORD_TOOLKIT_SPECS.filter((s) => permitidas.has(s.operation)).map((s) =>
258
258
  /* Se devuelve una copia sólo cuando hay algo que quitar: así el camino
259
259
  normal —el bot, que puede con todo— sigue entregando las MISMAS
@@ -8,7 +8,7 @@
8
8
  * orphan the node (the symptom Vector Store / AI / Markdown / Code /
9
9
  * File Transform all hit before this refactor).
10
10
  */
11
- import type { NodeType, NodeDispatchConfig } from './types';
11
+ import type { NodeType, NodeDispatchConfig } from './types.js';
12
12
  export declare const NODE_DISPATCH: Record<NodeType, NodeDispatchConfig>;
13
13
  /** Get all MongoDB collection names for cascade cleanup */
14
14
  export declare function getAllNodeCollections(): string[];
@@ -13,7 +13,7 @@
13
13
  * usarse sin adaptador. Los textos van en inglés porque los lee el modelo y
14
14
  * quien mire la lista de herramientas del servidor MCP.
15
15
  */
16
- import type { DocsOperation } from './docs-operations';
16
+ import type { DocsOperation } from './docs-operations.js';
17
17
  export interface DocsToolkitParameter {
18
18
  name: string;
19
19
  /** El esquema MCP sólo admite estos tres. */
@@ -19,7 +19,7 @@
19
19
  * herramientas del mismo grupo tienen que ir seguidas. Los tres grupos son los
20
20
  * que ya inventaba el JSX que sustituye.
21
21
  */
22
- import type { DriveOperation } from './drive-operations';
22
+ import type { DriveOperation } from './drive-operations.js';
23
23
  export interface DriveToolkitParameter {
24
24
  name: string;
25
25
  type: 'string' | 'number' | 'boolean';
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Google Calendar operation enum — single source of truth across the API,
3
+ * Dashboard, and Message Broker. Used by:
4
+ * - calendarAction entity / DTO (api): operation field + validation
5
+ * - dashboard CalendarActionGoogleOperation type
6
+ * - broker hostwebhook types + tool schemas
7
+ * - any future calendar-related node
8
+ *
9
+ * Adding a new Calendar operation = add it here, bump this package's
10
+ * version, publish to npm, and re-install in the consuming repos.
11
+ * Each consumer still owns its operation-specific config schema (the
12
+ * dashboard owns the UI form schema, the api owns the dispatch logic),
13
+ * but the canonical list of valid operation strings lives here.
14
+ */
15
+ export declare const GOOGLE_CALENDAR_OPERATIONS: readonly ["createEvent", "updateEvent", "deleteEvent", "listEvents", "getEvent", "listCalendars", "findFreeSlots", "proposeEvent", "confirmEvent"];
16
+ export type GoogleCalendarOperation = (typeof GOOGLE_CALENDAR_OPERATIONS)[number];
17
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
18
+ export declare function isGoogleCalendarOperation(value: unknown): value is GoogleCalendarOperation;
19
+ export type GoogleCalendarParamTarget = 'eventConfig' | 'listConfig' | 'root';
20
+ export type GoogleCalendarParamType =
21
+ /** Campo de texto con autocompletado de `{{payload.*}}`. */
22
+ 'template' | 'number' | 'select'
23
+ /** El `TimezonePicker` que ya existe en el dashboard. */
24
+ | 'timezone';
25
+ export interface GoogleCalendarParamSpec {
26
+ /** La clave DENTRO de `target`. Es la del cable, no un nombre de UI. */
27
+ name: string;
28
+ /** Dónde vive en la entidad. */
29
+ target: GoogleCalendarParamTarget;
30
+ label: string;
31
+ type: GoogleCalendarParamType;
32
+ required?: boolean;
33
+ /** Texto de ayuda. Llano: el paquete no lleva React. */
34
+ description?: string;
35
+ placeholder?: string;
36
+ default?: string | number;
37
+ options?: ReadonlyArray<{
38
+ value: string;
39
+ label: string;
40
+ }>;
41
+ min?: number;
42
+ max?: number;
43
+ /**
44
+ * Cómo se llama esta misma cosa en el `config` que espera el ejecutor
45
+ * compartido (`google-calendar-operations.service.ts`). El ejecutor está
46
+ * escrito para la ruta del toolkit, donde el LLM manda los nombres **sin**
47
+ * sufijo, así que `summaryTemplate` viaja como `summary`. Sólo lo llevan los
48
+ * params de las operaciones que van por ese despachador.
49
+ */
50
+ execKey?: string;
51
+ }
52
+ export interface GoogleCalendarOperationSpec {
53
+ /** Etiqueta del desplegable, y la misma que pinta el lienzo y el panel. */
54
+ label: string;
55
+ /** Sub-línea del desplegable. */
56
+ description: string;
57
+ /** Método de la API de Google al que corresponde. */
58
+ apiMethod: string;
59
+ /**
60
+ * Si se ejecuta por el despachador genérico (`calendarOps.run`) en vez de por
61
+ * un `case` escrito a mano. Son las cuatro que se abrieron el 2026-08-11.
62
+ */
63
+ viaExecutor?: boolean;
64
+ /** Orden de pantalla. */
65
+ params: GoogleCalendarParamSpec[];
66
+ }
67
+ export declare const GOOGLE_CALENDAR_OPERATION_SPECS: Record<GoogleCalendarOperation, GoogleCalendarOperationSpec>;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Google Calendar operation enum — single source of truth across the API,
3
+ * Dashboard, and Message Broker. Used by:
4
+ * - calendarAction entity / DTO (api): operation field + validation
5
+ * - dashboard CalendarActionGoogleOperation type
6
+ * - broker hostwebhook types + tool schemas
7
+ * - any future calendar-related node
8
+ *
9
+ * Adding a new Calendar operation = add it here, bump this package's
10
+ * version, publish to npm, and re-install in the consuming repos.
11
+ * Each consumer still owns its operation-specific config schema (the
12
+ * dashboard owns the UI form schema, the api owns the dispatch logic),
13
+ * but the canonical list of valid operation strings lives here.
14
+ */
15
+ export const GOOGLE_CALENDAR_OPERATIONS = [
16
+ 'createEvent',
17
+ 'updateEvent',
18
+ 'deleteEvent',
19
+ 'listEvents',
20
+ 'getEvent',
21
+ /** List all calendars the user can write to. Lets the LLM discover
22
+ * ids before passing `calendarId` to other ops. */
23
+ 'listCalendars',
24
+ /** freebusy.query — returns free windows in a date range. Optionally
25
+ * combine across attendees to find common availability. */
26
+ 'findFreeSlots',
27
+ /** Create a tentative event (status: tentative, no invites sent). The
28
+ * user sees it greyed out in their calendar; LLM follows up with
29
+ * confirmEvent to promote. Mirrors emailAction's createDraft → sendDraft. */
30
+ 'proposeEvent',
31
+ /** Promote a tentative event to confirmed + send invites. Mirrors
32
+ * emailAction's sendDraft. */
33
+ 'confirmEvent',
34
+ ];
35
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
36
+ export function isGoogleCalendarOperation(value) {
37
+ return (typeof value === 'string' &&
38
+ GOOGLE_CALENDAR_OPERATIONS.includes(value));
39
+ }
40
+ /* Fábricas de los campos que se repiten entre operaciones. */
41
+ const eventIdParam = (label, description) => ({
42
+ name: 'eventIdTemplate',
43
+ target: 'root',
44
+ label,
45
+ type: 'template',
46
+ required: true,
47
+ placeholder: '{{payload.eventId}}',
48
+ description,
49
+ execKey: 'eventId',
50
+ });
51
+ /** Los siete de `eventConfig`, que comparten `createEvent`, `updateEvent` y
52
+ `proposeEvent`. */
53
+ const eventConfigParams = () => [
54
+ { name: 'summaryTemplate', target: 'eventConfig', label: 'Summary', type: 'template', placeholder: '{{payload.title}}', execKey: 'summary' },
55
+ { name: 'descriptionTemplate', target: 'eventConfig', label: 'Description', type: 'template', placeholder: 'Event description... (supports {{templates}})', execKey: 'description' },
56
+ { name: 'locationTemplate', target: 'eventConfig', label: 'Location', type: 'template', placeholder: '{{payload.location}}', execKey: 'location' },
57
+ { name: 'startTemplate', target: 'eventConfig', label: 'Start Date', type: 'template', placeholder: '{{payload.startTime}}', execKey: 'start' },
58
+ { name: 'endTemplate', target: 'eventConfig', label: 'End Date', type: 'template', placeholder: '{{payload.endTime}}', execKey: 'end' },
59
+ {
60
+ name: 'attendeesTemplate',
61
+ target: 'eventConfig',
62
+ label: 'Attendees (comma-separated emails)',
63
+ type: 'template',
64
+ placeholder: '{{payload.attendees}}',
65
+ description: 'e.g. user@example.com, other@example.com',
66
+ execKey: 'attendees',
67
+ },
68
+ { name: 'timeZone', target: 'eventConfig', label: 'Time Zone', type: 'timezone', execKey: 'timeZone' },
69
+ ];
70
+ export const GOOGLE_CALENDAR_OPERATION_SPECS = {
71
+ createEvent: {
72
+ label: 'Create Event',
73
+ description: 'Create a new calendar event',
74
+ apiMethod: 'events.insert',
75
+ params: eventConfigParams(),
76
+ },
77
+ updateEvent: {
78
+ label: 'Update Event',
79
+ description: 'Update an existing event by ID',
80
+ apiMethod: 'events.patch',
81
+ params: [
82
+ eventIdParam('Event ID', 'Template to resolve the Google Calendar event ID'),
83
+ ...eventConfigParams(),
84
+ ],
85
+ },
86
+ deleteEvent: {
87
+ label: 'Delete Event',
88
+ description: 'Delete an event by ID',
89
+ apiMethod: 'events.delete',
90
+ params: [eventIdParam('Event ID', 'Template to resolve the Google Calendar event ID')],
91
+ },
92
+ listEvents: {
93
+ label: 'List Events',
94
+ description: 'List events in a date range',
95
+ apiMethod: 'events.list',
96
+ params: [
97
+ { name: 'timeMinTemplate', target: 'listConfig', label: 'Start Date', type: 'template', placeholder: '{{payload.from}}', execKey: 'timeMin' },
98
+ { name: 'timeMaxTemplate', target: 'listConfig', label: 'End Date', type: 'template', placeholder: '{{payload.to}}', execKey: 'timeMax' },
99
+ { name: 'maxResults', target: 'listConfig', label: 'Max Results', type: 'number', min: 1, max: 2500, default: 10 },
100
+ { name: 'query', target: 'listConfig', label: 'Search Query', type: 'template', placeholder: 'meeting' },
101
+ ],
102
+ },
103
+ getEvent: {
104
+ label: 'Get Event',
105
+ description: 'Get a single event by ID',
106
+ apiMethod: 'events.get',
107
+ params: [eventIdParam('Event ID', 'Template to resolve the Google Calendar event ID')],
108
+ },
109
+ /* ── Las cuatro que se abrieron al modo directo el 2026-08-11 ── */
110
+ listCalendars: {
111
+ label: 'List Calendars',
112
+ description: 'List the calendars you can write to (iterable output)',
113
+ apiMethod: 'calendarList.list',
114
+ viaExecutor: true,
115
+ /* Sin campos: no toma nada. Es de descubrimiento, así que en un pipeline
116
+ determinista aporta poco; está por completitud del enum. */
117
+ params: [],
118
+ },
119
+ findFreeSlots: {
120
+ label: 'Find Free Slots',
121
+ description: 'Find open windows in a date range (iterable output)',
122
+ apiMethod: 'freebusy.query',
123
+ viaExecutor: true,
124
+ params: [
125
+ { name: 'timeMinTemplate', target: 'listConfig', label: 'Window Start', type: 'template', required: true, placeholder: '{{payload.from}}', description: 'ISO 8601. Start of the window to search.', execKey: 'timeMin' },
126
+ { name: 'timeMaxTemplate', target: 'listConfig', label: 'Window End', type: 'template', required: true, placeholder: '{{payload.to}}', description: 'ISO 8601. End of the window to search.', execKey: 'timeMax' },
127
+ { name: 'durationMinutes', target: 'listConfig', label: 'Slot Length (minutes)', type: 'number', min: 15, max: 480, default: 30, description: 'Only windows at least this long are returned.', execKey: 'durationMinutes' },
128
+ { name: 'calendarIds', target: 'listConfig', label: 'Extra Calendars (comma-separated ids)', type: 'template', placeholder: 'primary, team@example.com', description: 'Combine availability across these. Empty = just the calendar configured above.', execKey: 'calendarIds' },
129
+ { name: 'timeZone', target: 'listConfig', label: 'Time Zone', type: 'timezone', description: 'IANA zone used to read the window bounds.', execKey: 'timeZone' },
130
+ ],
131
+ },
132
+ proposeEvent: {
133
+ label: 'Propose Event (tentative)',
134
+ description: 'Create a tentative event — no invites sent',
135
+ apiMethod: 'events.insert (status: tentative)',
136
+ viaExecutor: true,
137
+ params: [
138
+ ...eventConfigParams(),
139
+ /* `recurrence` sólo entra aquí, que va por el ejecutor. `createEvent` y
140
+ `updateEvent` siguen sin él porque su ruta es el `buildEventBody`
141
+ escrito a mano del servicio: es una asimetría entre modos que ya
142
+ existía y que esto no crea ni arregla. */
143
+ {
144
+ name: 'recurrenceTemplate',
145
+ target: 'eventConfig',
146
+ label: 'Recurrence (RRULE)',
147
+ type: 'template',
148
+ placeholder: 'RRULE:FREQ=WEEKLY;BYDAY=MO',
149
+ description: 'One RFC 5545 rule. Empty = a one-off event.',
150
+ execKey: 'recurrence',
151
+ },
152
+ ],
153
+ },
154
+ confirmEvent: {
155
+ label: 'Confirm Proposed Event',
156
+ description: 'Promote a tentative event and send invites',
157
+ apiMethod: 'events.patch (status: confirmed)',
158
+ viaExecutor: true,
159
+ params: [
160
+ eventIdParam('Proposal ID', 'The proposalId a Propose Event run returned. Normally {{payload.proposalId}} from an upstream node — this op is meant to sit downstream of a Propose Event.'),
161
+ {
162
+ name: 'sendUpdates',
163
+ target: 'root',
164
+ label: 'Invite Policy',
165
+ type: 'select',
166
+ default: 'all',
167
+ options: [
168
+ { value: 'all', label: 'All attendees' },
169
+ { value: 'externalOnly', label: 'External attendees only' },
170
+ { value: 'none', label: "Don't send invites" },
171
+ ],
172
+ execKey: 'sendUpdates',
173
+ },
174
+ ],
175
+ },
176
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Calendar AI Toolkit — las nueve herramientas que un calendarAction expone
3
+ * cuando `aiEnabled` está encendido.
4
+ *
5
+ * **Se escribe una sola vez.** Antes vivía dos veces —aquí y en
6
+ * `api/src/mcp-servers/toolkit-specs.ts`— y las dos copias YA habían derivado:
7
+ * las **siete** operaciones que aceptan `calendarId` describían el parámetro de
8
+ * dos maneras distintas. Gana la de la api, que es la única que dice cuál es el
9
+ * defecto:
10
+ *
11
+ * api "Optional calendar id. Defaults to the configured calendar
12
+ * (usually 'primary'). Use list_my_calendars to discover ids."
13
+ * dashboard "Optional override of the configured calendar. Use
14
+ * list_my_calendars first to discover ids when the user
15
+ * mentions a non-default calendar."
16
+ *
17
+ * Esa deriva estaba en la descripción de un PARÁMETRO, así que el conteo de la
18
+ * auditoría del 2026-08-10 no la veía y daba Calendar por limpio. Con las
19
+ * descripciones de parámetro incluidas, la deriva real de los ocho toolkits
20
+ * duplicados eran 32 y no 18.
21
+ *
22
+ * Dos cosas que **no** se añaden, a propósito:
23
+ * - `group`: Calendar nunca tuvo cabeceras de grupo en su lista, y meterlas
24
+ * es estructura visible nueva.
25
+ * - `destructive` en `delete_calendar_event`: cambiaría el comportamiento de
26
+ * `requireConfirmationForDestructive`. Mismo criterio que en Telegram.
27
+ *
28
+ * El array se generó desde la copia de la api para que las descripciones largas
29
+ * salieran idénticas, no tecleadas.
30
+ */
31
+ import type { GoogleCalendarOperation } from './calendar-operations.js';
32
+ export interface GoogleCalendarToolkitParameter {
33
+ name: string;
34
+ type: 'string' | 'number' | 'boolean';
35
+ description: string;
36
+ required: boolean;
37
+ }
38
+ export interface GoogleCalendarToolkitSpec {
39
+ operation: GoogleCalendarOperation;
40
+ /** Etiqueta corta de la fila en la lista de herramientas. */
41
+ label: string;
42
+ /** El nombre con el que el LLM llama a la herramienta. */
43
+ toolName: string;
44
+ /** Descripción y reglas de uso que ve el LLM. */
45
+ description: string;
46
+ parameters: GoogleCalendarToolkitParameter[];
47
+ }
48
+ export declare const GOOGLE_CALENDAR_TOOLKIT_SPECS: GoogleCalendarToolkitSpec[];
49
+ /** Índice por nombre de herramienta, para enrutar un `tools/call` sin recorrer. */
50
+ export declare const GOOGLE_CALENDAR_TOOLKIT_BY_TOOL_NAME: Record<string, GoogleCalendarToolkitSpec>;