@hostwebhook/node-types 1.69.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.
- package/dist/calendar-toolkit.d.ts +1 -1
- package/dist/connections.d.ts +1 -1
- package/dist/discord-operations.d.ts +1 -1
- package/dist/discord-operations.js +4 -4
- package/dist/discord-toolkit.d.ts +1 -1
- package/dist/discord-toolkit.js +3 -3
- package/dist/dispatch.d.ts +1 -1
- package/dist/docs-toolkit.d.ts +1 -1
- package/dist/drive-toolkit.d.ts +1 -1
- package/dist/esm/calendar-operations.d.ts +67 -0
- package/dist/esm/calendar-operations.js +176 -0
- package/dist/esm/calendar-toolkit.d.ts +50 -0
- package/dist/esm/calendar-toolkit.js +152 -0
- package/dist/esm/capacidad-de-credencial.d.ts +75 -0
- package/dist/esm/capacidad-de-credencial.js +68 -0
- package/dist/esm/connections.d.ts +17 -0
- package/dist/esm/connections.js +106 -0
- package/dist/esm/credentials.d.ts +144 -0
- package/dist/esm/credentials.js +199 -0
- package/dist/esm/discord-operations.d.ts +104 -0
- package/dist/esm/discord-operations.js +407 -0
- package/dist/esm/discord-toolkit.d.ts +64 -0
- package/dist/esm/discord-toolkit.js +260 -0
- package/dist/esm/dispatch.d.ts +16 -0
- package/dist/esm/dispatch.js +76 -0
- package/dist/esm/docs-operations.d.ts +99 -0
- package/dist/esm/docs-operations.js +127 -0
- package/dist/esm/docs-toolkit.d.ts +42 -0
- package/dist/esm/docs-toolkit.js +97 -0
- package/dist/esm/drive-operations.d.ts +103 -0
- package/dist/esm/drive-operations.js +319 -0
- package/dist/esm/drive-toolkit.d.ts +54 -0
- package/dist/esm/drive-toolkit.js +177 -0
- package/dist/esm/github-operations.d.ts +147 -0
- package/dist/esm/github-operations.js +551 -0
- package/dist/esm/gmail-operations.d.ts +190 -0
- package/dist/esm/gmail-operations.js +560 -0
- package/dist/esm/google-analytics-operations.d.ts +99 -0
- package/dist/esm/google-analytics-operations.js +222 -0
- package/dist/esm/google-contacts-operations.d.ts +93 -0
- package/dist/esm/google-contacts-operations.js +363 -0
- package/dist/esm/index.d.ts +66 -0
- package/dist/esm/index.js +50 -0
- package/dist/esm/jira-operations.d.ts +164 -0
- package/dist/esm/jira-operations.js +470 -0
- package/dist/esm/llm-models.d.ts +101 -0
- package/dist/esm/llm-models.js +230 -0
- package/dist/esm/mailchimp-operations.d.ts +56 -0
- package/dist/esm/mailchimp-operations.js +155 -0
- package/dist/esm/mongo-operations.d.ts +61 -0
- package/dist/esm/mongo-operations.js +120 -0
- package/dist/esm/notion-operations.d.ts +125 -0
- package/dist/esm/notion-operations.js +511 -0
- package/dist/esm/openrouter.d.ts +142 -0
- package/dist/esm/openrouter.js +99 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/postgres-operations.d.ts +60 -0
- package/dist/esm/postgres-operations.js +75 -0
- package/dist/esm/registry.d.ts +160 -0
- package/dist/esm/registry.js +555 -0
- package/dist/esm/sheets-operations.d.ts +78 -0
- package/dist/esm/sheets-operations.js +150 -0
- package/dist/esm/sheets-toolkit.d.ts +49 -0
- package/dist/esm/sheets-toolkit.js +127 -0
- package/dist/esm/shopify-operations.d.ts +95 -0
- package/dist/esm/shopify-operations.js +259 -0
- package/dist/esm/slack-operations.d.ts +81 -0
- package/dist/esm/slack-operations.js +244 -0
- package/dist/esm/slack-toolkit.d.ts +60 -0
- package/dist/esm/slack-toolkit.js +235 -0
- package/dist/esm/telegram-operations.d.ts +104 -0
- package/dist/esm/telegram-operations.js +351 -0
- package/dist/esm/telegram-toolkit.d.ts +52 -0
- package/dist/esm/telegram-toolkit.js +183 -0
- package/dist/esm/types.d.ts +149 -0
- package/dist/esm/types.js +8 -0
- package/dist/esm/ui.d.ts +13 -0
- package/dist/esm/ui.js +150 -0
- package/dist/esm/whatsapp-operations.d.ts +23 -0
- package/dist/esm/whatsapp-operations.js +36 -0
- package/dist/index.d.ts +66 -66
- package/dist/index.js +185 -185
- package/dist/openrouter.d.ts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/sheets-toolkit.d.ts +1 -1
- package/dist/slack-operations.d.ts +1 -1
- package/dist/slack-operations.js +4 -4
- package/dist/slack-toolkit.d.ts +1 -1
- package/dist/slack-toolkit.js +3 -3
- package/dist/telegram-toolkit.d.ts +1 -1
- package/dist/ui.d.ts +1 -1
- 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>;
|