@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
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Telegram Bot API operation enum — single source of truth across the API,
3
+ * Dashboard, and any future consumers (Message Broker, MCP server). Used by:
4
+ * - telegramAction entity / DTO (api): operation field + validation
5
+ * - dashboard TelegramAction operation picker
6
+ * - MCP toolkit-specs expansion (one aiEnabled telegramAction → N tools)
7
+ *
8
+ * Phase 1 covers the eight ops that handle ~95% of bot send use cases.
9
+ * Phase 2 candidates (sendMediaGroup, voice/video uploads, chat admin,
10
+ * setMyCommands, message reactions, inline-mode answers) get added by
11
+ * extending this list, bumping the package, and re-installing in
12
+ * consumers — same pattern as Gmail / Calendar / Drive.
13
+ */
14
+ export declare const TELEGRAM_OPERATIONS: readonly ["sendMessage", "replyToMessage", "sendPhoto", "sendDocument", "sendVoice", "sendAndWaitForResponse", "editMessageText", "deleteMessage", "answerCallbackQuery", "forwardMessage", "sendPoll"];
15
+ export type TelegramOperation = (typeof TELEGRAM_OPERATIONS)[number];
16
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
17
+ export declare function isTelegramOperation(value: unknown): value is TelegramOperation;
18
+ /**
19
+ * Per-operation form schema, same idea as SLACK_OPERATION_SPECS and
20
+ * DISCORD_OPERATION_SPECS: the detail page renders it with one loop instead of
21
+ * a branch per operation. It replaces 12 branches and a local `OPERATIONS`
22
+ * array of 11 entries whose count had already drifted from the truth — the
23
+ * mode chip read "Choose 1 of 10 ops" while the page painted 11 cards.
24
+ *
25
+ * Two things about this node's schema are worth knowing before writing a
26
+ * renderer for it:
27
+ *
28
+ * 1. **`chatId` is per-operation, not global.** The page used to hoist one
29
+ * shared field to the top of every form, but `answerCallbackQuery` has no
30
+ * chat at all (it answers a callback id) and `forwardMessage` needs two
31
+ * chats with their own labels — "Destination" and "Source". So it is
32
+ * declared op by op, and where it repeats it repeats on purpose.
33
+ * 2. **Three booleans default to ON.** See the note on `default` below; a
34
+ * renderer that coerces with `!!config[name]` silently turns them off.
35
+ */
36
+ export interface TelegramParamSpec {
37
+ /** Field key — the property name inside `operationConfig`. */
38
+ name: string;
39
+ /** UI label shown above the control. */
40
+ label: string;
41
+ /**
42
+ * Param type for form rendering.
43
+ *
44
+ * - `string` — one-line input with `{{payload.x}}` templating.
45
+ * - `text` — the same input, multiline; `rows` sets its height.
46
+ * - `select` — fixed option list (only `parseMode` today).
47
+ * - `boolean` — a Switch. Read it as `config[name] ?? default`, never as
48
+ * `!!config[name]`: see `default`.
49
+ * - `number` — numeric input clamped to `min`/`max` as it is typed.
50
+ * - `linesList` — **stored as an array of strings, edited as one per
51
+ * line.** Telegram's poll options. The cousin of Contacts' `csvList`,
52
+ * split on newlines instead of commas. A renderer that treats it as text
53
+ * turns the array into a string on the first save and `sendPoll` starts
54
+ * failing.
55
+ */
56
+ type: 'string' | 'text' | 'select' | 'boolean' | 'number' | 'linesList';
57
+ /** Required by the operation. Metadata — the form does not gate on it. */
58
+ required?: boolean;
59
+ /** Help text under the control. Absent where the form shows none. */
60
+ description?: string;
61
+ /** Hint shown inside the input. May contain newlines for `linesList`. */
62
+ placeholder?: string;
63
+ /**
64
+ * Value to show when the stored one is `undefined`.
65
+ *
66
+ * `includeDisapprove`, `isAnonymous` and `parseMode` all have one, and the
67
+ * first two default to **true**: the stored config only ever holds `false`
68
+ * when the user turned them off. `config[name] ?? default` reproduces that
69
+ * exactly; `!!config[name]` does not, and getting it wrong strips the
70
+ * Disapprove button off every approval flow that already exists.
71
+ */
72
+ default?: string | number | boolean;
73
+ /** `select` only — the fixed option list, in display order. */
74
+ options?: string[];
75
+ /** `number` only — the input clamps to these while typing. */
76
+ min?: number;
77
+ max?: number;
78
+ /** `text` only — height of the textarea. */
79
+ rows?: number;
80
+ /**
81
+ * Renders side by side with the next field in a two-column row. Only the
82
+ * Approve / Disapprove button labels use it — they are one decision split
83
+ * in two, and stacking them reads as two unrelated fields.
84
+ */
85
+ pairedWithNext?: boolean;
86
+ }
87
+ export interface TelegramOperationSpec {
88
+ /** UI label for the operation picker card. */
89
+ label: string;
90
+ /** Sub-line under the label in the picker. */
91
+ description: string;
92
+ /** Bot API method the operation maps to (core.telegram.org/bots/api). */
93
+ apiMethod: string;
94
+ /**
95
+ * The op accepts `reply_markup`, so the page offers the inline-keyboard
96
+ * builder for it. Used to live as a hardcoded array of five strings in the
97
+ * detail page. `sendAndWaitForResponse` is deliberately absent: it builds
98
+ * its own Approve / Disapprove keyboard and a second one would collide.
99
+ */
100
+ supportsInlineKeyboard?: boolean;
101
+ /** Parameter schema. Order matters for form rendering. */
102
+ params: TelegramParamSpec[];
103
+ }
104
+ export declare const TELEGRAM_OPERATION_SPECS: Record<TelegramOperation, TelegramOperationSpec>;
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Telegram Bot API operation enum — single source of truth across the API,
3
+ * Dashboard, and any future consumers (Message Broker, MCP server). Used by:
4
+ * - telegramAction entity / DTO (api): operation field + validation
5
+ * - dashboard TelegramAction operation picker
6
+ * - MCP toolkit-specs expansion (one aiEnabled telegramAction → N tools)
7
+ *
8
+ * Phase 1 covers the eight ops that handle ~95% of bot send use cases.
9
+ * Phase 2 candidates (sendMediaGroup, voice/video uploads, chat admin,
10
+ * setMyCommands, message reactions, inline-mode answers) get added by
11
+ * extending this list, bumping the package, and re-installing in
12
+ * consumers — same pattern as Gmail / Calendar / Drive.
13
+ */
14
+ export const TELEGRAM_OPERATIONS = [
15
+ 'sendMessage',
16
+ 'replyToMessage',
17
+ 'sendPhoto',
18
+ 'sendDocument',
19
+ 'sendVoice',
20
+ // Pause-the-pipeline op — sends a Telegram message with Approve /
21
+ // (optional) Disapprove inline buttons and waits for the recipient to
22
+ // tap one. When `allowFreeText` is on, a text reply in the same chat
23
+ // also resolves the wait. Backed by the same shared PendingApproval +
24
+ // send-and-wait infra emailAction uses, with a Telegram-specific
25
+ // resume path through triggers.processTelegramPush (intercepts
26
+ // callback_query.data === "swat:{token}:a|r" before normal dispatch).
27
+ // Output of the node carries `payload._waitResponse = { approved,
28
+ // decidedAt, ipAddress, comment?, responseText?, timedOut? }` for
29
+ // downstream Conditional nodes.
30
+ 'sendAndWaitForResponse',
31
+ 'editMessageText',
32
+ 'deleteMessage',
33
+ 'answerCallbackQuery',
34
+ 'forwardMessage',
35
+ 'sendPoll',
36
+ ];
37
+ /** Type guard — useful when validating untrusted input (DTOs, tool calls). */
38
+ export function isTelegramOperation(value) {
39
+ return (typeof value === 'string' &&
40
+ TELEGRAM_OPERATIONS.includes(value));
41
+ }
42
+ /* Los campos que se repiten entre operaciones. Fábricas y no constantes
43
+ compartidas: cada op recibe su propia copia y puede cambiarle la etiqueta o
44
+ la ayuda sin tocar a las demás. */
45
+ const chatId = () => ({
46
+ name: 'chatId',
47
+ label: 'Chat ID',
48
+ type: 'string',
49
+ required: true,
50
+ description: 'Numeric chat id (from a Telegram trigger payload — usually {{payload.chatId}}) or @channelusername.',
51
+ placeholder: '{{payload.chatId}}',
52
+ });
53
+ const parseMode = (description) => ({
54
+ name: 'parseMode',
55
+ label: 'Parse mode',
56
+ type: 'select',
57
+ options: ['HTML', 'MarkdownV2', 'none'],
58
+ // Se enseña como VALOR, no como placeholder: el campo sale relleno con HTML
59
+ // aunque nunca se haya guardado nada.
60
+ default: 'HTML',
61
+ ...(description ? { description } : {}),
62
+ });
63
+ const messageId = (label, description, placeholder = '{{payload.messageId}}') => ({
64
+ name: 'messageId',
65
+ label,
66
+ type: 'string',
67
+ required: true,
68
+ placeholder,
69
+ ...(description ? { description } : {}),
70
+ });
71
+ const caption = (description, rows) => ({
72
+ name: 'caption',
73
+ label: 'Caption',
74
+ type: 'text',
75
+ rows,
76
+ description,
77
+ placeholder: rows > 2 ? 'Optional caption' : 'Optional',
78
+ });
79
+ export const TELEGRAM_OPERATION_SPECS = {
80
+ sendMessage: {
81
+ label: 'Send message',
82
+ description: 'Text reply with optional inline keyboard',
83
+ apiMethod: 'POST /sendMessage',
84
+ supportsInlineKeyboard: true,
85
+ params: [
86
+ chatId(),
87
+ {
88
+ name: 'text',
89
+ label: 'Text',
90
+ type: 'text',
91
+ required: true,
92
+ rows: 4,
93
+ description: 'Message body. HTML by default — escape <, >, & in user-supplied content.',
94
+ placeholder: 'Hi {{payload.fromUsername}}, thanks for your message!',
95
+ },
96
+ parseMode('HTML / MarkdownV2 / none.'),
97
+ {
98
+ name: 'replyToMessageId',
99
+ label: 'Reply to message ID',
100
+ type: 'string',
101
+ description: "Optional. Numeric id of the message you're replying to. For a fully-required quote-reply, use the dedicated 'Reply to message' op instead.",
102
+ placeholder: '{{payload.messageId}}',
103
+ },
104
+ ],
105
+ },
106
+ replyToMessage: {
107
+ label: 'Reply to message',
108
+ description: "Quote-reply with the threaded indicator above the bot's message",
109
+ apiMethod: 'POST /sendMessage (reply_to_message_id)',
110
+ supportsInlineKeyboard: true,
111
+ params: [
112
+ chatId(),
113
+ messageId('Message ID to reply to', "Numeric id of the user message you're quote-replying to. From a Telegram trigger this is typically {{payload.message.message_id}}.", '{{payload.message.message_id}}'),
114
+ {
115
+ name: 'text',
116
+ label: 'Text',
117
+ type: 'text',
118
+ required: true,
119
+ rows: 4,
120
+ description: 'Reply body. HTML by default — escape <, >, & in user-supplied content.',
121
+ placeholder: 'Yes, I understood your question about {{payload.text}}',
122
+ },
123
+ parseMode('HTML / MarkdownV2 / none.'),
124
+ ],
125
+ },
126
+ sendPhoto: {
127
+ label: 'Send photo',
128
+ description: 'Image by URL or _file ref',
129
+ apiMethod: 'POST /sendPhoto',
130
+ supportsInlineKeyboard: true,
131
+ params: [
132
+ chatId(),
133
+ {
134
+ name: 'photo',
135
+ label: 'Photo URL or file_id',
136
+ type: 'string',
137
+ required: true,
138
+ description: 'Public URL Telegram can fetch, or a file_id from a prior send.',
139
+ placeholder: '{{payload.attachment._file.downloadUrl}}',
140
+ },
141
+ caption('Optional. HTML supported. Max 1024 chars.', 3),
142
+ ],
143
+ },
144
+ sendDocument: {
145
+ label: 'Send document',
146
+ description: 'File of any type by URL',
147
+ apiMethod: 'POST /sendDocument',
148
+ supportsInlineKeyboard: true,
149
+ params: [
150
+ chatId(),
151
+ {
152
+ name: 'document',
153
+ label: 'Document URL or file_id',
154
+ type: 'string',
155
+ required: true,
156
+ description: 'Public URL or file_id. Max 50MB when fetching by URL.',
157
+ placeholder: '{{payload.file._file.downloadUrl}}',
158
+ },
159
+ caption('Optional. HTML supported.', 2),
160
+ ],
161
+ },
162
+ sendVoice: {
163
+ label: 'Send voice',
164
+ description: 'Send a voice bubble — pass a URL / file_id (or chain from the AI Node synthesize_voice tool)',
165
+ apiMethod: 'POST /sendVoice',
166
+ params: [
167
+ chatId(),
168
+ {
169
+ name: 'voice',
170
+ label: 'Voice URL or file_id',
171
+ type: 'string',
172
+ required: true,
173
+ description: 'OGG/OPUS audio URL Telegram can fetch, or a file_id from a prior /sendVoice for cheap re-sends. To synthesize from text, add the AI Node `synthesize_voice` tool (Tools tab → + Add → Voice synthesis) and pass its result here via `{{payload.voice}}` or chain through the LLM.',
174
+ placeholder: 'https://… .ogg or {{payload.voice}}',
175
+ },
176
+ ],
177
+ },
178
+ sendAndWaitForResponse: {
179
+ label: 'Send & wait for response',
180
+ description: 'Sends a message with Approve / Disapprove buttons (and optional free-text reply) — pipeline pauses until the user responds',
181
+ apiMethod: 'POST /sendMessage + PendingApproval',
182
+ params: [
183
+ chatId(),
184
+ {
185
+ name: 'text',
186
+ label: 'Message',
187
+ type: 'text',
188
+ required: true,
189
+ rows: 4,
190
+ description: 'Body of the prompt shown above the Approve / Disapprove buttons. HTML supported by default.',
191
+ placeholder: 'Approve the ${{payload.amount}} payment to {{payload.vendor}}?',
192
+ },
193
+ parseMode('HTML / MarkdownV2 / none.'),
194
+ {
195
+ name: 'approveLabel',
196
+ label: 'Approve button label',
197
+ type: 'string',
198
+ description: 'Tap = approved.',
199
+ placeholder: 'Approve',
200
+ pairedWithNext: true,
201
+ },
202
+ {
203
+ name: 'disapproveLabel',
204
+ label: 'Disapprove button label',
205
+ type: 'string',
206
+ description: "Tap = rejected. Hidden when 'Include disapprove' is off.",
207
+ placeholder: 'Reject',
208
+ },
209
+ {
210
+ name: 'includeDisapprove',
211
+ label: 'Include disapprove button',
212
+ type: 'boolean',
213
+ default: true,
214
+ description: 'Off = approval-only (single button). Default on.',
215
+ },
216
+ {
217
+ name: 'allowFreeText',
218
+ label: 'Allow free-text reply',
219
+ type: 'boolean',
220
+ default: false,
221
+ description: "When on, a plain text reply in the same chat also resolves the wait — _waitResponse.responseText carries the typed message. Useful for capturing context ('approved with comment'). Default off.",
222
+ },
223
+ {
224
+ name: 'timeoutMinutes',
225
+ label: 'Timeout (minutes)',
226
+ type: 'number',
227
+ min: 1,
228
+ max: 20160,
229
+ default: 1440,
230
+ description: 'Pipeline auto-resumes (rejected) after this many minutes if no response. Default 1440 (24h).',
231
+ },
232
+ ],
233
+ },
234
+ editMessageText: {
235
+ label: 'Edit message',
236
+ description: 'Replace text of a previously-sent message',
237
+ apiMethod: 'POST /editMessageText',
238
+ supportsInlineKeyboard: true,
239
+ params: [
240
+ chatId(),
241
+ messageId('Message ID', 'Id of the message to edit (from a prior sendMessage result).'),
242
+ {
243
+ name: 'text',
244
+ label: 'New text',
245
+ type: 'text',
246
+ required: true,
247
+ rows: 3,
248
+ description: 'Replacement text for the message.',
249
+ placeholder: 'Updated content',
250
+ },
251
+ // Sin ayuda a propósito: es la única op donde el formulario nunca la ha
252
+ // enseñado, y no me invento copy nueva al mudar el campo.
253
+ parseMode(),
254
+ ],
255
+ },
256
+ deleteMessage: {
257
+ label: 'Delete message',
258
+ description: 'Remove a message from a chat',
259
+ apiMethod: 'POST /deleteMessage',
260
+ params: [
261
+ chatId(),
262
+ messageId('Message ID', 'Id of the message to delete.'),
263
+ ],
264
+ },
265
+ answerCallbackQuery: {
266
+ label: 'Answer callback',
267
+ description: 'Acknowledge an inline-button press (REQUIRED after callback_query)',
268
+ apiMethod: 'POST /answerCallbackQuery',
269
+ params: [
270
+ {
271
+ name: 'callbackQueryId',
272
+ label: 'Callback query ID',
273
+ type: 'string',
274
+ required: true,
275
+ description: 'From the trigger payload — usually {{payload.callbackQueryId}} when responding to an inline-button press.',
276
+ placeholder: '{{payload.callbackQueryId}}',
277
+ },
278
+ {
279
+ name: 'text',
280
+ label: 'Text',
281
+ type: 'string',
282
+ description: 'Optional. Toast (or alert if showAlert is on). Max 200 chars.',
283
+ placeholder: 'Saved!',
284
+ },
285
+ {
286
+ name: 'showAlert',
287
+ label: 'Show as alert',
288
+ type: 'boolean',
289
+ default: false,
290
+ description: 'When on, shows a modal alert above the chat instead of a toast.',
291
+ },
292
+ ],
293
+ },
294
+ forwardMessage: {
295
+ label: 'Forward message',
296
+ description: 'Forward an existing message to another chat',
297
+ apiMethod: 'POST /forwardMessage',
298
+ // Las tres sin ayuda: las etiquetas ya dicen cuál es cuál, y así estaba.
299
+ params: [
300
+ {
301
+ name: 'chatId',
302
+ label: 'Destination chat ID',
303
+ type: 'string',
304
+ required: true,
305
+ placeholder: '{{payload.targetChatId}}',
306
+ },
307
+ {
308
+ name: 'fromChatId',
309
+ label: 'Source chat ID',
310
+ type: 'string',
311
+ required: true,
312
+ placeholder: '{{payload.chatId}}',
313
+ },
314
+ messageId('Source message ID'),
315
+ ],
316
+ },
317
+ sendPoll: {
318
+ label: 'Send poll',
319
+ description: 'Multi-option poll (regular or quiz)',
320
+ apiMethod: 'POST /sendPoll',
321
+ params: [
322
+ chatId(),
323
+ {
324
+ name: 'question',
325
+ label: 'Question',
326
+ type: 'text',
327
+ required: true,
328
+ rows: 2,
329
+ description: 'Max 300 chars.',
330
+ placeholder: 'Which option?',
331
+ },
332
+ {
333
+ name: 'options',
334
+ label: 'Options (2-10)',
335
+ type: 'linesList',
336
+ required: true,
337
+ rows: 5,
338
+ description: 'One per line. Max 100 chars each.',
339
+ placeholder: 'Option A\nOption B\nOption C',
340
+ },
341
+ {
342
+ name: 'isAnonymous',
343
+ label: 'Anonymous',
344
+ type: 'boolean',
345
+ // Defecto ENCENDIDO, como includeDisapprove.
346
+ default: true,
347
+ description: 'Default true. Set false to expose voter identities.',
348
+ },
349
+ ],
350
+ },
351
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Telegram AI Toolkit — las herramientas que un telegramAction expone cuando
3
+ * `aiEnabled` está encendido.
4
+ *
5
+ * **Se escribe una sola vez**, como el de Sheets. Antes vivía dos veces: una
6
+ * copia en `dashboard/components/telegram-actions/telegram-operations-schemas.ts`
7
+ * y otra en `api/src/mcp-servers/toolkit-specs.ts`, las dos a mano, las dos con
8
+ * el mismo TODO escrito pidiendo justo esto. Y ya habían derivado: el
9
+ * `messageId` de `reply_telegram_message` era `number` en el dashboard y
10
+ * `string` en la api, mientras en las otras tres ops que lo llevan era `number`
11
+ * en las dos. Aquí es `number` y punto.
12
+ *
13
+ * Hay una TERCERA copia que también desaparece: la página de detalle pintaba la
14
+ * lista de las diez herramientas como diez `<li>` escritos a mano. Ahora sale de
15
+ * aquí, contada con `.length`, que es lo que evita que un día anuncie diez y
16
+ * exponga otra cosa.
17
+ *
18
+ * La forma es la que ya consume `toolkitSpecToMcpTool` en la api, para que pueda
19
+ * usarse sin adaptador. Los textos van en inglés porque los lee el modelo y
20
+ * quien mire la lista de herramientas del servidor MCP.
21
+ */
22
+ import type { TelegramOperation } from './telegram-operations.js';
23
+ export interface TelegramToolkitParameter {
24
+ name: string;
25
+ type: 'string' | 'number' | 'boolean';
26
+ description: string;
27
+ required: boolean;
28
+ }
29
+ export interface TelegramToolkitSpec {
30
+ operation: TelegramOperation;
31
+ /** Etiqueta corta de la fila en la lista de herramientas. */
32
+ label: string;
33
+ /**
34
+ * Nombre con el que el LLM llama a la herramienta. Lleva `_telegram_` para
35
+ * no chocar con el `send_email` de Gmail ni el `create_event` de Calendar
36
+ * cuando un mismo AI Node tiene varios toolkits encendidos.
37
+ */
38
+ toolName: string;
39
+ /** Descripción (más reglas de uso) que ve el LLM. */
40
+ description: string;
41
+ parameters: TelegramToolkitParameter[];
42
+ /**
43
+ * Encabezado de grupo para la lista de la página de detalle. Las filas
44
+ * consecutivas que comparten grupo se pintan bajo un único título, así que el
45
+ * ORDEN de este array es el que agrupa. Es el mismo que enseñaba el JSX que
46
+ * sustituye.
47
+ */
48
+ group?: string;
49
+ }
50
+ export declare const TELEGRAM_TOOLKIT_SPECS: TelegramToolkitSpec[];
51
+ /** Las herramientas por nombre, para despachar una llamada del modelo. */
52
+ export declare const TELEGRAM_TOOLKIT_BY_TOOL_NAME: Record<string, TelegramToolkitSpec>;