@mastra/telegram 0.0.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 (3) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +137 -0
  3. package/package.json +68 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # @mastra/telegram
2
+
3
+ ## 0.1.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added `@mastra/telegram` for connecting Mastra agents to Telegram bots. It supports multiple bots, webhook or polling delivery, commands, and streaming replies, and ships a dual ESM + CJS build. Set `encryptionKey` or `MASTRA_ENCRYPTION_KEY` to encrypt stored bot tokens and webhook secret tokens at rest. ([#19975](https://github.com/mastra-ai/mastra/pull/19975))
8
+
9
+ ```ts
10
+ import { Mastra } from '@mastra/core';
11
+ import { TelegramProvider } from '@mastra/telegram';
12
+
13
+ const telegram = new TelegramProvider();
14
+
15
+ export const mastra = new Mastra({
16
+ agents: { support },
17
+ channels: { telegram },
18
+ });
19
+
20
+ // Paste a BotFather token to connect an agent instantly:
21
+ const result = await telegram.connect('support', { botToken: process.env.TELEGRAM_BOT_TOKEN });
22
+ // → { type: 'immediate', installationId: '...' }
23
+ ```
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies [[`66bbfb5`](https://github.com/mastra-ai/mastra/commit/66bbfb5f05b473d39f88c0e4a481ccac41634f3a)]:
28
+ - @mastra/core@1.58.0-alpha.10
package/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # @mastra/telegram
2
+
3
+ Telegram channel wrapper for Mastra — a `ChannelProvider` (`@mastra/core/channels`) over **[`@chat-adapter/telegram`](https://www.npmjs.com/package/@chat-adapter/telegram)** (`^4.34.0`, aligned with the `@chat-adapter/*` version the monorepo builds against), to parity with `@mastra/slack`.
4
+
5
+ The adapter already handles the Bot API transport (webhook parse, send/edit, typing, rich messages, inline keyboards). This package adds the install/lifecycle layer: a multi-bot token store, `setWebhook` + secret-token verification, `setMyCommands`, and Mastra route/stream wiring.
6
+
7
+ **Shape (how Telegram differs from Slack):** no OAuth, no Ed25519, no app-factory. The BotFather token _is_ the credential — one token per bot, one bot per agent.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @mastra/telegram
13
+ # peer: @mastra/core — channels require >= 1.22.0
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import { Mastra } from '@mastra/core';
20
+ import { TelegramProvider } from '@mastra/telegram';
21
+
22
+ const telegram = new TelegramProvider({
23
+ baseUrl: 'https://your-app.example.com', // for setWebhook; auto-detected from the Mastra server if omitted
24
+ });
25
+
26
+ export const mastra = new Mastra({
27
+ agents: { support },
28
+ channels: { telegram },
29
+ });
30
+
31
+ // Paste a BotFather token to connect an agent instantly:
32
+ const result = await telegram.connect('support', { botToken: process.env.TELEGRAM_BOT_TOKEN });
33
+ // → { type: 'immediate', installationId: '...' }
34
+ ```
35
+
36
+ ## The connect flow
37
+
38
+ `connect(agentId, options?)` returns a discriminated `ChannelConnectResult` — Telegram never uses OAuth:
39
+
40
+ | Call | Result | Meaning |
41
+ | --------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------- |
42
+ | `connect(id, { botToken })` | `{ type: 'immediate' }` | Token validated via `getMe`; the bot is live. |
43
+ | `connect(id)` | `{ type: 'deep_link', url: 'https://t.me/botfather' }` | No token yet — open BotFather, run `/newbot`, then call `connect` again with the token. |
44
+
45
+ `connect` is idempotent per agent: a pending install upgrades to active (same id/webhook) when the token arrives, and re-connecting an already-active agent throws (disconnect first). **One bot = one agent.**
46
+
47
+ ## Webhook vs polling
48
+
49
+ Setting a webhook and long-polling `getUpdates` are mutually exclusive; the provider manages the switch per bot via the `mode` option:
50
+
51
+ - `auto` (default) — webhook when a `baseUrl` is available, otherwise polling.
52
+ - `webhook` — register `setWebhook` (requires a `baseUrl`).
53
+ - `polling` — clear any webhook first, then long-poll.
54
+
55
+ In polling mode the adapter's `getUpdates` loop starts automatically once the agent is wired (tune it with `longPolling`); `disconnect()` stops it.
56
+
57
+ In webhook mode the provider mounts one route, `POST /telegram/events/:webhookId`, and verifies the `X-Telegram-Bot-Api-Secret-Token` header (constant-time) on **every** request before delegating to the agent. The per-bot secret is generated automatically and never travels in the URL.
58
+
59
+ ## Commands
60
+
61
+ Commands are published via `setMyCommands` and default to the conventional `/start` `/help` `/settings` seed. Override per agent or provider-wide:
62
+
63
+ ```ts
64
+ await telegram.connect('support', {
65
+ botToken,
66
+ commands: ['/ask', { command: 'summarize', description: 'Summarize a link' }],
67
+ });
68
+ ```
69
+
70
+ Names are normalized to the Bot API constraints (lowercase `[a-z0-9_]`, 1-32 chars; description 1-256).
71
+
72
+ ## Streaming
73
+
74
+ Telegram has no native token streaming. With `streaming: true` (default) the reply is chunk-edited via `editMessageText` (4096-char cap handled by the adapter), and `typingStatus: true` (default) keeps a `sendChatAction` indicator alive. Set either to `false` to disable.
75
+
76
+ ## Configuration
77
+
78
+ `new TelegramProvider(config)`:
79
+
80
+ | Option | Default | Notes |
81
+ | ---------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
82
+ | `baseUrl` | Mastra server config | Public HTTPS base for `setWebhook`. |
83
+ | `storage` | Mastra channels storage, else in-memory | Installation persistence (`ChannelsStorage`). |
84
+ | `encryptionKey` | `MASTRA_ENCRYPTION_KEY` env | Encrypts `botToken`/`secretToken` at rest with AES-256-GCM when set; otherwise they are stored in plaintext. |
85
+ | `apiBaseUrl` | `https://api.telegram.org` | Override for a self-hosted Bot API server. |
86
+ | `mode` | `auto` | `auto` \| `webhook` \| `polling`. |
87
+ | `allowedUpdates` | message, edited_message, channel_post, callback_query, message_reaction | Passed to `setWebhook`. |
88
+ | `longPolling` | adapter defaults | Poll-loop tuning (`timeout`, `limit`, `retryDelayMs`…) for polling mode. |
89
+ | `commands` | `/start /help /settings` | Default command seed. |
90
+ | `commandScope` | Telegram default | `BotCommandScope` for `setMyCommands`. |
91
+ | `streaming` | `true` | Post-and-edit reply streaming. |
92
+ | `typingStatus` | `true` | Typing keepalive. |
93
+ | `toolDisplay` | `'text'` | How tool calls render. Telegram has no Block Kit, so `'cards'`/`'grouped'`/`'timeline'` degrade to text. |
94
+ | `waitUntil` | — | Keep serverless invocations alive (Vercel/Lambda). |
95
+
96
+ ### AgentChannels passthrough
97
+
98
+ These forward to the agent's `AgentChannels` (the same curated subset `@mastra/slack` exposes); each falls back to anything the agent author already configured:
99
+
100
+ | Option | Notes |
101
+ | --------------------------------- | ------------------------------------------------------------------------ |
102
+ | `handlers` | Override `onDirectMessage` / `onMention` / `onSubscribedMessage`. |
103
+ | `inlineMedia` | Which media types are sent inline to the model (Telegram photos, PDFs…). |
104
+ | `inlineLinks` | Promote URLs in messages to file parts. |
105
+ | `tools` | Expose reaction tools (`add_reaction`/`remove_reaction`). Default on. |
106
+ | `state` | State adapter for dedup, locking, subscriptions. |
107
+ | `threadContext` | Fetch recent messages when joining a thread mid-conversation. |
108
+ | `chatOptions` | Passthrough to the underlying Chat SDK. |
109
+ | `resolveResourceId` | Choose memory ownership for a thread. |
110
+ | `cors` / `formatError` / `logger` | Webhook-route CORS, error rendering, adapter logger. |
111
+ | `resolveWaitUntil` | Resolve `waitUntil` from the request context. |
112
+ | `onInstall` | Called after an agent connects and the install is persisted. |
113
+
114
+ ## Formatting & interactivity
115
+
116
+ Message rendering is owned by the adapter, not this provider — so there is no double-escaping to worry about:
117
+
118
+ - **MarkdownV2** — the adapter emits `parse_mode: MarkdownV2` with context-aware escaping. Return `{ raw: '…' }` from a card to ship a pre-escaped string yourself.
119
+ - **Inline keyboards** — supported via the adapter's card buttons. Telegram caps `callback_data` at **64 bytes**, so keep button ids/values short; rich elements beyond buttons render as fallback text.
120
+ - **Reactions** — enabled through `tools` (`add_reaction`/`remove_reaction`); `message_reaction` updates are requested by default.
121
+
122
+ ## Module format
123
+
124
+ Dual **ESM + CJS**. `@chat-adapter/telegram` is ESM-only (its `exports` declares only an `import` condition), and tsup externalises `dependencies` by default — so the adapter is kept external in the ESM build (lean, deduped) but bundled into the CJS output via `noExternal`. Both `import` and `require('@mastra/telegram')` therefore work. See `tsup.config.ts` for why this intentionally differs from `channels/slack`.
125
+
126
+ ## Development
127
+
128
+ ```bash
129
+ pnpm install
130
+ pnpm --filter @mastra/telegram typecheck
131
+ pnpm --filter @mastra/telegram test # vitest, undici-mocked Bot API
132
+ pnpm --filter @mastra/telegram build # tsup → dist
133
+ ```
134
+
135
+ ## License
136
+
137
+ Apache-2.0
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@mastra/telegram",
3
+ "version": "0.0.0",
4
+ "description": "Telegram integration for Mastra agents — a ChannelProvider over @chat-adapter/telegram with webhooks, secret verification, commands, and streaming replies",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "CHANGELOG.md"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "import": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "require": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.cjs"
22
+ }
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "tsup",
27
+ "dev": "tsup --watch",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest"
31
+ },
32
+ "dependencies": {
33
+ "@chat-adapter/telegram": "^4.34.0"
34
+ },
35
+ "devDependencies": {
36
+ "@mastra/core": "workspace:*",
37
+ "@types/node": "^22.20.1",
38
+ "tsup": "^8.5.1",
39
+ "typescript": "catalog:",
40
+ "undici": "^6.0.0",
41
+ "vitest": "^4.1.10"
42
+ },
43
+ "peerDependencies": {
44
+ "@mastra/core": ">=1.22.0 <2.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "keywords": [
50
+ "mastra",
51
+ "telegram",
52
+ "chatbot",
53
+ "ai",
54
+ "agent"
55
+ ],
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/mastra-ai/mastra.git",
59
+ "directory": "channels/telegram"
60
+ },
61
+ "homepage": "https://mastra.ai",
62
+ "bugs": {
63
+ "url": "https://github.com/mastra-ai/mastra/issues"
64
+ },
65
+ "engines": {
66
+ "node": ">=22.13.0"
67
+ }
68
+ }