@elizaos/plugin-telegram 2.0.0-alpha.9 → 2.0.0-beta.1

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/index.js CHANGED
@@ -1,3 +1,322 @@
1
+ import {
2
+ TelegramAccountAuthSession,
3
+ clearTelegramAccountAuthState,
4
+ clearTelegramAccountSession,
5
+ defaultTelegramAccountDeviceModel,
6
+ defaultTelegramAccountSystemVersion,
7
+ loadTelegramAccountSessionString,
8
+ resolveTelegramAccountSessionFile,
9
+ saveTelegramAccountSessionString,
10
+ telegramAccountAuthStateExists,
11
+ telegramAccountSessionExists
12
+ } from "./chunk-KFEFF6RI.js";
13
+
14
+ // src/index.ts
15
+ import { getConnectorAccountManager, logger as logger7 } from "@elizaos/core";
16
+
17
+ // src/account-setup-routes.ts
18
+ function isConnectorSetupService(service) {
19
+ if (!service || typeof service !== "object") {
20
+ return false;
21
+ }
22
+ const candidate = service;
23
+ return typeof candidate.getConfig === "function" && typeof candidate.updateConfig === "function" && typeof candidate.persistConfig === "function";
24
+ }
25
+ function getSetupService(runtime) {
26
+ const service = runtime.getService("connector-setup");
27
+ return isConnectorSetupService(service) ? service : null;
28
+ }
29
+ var telegramAccountAuthSession = null;
30
+ async function stopTelegramAccountAuthSession() {
31
+ if (telegramAccountAuthSession) {
32
+ try {
33
+ await telegramAccountAuthSession.stop();
34
+ } catch {
35
+ }
36
+ telegramAccountAuthSession = null;
37
+ }
38
+ }
39
+ function readConnectorConfig(config) {
40
+ const connectors = config.connectors;
41
+ const raw = connectors?.telegramAccount;
42
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
43
+ return {};
44
+ }
45
+ return raw;
46
+ }
47
+ function hasConfiguredTelegramAccount(connConfig) {
48
+ return Boolean(
49
+ typeof connConfig.phone === "string" && connConfig.phone.trim() && (typeof connConfig.appId === "string" || typeof connConfig.appId === "number") && typeof connConfig.appHash === "string" && connConfig.appHash.trim() && typeof connConfig.deviceModel === "string" && connConfig.deviceModel.trim() && typeof connConfig.systemVersion === "string" && connConfig.systemVersion.trim() && connConfig.enabled !== false
50
+ );
51
+ }
52
+ function resolveConfiguredPhone(runtime, connConfig) {
53
+ if (typeof connConfig.phone === "string" && connConfig.phone.trim().length > 0) {
54
+ return connConfig.phone.trim();
55
+ }
56
+ const setting = runtime.getSetting("TELEGRAM_ACCOUNT_PHONE");
57
+ return typeof setting === "string" && setting.trim().length > 0 ? setting.trim() : null;
58
+ }
59
+ function resolveService(runtime) {
60
+ const service = runtime.getService("telegram-account");
61
+ return service ?? null;
62
+ }
63
+ function isServiceConnected(service) {
64
+ if (!service) {
65
+ return false;
66
+ }
67
+ if (typeof service.isConnected === "function") {
68
+ return service.isConnected();
69
+ }
70
+ const withFlags = service;
71
+ if (typeof withFlags.isServiceConnected === "function") {
72
+ return withFlags.isServiceConnected();
73
+ }
74
+ return withFlags.connected === true;
75
+ }
76
+ function statusFromState(runtime, config) {
77
+ const connectorConfig = readConnectorConfig(config);
78
+ const configured = hasConfiguredTelegramAccount(connectorConfig);
79
+ const sessExists = telegramAccountSessionExists();
80
+ const authSnapshot = telegramAccountAuthSession?.getSnapshot() ?? null;
81
+ const service = resolveService(runtime);
82
+ const serviceConnected = isServiceConnected(service);
83
+ const serviceAccount = typeof service?.getAccountSummary === "function" ? service.getAccountSummary() : null;
84
+ const fallbackPhone = resolveConfiguredPhone(runtime, connectorConfig);
85
+ let status = authSnapshot?.status ?? (serviceConnected ? "connected" : configured || sessExists ? "configured" : "idle");
86
+ if (serviceConnected && status === "configured") {
87
+ status = "connected";
88
+ }
89
+ return {
90
+ available: true,
91
+ status,
92
+ configured,
93
+ sessionExists: sessExists,
94
+ serviceConnected,
95
+ restartRequired: status === "configured" && !serviceConnected,
96
+ hasAppCredentials: Boolean(
97
+ (typeof connectorConfig.appId === "string" || typeof connectorConfig.appId === "number") && typeof connectorConfig.appHash === "string" && connectorConfig.appHash.trim().length > 0
98
+ ),
99
+ phone: authSnapshot?.phone ?? fallbackPhone,
100
+ isCodeViaApp: authSnapshot?.isCodeViaApp ?? false,
101
+ account: authSnapshot?.account ?? serviceAccount ?? null,
102
+ error: authSnapshot?.error ?? null
103
+ };
104
+ }
105
+ function ensureConnectorBlock(config) {
106
+ if (!config.connectors) {
107
+ config.connectors = {};
108
+ }
109
+ const connectors = config.connectors;
110
+ if (!connectors.telegramAccount || typeof connectors.telegramAccount !== "object" || Array.isArray(connectors.telegramAccount)) {
111
+ connectors.telegramAccount = {};
112
+ }
113
+ return connectors.telegramAccount;
114
+ }
115
+ function createSessionOptions(config) {
116
+ const connectorConfig = readConnectorConfig(config);
117
+ return {
118
+ deviceModel: typeof connectorConfig.deviceModel === "string" && connectorConfig.deviceModel.trim().length > 0 ? connectorConfig.deviceModel.trim() : defaultTelegramAccountDeviceModel(),
119
+ systemVersion: typeof connectorConfig.systemVersion === "string" && connectorConfig.systemVersion.trim().length > 0 ? connectorConfig.systemVersion.trim() : defaultTelegramAccountSystemVersion()
120
+ };
121
+ }
122
+ function ensureAuthSession(config) {
123
+ if (telegramAccountAuthSession) {
124
+ return telegramAccountAuthSession;
125
+ }
126
+ if (!telegramAccountAuthStateExists()) {
127
+ return null;
128
+ }
129
+ telegramAccountAuthSession = new TelegramAccountAuthSession(
130
+ createSessionOptions(config)
131
+ );
132
+ return telegramAccountAuthSession;
133
+ }
134
+ async function handleStatus(_req, res, runtime) {
135
+ const setupService = getSetupService(runtime);
136
+ const config = setupService?.getConfig() ?? {};
137
+ ensureAuthSession(config);
138
+ res.status(200).json(statusFromState(runtime, config));
139
+ }
140
+ async function handleAuthStart(req, res, runtime) {
141
+ const body = req.body ?? {};
142
+ const setupService = getSetupService(runtime);
143
+ const config = setupService?.getConfig() ?? {};
144
+ const connectorConfig = readConnectorConfig(config);
145
+ const phone = typeof body.phone === "string" && body.phone.trim() || resolveConfiguredPhone(runtime, connectorConfig);
146
+ if (!phone) {
147
+ res.status(400).json({ error: "telegram phone number is required" });
148
+ return;
149
+ }
150
+ await telegramAccountAuthSession?.stop();
151
+ telegramAccountAuthSession = new TelegramAccountAuthSession(
152
+ createSessionOptions(config)
153
+ );
154
+ const credentials = hasConfiguredTelegramAccount(connectorConfig) && (typeof connectorConfig.appId === "string" || typeof connectorConfig.appId === "number") && typeof connectorConfig.appHash === "string" ? {
155
+ apiId: Number(connectorConfig.appId),
156
+ apiHash: connectorConfig.appHash
157
+ } : null;
158
+ try {
159
+ await telegramAccountAuthSession.start({ phone, credentials });
160
+ const resolved = telegramAccountAuthSession.getResolvedConnectorConfig();
161
+ if (resolved && setupService) {
162
+ setupService.updateConfig((cfg) => {
163
+ Object.assign(ensureConnectorBlock(cfg), resolved);
164
+ });
165
+ }
166
+ const freshConfig = setupService?.getConfig() ?? config;
167
+ res.status(200).json(statusFromState(runtime, freshConfig));
168
+ } catch (error) {
169
+ res.status(500).json({
170
+ error: error instanceof Error ? error.message : String(error)
171
+ });
172
+ }
173
+ }
174
+ async function handleAuthSubmit(req, res, runtime) {
175
+ const body = req.body ?? {};
176
+ const setupService = getSetupService(runtime);
177
+ const config = setupService?.getConfig() ?? {};
178
+ if (!ensureAuthSession(config)) {
179
+ res.status(400).json({ error: "telegram login session has not been started" });
180
+ return;
181
+ }
182
+ if (!telegramAccountAuthSession) {
183
+ res.status(400).json({ error: "telegram login session has not been started" });
184
+ return;
185
+ }
186
+ try {
187
+ await telegramAccountAuthSession.submit(body);
188
+ const resolved = telegramAccountAuthSession.getResolvedConnectorConfig();
189
+ if (resolved && setupService) {
190
+ setupService.updateConfig((cfg) => {
191
+ Object.assign(ensureConnectorBlock(cfg), resolved);
192
+ });
193
+ }
194
+ const freshConfig = setupService?.getConfig() ?? config;
195
+ res.status(200).json(statusFromState(runtime, freshConfig));
196
+ } catch (error) {
197
+ res.status(500).json({
198
+ error: error instanceof Error ? error.message : String(error)
199
+ });
200
+ }
201
+ }
202
+ async function handleDisconnect(_req, res, runtime) {
203
+ await telegramAccountAuthSession?.stop();
204
+ telegramAccountAuthSession = null;
205
+ clearTelegramAccountAuthState();
206
+ clearTelegramAccountSession();
207
+ const service = resolveService(runtime);
208
+ if (typeof service?.stop === "function") {
209
+ await service.stop();
210
+ }
211
+ const setupService = getSetupService(runtime);
212
+ if (setupService) {
213
+ setupService.updateConfig((cfg) => {
214
+ const connectors = cfg.connectors;
215
+ if (connectors?.telegramAccount) {
216
+ delete connectors.telegramAccount;
217
+ }
218
+ });
219
+ }
220
+ const config = setupService?.getConfig() ?? {};
221
+ res.status(200).json({
222
+ ok: true,
223
+ ...statusFromState(runtime, config)
224
+ });
225
+ }
226
+ var telegramAccountRoutes = [
227
+ {
228
+ type: "GET",
229
+ path: "/api/telegram-account/status",
230
+ handler: handleStatus,
231
+ rawPath: true
232
+ },
233
+ {
234
+ type: "POST",
235
+ path: "/api/telegram-account/auth/start",
236
+ handler: handleAuthStart,
237
+ rawPath: true
238
+ },
239
+ {
240
+ type: "POST",
241
+ path: "/api/telegram-account/auth/submit",
242
+ handler: handleAuthSubmit,
243
+ rawPath: true
244
+ },
245
+ {
246
+ type: "POST",
247
+ path: "/api/telegram-account/disconnect",
248
+ handler: handleDisconnect,
249
+ rawPath: true
250
+ }
251
+ ];
252
+
253
+ // src/accounts.ts
254
+ var DEFAULT_ACCOUNT_ID = "default";
255
+ function readNonEmptyString(value) {
256
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
257
+ }
258
+ function normalizeTelegramAccountId(accountId) {
259
+ return readNonEmptyString(accountId) ?? DEFAULT_ACCOUNT_ID;
260
+ }
261
+ function getTelegramMultiAccountConfig(runtime) {
262
+ const characterTelegram = runtime.character?.settings?.telegram;
263
+ return {
264
+ enabled: characterTelegram?.enabled,
265
+ botToken: characterTelegram?.botToken,
266
+ apiRoot: characterTelegram?.apiRoot,
267
+ accounts: characterTelegram?.accounts
268
+ };
269
+ }
270
+ function listTelegramAccountIds(runtime) {
271
+ const accounts = getTelegramMultiAccountConfig(runtime).accounts;
272
+ if (!accounts || typeof accounts !== "object") {
273
+ return [DEFAULT_ACCOUNT_ID];
274
+ }
275
+ const ids = Object.keys(accounts).filter(Boolean);
276
+ return ids.length > 0 ? ids.slice().sort((a, b) => a.localeCompare(b)) : [DEFAULT_ACCOUNT_ID];
277
+ }
278
+ function resolveDefaultTelegramAccountId(runtime) {
279
+ const ids = listTelegramAccountIds(runtime);
280
+ return ids.includes(DEFAULT_ACCOUNT_ID) ? DEFAULT_ACCOUNT_ID : ids[0] ?? DEFAULT_ACCOUNT_ID;
281
+ }
282
+ function getAccountConfig(runtime, accountId) {
283
+ const accounts = getTelegramMultiAccountConfig(runtime).accounts;
284
+ return accounts && typeof accounts === "object" ? accounts[accountId] : void 0;
285
+ }
286
+ function resolveTelegramBotToken(runtime, accountId, merged) {
287
+ const configToken = readNonEmptyString(merged.botToken);
288
+ if (configToken) {
289
+ return configToken;
290
+ }
291
+ if (accountId !== DEFAULT_ACCOUNT_ID) {
292
+ return void 0;
293
+ }
294
+ return readNonEmptyString(runtime.getSetting("TELEGRAM_BOT_TOKEN")) ?? readNonEmptyString(process.env.TELEGRAM_BOT_TOKEN);
295
+ }
296
+ function resolveTelegramAccount(runtime, accountId) {
297
+ const normalizedAccountId = normalizeTelegramAccountId(accountId);
298
+ const multi = getTelegramMultiAccountConfig(runtime);
299
+ const accountConfig = getAccountConfig(runtime, normalizedAccountId) ?? {};
300
+ const merged = {
301
+ enabled: multi.enabled,
302
+ botToken: multi.botToken,
303
+ apiRoot: multi.apiRoot,
304
+ ...accountConfig
305
+ };
306
+ const apiRoot = readNonEmptyString(merged.apiRoot) ?? readNonEmptyString(runtime.getSetting("TELEGRAM_API_ROOT")) ?? readNonEmptyString(process.env.TELEGRAM_API_ROOT) ?? "https://api.telegram.org";
307
+ return {
308
+ accountId: normalizedAccountId,
309
+ enabled: multi.enabled !== false && merged.enabled !== false,
310
+ name: readNonEmptyString(merged.name),
311
+ botToken: resolveTelegramBotToken(runtime, normalizedAccountId, merged),
312
+ apiRoot,
313
+ config: merged
314
+ };
315
+ }
316
+ function listEnabledTelegramAccounts(runtime) {
317
+ return listTelegramAccountIds(runtime).map((accountId) => resolveTelegramAccount(runtime, accountId)).filter((account) => account.enabled && account.botToken);
318
+ }
319
+
1
320
  // src/constants.ts
2
321
  var MESSAGE_CONSTANTS = {
3
322
  MAX_MESSAGES: 50,
@@ -12,38 +331,97 @@ var MESSAGE_CONSTANTS = {
12
331
  };
13
332
  var TELEGRAM_SERVICE_NAME = "telegram";
14
333
 
15
- // src/service.ts
16
- import {
17
- ChannelType as ChannelType2,
18
- EventType as EventType2,
19
- Role,
20
- Service,
21
- createUniqueUuid as createUniqueUuid2,
22
- logger as logger3
23
- } from "@elizaos/core";
24
- import { Telegraf } from "telegraf";
334
+ // src/connector-account-provider.ts
335
+ function nowMs() {
336
+ return Date.now();
337
+ }
338
+ function synthesizeAccount(accountId, name, externalId) {
339
+ return {
340
+ id: accountId,
341
+ provider: TELEGRAM_SERVICE_NAME,
342
+ label: name ?? `Telegram (${accountId})`,
343
+ role: "AGENT",
344
+ purpose: ["messaging"],
345
+ accessGate: "open",
346
+ status: "connected",
347
+ externalId,
348
+ displayHandle: name,
349
+ createdAt: nowMs(),
350
+ updatedAt: nowMs(),
351
+ metadata: {
352
+ synthesized: true,
353
+ source: "env"
354
+ }
355
+ };
356
+ }
357
+ function createTelegramConnectorAccountProvider(runtime) {
358
+ return {
359
+ provider: TELEGRAM_SERVICE_NAME,
360
+ label: "Telegram",
361
+ listAccounts: async (manager) => {
362
+ const persisted = await manager.getStorage().listAccounts(TELEGRAM_SERVICE_NAME);
363
+ const persistedById = new Map(persisted.map((a) => [a.id, a]));
364
+ const enabled = listEnabledTelegramAccounts(runtime);
365
+ const synthesized = enabled.filter((account) => !persistedById.has(account.accountId)).map(
366
+ (account) => synthesizeAccount(account.accountId, account.name, void 0)
367
+ );
368
+ if (synthesized.length === 0 && persisted.length === 0) {
369
+ const fallback = resolveTelegramAccount(runtime, DEFAULT_ACCOUNT_ID);
370
+ if (fallback.botToken) {
371
+ synthesized.push(
372
+ synthesizeAccount(DEFAULT_ACCOUNT_ID, fallback.name, void 0)
373
+ );
374
+ }
375
+ }
376
+ return [...persisted, ...synthesized];
377
+ },
378
+ createAccount: async (input) => {
379
+ return {
380
+ ...input,
381
+ provider: TELEGRAM_SERVICE_NAME,
382
+ role: input.role ?? "AGENT",
383
+ purpose: input.purpose ?? ["messaging"],
384
+ accessGate: input.accessGate ?? "open",
385
+ status: input.status ?? "connected"
386
+ };
387
+ },
388
+ patchAccount: async (_accountId, patch) => {
389
+ return { ...patch, provider: TELEGRAM_SERVICE_NAME };
390
+ },
391
+ deleteAccount: async () => {
392
+ }
393
+ // Telegram bots use a long-lived bot token; no OAuth flow exists.
394
+ // startOAuth / completeOAuth are intentionally omitted.
395
+ };
396
+ }
25
397
 
26
398
  // src/messageManager.ts
399
+ import fs from "fs";
27
400
  import {
28
401
  ChannelType,
402
+ createUniqueUuid,
29
403
  EventType,
404
+ lifeOpsPassiveConnectorsEnabled,
405
+ logger as logger2,
30
406
  ModelType,
31
- ServiceType,
32
- createUniqueUuid,
33
- logger as logger2
407
+ ServiceType
34
408
  } from "@elizaos/core";
35
409
  import { Markup as Markup2 } from "telegraf";
36
410
 
37
411
  // src/utils.ts
38
- import { Markup } from "telegraf";
39
412
  import { logger } from "@elizaos/core";
413
+ import { Markup } from "telegraf";
40
414
  var TELEGRAM_RESERVED_REGEX = /([_*[\]()~`>#+\-=|{}.!\\])/g;
41
415
  function escapePlainText(text) {
42
- if (!text) return "";
416
+ if (!text) {
417
+ return "";
418
+ }
43
419
  return text.replace(TELEGRAM_RESERVED_REGEX, "\\$1");
44
420
  }
45
421
  function escapePlainTextPreservingBlockquote(text) {
46
- if (!text) return "";
422
+ if (!text) {
423
+ return "";
424
+ }
47
425
  return text.split("\n").map((line) => {
48
426
  const match = line.match(/^(>+\s?)(.*)$/);
49
427
  if (match) {
@@ -53,11 +431,15 @@ function escapePlainTextPreservingBlockquote(text) {
53
431
  }).join("\n");
54
432
  }
55
433
  function escapeCode(text) {
56
- if (!text) return "";
434
+ if (!text) {
435
+ return "";
436
+ }
57
437
  return text.replace(/([`\\])/g, "\\$1");
58
438
  }
59
439
  function escapeUrl(url) {
60
- if (!url) return "";
440
+ if (!url) {
441
+ return "";
442
+ }
61
443
  return url.replace(/([)\\])/g, "\\$1");
62
444
  }
63
445
  function convertMarkdownToTelegram(markdown) {
@@ -68,14 +450,18 @@ function convertMarkdownToTelegram(markdown) {
68
450
  return placeholder;
69
451
  }
70
452
  let converted = markdown;
71
- converted = converted.replace(/```(\w+)?\n([\s\S]*?)```/g, (_match, lang, code) => {
72
- const escapedCode = escapeCode(code);
73
- const formatted = "```" + (lang || "") + "\n" + escapedCode + "```";
74
- return storeReplacement(formatted);
75
- });
453
+ converted = converted.replace(
454
+ /```(\w+)?\n([\s\S]*?)```/g,
455
+ (_match, lang, code) => {
456
+ const escapedCode = escapeCode(code);
457
+ const formatted = `\`\`\`${lang || ""}
458
+ ${escapedCode}\`\`\``;
459
+ return storeReplacement(formatted);
460
+ }
461
+ );
76
462
  converted = converted.replace(/`([^`]+)`/g, (_match, code) => {
77
463
  const escapedCode = escapeCode(code);
78
- const formatted = "`" + escapedCode + "`";
464
+ const formatted = `\`${escapedCode}\``;
79
465
  return storeReplacement(formatted);
80
466
  });
81
467
  converted = converted.replace(
@@ -97,20 +483,26 @@ function convertMarkdownToTelegram(markdown) {
97
483
  const formatted = `~${formattedContent}~`;
98
484
  return storeReplacement(formatted);
99
485
  });
100
- converted = converted.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, (_match, content) => {
101
- const formattedContent = escapePlainText(content);
102
- const formatted = `_${formattedContent}_`;
103
- return storeReplacement(formatted);
104
- });
486
+ converted = converted.replace(
487
+ /(?<!\*)\*([^*\n]+)\*(?!\*)/g,
488
+ (_match, content) => {
489
+ const formattedContent = escapePlainText(content);
490
+ const formatted = `_${formattedContent}_`;
491
+ return storeReplacement(formatted);
492
+ }
493
+ );
105
494
  converted = converted.replace(/_([^_\n]+)_/g, (_match, content) => {
106
495
  const formattedContent = escapePlainText(content);
107
496
  const formatted = `_${formattedContent}_`;
108
497
  return storeReplacement(formatted);
109
498
  });
110
- converted = converted.replace(/^(#{1,6})\s*(.*)$/gm, (_match, _hashes, headerContent) => {
111
- const formatted = `*${escapePlainText(headerContent.trim())}*`;
112
- return storeReplacement(formatted);
113
- });
499
+ converted = converted.replace(
500
+ /^(#{1,6})\s*(.*)$/gm,
501
+ (_match, _hashes, headerContent) => {
502
+ const formatted = `*${escapePlainText(headerContent.trim())}*`;
503
+ return storeReplacement(formatted);
504
+ }
505
+ );
114
506
  const NULL_CHAR = String.fromCharCode(0);
115
507
  const PLACEHOLDER_PATTERN = new RegExp(`(${NULL_CHAR}\\d+${NULL_CHAR})`, "g");
116
508
  const PLACEHOLDER_TEST = new RegExp(`^${NULL_CHAR}\\d+${NULL_CHAR}$`);
@@ -123,16 +515,21 @@ function convertMarkdownToTelegram(markdown) {
123
515
  }
124
516
  }).join("");
125
517
  const finalResult = finalEscaped.replace(PLACEHOLDER_REPLACE, (_, index) => {
126
- return replacements[parseInt(index)];
518
+ return replacements[Number.parseInt(index, 10)];
127
519
  });
128
520
  return finalResult;
129
521
  }
130
522
  function convertToTelegramButtons(buttons) {
131
- if (!buttons) return [];
523
+ if (!buttons) {
524
+ return [];
525
+ }
132
526
  const telegramButtons = [];
133
527
  for (const button of buttons) {
134
- if (!button || !button.text || !button.url) {
135
- logger.warn({ button }, "Invalid button configuration, skipping");
528
+ if (!button?.text || !button.url) {
529
+ logger.warn(
530
+ { src: "plugin:telegram", button },
531
+ "Invalid button configuration, skipping"
532
+ );
136
533
  continue;
137
534
  }
138
535
  let telegramButton;
@@ -144,7 +541,10 @@ function convertToTelegramButtons(buttons) {
144
541
  telegramButton = Markup.button.url(button.text, button.url);
145
542
  break;
146
543
  default:
147
- logger.warn({ src: "plugin:telegram", buttonKind: button.kind }, "Unknown button kind, treating as URL button");
544
+ logger.warn(
545
+ { src: "plugin:telegram", buttonKind: button.kind },
546
+ "Unknown button kind, treating as URL button"
547
+ );
148
548
  telegramButton = Markup.button.url(button.text, button.url);
149
549
  break;
150
550
  }
@@ -153,15 +553,20 @@ function convertToTelegramButtons(buttons) {
153
553
  return telegramButtons;
154
554
  }
155
555
  function cleanText(text) {
156
- if (!text) return "";
556
+ if (!text) {
557
+ return "";
558
+ }
157
559
  return text.split("\0").join("");
158
560
  }
159
561
 
160
562
  // src/messageManager.ts
161
- import fs from "fs";
162
563
  var MAX_MESSAGE_LENGTH = 4096;
564
+ function isPdfTextService(service) {
565
+ return typeof service === "object" && service !== null && typeof service.convertPdfToText === "function";
566
+ }
163
567
  var getChannelType = (chat) => {
164
- switch (chat.type) {
568
+ const chatType = chat.type;
569
+ switch (chatType) {
165
570
  case "private":
166
571
  return ChannelType.DM;
167
572
  case "group":
@@ -169,21 +574,26 @@ var getChannelType = (chat) => {
169
574
  case "channel":
170
575
  return ChannelType.GROUP;
171
576
  default:
172
- throw new Error(`Unrecognized Telegram chat type: ${chat.type}`);
577
+ throw new Error(`Unrecognized Telegram chat type: ${String(chatType)}`);
173
578
  }
174
579
  };
175
580
  var MessageManager = class {
176
581
  bot;
177
582
  runtime;
583
+ accountId;
178
584
  /**
179
585
  * Constructor for creating a new instance of a BotAgent.
180
586
  *
181
587
  * @param {Telegraf<Context>} bot - The Telegraf instance used for interacting with the bot platform.
182
588
  * @param {IAgentRuntime} runtime - The runtime environment for the agent.
183
589
  */
184
- constructor(bot, runtime) {
590
+ constructor(bot, runtime, accountId = "default") {
185
591
  this.bot = bot;
186
592
  this.runtime = runtime;
593
+ this.accountId = accountId;
594
+ }
595
+ scopedTelegramKey(key) {
596
+ return this.accountId === "default" ? key : `${this.accountId}:${key}`;
187
597
  }
188
598
  /**
189
599
  * Process an image from a Telegram message to extract the image URL and description.
@@ -194,13 +604,22 @@ var MessageManager = class {
194
604
  async processImage(message) {
195
605
  try {
196
606
  let imageUrl = null;
197
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, messageId: message.message_id }, "Processing image from message");
607
+ logger2.debug(
608
+ {
609
+ src: "plugin:telegram",
610
+ agentId: this.runtime.agentId,
611
+ messageId: message.message_id
612
+ },
613
+ "Processing image from message"
614
+ );
198
615
  if ("photo" in message && message.photo?.length > 0) {
199
616
  const photo = message.photo[message.photo.length - 1];
200
617
  const fileLink = await this.bot.telegram.getFileLink(photo.file_id);
201
618
  imageUrl = fileLink.toString();
202
619
  } else if ("document" in message && message.document?.mime_type?.startsWith("image/") && !message.document?.mime_type?.startsWith("application/pdf")) {
203
- const fileLink = await this.bot.telegram.getFileLink(message.document.file_id);
620
+ const fileLink = await this.bot.telegram.getFileLink(
621
+ message.document.file_id
622
+ );
204
623
  imageUrl = fileLink.toString();
205
624
  }
206
625
  if (imageUrl) {
@@ -212,7 +631,14 @@ var MessageManager = class {
212
631
  ${description}]` };
213
632
  }
214
633
  } catch (error) {
215
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error processing image");
634
+ logger2.error(
635
+ {
636
+ src: "plugin:telegram",
637
+ agentId: this.runtime.agentId,
638
+ error: error instanceof Error ? error.message : String(error)
639
+ },
640
+ "Error processing image"
641
+ );
216
642
  }
217
643
  return null;
218
644
  }
@@ -231,7 +657,16 @@ ${description}]` };
231
657
  const document = message.document;
232
658
  const fileLink = await this.bot.telegram.getFileLink(document.file_id);
233
659
  const documentUrl = fileLink.toString();
234
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: document.file_name, mimeType: document.mime_type, fileSize: document.file_size }, "Processing document");
660
+ logger2.debug(
661
+ {
662
+ src: "plugin:telegram",
663
+ agentId: this.runtime.agentId,
664
+ fileName: document.file_name,
665
+ mimeType: document.mime_type,
666
+ fileSize: document.file_size
667
+ },
668
+ "Processing document"
669
+ );
235
670
  const documentProcessor = this.getDocumentProcessor(document.mime_type);
236
671
  if (documentProcessor) {
237
672
  return await documentProcessor(document, documentUrl);
@@ -247,7 +682,14 @@ Size: ${document.file_size || 0} bytes]`,
247
682
  fileSize: document.file_size
248
683
  };
249
684
  } catch (error) {
250
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error processing document");
685
+ logger2.error(
686
+ {
687
+ src: "plugin:telegram",
688
+ agentId: this.runtime.agentId,
689
+ error: error instanceof Error ? error.message : String(error)
690
+ },
691
+ "Error processing document"
692
+ );
251
693
  return null;
252
694
  }
253
695
  }
@@ -255,7 +697,9 @@ Size: ${document.file_size || 0} bytes]`,
255
697
  * Get the appropriate document processor based on MIME type.
256
698
  */
257
699
  getDocumentProcessor(mimeType) {
258
- if (!mimeType) return null;
700
+ if (!mimeType) {
701
+ return null;
702
+ }
259
703
  const processors = {
260
704
  "application/pdf": this.processPdfDocument.bind(this),
261
705
  "text/": this.processTextDocument.bind(this),
@@ -274,9 +718,13 @@ Size: ${document.file_size || 0} bytes]`,
274
718
  */
275
719
  async processPdfDocument(document, documentUrl) {
276
720
  try {
277
- const pdfService = this.runtime.getService(ServiceType.PDF);
721
+ const pdfServiceCandidate = this.runtime.getService(ServiceType.PDF);
722
+ const pdfService = isPdfTextService(pdfServiceCandidate) ? pdfServiceCandidate : null;
278
723
  if (!pdfService) {
279
- logger2.warn({ src: "plugin:telegram", agentId: this.runtime.agentId }, "PDF service not available, using fallback");
724
+ logger2.warn(
725
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
726
+ "PDF service not available, using fallback"
727
+ );
280
728
  return {
281
729
  title: `PDF Document: ${document.file_name || "Unknown Document"}`,
282
730
  fullText: "",
@@ -294,7 +742,15 @@ Unable to extract text content]`,
294
742
  }
295
743
  const pdfBuffer = await response.arrayBuffer();
296
744
  const text = await pdfService.convertPdfToText(Buffer.from(pdfBuffer));
297
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: document.file_name, charactersExtracted: text.length }, "PDF processed successfully");
745
+ logger2.debug(
746
+ {
747
+ src: "plugin:telegram",
748
+ agentId: this.runtime.agentId,
749
+ fileName: document.file_name,
750
+ charactersExtracted: text.length
751
+ },
752
+ "PDF processed successfully"
753
+ );
298
754
  return {
299
755
  title: document.file_name || "Unknown Document",
300
756
  fullText: text,
@@ -306,7 +762,15 @@ Text extracted successfully: ${text.length} characters]`,
306
762
  fileSize: document.file_size
307
763
  };
308
764
  } catch (error) {
309
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: document.file_name, error: error instanceof Error ? error.message : String(error) }, "Error processing PDF document");
765
+ logger2.error(
766
+ {
767
+ src: "plugin:telegram",
768
+ agentId: this.runtime.agentId,
769
+ fileName: document.file_name,
770
+ error: error instanceof Error ? error.message : String(error)
771
+ },
772
+ "Error processing PDF document"
773
+ );
310
774
  return {
311
775
  title: `PDF Document: ${document.file_name || "Unknown Document"}`,
312
776
  fullText: "",
@@ -329,7 +793,15 @@ Error: Unable to extract text content]`,
329
793
  throw new Error(`Failed to fetch text document: ${response.status}`);
330
794
  }
331
795
  const text = await response.text();
332
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: document.file_name, charactersExtracted: text.length }, "Text document processed successfully");
796
+ logger2.debug(
797
+ {
798
+ src: "plugin:telegram",
799
+ agentId: this.runtime.agentId,
800
+ fileName: document.file_name,
801
+ charactersExtracted: text.length
802
+ },
803
+ "Text document processed successfully"
804
+ );
333
805
  return {
334
806
  title: document.file_name || "Unknown Document",
335
807
  fullText: text,
@@ -341,7 +813,15 @@ Text extracted successfully: ${text.length} characters]`,
341
813
  fileSize: document.file_size
342
814
  };
343
815
  } catch (error) {
344
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: document.file_name, error: error instanceof Error ? error.message : String(error) }, "Error processing text document");
816
+ logger2.error(
817
+ {
818
+ src: "plugin:telegram",
819
+ agentId: this.runtime.agentId,
820
+ fileName: document.file_name,
821
+ error: error instanceof Error ? error.message : String(error)
822
+ },
823
+ "Error processing text document"
824
+ );
345
825
  return {
346
826
  title: `Text Document: ${document.file_name || "Unknown Document"}`,
347
827
  fullText: "",
@@ -363,7 +843,7 @@ Error: Unable to read content]`,
363
843
  */
364
844
  async processMessage(message) {
365
845
  let processedContent = "";
366
- let attachments = [];
846
+ const attachments = [];
367
847
  if ("text" in message && message.text) {
368
848
  processedContent = message.text;
369
849
  } else if ("caption" in message && message.caption) {
@@ -374,7 +854,9 @@ Error: Unable to read content]`,
374
854
  const documentInfo = await this.processDocument(message);
375
855
  if (documentInfo) {
376
856
  try {
377
- const fileLink = await this.bot.telegram.getFileLink(document.file_id);
857
+ const fileLink = await this.bot.telegram.getFileLink(
858
+ document.file_id
859
+ );
378
860
  const title = documentInfo.title;
379
861
  const fullText = documentInfo.fullText;
380
862
  if (fullText) {
@@ -398,9 +880,24 @@ ${fullText}
398
880
  description: documentInfo.formattedDescription,
399
881
  text: fullText
400
882
  });
401
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: documentInfo.fileName }, "Document processed successfully");
883
+ logger2.debug(
884
+ {
885
+ src: "plugin:telegram",
886
+ agentId: this.runtime.agentId,
887
+ fileName: documentInfo.fileName
888
+ },
889
+ "Document processed successfully"
890
+ );
402
891
  } catch (error) {
403
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, fileName: documentInfo.fileName, error: error instanceof Error ? error.message : String(error) }, "Error processing document");
892
+ logger2.error(
893
+ {
894
+ src: "plugin:telegram",
895
+ agentId: this.runtime.agentId,
896
+ fileName: documentInfo.fileName,
897
+ error: error instanceof Error ? error.message : String(error)
898
+ },
899
+ "Error processing document"
900
+ );
404
901
  attachments.push({
405
902
  id: document.file_id,
406
903
  url: "",
@@ -440,7 +937,15 @@ Type: ${document.mime_type || "unknown"}`
440
937
  });
441
938
  }
442
939
  }
443
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, hasContent: !!processedContent, attachmentsCount: attachments.length }, "Message processed");
940
+ logger2.debug(
941
+ {
942
+ src: "plugin:telegram",
943
+ agentId: this.runtime.agentId,
944
+ hasContent: !!processedContent,
945
+ attachmentsCount: attachments.length
946
+ },
947
+ "Message processed"
948
+ );
444
949
  return { processedContent, attachments };
445
950
  }
446
951
  /**
@@ -451,7 +956,7 @@ Type: ${document.mime_type || "unknown"}`
451
956
  * @param {number} [replyToMessageId] - The ID of the message to reply to, if any
452
957
  * @returns {Promise<Message.TextMessage[]>} - An array of TextMessage objects representing the messages sent
453
958
  */
454
- async sendMessageInChunks(ctx, content, replyToMessageId) {
959
+ async sendMessageInChunks(ctx, content, replyToMessageId, messageThreadId) {
455
960
  if (content.attachments && content.attachments.length > 0) {
456
961
  content.attachments.map(async (attachment) => {
457
962
  const typeMap = {
@@ -461,7 +966,7 @@ Type: ${document.mime_type || "unknown"}`
461
966
  video: "video" /* VIDEO */,
462
967
  audio: "audio" /* AUDIO */
463
968
  };
464
- let mediaType = void 0;
969
+ let mediaType;
465
970
  for (const prefix in typeMap) {
466
971
  if (attachment.contentType?.startsWith(prefix)) {
467
972
  mediaType = typeMap[prefix];
@@ -473,7 +978,12 @@ Type: ${document.mime_type || "unknown"}`
473
978
  `Unsupported Telegram attachment content type: ${attachment.contentType}`
474
979
  );
475
980
  }
476
- await this.sendMedia(ctx, attachment.url, mediaType, attachment.description);
981
+ await this.sendMedia(
982
+ ctx,
983
+ attachment.url,
984
+ mediaType,
985
+ attachment.description
986
+ );
477
987
  });
478
988
  return [];
479
989
  } else {
@@ -481,21 +991,32 @@ Type: ${document.mime_type || "unknown"}`
481
991
  const sentMessages = [];
482
992
  const telegramButtons = convertToTelegramButtons(content.buttons ?? []);
483
993
  if (!ctx.chat) {
484
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId }, "sendMessageInChunks: ctx.chat is undefined");
994
+ logger2.error(
995
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
996
+ "sendMessageInChunks: ctx.chat is undefined"
997
+ );
485
998
  return [];
486
999
  }
487
1000
  await ctx.telegram.sendChatAction(ctx.chat.id, "typing");
488
1001
  for (let i = 0; i < chunks.length; i++) {
489
1002
  const chunk = convertMarkdownToTelegram(chunks[i]);
490
1003
  if (!ctx.chat) {
491
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId }, "sendMessageInChunks loop: ctx.chat is undefined");
1004
+ logger2.error(
1005
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
1006
+ "sendMessageInChunks loop: ctx.chat is undefined"
1007
+ );
492
1008
  continue;
493
1009
  }
494
- const sentMessage = await ctx.telegram.sendMessage(ctx.chat.id, chunk, {
495
- reply_parameters: i === 0 && replyToMessageId ? { message_id: replyToMessageId } : void 0,
496
- parse_mode: "MarkdownV2",
497
- ...Markup2.inlineKeyboard(telegramButtons)
498
- });
1010
+ const sentMessage = await ctx.telegram.sendMessage(
1011
+ ctx.chat.id,
1012
+ chunk,
1013
+ {
1014
+ reply_parameters: i === 0 && replyToMessageId ? { message_id: replyToMessageId } : void 0,
1015
+ message_thread_id: messageThreadId,
1016
+ parse_mode: "MarkdownV2",
1017
+ ...Markup2.inlineKeyboard(telegramButtons)
1018
+ }
1019
+ );
499
1020
  sentMessages.push(sentMessage);
500
1021
  }
501
1022
  return sentMessages;
@@ -544,9 +1065,26 @@ Type: ${document.mime_type || "unknown"}`
544
1065
  fileStream.destroy();
545
1066
  }
546
1067
  }
547
- logger2.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, mediaType: type, mediaPath }, "Media sent successfully");
1068
+ logger2.debug(
1069
+ {
1070
+ src: "plugin:telegram",
1071
+ agentId: this.runtime.agentId,
1072
+ mediaType: type,
1073
+ mediaPath
1074
+ },
1075
+ "Media sent successfully"
1076
+ );
548
1077
  } catch (error) {
549
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, mediaType: type, mediaPath, error: error instanceof Error ? error.message : String(error) }, "Failed to send media");
1078
+ logger2.error(
1079
+ {
1080
+ src: "plugin:telegram",
1081
+ agentId: this.runtime.agentId,
1082
+ mediaType: type,
1083
+ mediaPath,
1084
+ error: error instanceof Error ? error.message : String(error)
1085
+ },
1086
+ "Failed to send media"
1087
+ );
550
1088
  throw error;
551
1089
  }
552
1090
  }
@@ -558,18 +1096,24 @@ Type: ${document.mime_type || "unknown"}`
558
1096
  */
559
1097
  splitMessage(text) {
560
1098
  const chunks = [];
561
- if (!text) return chunks;
1099
+ if (!text) {
1100
+ return chunks;
1101
+ }
562
1102
  let currentChunk = "";
563
1103
  const lines = text.split("\n");
564
1104
  for (const line of lines) {
565
1105
  if (currentChunk.length + line.length + 1 <= MAX_MESSAGE_LENGTH) {
566
1106
  currentChunk += (currentChunk ? "\n" : "") + line;
567
1107
  } else {
568
- if (currentChunk) chunks.push(currentChunk);
1108
+ if (currentChunk) {
1109
+ chunks.push(currentChunk);
1110
+ }
569
1111
  currentChunk = line;
570
1112
  }
571
1113
  }
572
- if (currentChunk) chunks.push(currentChunk);
1114
+ if (currentChunk) {
1115
+ chunks.push(currentChunk);
1116
+ }
573
1117
  return chunks;
574
1118
  }
575
1119
  /**
@@ -578,18 +1122,35 @@ Type: ${document.mime_type || "unknown"}`
578
1122
  * @returns {Promise<void>}
579
1123
  */
580
1124
  async handleMessage(ctx) {
581
- if (!ctx.message || !ctx.from) return;
1125
+ if (!ctx.message || !ctx.from) {
1126
+ return;
1127
+ }
582
1128
  const message = ctx.message;
583
1129
  try {
584
- const entityId = createUniqueUuid(this.runtime, ctx.from.id.toString());
1130
+ const telegramUserId = ctx.from.id.toString();
1131
+ const entityId = createUniqueUuid(
1132
+ this.runtime,
1133
+ this.scopedTelegramKey(telegramUserId)
1134
+ );
585
1135
  const threadId = "is_topic_message" in message && message.is_topic_message ? message.message_thread_id?.toString() : void 0;
586
1136
  if (!ctx.chat) {
587
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId }, "handleMessage: ctx.chat is undefined");
1137
+ logger2.error(
1138
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
1139
+ "handleMessage: ctx.chat is undefined"
1140
+ );
588
1141
  return;
589
1142
  }
590
1143
  const telegramRoomid = threadId ? `${ctx.chat.id}-${threadId}` : ctx.chat.id.toString();
591
- const roomId = createUniqueUuid(this.runtime, telegramRoomid);
592
- const messageId = createUniqueUuid(this.runtime, message?.message_id?.toString());
1144
+ const telegramChatId = ctx.chat.id.toString();
1145
+ const scopedRoomKey = this.scopedTelegramKey(telegramRoomid);
1146
+ const scopedChatKey = this.scopedTelegramKey(telegramChatId);
1147
+ const roomId = createUniqueUuid(this.runtime, scopedRoomKey);
1148
+ const worldId = createUniqueUuid(this.runtime, scopedChatKey);
1149
+ const telegramMessageId = message.message_id.toString();
1150
+ const messageId = createUniqueUuid(
1151
+ this.runtime,
1152
+ this.scopedTelegramKey(telegramMessageId)
1153
+ );
593
1154
  const { processedContent, attachments } = await this.processMessage(message);
594
1155
  const cleanedContent = cleanText(processedContent);
595
1156
  const cleanedAttachments = attachments.map((att) => ({
@@ -603,16 +1164,17 @@ Type: ${document.mime_type || "unknown"}`
603
1164
  }
604
1165
  const chat = message.chat;
605
1166
  const channelType = getChannelType(chat);
606
- const sourceId = createUniqueUuid(this.runtime, "" + chat.id);
607
1167
  await this.runtime.ensureConnection({
608
1168
  entityId,
609
1169
  roomId,
1170
+ roomName: "title" in chat && typeof chat.title === "string" && chat.title || "first_name" in chat && typeof chat.first_name === "string" && chat.first_name || "username" in chat && typeof chat.username === "string" && chat.username || telegramRoomid,
610
1171
  userName: ctx.from.username,
611
1172
  name: ctx.from.first_name,
1173
+ userId: telegramUserId,
612
1174
  source: "telegram",
613
1175
  channelId: telegramRoomid,
614
1176
  type: channelType,
615
- worldId: createUniqueUuid(this.runtime, roomId),
1177
+ worldId,
616
1178
  worldName: telegramRoomid
617
1179
  });
618
1180
  const memory = {
@@ -624,44 +1186,76 @@ Type: ${document.mime_type || "unknown"}`
624
1186
  text: cleanedContent || " ",
625
1187
  attachments: cleanedAttachments,
626
1188
  source: "telegram",
1189
+ metadata: { accountId: this.accountId },
627
1190
  channelType,
628
- inReplyTo: "reply_to_message" in message && message.reply_to_message ? createUniqueUuid(this.runtime, message.reply_to_message.message_id.toString()) : void 0
1191
+ inReplyTo: "reply_to_message" in message && message.reply_to_message ? createUniqueUuid(
1192
+ this.runtime,
1193
+ this.scopedTelegramKey(
1194
+ message.reply_to_message.message_id.toString()
1195
+ )
1196
+ ) : void 0
629
1197
  },
630
1198
  metadata: {
1199
+ type: "message",
1200
+ source: "telegram",
1201
+ accountId: this.accountId,
1202
+ provider: "telegram",
1203
+ timestamp: message.date * 1e3,
631
1204
  entityName: ctx.from.first_name,
632
1205
  entityUserName: ctx.from.username,
633
1206
  fromBot: ctx.from.is_bot,
634
- // include very technical/exact reference to this user for security reasons
635
- // don't remove or change this, spartan needs this
636
- fromId: chat.id,
637
- sourceId,
638
- // why message? all Memories contain content (which is basically a message)
639
- // what are the other types? see MemoryType
640
- type: "message"
641
- // MemoryType.MESSAGE
642
- // scope: `shared`, `private`, or `room`
1207
+ fromId: telegramUserId,
1208
+ sourceId: entityId,
1209
+ chatType: chat.type,
1210
+ messageIdFull: telegramMessageId,
1211
+ sender: {
1212
+ id: telegramUserId,
1213
+ name: ctx.from.first_name,
1214
+ username: ctx.from.username
1215
+ },
1216
+ telegram: {
1217
+ chatId: telegramChatId,
1218
+ messageId: telegramMessageId,
1219
+ threadId
1220
+ },
1221
+ telegramUserId,
1222
+ telegramChatId
643
1223
  },
644
1224
  createdAt: message.date * 1e3
645
1225
  };
646
- const callback = async (content, _files) => {
1226
+ const callback = async (content, _actionName) => {
647
1227
  try {
648
- if (!content.text) return [];
1228
+ if (!content.text) {
1229
+ return [];
1230
+ }
649
1231
  let sentMessages = false;
650
1232
  if (content?.channelType === "DM") {
651
1233
  sentMessages = [];
652
1234
  if (ctx.from) {
653
- const res = await this.bot.telegram.sendMessage(ctx.from.id, content.text);
1235
+ const res = await this.bot.telegram.sendMessage(
1236
+ ctx.from.id,
1237
+ content.text
1238
+ );
654
1239
  sentMessages.push(res);
655
1240
  }
656
1241
  } else {
657
- sentMessages = await this.sendMessageInChunks(ctx, content, message.message_id);
1242
+ sentMessages = await this.sendMessageInChunks(
1243
+ ctx,
1244
+ content,
1245
+ message.message_id
1246
+ );
1247
+ }
1248
+ if (!Array.isArray(sentMessages)) {
1249
+ return [];
658
1250
  }
659
- if (!Array.isArray(sentMessages)) return [];
660
1251
  const memories = [];
661
1252
  for (let i = 0; i < sentMessages.length; i++) {
662
1253
  const sentMessage = sentMessages[i];
663
1254
  const responseMemory = {
664
- id: createUniqueUuid(this.runtime, sentMessage.message_id.toString()),
1255
+ id: createUniqueUuid(
1256
+ this.runtime,
1257
+ this.scopedTelegramKey(sentMessage.message_id.toString())
1258
+ ),
665
1259
  entityId: this.runtime.agentId,
666
1260
  agentId: this.runtime.agentId,
667
1261
  roomId,
@@ -670,7 +1264,25 @@ Type: ${document.mime_type || "unknown"}`
670
1264
  source: "telegram",
671
1265
  text: sentMessage.text,
672
1266
  inReplyTo: messageId,
673
- channelType
1267
+ channelType,
1268
+ metadata: { accountId: this.accountId }
1269
+ },
1270
+ metadata: {
1271
+ type: "message",
1272
+ source: "telegram",
1273
+ accountId: this.accountId,
1274
+ provider: "telegram",
1275
+ timestamp: sentMessage.date * 1e3,
1276
+ fromBot: true,
1277
+ fromId: this.runtime.agentId,
1278
+ sourceId: this.runtime.agentId,
1279
+ chatType: chat.type,
1280
+ messageIdFull: sentMessage.message_id.toString(),
1281
+ telegram: {
1282
+ chatId: sentMessage.chat.id,
1283
+ messageId: sentMessage.message_id.toString(),
1284
+ threadId
1285
+ }
674
1286
  },
675
1287
  createdAt: sentMessage.date * 1e3
676
1288
  };
@@ -679,26 +1291,65 @@ Type: ${document.mime_type || "unknown"}`
679
1291
  }
680
1292
  return memories;
681
1293
  } catch (error) {
682
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error in message callback");
1294
+ logger2.error(
1295
+ {
1296
+ src: "plugin:telegram",
1297
+ agentId: this.runtime.agentId,
1298
+ error: error instanceof Error ? error.message : String(error)
1299
+ },
1300
+ "Error in message callback"
1301
+ );
683
1302
  return [];
684
1303
  }
685
1304
  };
686
- if (this.runtime.hasElizaOS()) {
687
- await this.runtime.elizaOS.handleMessage(this.runtime.agentId, memory, {
688
- onResponse: async (content) => {
689
- await callback(content);
690
- }
691
- });
1305
+ const telegramAutoReplyRaw = this.runtime.getSetting(
1306
+ "TELEGRAM_AUTO_REPLY"
1307
+ );
1308
+ const telegramAutoReply = !lifeOpsPassiveConnectorsEnabled(this.runtime) && (telegramAutoReplyRaw === true || telegramAutoReplyRaw === "true");
1309
+ if (!telegramAutoReply) {
1310
+ try {
1311
+ await this.runtime.createMemory(memory, "messages");
1312
+ } catch (persistError) {
1313
+ logger2.warn(
1314
+ {
1315
+ src: "plugin:telegram",
1316
+ agentId: this.runtime.agentId,
1317
+ error: persistError instanceof Error ? persistError.message : String(persistError)
1318
+ },
1319
+ "Failed to persist inbound memory while auto-reply is disabled"
1320
+ );
1321
+ }
1322
+ logger2.debug(
1323
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
1324
+ "Auto-reply disabled (TELEGRAM_AUTO_REPLY=false); message ingested without response"
1325
+ );
692
1326
  } else if (this.runtime.messageService) {
693
- await this.runtime.messageService.handleMessage(this.runtime, memory, callback);
1327
+ await this.runtime.messageService.handleMessage(
1328
+ this.runtime,
1329
+ memory,
1330
+ callback
1331
+ );
694
1332
  } else {
695
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId }, "Message service is not available");
1333
+ logger2.error(
1334
+ { src: "plugin:telegram", agentId: this.runtime.agentId },
1335
+ "Message service is not available"
1336
+ );
696
1337
  throw new Error(
697
1338
  "Message service is not initialized. Ensure the message service is properly configured."
698
1339
  );
699
1340
  }
700
1341
  } catch (error) {
701
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId: ctx.chat?.id, messageId: ctx.message?.message_id, from: ctx.from?.username || ctx.from?.id, error: error instanceof Error ? error.message : String(error) }, "Error handling Telegram message");
1342
+ logger2.error(
1343
+ {
1344
+ src: "plugin:telegram",
1345
+ agentId: this.runtime.agentId,
1346
+ chatId: ctx.chat?.id,
1347
+ messageId: ctx.message?.message_id,
1348
+ from: ctx.from?.username || ctx.from?.id,
1349
+ error: error instanceof Error ? error.message : String(error)
1350
+ },
1351
+ "Error handling Telegram message"
1352
+ );
702
1353
  throw error;
703
1354
  }
704
1355
  }
@@ -708,7 +1359,9 @@ Type: ${document.mime_type || "unknown"}`
708
1359
  * @returns {Promise<void>} A Promise that resolves when the reaction handling is complete
709
1360
  */
710
1361
  async handleReaction(ctx) {
711
- if (!ctx.update.message_reaction || !ctx.from) return;
1362
+ if (!ctx.update.message_reaction || !ctx.from) {
1363
+ return;
1364
+ }
712
1365
  const reaction = ctx.update.message_reaction;
713
1366
  const reactedToMessageId = reaction.message_id;
714
1367
  const originalMessagePlaceholder = {
@@ -720,11 +1373,19 @@ Type: ${document.mime_type || "unknown"}`
720
1373
  const reactionType = reaction.new_reaction[0].type;
721
1374
  const reactionEmoji = reaction.new_reaction[0].type;
722
1375
  try {
723
- const entityId = createUniqueUuid(this.runtime, ctx.from.id.toString());
724
- const roomId = createUniqueUuid(this.runtime, ctx.chat.id.toString());
1376
+ const entityId = createUniqueUuid(
1377
+ this.runtime,
1378
+ this.scopedTelegramKey(ctx.from.id.toString())
1379
+ );
1380
+ const roomId = createUniqueUuid(
1381
+ this.runtime,
1382
+ this.scopedTelegramKey(ctx.chat.id.toString())
1383
+ );
725
1384
  const reactionId = createUniqueUuid(
726
1385
  this.runtime,
727
- `${reaction.message_id}-${ctx.from.id}-${Date.now()}`
1386
+ this.scopedTelegramKey(
1387
+ `${reaction.message_id}-${ctx.from.id}-${Date.now()}`
1388
+ )
728
1389
  );
729
1390
  const memory = {
730
1391
  id: reactionId,
@@ -735,7 +1396,22 @@ Type: ${document.mime_type || "unknown"}`
735
1396
  channelType: getChannelType(reaction.chat),
736
1397
  text: `Reacted with: ${reactionType === "emoji" ? reactionEmoji : reactionType}`,
737
1398
  source: "telegram",
738
- inReplyTo: createUniqueUuid(this.runtime, reaction.message_id.toString())
1399
+ inReplyTo: createUniqueUuid(
1400
+ this.runtime,
1401
+ this.scopedTelegramKey(reaction.message_id.toString())
1402
+ ),
1403
+ metadata: { accountId: this.accountId }
1404
+ },
1405
+ metadata: {
1406
+ type: "custom",
1407
+ eventType: "reaction",
1408
+ source: "telegram",
1409
+ accountId: this.accountId,
1410
+ provider: "telegram",
1411
+ telegram: {
1412
+ chatId: reaction.chat.id.toString(),
1413
+ messageId: reaction.message_id.toString()
1414
+ }
739
1415
  },
740
1416
  createdAt: Date.now()
741
1417
  };
@@ -744,19 +1420,36 @@ Type: ${document.mime_type || "unknown"}`
744
1420
  const replyText = content.text ?? "";
745
1421
  const sentMessage = await ctx.reply(replyText);
746
1422
  const responseMemory = {
747
- id: createUniqueUuid(this.runtime, sentMessage.message_id.toString()),
1423
+ id: createUniqueUuid(
1424
+ this.runtime,
1425
+ this.scopedTelegramKey(sentMessage.message_id.toString())
1426
+ ),
748
1427
  entityId: this.runtime.agentId,
749
1428
  agentId: this.runtime.agentId,
750
1429
  roomId,
751
1430
  content: {
752
1431
  ...content,
753
- inReplyTo: reactionId
1432
+ inReplyTo: reactionId,
1433
+ metadata: { accountId: this.accountId }
1434
+ },
1435
+ metadata: {
1436
+ type: "message",
1437
+ source: "telegram",
1438
+ accountId: this.accountId,
1439
+ provider: "telegram"
754
1440
  },
755
1441
  createdAt: sentMessage.date * 1e3
756
1442
  };
757
1443
  return [responseMemory];
758
1444
  } catch (error) {
759
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error in reaction callback");
1445
+ logger2.error(
1446
+ {
1447
+ src: "plugin:telegram",
1448
+ agentId: this.runtime.agentId,
1449
+ error: error instanceof Error ? error.message : String(error)
1450
+ },
1451
+ "Error in reaction callback"
1452
+ );
760
1453
  return [];
761
1454
  }
762
1455
  };
@@ -765,6 +1458,8 @@ Type: ${document.mime_type || "unknown"}`
765
1458
  message: memory,
766
1459
  callback,
767
1460
  source: "telegram",
1461
+ accountId: this.accountId,
1462
+ metadata: { accountId: this.accountId },
768
1463
  ctx,
769
1464
  originalMessage: originalMessagePlaceholder,
770
1465
  // Cast needed due to placeholder
@@ -776,6 +1471,8 @@ Type: ${document.mime_type || "unknown"}`
776
1471
  message: memory,
777
1472
  callback,
778
1473
  source: "telegram",
1474
+ accountId: this.accountId,
1475
+ metadata: { accountId: this.accountId },
779
1476
  ctx,
780
1477
  originalMessage: originalMessagePlaceholder,
781
1478
  // Cast needed due to placeholder
@@ -783,7 +1480,14 @@ Type: ${document.mime_type || "unknown"}`
783
1480
  originalReaction: reaction.new_reaction[0]
784
1481
  });
785
1482
  } catch (error) {
786
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error handling reaction");
1483
+ logger2.error(
1484
+ {
1485
+ src: "plugin:telegram",
1486
+ agentId: this.runtime.agentId,
1487
+ error: error instanceof Error ? error.message : String(error)
1488
+ },
1489
+ "Error handling reaction"
1490
+ );
787
1491
  }
788
1492
  }
789
1493
  /**
@@ -793,7 +1497,7 @@ Type: ${document.mime_type || "unknown"}`
793
1497
  * @param {number} [replyToMessageId] - Optional message ID to reply to
794
1498
  * @returns {Promise<Message.TextMessage[]>} The sent messages
795
1499
  */
796
- async sendMessage(chatId, content, replyToMessageId) {
1500
+ async sendMessage(chatId, content, replyToMessageId, messageThreadId) {
797
1501
  try {
798
1502
  const ctx = {
799
1503
  chat: { id: chatId },
@@ -802,14 +1506,25 @@ Type: ${document.mime_type || "unknown"}`
802
1506
  const sentMessages = await this.sendMessageInChunks(
803
1507
  ctx,
804
1508
  content,
805
- replyToMessageId
1509
+ replyToMessageId,
1510
+ messageThreadId
1511
+ );
1512
+ if (!sentMessages?.length) {
1513
+ return [];
1514
+ }
1515
+ const roomKey = messageThreadId ? `${chatId.toString()}-${messageThreadId}` : chatId.toString();
1516
+ const roomId = createUniqueUuid(
1517
+ this.runtime,
1518
+ this.scopedTelegramKey(roomKey)
806
1519
  );
807
- if (!sentMessages?.length) return [];
808
- const roomId = createUniqueUuid(this.runtime, chatId.toString());
809
1520
  const memories = [];
1521
+ const contentMetadata = content.metadata && typeof content.metadata === "object" && !Array.isArray(content.metadata) ? content.metadata : {};
810
1522
  for (const sentMessage of sentMessages) {
811
1523
  const memory = {
812
- id: createUniqueUuid(this.runtime, sentMessage.message_id.toString()),
1524
+ id: createUniqueUuid(
1525
+ this.runtime,
1526
+ this.scopedTelegramKey(sentMessage.message_id.toString())
1527
+ ),
813
1528
  entityId: this.runtime.agentId,
814
1529
  agentId: this.runtime.agentId,
815
1530
  roomId,
@@ -817,11 +1532,34 @@ Type: ${document.mime_type || "unknown"}`
817
1532
  ...content,
818
1533
  text: sentMessage.text,
819
1534
  source: "telegram",
1535
+ metadata: { ...contentMetadata, accountId: this.accountId },
820
1536
  channelType: getChannelType({
821
1537
  id: typeof chatId === "string" ? Number.parseInt(chatId, 10) : chatId,
822
1538
  type: "private"
823
1539
  // Default to private, will be overridden if in context
824
- })
1540
+ }),
1541
+ ...messageThreadId ? {
1542
+ metadata: {
1543
+ ...contentMetadata,
1544
+ accountId: this.accountId,
1545
+ threadId: messageThreadId
1546
+ }
1547
+ } : {}
1548
+ },
1549
+ metadata: {
1550
+ type: "message",
1551
+ source: "telegram",
1552
+ accountId: this.accountId,
1553
+ provider: "telegram",
1554
+ fromBot: true,
1555
+ fromId: this.runtime.agentId,
1556
+ sourceId: this.runtime.agentId,
1557
+ messageIdFull: sentMessage.message_id.toString(),
1558
+ telegram: {
1559
+ chatId: sentMessage.chat.id.toString(),
1560
+ messageId: sentMessage.message_id.toString(),
1561
+ threadId: messageThreadId?.toString()
1562
+ }
825
1563
  },
826
1564
  createdAt: sentMessage.date * 1e3
827
1565
  };
@@ -829,39 +1567,440 @@ Type: ${document.mime_type || "unknown"}`
829
1567
  memories.push(memory);
830
1568
  }
831
1569
  if (memories.length > 0) {
1570
+ const firstMemory = memories[0];
832
1571
  this.runtime.emitEvent(EventType.MESSAGE_SENT, {
833
1572
  runtime: this.runtime,
834
- message: memories[0],
835
- source: "telegram"
1573
+ message: firstMemory,
1574
+ source: "telegram",
1575
+ accountId: this.accountId,
1576
+ metadata: { accountId: this.accountId }
836
1577
  });
837
- }
838
- this.runtime.emitEvent(
839
- "TELEGRAM_MESSAGE_SENT" /* MESSAGE_SENT */,
840
- {
1578
+ const telegramMessageSentPayload = {
841
1579
  runtime: this.runtime,
842
1580
  source: "telegram",
1581
+ accountId: this.accountId,
1582
+ metadata: { accountId: this.accountId },
843
1583
  originalMessages: sentMessages,
844
1584
  chatId,
845
- message: memories[0]
846
- }
847
- );
1585
+ message: firstMemory
1586
+ };
1587
+ this.runtime.emitEvent(
1588
+ "TELEGRAM_MESSAGE_SENT" /* MESSAGE_SENT */,
1589
+ telegramMessageSentPayload
1590
+ );
1591
+ }
848
1592
  return sentMessages;
849
1593
  } catch (error) {
850
- logger2.error({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId, error: error instanceof Error ? error.message : String(error) }, "Error sending message to Telegram");
1594
+ logger2.error(
1595
+ {
1596
+ src: "plugin:telegram",
1597
+ agentId: this.runtime.agentId,
1598
+ chatId,
1599
+ error: error instanceof Error ? error.message : String(error)
1600
+ },
1601
+ "Error sending message to Telegram"
1602
+ );
851
1603
  return [];
852
1604
  }
853
1605
  }
854
1606
  };
855
1607
 
1608
+ // src/owner-pairing-service.ts
1609
+ import { logger as logger3, Service } from "@elizaos/core";
1610
+ var TELEGRAM_OWNER_PAIRING_SERVICE_TYPE = "OWNER_PAIRING_TELEGRAM";
1611
+ var RATE_LIMIT_MAX_ATTEMPTS = 5;
1612
+ var RATE_LIMIT_WINDOW_MS = 6e4;
1613
+ async function auditEmit(runtime, action, outcome, metadata) {
1614
+ try {
1615
+ await runtime.emitEvent(
1616
+ ["AUTH_AUDIT"],
1617
+ {
1618
+ runtime,
1619
+ action,
1620
+ outcome,
1621
+ metadata,
1622
+ source: "telegram"
1623
+ }
1624
+ );
1625
+ } catch {
1626
+ }
1627
+ }
1628
+ var pairAttempts = /* @__PURE__ */ new Map();
1629
+ function isRateLimited(userId) {
1630
+ const now = Date.now();
1631
+ const windowStart = now - RATE_LIMIT_WINDOW_MS;
1632
+ const attempts = (pairAttempts.get(userId) ?? []).filter(
1633
+ (ts) => ts > windowStart
1634
+ );
1635
+ pairAttempts.set(userId, attempts);
1636
+ if (attempts.length >= RATE_LIMIT_MAX_ATTEMPTS) {
1637
+ return true;
1638
+ }
1639
+ attempts.push(now);
1640
+ pairAttempts.set(userId, attempts);
1641
+ return false;
1642
+ }
1643
+ function isValidPairCode(code) {
1644
+ return /^\d{6}$/.test(code.trim());
1645
+ }
1646
+ function resolveVerifyService(runtime) {
1647
+ try {
1648
+ const svc = runtime.getService("OWNER_BIND_VERIFY");
1649
+ if (svc && typeof svc === "object" && typeof svc.verifyOwnerBindFromConnector === "function") {
1650
+ return svc;
1651
+ }
1652
+ } catch {
1653
+ }
1654
+ return null;
1655
+ }
1656
+ function resolveDisplayHandle(from) {
1657
+ if (from.username) {
1658
+ return `@${from.username}`;
1659
+ }
1660
+ if (from.first_name) {
1661
+ return from.first_name;
1662
+ }
1663
+ return String(from.id);
1664
+ }
1665
+ async function handleElizaPairCommand(ctx, runtime) {
1666
+ const from = ctx.from;
1667
+ if (!from) {
1668
+ return;
1669
+ }
1670
+ const userId = String(from.id);
1671
+ const displayHandle = resolveDisplayHandle(from);
1672
+ if (isRateLimited(userId)) {
1673
+ logger3.warn(
1674
+ { src: "plugin:telegram:owner-pairing", userId },
1675
+ "Rate limit hit for /eliza_pair"
1676
+ );
1677
+ await auditEmit(
1678
+ runtime,
1679
+ "auth.owner.pair.telegram.rate_limited",
1680
+ "failure",
1681
+ { externalId: userId }
1682
+ );
1683
+ await ctx.reply(
1684
+ "Too many pairing attempts. Please wait a moment before trying again."
1685
+ );
1686
+ return;
1687
+ }
1688
+ const message = ctx.message;
1689
+ const rawText = message && "text" in message ? message.text : void 0;
1690
+ let code = null;
1691
+ if (typeof rawText === "string") {
1692
+ const parts = rawText.trim().split(/\s+/);
1693
+ if (parts.length >= 2) {
1694
+ code = parts[1] ?? null;
1695
+ }
1696
+ }
1697
+ if (!code?.trim()) {
1698
+ await ctx.reply(
1699
+ "Usage: /eliza\\_pair <code> \u2014 enter the 6-digit code shown in the Eliza dashboard."
1700
+ );
1701
+ return;
1702
+ }
1703
+ code = code.trim();
1704
+ if (!isValidPairCode(code)) {
1705
+ await ctx.reply(
1706
+ "The pairing code must be exactly 6 digits. Check the Eliza dashboard and try again."
1707
+ );
1708
+ return;
1709
+ }
1710
+ const verifySvc = resolveVerifyService(runtime);
1711
+ if (!verifySvc) {
1712
+ logger3.error(
1713
+ { src: "plugin:telegram:owner-pairing", userId },
1714
+ "OWNER_BIND_VERIFY service not available \u2014 cannot complete pairing"
1715
+ );
1716
+ await auditEmit(
1717
+ runtime,
1718
+ "auth.owner.pair.telegram.service_unavailable",
1719
+ "failure",
1720
+ { externalId: userId }
1721
+ );
1722
+ await ctx.reply(
1723
+ "Eliza could not reach the pairing service right now. Please try again in a moment."
1724
+ );
1725
+ return;
1726
+ }
1727
+ let result;
1728
+ try {
1729
+ result = await verifySvc.verifyOwnerBindFromConnector({
1730
+ connector: "telegram",
1731
+ externalId: userId,
1732
+ displayHandle,
1733
+ code
1734
+ });
1735
+ } catch (err) {
1736
+ logger3.error(
1737
+ {
1738
+ src: "plugin:telegram:owner-pairing",
1739
+ userId,
1740
+ error: err instanceof Error ? err.message : String(err)
1741
+ },
1742
+ "verifyOwnerBindFromConnector threw unexpectedly"
1743
+ );
1744
+ await auditEmit(
1745
+ runtime,
1746
+ "auth.owner.pair.telegram.verify_error",
1747
+ "failure",
1748
+ { externalId: userId }
1749
+ );
1750
+ await ctx.reply(
1751
+ "Something went wrong while verifying the pairing code. Please try again."
1752
+ );
1753
+ return;
1754
+ }
1755
+ if (result.success) {
1756
+ logger3.info(
1757
+ { src: "plugin:telegram:owner-pairing", userId, displayHandle },
1758
+ "Owner pairing completed successfully"
1759
+ );
1760
+ await auditEmit(runtime, "auth.owner.pair.telegram.success", "success", {
1761
+ externalId: userId,
1762
+ displayHandle
1763
+ });
1764
+ await ctx.reply("Paired with Eliza. You can now log in via Telegram.");
1765
+ } else {
1766
+ logger3.warn(
1767
+ {
1768
+ src: "plugin:telegram:owner-pairing",
1769
+ userId,
1770
+ backendError: result.error
1771
+ },
1772
+ "Owner pairing rejected by backend"
1773
+ );
1774
+ await auditEmit(runtime, "auth.owner.pair.telegram.failure", "failure", {
1775
+ externalId: userId
1776
+ });
1777
+ await ctx.reply(
1778
+ "Pair code invalid or expired. Check the Eliza dashboard for a fresh code."
1779
+ );
1780
+ }
1781
+ }
1782
+ var TelegramOwnerPairingServiceImpl = class _TelegramOwnerPairingServiceImpl extends Service {
1783
+ static serviceType = TELEGRAM_OWNER_PAIRING_SERVICE_TYPE;
1784
+ capabilityDescription = "Handles Telegram-side owner pairing (command code verification) and DM login-link delivery for Eliza remote auth";
1785
+ static async start(runtime) {
1786
+ const service = new _TelegramOwnerPairingServiceImpl(runtime);
1787
+ if (resolveVerifyService(runtime)) {
1788
+ service.registerPairCommand(runtime);
1789
+ logger3.info(
1790
+ {
1791
+ src: "plugin:telegram:owner-pairing",
1792
+ agentId: runtime.agentId
1793
+ },
1794
+ "TelegramOwnerPairingService started; /eliza_pair command registered"
1795
+ );
1796
+ } else {
1797
+ logger3.info(
1798
+ {
1799
+ src: "plugin:telegram:owner-pairing",
1800
+ agentId: runtime.agentId
1801
+ },
1802
+ "TelegramOwnerPairingService started without /eliza_pair because OWNER_BIND_VERIFY is not registered"
1803
+ );
1804
+ }
1805
+ return service;
1806
+ }
1807
+ async stop() {
1808
+ pairAttempts.clear();
1809
+ }
1810
+ /**
1811
+ * Registers the /eliza_pair command with the active Telegraf bot instance
1812
+ * by looking up the TelegramService from the runtime service registry.
1813
+ * Called during `start`; it is safe to call this before or after the bot
1814
+ * has finished initialising because Telegraf accepts handler registration
1815
+ * at any point before `launch()`.
1816
+ *
1817
+ * If the TelegramService is unavailable, the command is not registered.
1818
+ */
1819
+ registerPairCommand(runtime) {
1820
+ const telegramSvc = runtime.getService(TELEGRAM_SERVICE_NAME);
1821
+ if (!telegramSvc || typeof telegramSvc !== "object") {
1822
+ logger3.warn(
1823
+ { src: "plugin:telegram:owner-pairing", agentId: runtime.agentId },
1824
+ "TelegramService unavailable during owner-pairing start; /eliza_pair command not registered"
1825
+ );
1826
+ return;
1827
+ }
1828
+ const bot = "bot" in telegramSvc ? telegramSvc.bot : null;
1829
+ if (!bot || typeof bot.command !== "function") {
1830
+ logger3.warn(
1831
+ { src: "plugin:telegram:owner-pairing", agentId: runtime.agentId },
1832
+ "Telegraf bot instance not available \u2014 /eliza_pair will not be registered"
1833
+ );
1834
+ return;
1835
+ }
1836
+ const telegrafBot = bot;
1837
+ telegrafBot.command("eliza_pair", async (ctx) => {
1838
+ await handleElizaPairCommand(ctx, runtime);
1839
+ });
1840
+ logger3.debug(
1841
+ { src: "plugin:telegram:owner-pairing", agentId: runtime.agentId },
1842
+ "/eliza_pair command registered with Telegraf bot"
1843
+ );
1844
+ }
1845
+ async sendOwnerLoginDmLink(params) {
1846
+ const { externalId, link } = params;
1847
+ const telegramSvc = this.runtime.getService(
1848
+ TELEGRAM_SERVICE_NAME
1849
+ );
1850
+ const bot = telegramSvc && typeof telegramSvc === "object" && "bot" in telegramSvc ? telegramSvc.bot : null;
1851
+ if (!bot || typeof bot.telegram !== "object") {
1852
+ throw new Error(
1853
+ "Telegram bot is not available \u2014 cannot send DM login link"
1854
+ );
1855
+ }
1856
+ const telegrafBot = bot;
1857
+ const chatId = Number(externalId);
1858
+ if (!Number.isFinite(chatId) || chatId <= 0) {
1859
+ throw new Error(
1860
+ `Invalid Telegram externalId "${externalId}" \u2014 must be a positive numeric user ID`
1861
+ );
1862
+ }
1863
+ const message = `Click to log in to Eliza: ${link}
1864
+
1865
+ _This link expires in 5 minutes. Do not share it._`;
1866
+ try {
1867
+ await telegrafBot.telegram.sendMessage(chatId, message, {
1868
+ parse_mode: "Markdown"
1869
+ });
1870
+ logger3.info(
1871
+ { src: "plugin:telegram:owner-pairing", externalId },
1872
+ "Login DM link sent"
1873
+ );
1874
+ } catch (err) {
1875
+ throw new Error(
1876
+ `Failed to send DM login link to Telegram user ${externalId}: ${err instanceof Error ? err.message : String(err)}`
1877
+ );
1878
+ }
1879
+ }
1880
+ };
1881
+
856
1882
  // src/service.ts
857
- var TelegramService = class _TelegramService extends Service {
1883
+ import {
1884
+ ChannelType as ChannelType2,
1885
+ createUniqueUuid as createUniqueUuid2,
1886
+ EventType as EventType2,
1887
+ logger as logger4,
1888
+ Role,
1889
+ Service as Service2
1890
+ } from "@elizaos/core";
1891
+ import { Telegraf } from "telegraf";
1892
+ var CANONICAL_OWNER_SETTING_KEYS = ["ELIZA_ADMIN_ENTITY_ID"];
1893
+ var TELEGRAM_CONNECTOR_CONTEXTS = ["social", "connectors"];
1894
+ var TELEGRAM_CONNECTOR_CAPABILITIES = [
1895
+ "send_message",
1896
+ "resolve_targets",
1897
+ "list_rooms",
1898
+ "chat_context",
1899
+ "user_context"
1900
+ ];
1901
+ var TELEGRAM_CHAT_ID_PATTERN = /^-?\d+$/;
1902
+ var TELEGRAM_THREADED_CHANNEL_PATTERN = /^(-?\d+)-(\d+)$/;
1903
+ function normalizeConnectorLimit(limit, fallback = 50) {
1904
+ if (!Number.isFinite(limit) || !limit || limit <= 0) {
1905
+ return fallback;
1906
+ }
1907
+ return Math.min(Math.floor(limit), 200);
1908
+ }
1909
+ function filterMemoriesByQuery(memories, query, limit) {
1910
+ const normalized = query.trim().toLowerCase();
1911
+ if (!normalized) {
1912
+ return memories.slice(0, limit);
1913
+ }
1914
+ return memories.filter((memory) => {
1915
+ const text = typeof memory.content?.text === "string" ? memory.content.text : "";
1916
+ return text.toLowerCase().includes(normalized);
1917
+ }).slice(0, limit);
1918
+ }
1919
+ var ACTIVE_TELEGRAM_POLLERS = /* @__PURE__ */ new Map();
1920
+ function getCanonicalOwnerId(runtime) {
1921
+ for (const key of CANONICAL_OWNER_SETTING_KEYS) {
1922
+ const value = runtime.getSetting(key);
1923
+ if (typeof value !== "string") {
1924
+ continue;
1925
+ }
1926
+ const trimmed = value.trim();
1927
+ if (trimmed.length > 0) {
1928
+ return trimmed;
1929
+ }
1930
+ }
1931
+ return null;
1932
+ }
1933
+ function getTelegramChatDisplayName(chat, fallback) {
1934
+ if (!chat) {
1935
+ return fallback;
1936
+ }
1937
+ if ("title" in chat && typeof chat.title === "string" && chat.title.trim()) {
1938
+ return chat.title;
1939
+ }
1940
+ if ("first_name" in chat && typeof chat.first_name === "string" && chat.first_name.trim()) {
1941
+ return chat.first_name;
1942
+ }
1943
+ if ("username" in chat && typeof chat.username === "string" && chat.username.trim()) {
1944
+ return chat.username;
1945
+ }
1946
+ return fallback;
1947
+ }
1948
+ function normalizeTelegramConnectorQuery(value) {
1949
+ return value.trim().replace(/^@/, "").toLowerCase();
1950
+ }
1951
+ function scoreTelegramConnectorMatch(query, id, labels) {
1952
+ if (!query) {
1953
+ return 0.45;
1954
+ }
1955
+ if (id.toLowerCase() === query) {
1956
+ return 1;
1957
+ }
1958
+ let bestScore = 0;
1959
+ for (const label of labels) {
1960
+ const normalized = label?.trim().replace(/^@/, "").toLowerCase();
1961
+ if (!normalized) {
1962
+ continue;
1963
+ }
1964
+ if (normalized === query) {
1965
+ bestScore = Math.max(bestScore, 0.95);
1966
+ } else if (normalized.startsWith(query)) {
1967
+ bestScore = Math.max(bestScore, 0.85);
1968
+ } else if (normalized.includes(query)) {
1969
+ bestScore = Math.max(bestScore, 0.7);
1970
+ }
1971
+ }
1972
+ return bestScore;
1973
+ }
1974
+ function parseTelegramTargetParts(channelId, explicitThreadId) {
1975
+ const explicitThreadNumber = explicitThreadId && /^\d+$/.test(explicitThreadId) ? Number.parseInt(explicitThreadId, 10) : void 0;
1976
+ const threadedMatch = channelId.match(TELEGRAM_THREADED_CHANNEL_PATTERN);
1977
+ if (threadedMatch) {
1978
+ return {
1979
+ chatId: threadedMatch[1],
1980
+ threadId: explicitThreadNumber ?? Number.parseInt(threadedMatch[2], 10)
1981
+ };
1982
+ }
1983
+ return { chatId: channelId, threadId: explicitThreadNumber };
1984
+ }
1985
+ function telegramChatKind(chat) {
1986
+ if (chat.type === "private") {
1987
+ return "user";
1988
+ }
1989
+ if (chat.type === "channel") {
1990
+ return "channel";
1991
+ }
1992
+ return "group";
1993
+ }
1994
+ var TelegramService = class _TelegramService extends Service2 {
858
1995
  static serviceType = TELEGRAM_SERVICE_NAME;
859
1996
  capabilityDescription = "The agent is able to send and receive messages on telegram";
860
- bot;
861
- messageManager;
862
- options;
1997
+ bot = null;
1998
+ messageManager = null;
863
1999
  knownChats = /* @__PURE__ */ new Map();
864
2000
  syncedEntityIds = /* @__PURE__ */ new Set();
2001
+ botToken;
2002
+ defaultAccountId = DEFAULT_ACCOUNT_ID;
2003
+ accountStates = /* @__PURE__ */ new Map();
865
2004
  /**
866
2005
  * Constructor for TelegramService class.
867
2006
  * @param {IAgentRuntime} runtime - The runtime object for the agent.
@@ -871,31 +2010,134 @@ var TelegramService = class _TelegramService extends Service {
871
2010
  if (!runtime) {
872
2011
  this.bot = null;
873
2012
  this.messageManager = null;
2013
+ this.botToken = null;
874
2014
  return;
875
2015
  }
876
- logger3.debug({ src: "plugin:telegram", agentId: runtime.agentId }, "Constructing TelegramService");
877
- const botToken = runtime.getSetting("TELEGRAM_BOT_TOKEN");
878
- if (!botToken || botToken.trim() === "") {
879
- logger3.warn({ src: "plugin:telegram", agentId: runtime.agentId }, "Bot token not provided, Telegram functionality unavailable");
2016
+ logger4.debug(
2017
+ { src: "plugin:telegram", agentId: runtime.agentId },
2018
+ "Constructing TelegramService"
2019
+ );
2020
+ this.defaultAccountId = resolveDefaultTelegramAccountId(runtime);
2021
+ const account = resolveTelegramAccount(runtime, this.defaultAccountId);
2022
+ this.botToken = account.botToken ?? null;
2023
+ if (!account.botToken) {
2024
+ logger4.warn(
2025
+ {
2026
+ src: "plugin:telegram",
2027
+ agentId: runtime.agentId,
2028
+ accountId: account.accountId
2029
+ },
2030
+ "Bot token not provided, Telegram functionality unavailable"
2031
+ );
880
2032
  this.bot = null;
881
2033
  this.messageManager = null;
882
2034
  return;
883
2035
  }
884
- this.options = {
885
- telegram: {
886
- apiRoot: runtime.getSetting("TELEGRAM_API_ROOT") || process.env.TELEGRAM_API_ROOT || "https://api.telegram.org"
887
- }
888
- };
889
2036
  try {
890
- this.bot = new Telegraf(botToken, this.options);
891
- this.messageManager = new MessageManager(this.bot, this.runtime);
892
- logger3.debug({ src: "plugin:telegram", agentId: runtime.agentId }, "TelegramService constructor completed");
2037
+ const state = this.createAccountRuntime(account);
2038
+ this.setDefaultAccountState(state);
2039
+ logger4.debug(
2040
+ {
2041
+ src: "plugin:telegram",
2042
+ agentId: runtime.agentId,
2043
+ accountId: account.accountId
2044
+ },
2045
+ "TelegramService constructor completed"
2046
+ );
893
2047
  } catch (error) {
894
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Failed to initialize Telegram bot");
2048
+ logger4.error(
2049
+ {
2050
+ src: "plugin:telegram",
2051
+ agentId: runtime.agentId,
2052
+ error: error instanceof Error ? error.message : String(error)
2053
+ },
2054
+ "Failed to initialize Telegram bot"
2055
+ );
895
2056
  this.bot = null;
896
2057
  this.messageManager = null;
897
2058
  }
898
2059
  }
2060
+ createAccountRuntime(account) {
2061
+ if (!account.botToken) {
2062
+ throw new Error(`Telegram account ${account.accountId} has no bot token`);
2063
+ }
2064
+ const bot = new Telegraf(account.botToken, {
2065
+ telegram: { apiRoot: account.apiRoot }
2066
+ });
2067
+ const messageManager = new MessageManager(
2068
+ bot,
2069
+ this.runtime,
2070
+ account.accountId
2071
+ );
2072
+ return {
2073
+ accountId: account.accountId,
2074
+ account,
2075
+ bot,
2076
+ messageManager
2077
+ };
2078
+ }
2079
+ setDefaultAccountState(state) {
2080
+ this.accountStates.set(state.accountId, state);
2081
+ if (state.accountId === this.defaultAccountId || !this.bot) {
2082
+ this.bot = state.bot;
2083
+ this.messageManager = state.messageManager;
2084
+ this.botToken = state.account.botToken ?? null;
2085
+ }
2086
+ }
2087
+ getDefaultAccountState() {
2088
+ if (!(this.accountStates instanceof Map) || this.accountStates.size === 0) {
2089
+ return null;
2090
+ }
2091
+ return this.accountStates.get(this.defaultAccountId) ?? this.accountStates.values().next().value ?? null;
2092
+ }
2093
+ getAccountState(accountId) {
2094
+ if (!(this.accountStates instanceof Map) || this.accountStates.size === 0) {
2095
+ return null;
2096
+ }
2097
+ if (accountId) {
2098
+ return this.accountStates.get(normalizeTelegramAccountId(accountId)) ?? null;
2099
+ }
2100
+ return this.getDefaultAccountState();
2101
+ }
2102
+ getAccountIds() {
2103
+ if (this.accountStates instanceof Map && this.accountStates.size > 0) {
2104
+ return Array.from(this.accountStates.keys());
2105
+ }
2106
+ return [normalizeTelegramAccountId(this.defaultAccountId)];
2107
+ }
2108
+ resolveAccountIdFromContext(context, target) {
2109
+ const scopedTarget = target;
2110
+ const scopedContext = context;
2111
+ return scopedTarget?.accountId ?? scopedContext?.target?.accountId ?? scopedContext?.accountId ?? scopedContext?.account?.accountId ?? void 0;
2112
+ }
2113
+ async resolveAccountIdForTarget(runtime, target, fallback) {
2114
+ const direct = target?.accountId ?? fallback?.accountId;
2115
+ if (direct) {
2116
+ return normalizeTelegramAccountId(direct);
2117
+ }
2118
+ const roomId = target?.roomId ?? fallback?.roomId;
2119
+ if (roomId && typeof runtime.getRoom === "function") {
2120
+ const room = await runtime.getRoom(roomId);
2121
+ const metadata = room?.metadata;
2122
+ if (typeof metadata?.accountId === "string" && metadata.accountId.trim()) {
2123
+ return normalizeTelegramAccountId(metadata.accountId);
2124
+ }
2125
+ const telegram = metadata?.telegram && typeof metadata.telegram === "object" ? metadata.telegram : void 0;
2126
+ if (typeof telegram?.accountId === "string" && telegram.accountId.trim()) {
2127
+ return normalizeTelegramAccountId(telegram.accountId);
2128
+ }
2129
+ }
2130
+ return normalizeTelegramAccountId(this.defaultAccountId);
2131
+ }
2132
+ scopedTelegramKey(key, accountId) {
2133
+ const normalized = normalizeTelegramAccountId(
2134
+ accountId ?? this.defaultAccountId
2135
+ );
2136
+ return normalized === DEFAULT_ACCOUNT_ID ? key : `${normalized}:${key}`;
2137
+ }
2138
+ knownChatKeyMatchesAccount(key, chat, accountId) {
2139
+ return key === this.scopedTelegramKey(chat.id.toString(), accountId);
2140
+ }
899
2141
  /**
900
2142
  * Starts the Telegram service for the given runtime.
901
2143
  *
@@ -904,34 +2146,88 @@ var TelegramService = class _TelegramService extends Service {
904
2146
  */
905
2147
  static async start(runtime) {
906
2148
  const service = new _TelegramService(runtime);
2149
+ for (const account of listEnabledTelegramAccounts(runtime)) {
2150
+ if (!service.getAccountState(account.accountId)) {
2151
+ service.setDefaultAccountState(service.createAccountRuntime(account));
2152
+ }
2153
+ }
907
2154
  if (!service.bot) {
908
- logger3.warn({ src: "plugin:telegram", agentId: runtime.agentId }, "Service started without bot functionality");
2155
+ logger4.warn(
2156
+ { src: "plugin:telegram", agentId: runtime.agentId },
2157
+ "Service started without bot functionality"
2158
+ );
909
2159
  return service;
910
2160
  }
911
2161
  const maxRetries = 5;
912
- let retryCount = 0;
913
- let lastError = null;
914
- while (retryCount < maxRetries) {
915
- try {
916
- logger3.info({ src: "plugin:telegram", agentId: runtime.agentId, agentName: runtime.character.name }, "Starting Telegram bot");
917
- await service.initializeBot();
918
- service.setupMiddlewares();
919
- service.setupMessageHandlers();
920
- await service.bot.telegram.getMe();
921
- logger3.success({ src: "plugin:telegram", agentId: runtime.agentId, agentName: runtime.character.name }, "Telegram bot started successfully");
922
- return service;
923
- } catch (error) {
924
- lastError = error instanceof Error ? error : new Error(String(error));
925
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId, attempt: retryCount + 1, error: lastError.message }, "Initialization attempt failed");
926
- retryCount++;
927
- if (retryCount < maxRetries) {
928
- const delay = 2 ** retryCount * 1e3;
929
- logger3.info({ src: "plugin:telegram", agentId: runtime.agentId, delaySeconds: delay / 1e3 }, "Retrying initialization");
930
- await new Promise((resolve) => setTimeout(resolve, delay));
2162
+ for (const state of service.accountStates.values()) {
2163
+ let retryCount = 0;
2164
+ let lastError = null;
2165
+ while (retryCount < maxRetries) {
2166
+ try {
2167
+ logger4.info(
2168
+ {
2169
+ src: "plugin:telegram",
2170
+ agentId: runtime.agentId,
2171
+ agentName: runtime.character.name,
2172
+ accountId: state.accountId
2173
+ },
2174
+ "Starting Telegram bot"
2175
+ );
2176
+ await service.initializeBot(state);
2177
+ service.setupMiddlewares(state);
2178
+ service.setupMessageHandlers(state);
2179
+ await state.bot.telegram.getMe();
2180
+ logger4.success(
2181
+ {
2182
+ src: "plugin:telegram",
2183
+ agentId: runtime.agentId,
2184
+ agentName: runtime.character.name,
2185
+ accountId: state.accountId
2186
+ },
2187
+ "Telegram bot started successfully"
2188
+ );
2189
+ break;
2190
+ } catch (error) {
2191
+ lastError = error instanceof Error ? error : new Error(String(error));
2192
+ logger4.error(
2193
+ {
2194
+ src: "plugin:telegram",
2195
+ agentId: runtime.agentId,
2196
+ accountId: state.accountId,
2197
+ attempt: retryCount + 1,
2198
+ error: lastError.message
2199
+ },
2200
+ "Initialization attempt failed"
2201
+ );
2202
+ retryCount++;
2203
+ if (retryCount < maxRetries) {
2204
+ const delay = 2 ** retryCount * 1e3;
2205
+ logger4.info(
2206
+ {
2207
+ src: "plugin:telegram",
2208
+ agentId: runtime.agentId,
2209
+ accountId: state.accountId,
2210
+ delaySeconds: delay / 1e3
2211
+ },
2212
+ "Retrying initialization"
2213
+ );
2214
+ await new Promise((resolve) => setTimeout(resolve, delay));
2215
+ }
931
2216
  }
932
2217
  }
2218
+ if (retryCount >= maxRetries) {
2219
+ logger4.error(
2220
+ {
2221
+ src: "plugin:telegram",
2222
+ agentId: runtime.agentId,
2223
+ accountId: state.accountId,
2224
+ maxRetries,
2225
+ error: lastError?.message
2226
+ },
2227
+ "Initialization failed after all attempts"
2228
+ );
2229
+ }
933
2230
  }
934
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId, maxRetries, error: lastError?.message }, "Initialization failed after all attempts");
935
2231
  return service;
936
2232
  }
937
2233
  /**
@@ -939,7 +2235,7 @@ var TelegramService = class _TelegramService extends Service {
939
2235
  * @param {IAgentRuntime} runtime - The agent runtime to stop
940
2236
  */
941
2237
  static async stop(runtime) {
942
- const tgClient = runtime.getService(TELEGRAM_SERVICE_NAME);
2238
+ const tgClient = await runtime.getService(TELEGRAM_SERVICE_NAME);
943
2239
  if (tgClient) {
944
2240
  await tgClient.stop();
945
2241
  }
@@ -950,31 +2246,109 @@ var TelegramService = class _TelegramService extends Service {
950
2246
  * @returns A Promise that resolves once the bot has stopped.
951
2247
  */
952
2248
  async stop() {
953
- this.bot?.stop();
2249
+ const states = this.accountStates instanceof Map ? Array.from(this.accountStates.values()) : [];
2250
+ if (states.length > 0) {
2251
+ for (const state of states) {
2252
+ state.bot.stop("service-stop");
2253
+ const token = state.account.botToken;
2254
+ if (token) {
2255
+ const active = ACTIVE_TELEGRAM_POLLERS.get(token);
2256
+ if (active?.bot === state.bot) {
2257
+ ACTIVE_TELEGRAM_POLLERS.delete(token);
2258
+ }
2259
+ }
2260
+ }
2261
+ return;
2262
+ }
2263
+ const bot = this.bot;
2264
+ if (bot) {
2265
+ bot.stop("service-stop");
2266
+ if (this.botToken) {
2267
+ const active = ACTIVE_TELEGRAM_POLLERS.get(this.botToken);
2268
+ if (active?.bot === bot) {
2269
+ ACTIVE_TELEGRAM_POLLERS.delete(this.botToken);
2270
+ }
2271
+ }
2272
+ }
954
2273
  }
955
2274
  /**
956
2275
  * Initializes the Telegram bot by launching it, getting bot info, and setting up message manager.
957
2276
  * @returns {Promise<void>} A Promise that resolves when the initialization is complete.
958
2277
  */
959
- async initializeBot() {
960
- this.bot?.start((ctx) => {
2278
+ async initializeBot(state) {
2279
+ const activeState = state ?? this.getDefaultAccountState();
2280
+ const bot = activeState?.bot ?? this.bot;
2281
+ if (!bot) {
2282
+ throw new Error("Telegram bot is not initialized");
2283
+ }
2284
+ const botToken = activeState?.account.botToken ?? this.botToken;
2285
+ const accountId = activeState?.accountId ?? this.defaultAccountId;
2286
+ if (botToken) {
2287
+ const active = ACTIVE_TELEGRAM_POLLERS.get(botToken);
2288
+ if (active && active.bot !== bot) {
2289
+ logger4.warn(
2290
+ {
2291
+ src: "plugin:telegram",
2292
+ agentId: this.runtime.agentId,
2293
+ accountId,
2294
+ previousAgentId: active.agentId
2295
+ },
2296
+ "Stopping existing Telegram poller before launching a new one"
2297
+ );
2298
+ try {
2299
+ active.bot.stop("replaced-by-new-runtime");
2300
+ } catch (error) {
2301
+ logger4.warn(
2302
+ {
2303
+ src: "plugin:telegram",
2304
+ agentId: this.runtime.agentId,
2305
+ accountId,
2306
+ error: error instanceof Error ? error.message : String(error)
2307
+ },
2308
+ "Failed to stop previous Telegram poller cleanly"
2309
+ );
2310
+ }
2311
+ ACTIVE_TELEGRAM_POLLERS.delete(botToken);
2312
+ await new Promise((resolve) => setTimeout(resolve, 300));
2313
+ }
2314
+ }
2315
+ bot.start((ctx) => {
2316
+ const slashStartPayload = {
2317
+ ctx,
2318
+ runtime: this.runtime,
2319
+ source: "telegram",
2320
+ accountId,
2321
+ metadata: { accountId }
2322
+ };
961
2323
  this.runtime.emitEvent(
962
2324
  "TELEGRAM_SLASH_START" /* SLASH_START */,
963
- {
964
- ctx,
965
- runtime: this.runtime,
966
- source: "telegram"
967
- }
2325
+ slashStartPayload
968
2326
  );
969
2327
  });
970
- this.bot?.launch({
2328
+ await bot.launch({
971
2329
  dropPendingUpdates: true,
972
2330
  allowedUpdates: ["message", "message_reaction"]
973
2331
  });
974
- const botInfo = await this.bot.telegram.getMe();
975
- logger3.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, botId: botInfo.id, botUsername: botInfo.username }, "Bot info retrieved");
976
- process.once("SIGINT", () => this.bot?.stop("SIGINT"));
977
- process.once("SIGTERM", () => this.bot?.stop("SIGTERM"));
2332
+ if (botToken) {
2333
+ ACTIVE_TELEGRAM_POLLERS.set(botToken, {
2334
+ bot,
2335
+ agentId: this.runtime.agentId,
2336
+ accountId
2337
+ });
2338
+ }
2339
+ const botInfo = await bot.telegram.getMe();
2340
+ logger4.debug(
2341
+ {
2342
+ src: "plugin:telegram",
2343
+ agentId: this.runtime.agentId,
2344
+ accountId,
2345
+ botId: botInfo.id,
2346
+ botUsername: botInfo.username
2347
+ },
2348
+ "Bot info retrieved"
2349
+ );
2350
+ process.once("SIGINT", () => bot.stop("SIGINT"));
2351
+ process.once("SIGTERM", () => bot.stop("SIGTERM"));
978
2352
  }
979
2353
  /**
980
2354
  * Sets up the middleware chain for preprocessing messages before they reach handlers.
@@ -991,9 +2365,11 @@ var TelegramService = class _TelegramService extends Service {
991
2365
  *
992
2366
  * @private
993
2367
  */
994
- setupMiddlewares() {
995
- this.bot?.use(this.authorizationMiddleware.bind(this));
996
- this.bot?.use(this.chatAndEntityMiddleware.bind(this));
2368
+ setupMiddlewares(state) {
2369
+ const bot = state?.bot ?? this.bot;
2370
+ const accountId = state?.accountId ?? this.defaultAccountId;
2371
+ bot?.use((ctx, next) => this.authorizationMiddleware(ctx, next, accountId));
2372
+ bot?.use((ctx, next) => this.chatAndEntityMiddleware(ctx, next, accountId));
997
2373
  }
998
2374
  /**
999
2375
  * Authorization middleware - checks if chat is allowed to interact with the bot
@@ -1004,9 +2380,17 @@ var TelegramService = class _TelegramService extends Service {
1004
2380
  * @returns {Promise<void>}
1005
2381
  * @private
1006
2382
  */
1007
- async authorizationMiddleware(ctx, next) {
1008
- if (!await this.isGroupAuthorized(ctx)) {
1009
- logger3.debug({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId: ctx.chat?.id }, "Chat not authorized, skipping");
2383
+ async authorizationMiddleware(ctx, next, accountId = this.defaultAccountId) {
2384
+ if (!await this.isGroupAuthorized(ctx, accountId)) {
2385
+ logger4.debug(
2386
+ {
2387
+ src: "plugin:telegram",
2388
+ agentId: this.runtime.agentId,
2389
+ accountId,
2390
+ chatId: ctx.chat?.id
2391
+ },
2392
+ "Chat not authorized, skipping"
2393
+ );
1010
2394
  return;
1011
2395
  }
1012
2396
  await next();
@@ -1021,14 +2405,16 @@ var TelegramService = class _TelegramService extends Service {
1021
2405
  * @returns {Promise<void>}
1022
2406
  * @private
1023
2407
  */
1024
- async chatAndEntityMiddleware(ctx, next) {
1025
- if (!ctx.chat) return next();
2408
+ async chatAndEntityMiddleware(ctx, next, accountId = this.defaultAccountId) {
2409
+ if (!ctx.chat) {
2410
+ return next();
2411
+ }
1026
2412
  const chatId = ctx.chat.id.toString();
1027
- if (!this.knownChats.has(chatId)) {
1028
- await this.handleNewChat(ctx);
2413
+ if (!this.knownChats.has(this.scopedTelegramKey(chatId, accountId))) {
2414
+ await this.handleNewChat(ctx, accountId);
1029
2415
  return next();
1030
2416
  }
1031
- await this.processExistingChat(ctx);
2417
+ await this.processExistingChat(ctx, accountId);
1032
2418
  await next();
1033
2419
  }
1034
2420
  /**
@@ -1039,18 +2425,29 @@ var TelegramService = class _TelegramService extends Service {
1039
2425
  * @returns {Promise<void>}
1040
2426
  * @private
1041
2427
  */
1042
- async processExistingChat(ctx) {
1043
- if (!ctx.chat) return;
2428
+ async processExistingChat(ctx, accountId = this.defaultAccountId) {
2429
+ if (!ctx.chat) {
2430
+ return;
2431
+ }
1044
2432
  const chat = ctx.chat;
1045
2433
  if (chat.type === "supergroup" && chat.is_forum && ctx.message?.message_thread_id) {
1046
2434
  try {
1047
- await this.handleForumTopic(ctx);
2435
+ await this.handleForumTopic(ctx, accountId);
1048
2436
  } catch (error) {
1049
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId: chat.id, error: error instanceof Error ? error.message : String(error) }, "Error handling forum topic");
2437
+ logger4.error(
2438
+ {
2439
+ src: "plugin:telegram",
2440
+ agentId: this.runtime.agentId,
2441
+ accountId,
2442
+ chatId: chat.id,
2443
+ error: error instanceof Error ? error.message : String(error)
2444
+ },
2445
+ "Error handling forum topic"
2446
+ );
1050
2447
  }
1051
2448
  }
1052
2449
  if (ctx.from && ctx.chat.type !== "private") {
1053
- await this.syncEntity(ctx);
2450
+ await this.syncEntity(ctx, accountId);
1054
2451
  }
1055
2452
  }
1056
2453
  /**
@@ -1059,19 +2456,38 @@ var TelegramService = class _TelegramService extends Service {
1059
2456
  *
1060
2457
  * @private
1061
2458
  */
1062
- setupMessageHandlers() {
1063
- this.bot?.on("message", async (ctx) => {
2459
+ setupMessageHandlers(state) {
2460
+ const bot = state?.bot ?? this.bot;
2461
+ const messageManager = state?.messageManager ?? this.messageManager;
2462
+ const accountId = state?.accountId ?? this.defaultAccountId;
2463
+ bot?.on("message", async (ctx) => {
1064
2464
  try {
1065
- await this.messageManager.handleMessage(ctx);
2465
+ await messageManager?.handleMessage(ctx);
1066
2466
  } catch (error) {
1067
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error handling message");
2467
+ logger4.error(
2468
+ {
2469
+ src: "plugin:telegram",
2470
+ agentId: this.runtime.agentId,
2471
+ accountId,
2472
+ error: error instanceof Error ? error.message : String(error)
2473
+ },
2474
+ "Error handling message"
2475
+ );
1068
2476
  }
1069
2477
  });
1070
- this.bot?.on("message_reaction", async (ctx) => {
2478
+ bot?.on("message_reaction", async (ctx) => {
1071
2479
  try {
1072
- await this.messageManager.handleReaction(ctx);
2480
+ await messageManager?.handleReaction(ctx);
1073
2481
  } catch (error) {
1074
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error handling reaction");
2482
+ logger4.error(
2483
+ {
2484
+ src: "plugin:telegram",
2485
+ agentId: this.runtime.agentId,
2486
+ accountId,
2487
+ error: error instanceof Error ? error.message : String(error)
2488
+ },
2489
+ "Error handling reaction"
2490
+ );
1075
2491
  }
1076
2492
  });
1077
2493
  }
@@ -1080,9 +2496,15 @@ var TelegramService = class _TelegramService extends Service {
1080
2496
  * @param {Context} ctx - The context of the incoming update.
1081
2497
  * @returns {Promise<boolean>} A Promise that resolves with a boolean indicating if the group is authorized.
1082
2498
  */
1083
- async isGroupAuthorized(ctx) {
2499
+ async isGroupAuthorized(ctx, accountId = this.defaultAccountId) {
1084
2500
  const chatId = ctx.chat?.id.toString();
1085
- if (!chatId) return false;
2501
+ if (!chatId) {
2502
+ return false;
2503
+ }
2504
+ const accountAllowedChats = this.getAccountState(accountId)?.account.config.allowedChats;
2505
+ if (accountAllowedChats?.length) {
2506
+ return accountAllowedChats.includes(chatId);
2507
+ }
1086
2508
  const allowedChats = this.runtime.getSetting("TELEGRAM_ALLOWED_CHATS");
1087
2509
  if (!allowedChats) {
1088
2510
  return true;
@@ -1091,7 +2513,15 @@ var TelegramService = class _TelegramService extends Service {
1091
2513
  const allowedChatsList = JSON.parse(allowedChats);
1092
2514
  return allowedChatsList.includes(chatId);
1093
2515
  } catch (error) {
1094
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error parsing TELEGRAM_ALLOWED_CHATS");
2516
+ logger4.error(
2517
+ {
2518
+ src: "plugin:telegram",
2519
+ agentId: this.runtime.agentId,
2520
+ accountId,
2521
+ error: error instanceof Error ? error.message : String(error)
2522
+ },
2523
+ "Error parsing TELEGRAM_ALLOWED_CHATS"
2524
+ );
1095
2525
  return false;
1096
2526
  }
1097
2527
  }
@@ -1106,18 +2536,26 @@ var TelegramService = class _TelegramService extends Service {
1106
2536
  * @returns {Promise<void>}
1107
2537
  * @private
1108
2538
  */
1109
- async syncEntity(ctx) {
1110
- if (!ctx.chat) return;
2539
+ async syncEntity(ctx, accountId = this.defaultAccountId) {
2540
+ if (!ctx.chat) {
2541
+ return;
2542
+ }
1111
2543
  const chat = ctx.chat;
1112
2544
  const chatId = chat.id.toString();
1113
- const worldId = createUniqueUuid2(this.runtime, chatId);
2545
+ const worldId = createUniqueUuid2(
2546
+ this.runtime,
2547
+ this.scopedTelegramKey(chatId, accountId)
2548
+ );
1114
2549
  const roomId = createUniqueUuid2(
1115
2550
  this.runtime,
1116
- ctx.message?.message_thread_id ? `${ctx.chat.id}-${ctx.message.message_thread_id}` : ctx.chat.id.toString()
2551
+ this.scopedTelegramKey(
2552
+ ctx.message?.message_thread_id ? `${ctx.chat.id}-${ctx.message.message_thread_id}` : ctx.chat.id.toString(),
2553
+ accountId
2554
+ )
1117
2555
  );
1118
- await this.syncMessageSender(ctx, worldId, roomId, chatId);
1119
- await this.syncNewChatMember(ctx, worldId, roomId, chatId);
1120
- await this.syncLeftChatMember(ctx);
2556
+ await this.syncMessageSender(ctx, worldId, roomId, chatId, accountId);
2557
+ await this.syncNewChatMember(ctx, worldId, roomId, chatId, accountId);
2558
+ await this.syncLeftChatMember(ctx, accountId);
1121
2559
  }
1122
2560
  /**
1123
2561
  * Synchronizes the message sender entity with the runtime system.
@@ -1130,13 +2568,20 @@ var TelegramService = class _TelegramService extends Service {
1130
2568
  * @returns {Promise<void>}
1131
2569
  * @private
1132
2570
  */
1133
- async syncMessageSender(ctx, worldId, roomId, chatId) {
1134
- if (ctx.from && !this.syncedEntityIds.has(ctx.from.id.toString())) {
2571
+ async syncMessageSender(ctx, worldId, roomId, chatId, accountId = this.defaultAccountId) {
2572
+ if (ctx.from) {
1135
2573
  const telegramId = ctx.from.id.toString();
1136
- const entityId = createUniqueUuid2(this.runtime, telegramId);
2574
+ const entityId = createUniqueUuid2(
2575
+ this.runtime,
2576
+ this.scopedTelegramKey(telegramId, accountId)
2577
+ );
2578
+ if (this.syncedEntityIds.has(entityId)) {
2579
+ return;
2580
+ }
1137
2581
  await this.runtime.ensureConnection({
1138
2582
  entityId,
1139
2583
  roomId,
2584
+ roomName: getTelegramChatDisplayName(ctx.chat, chatId),
1140
2585
  userName: ctx.from.username,
1141
2586
  userId: telegramId,
1142
2587
  name: ctx.from.first_name || ctx.from.username || "Unknown User",
@@ -1159,38 +2604,48 @@ var TelegramService = class _TelegramService extends Service {
1159
2604
  * @returns {Promise<void>}
1160
2605
  * @private
1161
2606
  */
1162
- async syncNewChatMember(ctx, worldId, roomId, chatId) {
1163
- if (ctx.message && "new_chat_member" in ctx.message) {
1164
- const newMember = ctx.message.new_chat_member;
1165
- const telegramId = newMember.id.toString();
1166
- const entityId = createUniqueUuid2(this.runtime, telegramId);
1167
- if (this.syncedEntityIds.has(telegramId)) return;
1168
- await this.runtime.ensureConnection({
1169
- entityId,
1170
- roomId,
1171
- userName: newMember.username,
1172
- userId: telegramId,
1173
- name: newMember.first_name || newMember.username || "Unknown User",
1174
- source: "telegram",
1175
- channelId: chatId,
1176
- type: ChannelType2.GROUP,
1177
- worldId
1178
- });
1179
- this.syncedEntityIds.add(entityId);
1180
- this.runtime.emitEvent(
1181
- "TELEGRAM_ENTITY_JOINED" /* ENTITY_JOINED */,
1182
- {
2607
+ async syncNewChatMember(ctx, worldId, roomId, chatId, accountId = this.defaultAccountId) {
2608
+ if (ctx.message && "new_chat_members" in ctx.message) {
2609
+ for (const newMember of ctx.message.new_chat_members) {
2610
+ const telegramId = newMember.id.toString();
2611
+ const entityId = createUniqueUuid2(
2612
+ this.runtime,
2613
+ this.scopedTelegramKey(telegramId, accountId)
2614
+ );
2615
+ if (this.syncedEntityIds.has(entityId)) {
2616
+ continue;
2617
+ }
2618
+ await this.runtime.ensureConnection({
2619
+ entityId,
2620
+ roomId,
2621
+ roomName: getTelegramChatDisplayName(ctx.chat, chatId),
2622
+ userName: newMember.username,
2623
+ userId: telegramId,
2624
+ name: newMember.first_name || newMember.username || "Unknown User",
2625
+ source: "telegram",
2626
+ channelId: chatId,
2627
+ type: ChannelType2.GROUP,
2628
+ worldId
2629
+ });
2630
+ this.syncedEntityIds.add(entityId);
2631
+ const entityJoinedPayload = {
1183
2632
  runtime: this.runtime,
1184
2633
  entityId,
1185
2634
  worldId,
1186
2635
  source: "telegram",
2636
+ accountId,
2637
+ metadata: { accountId },
1187
2638
  telegramUser: {
1188
2639
  id: newMember.id,
1189
2640
  username: newMember.username,
1190
2641
  first_name: newMember.first_name
1191
2642
  }
1192
- }
1193
- );
2643
+ };
2644
+ this.runtime.emitEvent(
2645
+ "TELEGRAM_ENTITY_JOINED" /* ENTITY_JOINED */,
2646
+ entityJoinedPayload
2647
+ );
2648
+ }
1194
2649
  }
1195
2650
  }
1196
2651
  /**
@@ -1200,15 +2655,19 @@ var TelegramService = class _TelegramService extends Service {
1200
2655
  * @returns {Promise<void>}
1201
2656
  * @private
1202
2657
  */
1203
- async syncLeftChatMember(ctx) {
2658
+ async syncLeftChatMember(ctx, accountId = this.defaultAccountId) {
1204
2659
  if (ctx.message && "left_chat_member" in ctx.message) {
1205
2660
  const leftMember = ctx.message.left_chat_member;
1206
2661
  const telegramId = leftMember.id.toString();
1207
- const entityId = createUniqueUuid2(this.runtime, telegramId);
2662
+ const entityId = createUniqueUuid2(
2663
+ this.runtime,
2664
+ this.scopedTelegramKey(telegramId, accountId)
2665
+ );
1208
2666
  const existingEntity = await this.runtime.getEntityById(entityId);
1209
2667
  if (existingEntity) {
1210
2668
  existingEntity.metadata = {
1211
2669
  ...existingEntity.metadata,
2670
+ accountId,
1212
2671
  status: "INACTIVE",
1213
2672
  leftAt: Date.now()
1214
2673
  };
@@ -1224,28 +2683,43 @@ var TelegramService = class _TelegramService extends Service {
1224
2683
  * @returns {Promise<void>}
1225
2684
  * @private
1226
2685
  */
1227
- async handleForumTopic(ctx) {
1228
- if (!ctx.chat || !ctx.message?.message_thread_id) return;
2686
+ async handleForumTopic(ctx, accountId = this.defaultAccountId) {
2687
+ if (!ctx.chat || !ctx.message?.message_thread_id) {
2688
+ return;
2689
+ }
1229
2690
  const chat = ctx.chat;
1230
2691
  const chatId = chat.id.toString();
1231
- const worldId = createUniqueUuid2(this.runtime, chatId);
1232
- const room = await this.buildForumTopicRoom(ctx, worldId);
1233
- if (!room) return;
2692
+ const worldId = createUniqueUuid2(
2693
+ this.runtime,
2694
+ this.scopedTelegramKey(chatId, accountId)
2695
+ );
2696
+ const room = await this.buildForumTopicRoom(ctx, worldId, accountId);
2697
+ if (!room) {
2698
+ return;
2699
+ }
1234
2700
  await this.runtime.ensureRoomExists(room);
1235
2701
  }
1236
2702
  /**
1237
2703
  * Builds entity for message sender
1238
2704
  */
1239
- buildMsgSenderEntity(from) {
1240
- if (!from) return null;
1241
- const userId = createUniqueUuid2(this.runtime, from.id.toString());
2705
+ buildMsgSenderEntity(from, accountId = this.defaultAccountId) {
2706
+ if (!from) {
2707
+ return null;
2708
+ }
2709
+ const userId = createUniqueUuid2(
2710
+ this.runtime,
2711
+ this.scopedTelegramKey(from.id.toString(), accountId)
2712
+ );
1242
2713
  const telegramId = from.id.toString();
1243
2714
  return {
1244
2715
  id: userId,
1245
2716
  agentId: this.runtime.agentId,
1246
2717
  names: [from.first_name || from.username || "Unknown User"],
1247
2718
  metadata: {
2719
+ source: "telegram",
2720
+ accountId,
1248
2721
  telegram: {
2722
+ accountId,
1249
2723
  id: telegramId,
1250
2724
  username: from.username,
1251
2725
  name: from.first_name || from.username || "Unknown User"
@@ -1262,18 +2736,26 @@ var TelegramService = class _TelegramService extends Service {
1262
2736
  * @returns {Promise<void>}
1263
2737
  * @private
1264
2738
  */
1265
- async handleNewChat(ctx) {
1266
- if (!ctx.chat) return;
2739
+ async handleNewChat(ctx, accountId = this.defaultAccountId) {
2740
+ if (!ctx.chat) {
2741
+ return;
2742
+ }
1267
2743
  const chat = ctx.chat;
1268
2744
  const chatId = chat.id.toString();
1269
- this.knownChats.set(chatId, chat);
2745
+ this.knownChats.set(this.scopedTelegramKey(chatId, accountId), chat);
1270
2746
  const { chatTitle, channelType } = this.getChatTypeInfo(chat);
1271
- const worldId = createUniqueUuid2(this.runtime, chatId);
2747
+ const worldId = createUniqueUuid2(
2748
+ this.runtime,
2749
+ this.scopedTelegramKey(chatId, accountId)
2750
+ );
1272
2751
  const existingWorld = await this.runtime.getWorld(worldId);
1273
2752
  if (existingWorld) {
1274
2753
  return;
1275
2754
  }
1276
- const userId = ctx.from ? createUniqueUuid2(this.runtime, ctx.from.id.toString()) : null;
2755
+ const userId = ctx.from ? createUniqueUuid2(
2756
+ this.runtime,
2757
+ this.scopedTelegramKey(ctx.from.id.toString(), accountId)
2758
+ ) : null;
1277
2759
  let admins = [];
1278
2760
  let owner = null;
1279
2761
  if (chat.type === "group" || chat.type === "supergroup" || chat.type === "channel") {
@@ -1285,20 +2767,33 @@ var TelegramService = class _TelegramService extends Service {
1285
2767
  );
1286
2768
  owner = foundOwner || null;
1287
2769
  } catch (error) {
1288
- logger3.warn({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId, error: error instanceof Error ? error.message : String(error) }, "Could not get chat administrators");
2770
+ logger4.warn(
2771
+ {
2772
+ src: "plugin:telegram",
2773
+ agentId: this.runtime.agentId,
2774
+ chatId,
2775
+ error: error instanceof Error ? error.message : String(error)
2776
+ },
2777
+ "Could not get chat administrators"
2778
+ );
1289
2779
  }
1290
2780
  }
1291
- let ownerId = userId;
1292
- if (owner) {
1293
- ownerId = createUniqueUuid2(this.runtime, String(owner.user.id));
2781
+ const canonicalOwnerId = getCanonicalOwnerId(this.runtime);
2782
+ let ownerId = canonicalOwnerId ?? userId;
2783
+ if (!canonicalOwnerId && owner) {
2784
+ ownerId = createUniqueUuid2(
2785
+ this.runtime,
2786
+ this.scopedTelegramKey(String(owner.user.id), accountId)
2787
+ );
1294
2788
  }
1295
2789
  const world = {
1296
2790
  id: worldId,
1297
2791
  name: chatTitle,
1298
2792
  agentId: this.runtime.agentId,
1299
- serverId: chatId,
2793
+ messageServerId: chatId,
1300
2794
  metadata: {
1301
2795
  source: "telegram",
2796
+ accountId,
1302
2797
  ...ownerId && { ownership: { ownerId } },
1303
2798
  roles: ownerId ? {
1304
2799
  [ownerId]: Role.OWNER
@@ -1309,27 +2804,35 @@ var TelegramService = class _TelegramService extends Service {
1309
2804
  };
1310
2805
  await this.runtime.ensureWorldExists(world);
1311
2806
  const generalRoom = {
1312
- id: createUniqueUuid2(this.runtime, chatId),
2807
+ id: createUniqueUuid2(
2808
+ this.runtime,
2809
+ this.scopedTelegramKey(chatId, accountId)
2810
+ ),
1313
2811
  name: chatTitle,
1314
2812
  source: "telegram",
1315
2813
  type: channelType,
1316
2814
  channelId: chatId,
1317
2815
  serverId: chatId,
1318
- worldId
2816
+ worldId,
2817
+ metadata: {
2818
+ source: "telegram",
2819
+ accountId,
2820
+ telegram: { accountId, chatId }
2821
+ }
1319
2822
  };
1320
2823
  await this.runtime.ensureRoomExists(generalRoom);
1321
2824
  const rooms = [generalRoom];
1322
2825
  if (chat.type === "supergroup" && chat.is_forum && ctx.message?.message_thread_id) {
1323
- const topicRoom = await this.buildForumTopicRoom(ctx, worldId);
2826
+ const topicRoom = await this.buildForumTopicRoom(ctx, worldId, accountId);
1324
2827
  if (topicRoom) {
1325
2828
  rooms.push(topicRoom);
1326
2829
  await this.runtime.ensureRoomExists(topicRoom);
1327
2830
  }
1328
2831
  }
1329
- const entities = await this.buildStandardizedEntities(chat);
2832
+ const entities = await this.buildStandardizedEntities(chat, accountId);
1330
2833
  if (ctx.from) {
1331
- const senderEntity = this.buildMsgSenderEntity(ctx.from);
1332
- if (senderEntity && senderEntity.id && !entities.some((e) => e.id === senderEntity.id)) {
2834
+ const senderEntity = this.buildMsgSenderEntity(ctx.from, accountId);
2835
+ if (senderEntity?.id && !entities.some((e) => e.id === senderEntity.id)) {
1333
2836
  entities.push(senderEntity);
1334
2837
  this.syncedEntityIds.add(senderEntity.id);
1335
2838
  }
@@ -1337,9 +2840,11 @@ var TelegramService = class _TelegramService extends Service {
1337
2840
  await this.batchProcessEntities(
1338
2841
  entities,
1339
2842
  generalRoom.id,
1340
- generalRoom.channelId,
2843
+ generalRoom.name || generalRoom.channelId || chatId,
2844
+ generalRoom.channelId || chatId,
1341
2845
  generalRoom.type,
1342
- worldId
2846
+ worldId,
2847
+ accountId
1343
2848
  );
1344
2849
  const telegramWorldPayload = {
1345
2850
  runtime: this.runtime,
@@ -1347,18 +2852,25 @@ var TelegramService = class _TelegramService extends Service {
1347
2852
  rooms,
1348
2853
  entities,
1349
2854
  source: "telegram",
2855
+ accountId,
2856
+ metadata: { accountId },
1350
2857
  chat,
1351
- botUsername: this.bot?.botInfo?.username
2858
+ botUsername: this.getAccountState(accountId)?.bot.botInfo?.username
1352
2859
  };
1353
2860
  if (chat.type !== "private") {
1354
- await this.runtime.emitEvent("TELEGRAM_WORLD_JOINED" /* WORLD_JOINED */, telegramWorldPayload);
2861
+ await this.runtime.emitEvent(
2862
+ "TELEGRAM_WORLD_JOINED" /* WORLD_JOINED */,
2863
+ telegramWorldPayload
2864
+ );
1355
2865
  }
1356
2866
  await this.runtime.emitEvent(EventType2.WORLD_JOINED, {
1357
2867
  runtime: this.runtime,
1358
2868
  world,
1359
2869
  rooms,
1360
2870
  entities,
1361
- source: "telegram"
2871
+ source: "telegram",
2872
+ accountId,
2873
+ metadata: { accountId }
1362
2874
  });
1363
2875
  }
1364
2876
  /**
@@ -1372,7 +2884,7 @@ var TelegramService = class _TelegramService extends Service {
1372
2884
  * @returns {Promise<void>}
1373
2885
  * @private
1374
2886
  */
1375
- async batchProcessEntities(entities, roomId, channelId, roomType, worldId) {
2887
+ async batchProcessEntities(entities, roomId, roomName, channelId, roomType, worldId, accountId = this.defaultAccountId) {
1376
2888
  const batchSize = 50;
1377
2889
  for (let i = 0; i < entities.length; i += batchSize) {
1378
2890
  const entityBatch = entities.slice(i, i + batchSize);
@@ -1384,6 +2896,7 @@ var TelegramService = class _TelegramService extends Service {
1384
2896
  await this.runtime.ensureConnection({
1385
2897
  entityId: entity.id,
1386
2898
  roomId,
2899
+ roomName,
1387
2900
  userName: telegramMetadata?.username,
1388
2901
  name: telegramMetadata?.name,
1389
2902
  userId: telegramMetadata?.id,
@@ -1393,11 +2906,28 @@ var TelegramService = class _TelegramService extends Service {
1393
2906
  worldId
1394
2907
  });
1395
2908
  } else {
1396
- logger3.warn({ src: "plugin:telegram", agentId: this.runtime.agentId, entityNames: entity.names }, "Skipping entity sync due to missing ID");
2909
+ logger4.warn(
2910
+ {
2911
+ src: "plugin:telegram",
2912
+ agentId: this.runtime.agentId,
2913
+ accountId,
2914
+ entityNames: entity.names
2915
+ },
2916
+ "Skipping entity sync due to missing ID"
2917
+ );
1397
2918
  }
1398
2919
  } catch (err) {
1399
2920
  const telegramMetadata = entity.metadata?.telegram;
1400
- logger3.warn({ src: "plugin:telegram", agentId: this.runtime.agentId, username: telegramMetadata?.username, error: err instanceof Error ? err.message : String(err) }, "Failed to sync user");
2921
+ logger4.warn(
2922
+ {
2923
+ src: "plugin:telegram",
2924
+ agentId: this.runtime.agentId,
2925
+ accountId,
2926
+ username: telegramMetadata?.username,
2927
+ error: err instanceof Error ? err.message : String(err)
2928
+ },
2929
+ "Failed to sync user"
2930
+ );
1401
2931
  }
1402
2932
  })
1403
2933
  );
@@ -1415,9 +2945,10 @@ var TelegramService = class _TelegramService extends Service {
1415
2945
  * @private
1416
2946
  */
1417
2947
  getChatTypeInfo(chat) {
2948
+ const chatType = chat.type;
1418
2949
  let chatTitle;
1419
2950
  let channelType;
1420
- switch (chat.type) {
2951
+ switch (chatType) {
1421
2952
  case "private":
1422
2953
  chatTitle = `Chat with ${chat.first_name || "Unknown User"}`;
1423
2954
  channelType = ChannelType2.DM;
@@ -1435,8 +2966,7 @@ var TelegramService = class _TelegramService extends Service {
1435
2966
  channelType = ChannelType2.FEED;
1436
2967
  break;
1437
2968
  default:
1438
- chatTitle = "Unknown Chat";
1439
- channelType = ChannelType2.GROUP;
2969
+ throw new Error(`Unrecognized Telegram chat type: ${String(chatType)}`);
1440
2970
  }
1441
2971
  return { chatTitle, channelType };
1442
2972
  }
@@ -1448,37 +2978,50 @@ var TelegramService = class _TelegramService extends Service {
1448
2978
  * @returns {Promise<Entity[]>} Array of standardized Entity objects
1449
2979
  * @private
1450
2980
  */
1451
- async buildStandardizedEntities(chat) {
2981
+ async buildStandardizedEntities(chat, accountId = this.defaultAccountId) {
1452
2982
  const entities = [];
1453
2983
  try {
1454
2984
  if (chat.type === "private" && chat.id) {
1455
- const userId = createUniqueUuid2(this.runtime, chat.id.toString());
2985
+ const userId = createUniqueUuid2(
2986
+ this.runtime,
2987
+ this.scopedTelegramKey(chat.id.toString(), accountId)
2988
+ );
1456
2989
  entities.push({
1457
2990
  id: userId,
1458
2991
  names: [chat.first_name || "Unknown User"],
1459
2992
  agentId: this.runtime.agentId,
1460
2993
  metadata: {
1461
2994
  telegram: {
2995
+ accountId,
1462
2996
  id: chat.id.toString(),
1463
2997
  username: chat.username || "unknown",
1464
2998
  name: chat.first_name || "Unknown User"
1465
2999
  },
1466
- source: "telegram"
3000
+ source: "telegram",
3001
+ accountId
1467
3002
  }
1468
3003
  });
1469
3004
  this.syncedEntityIds.add(userId);
1470
3005
  } else if (chat.type === "group" || chat.type === "supergroup") {
1471
3006
  try {
1472
- const admins = await this.bot?.telegram.getChatAdministrators(chat.id);
3007
+ const admins = await this.getAccountState(
3008
+ accountId
3009
+ )?.bot.telegram.getChatAdministrators(chat.id);
1473
3010
  if (admins && admins.length > 0) {
1474
3011
  for (const admin of admins) {
1475
- const userId = createUniqueUuid2(this.runtime, admin.user.id.toString());
3012
+ const userId = createUniqueUuid2(
3013
+ this.runtime,
3014
+ this.scopedTelegramKey(admin.user.id.toString(), accountId)
3015
+ );
1476
3016
  entities.push({
1477
3017
  id: userId,
1478
- names: [admin.user.first_name || admin.user.username || "Unknown Admin"],
3018
+ names: [
3019
+ admin.user.first_name || admin.user.username || "Unknown Admin"
3020
+ ],
1479
3021
  agentId: this.runtime.agentId,
1480
3022
  metadata: {
1481
3023
  telegram: {
3024
+ accountId,
1482
3025
  id: admin.user.id.toString(),
1483
3026
  username: admin.user.username || "unknown",
1484
3027
  name: admin.user.first_name || "Unknown Admin",
@@ -1486,6 +3029,7 @@ var TelegramService = class _TelegramService extends Service {
1486
3029
  adminTitle: admin.custom_title || (admin.status === "creator" ? "Owner" : "Admin")
1487
3030
  },
1488
3031
  source: "telegram",
3032
+ accountId,
1489
3033
  roles: [admin.status === "creator" ? Role.OWNER : Role.ADMIN]
1490
3034
  }
1491
3035
  });
@@ -1493,11 +3037,26 @@ var TelegramService = class _TelegramService extends Service {
1493
3037
  }
1494
3038
  }
1495
3039
  } catch (error) {
1496
- logger3.warn({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId: chat.id, error: error instanceof Error ? error.message : String(error) }, "Could not fetch administrators");
3040
+ logger4.warn(
3041
+ {
3042
+ src: "plugin:telegram",
3043
+ agentId: this.runtime.agentId,
3044
+ chatId: chat.id,
3045
+ error: error instanceof Error ? error.message : String(error)
3046
+ },
3047
+ "Could not fetch administrators"
3048
+ );
1497
3049
  }
1498
3050
  }
1499
3051
  } catch (error) {
1500
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, error: error instanceof Error ? error.message : String(error) }, "Error building standardized entities");
3052
+ logger4.error(
3053
+ {
3054
+ src: "plugin:telegram",
3055
+ agentId: this.runtime.agentId,
3056
+ error: error instanceof Error ? error.message : String(error)
3057
+ },
3058
+ "Error building standardized entities"
3059
+ );
1501
3060
  }
1502
3061
  return entities;
1503
3062
  }
@@ -1510,13 +3069,20 @@ var TelegramService = class _TelegramService extends Service {
1510
3069
  * @returns {Promise<Room | null>} A Promise that resolves with the room or null if not a topic
1511
3070
  * @private
1512
3071
  */
1513
- async buildForumTopicRoom(ctx, worldId) {
1514
- if (!ctx.chat || !ctx.message?.message_thread_id) return null;
1515
- if (ctx.chat.type !== "supergroup" || !ctx.chat.is_forum) return null;
3072
+ async buildForumTopicRoom(ctx, worldId, accountId = this.defaultAccountId) {
3073
+ if (!ctx.chat || !ctx.message?.message_thread_id) {
3074
+ return null;
3075
+ }
3076
+ if (ctx.chat.type !== "supergroup" || !ctx.chat.is_forum) {
3077
+ return null;
3078
+ }
1516
3079
  const chat = ctx.chat;
1517
3080
  const chatId = chat.id.toString();
1518
3081
  const threadId = ctx.message.message_thread_id.toString();
1519
- const roomId = createUniqueUuid2(this.runtime, `${chatId}-${threadId}`);
3082
+ const roomId = createUniqueUuid2(
3083
+ this.runtime,
3084
+ this.scopedTelegramKey(`${chatId}-${threadId}`, accountId)
3085
+ );
1520
3086
  try {
1521
3087
  const replyMessage = JSON.parse(JSON.stringify(ctx.message));
1522
3088
  let topicName = `Topic #${threadId}`;
@@ -1540,46 +3106,572 @@ var TelegramService = class _TelegramService extends Service {
1540
3106
  serverId: chatId,
1541
3107
  worldId,
1542
3108
  metadata: {
3109
+ source: "telegram",
3110
+ accountId,
1543
3111
  threadId,
1544
3112
  isForumTopic: true,
1545
- parentChatId: chatId
3113
+ parentChatId: chatId,
3114
+ telegram: {
3115
+ accountId,
3116
+ chatId,
3117
+ threadId
3118
+ }
1546
3119
  }
1547
3120
  };
1548
3121
  return room;
1549
3122
  } catch (error) {
1550
- logger3.error({ src: "plugin:telegram", agentId: this.runtime.agentId, chatId, threadId, error: error instanceof Error ? error.message : String(error) }, "Error building forum topic room");
3123
+ logger4.error(
3124
+ {
3125
+ src: "plugin:telegram",
3126
+ agentId: this.runtime.agentId,
3127
+ accountId,
3128
+ chatId,
3129
+ threadId,
3130
+ error: error instanceof Error ? error.message : String(error)
3131
+ },
3132
+ "Error building forum topic room"
3133
+ );
3134
+ return null;
3135
+ }
3136
+ }
3137
+ buildConnectorChatTarget(chat, score = 0.5, threadId, accountId = this.defaultAccountId) {
3138
+ const chatId = chat.id.toString();
3139
+ const roomKey = threadId ? `${chatId}-${threadId}` : chatId;
3140
+ const roomId = createUniqueUuid2(
3141
+ this.runtime,
3142
+ this.scopedTelegramKey(roomKey, accountId)
3143
+ );
3144
+ const label = getTelegramChatDisplayName(chat, chatId);
3145
+ return {
3146
+ target: {
3147
+ source: "telegram",
3148
+ accountId,
3149
+ roomId,
3150
+ channelId: roomKey,
3151
+ threadId: threadId?.toString()
3152
+ },
3153
+ label,
3154
+ kind: threadId ? "thread" : telegramChatKind(chat),
3155
+ description: threadId && "title" in chat ? `Telegram topic ${threadId} in ${chat.title}` : `Telegram ${chat.type}`,
3156
+ score,
3157
+ contexts: ["social", "connectors"],
3158
+ metadata: {
3159
+ accountId,
3160
+ telegramChatId: chatId,
3161
+ telegramThreadId: threadId,
3162
+ telegramChatType: chat.type,
3163
+ username: "username" in chat ? chat.username : void 0,
3164
+ title: "title" in chat ? chat.title : void 0
3165
+ }
3166
+ };
3167
+ }
3168
+ buildConnectorRoomTarget(room, score = 0.5) {
3169
+ if (room.source !== "telegram" || !room.channelId) {
3170
+ return null;
3171
+ }
3172
+ const metadata = room.metadata;
3173
+ const accountId = typeof metadata?.accountId === "string" && metadata.accountId.trim() ? normalizeTelegramAccountId(metadata.accountId) : normalizeTelegramAccountId(this.defaultAccountId);
3174
+ const threadId = typeof metadata?.threadId === "string" ? metadata.threadId : typeof room.channelId === "string" ? parseTelegramTargetParts(room.channelId).threadId?.toString() : void 0;
3175
+ return {
3176
+ target: {
3177
+ source: "telegram",
3178
+ accountId,
3179
+ roomId: room.id,
3180
+ channelId: room.channelId,
3181
+ threadId
3182
+ },
3183
+ label: room.name || room.channelId,
3184
+ kind: threadId ? "thread" : "group",
3185
+ description: threadId ? `Telegram topic ${threadId}` : "Telegram chat room",
3186
+ score,
3187
+ contexts: ["social", "connectors"],
3188
+ metadata: {
3189
+ accountId,
3190
+ telegramChatId: room.channelId,
3191
+ telegramThreadId: threadId,
3192
+ roomName: room.name
3193
+ }
3194
+ };
3195
+ }
3196
+ dedupeConnectorTargets(targets) {
3197
+ const byKey = /* @__PURE__ */ new Map();
3198
+ for (const target of targets) {
3199
+ const key = [
3200
+ target.target.accountId ?? "",
3201
+ target.kind ?? "target",
3202
+ target.target.channelId ?? "",
3203
+ target.target.entityId ?? "",
3204
+ target.target.threadId ?? ""
3205
+ ].join(":");
3206
+ const existing = byKey.get(key);
3207
+ if (!existing || (target.score ?? 0) > (existing.score ?? 0)) {
3208
+ byKey.set(key, target);
3209
+ }
3210
+ }
3211
+ return Array.from(byKey.values()).sort(
3212
+ (a, b) => (b.score ?? 0) - (a.score ?? 0)
3213
+ );
3214
+ }
3215
+ async getTelegramChatForTarget(chatId, accountId = this.defaultAccountId) {
3216
+ const known = this.knownChats.get(this.scopedTelegramKey(String(chatId), accountId)) ?? (normalizeTelegramAccountId(accountId) === DEFAULT_ACCOUNT_ID ? this.knownChats.get(String(chatId)) : void 0);
3217
+ if (known) {
3218
+ return known;
3219
+ }
3220
+ const bot = this.getAccountState(accountId)?.bot ?? this.bot;
3221
+ if (!bot) {
3222
+ return null;
3223
+ }
3224
+ try {
3225
+ const chat = await bot.telegram.getChat(chatId);
3226
+ this.knownChats.set(
3227
+ this.scopedTelegramKey(String(chat.id), accountId),
3228
+ chat
3229
+ );
3230
+ return chat;
3231
+ } catch {
3232
+ return null;
3233
+ }
3234
+ }
3235
+ async resolveConnectorTargets(query, context) {
3236
+ const normalizedQuery = normalizeTelegramConnectorQuery(query);
3237
+ const targets = [];
3238
+ const explicitAccountId = this.resolveAccountIdFromContext(
3239
+ context,
3240
+ context.target
3241
+ );
3242
+ const accountIds = explicitAccountId ? [normalizeTelegramAccountId(explicitAccountId)] : this.getAccountIds();
3243
+ for (const accountId of accountIds) {
3244
+ for (const [key, chat] of this.knownChats.entries()) {
3245
+ if (!this.knownChatKeyMatchesAccount(key, chat, accountId)) {
3246
+ continue;
3247
+ }
3248
+ const score = scoreTelegramConnectorMatch(
3249
+ normalizedQuery,
3250
+ chat.id.toString(),
3251
+ [
3252
+ "title" in chat ? chat.title : void 0,
3253
+ "username" in chat ? chat.username : void 0,
3254
+ "first_name" in chat ? chat.first_name : void 0,
3255
+ "last_name" in chat ? chat.last_name : void 0
3256
+ ]
3257
+ );
3258
+ if (score <= 0) {
3259
+ continue;
3260
+ }
3261
+ targets.push(
3262
+ this.buildConnectorChatTarget(chat, score, void 0, accountId)
3263
+ );
3264
+ }
3265
+ }
3266
+ if (normalizedQuery && (TELEGRAM_CHAT_ID_PATTERN.test(normalizedQuery) || query.trim().startsWith("@"))) {
3267
+ const lookup = TELEGRAM_CHAT_ID_PATTERN.test(normalizedQuery) ? normalizedQuery : query.trim();
3268
+ const accountId = accountIds[0] ?? this.defaultAccountId;
3269
+ const chat = await this.getTelegramChatForTarget(lookup, accountId);
3270
+ if (chat) {
3271
+ targets.push(
3272
+ this.buildConnectorChatTarget(chat, 1, void 0, accountId)
3273
+ );
3274
+ }
3275
+ }
3276
+ const room = context.roomId && typeof context.runtime.getRoom === "function" ? await context.runtime.getRoom(context.roomId) : null;
3277
+ if (room) {
3278
+ const roomTarget = this.buildConnectorRoomTarget(room, 0.6);
3279
+ if (roomTarget) {
3280
+ targets.push(roomTarget);
3281
+ }
3282
+ }
3283
+ return this.dedupeConnectorTargets(targets).slice(0, 25);
3284
+ }
3285
+ async listConnectorRooms(context) {
3286
+ const explicitAccountId = this.resolveAccountIdFromContext(
3287
+ context,
3288
+ context.target
3289
+ );
3290
+ const accountIds = explicitAccountId ? [normalizeTelegramAccountId(explicitAccountId)] : this.getAccountIds();
3291
+ const targets = [];
3292
+ for (const accountId of accountIds) {
3293
+ for (const [key, chat] of this.knownChats.entries()) {
3294
+ if (!this.knownChatKeyMatchesAccount(key, chat, accountId)) {
3295
+ continue;
3296
+ }
3297
+ targets.push(
3298
+ this.buildConnectorChatTarget(chat, 0.5, void 0, accountId)
3299
+ );
3300
+ }
3301
+ }
3302
+ const room = context.roomId && typeof context.runtime.getRoom === "function" ? await context.runtime.getRoom(context.roomId) : null;
3303
+ if (room) {
3304
+ const roomTarget = this.buildConnectorRoomTarget(room, 0.7);
3305
+ if (roomTarget) {
3306
+ targets.push(roomTarget);
3307
+ }
3308
+ }
3309
+ return this.dedupeConnectorTargets(targets).slice(0, 50);
3310
+ }
3311
+ async listRecentConnectorTargets(context) {
3312
+ return this.listConnectorRooms(context);
3313
+ }
3314
+ async fetchConnectorMessages(context, params = {}) {
3315
+ const limit = normalizeConnectorLimit(params.limit);
3316
+ const target = params.target ?? context.target;
3317
+ const accountId = await this.resolveAccountIdForTarget(
3318
+ context.runtime,
3319
+ target,
3320
+ { accountId: context.accountId }
3321
+ );
3322
+ if (target?.roomId) {
3323
+ const memories = await context.runtime.getMemories({
3324
+ tableName: "messages",
3325
+ roomId: target.roomId,
3326
+ limit,
3327
+ orderBy: "createdAt",
3328
+ orderDirection: "desc"
3329
+ });
3330
+ return memories.filter((memory) => {
3331
+ const metadata = memory.metadata;
3332
+ return !metadata?.accountId || metadata.accountId === accountId;
3333
+ });
3334
+ }
3335
+ const targets = (await this.listRecentConnectorTargets(context)).slice(
3336
+ 0,
3337
+ 10
3338
+ );
3339
+ const roomIds = Array.from(
3340
+ new Set(
3341
+ targets.map((candidate) => candidate.target.roomId).filter((roomId) => Boolean(roomId))
3342
+ )
3343
+ );
3344
+ const chunks = await Promise.all(
3345
+ roomIds.map(
3346
+ (roomId) => context.runtime.getMemories({
3347
+ tableName: "messages",
3348
+ roomId,
3349
+ limit,
3350
+ orderBy: "createdAt",
3351
+ orderDirection: "desc"
3352
+ })
3353
+ )
3354
+ );
3355
+ return chunks.flat().filter((memory) => {
3356
+ const metadata = memory.metadata;
3357
+ return !metadata?.accountId || metadata.accountId === accountId;
3358
+ }).sort((left, right) => (right.createdAt ?? 0) - (left.createdAt ?? 0)).slice(0, limit);
3359
+ }
3360
+ async searchConnectorMessages(context, params) {
3361
+ const limit = normalizeConnectorLimit(params.limit);
3362
+ const messages = await this.fetchConnectorMessages(context, {
3363
+ target: params.target ?? context.target,
3364
+ limit: Math.max(limit, 100)
3365
+ });
3366
+ return filterMemoriesByQuery(messages, params.query, limit);
3367
+ }
3368
+ async getConnectorChatContext(target, context) {
3369
+ const room = target.roomId && typeof context.runtime.getRoom === "function" ? await context.runtime.getRoom(target.roomId) : null;
3370
+ const accountId = await this.resolveAccountIdForTarget(
3371
+ context.runtime,
3372
+ target,
3373
+ {
3374
+ accountId: context.accountId,
3375
+ roomId: target.roomId ?? context.roomId
3376
+ }
3377
+ );
3378
+ const channelId = target.channelId ?? room?.channelId;
3379
+ if (!channelId) {
3380
+ return null;
3381
+ }
3382
+ const parts = parseTelegramTargetParts(channelId, target.threadId);
3383
+ const chat = await this.getTelegramChatForTarget(parts.chatId, accountId);
3384
+ const roomId = target.roomId ?? room?.id ?? createUniqueUuid2(
3385
+ this.runtime,
3386
+ this.scopedTelegramKey(
3387
+ parts.threadId ? `${parts.chatId}-${parts.threadId}` : String(parts.chatId),
3388
+ accountId
3389
+ )
3390
+ );
3391
+ const memories = await context.runtime.getMemories({
3392
+ tableName: "messages",
3393
+ roomId,
3394
+ count: 10,
3395
+ orderBy: "createdAt",
3396
+ orderDirection: "desc"
3397
+ });
3398
+ const recentMessages = memories.slice().reverse().map((memory) => ({
3399
+ entityId: memory.entityId,
3400
+ name: typeof memory.content?.name === "string" ? memory.content.name : void 0,
3401
+ text: memory.content?.text ?? "",
3402
+ timestamp: memory.createdAt,
3403
+ metadata: {
3404
+ memoryId: memory.id,
3405
+ accountId,
3406
+ source: memory.content?.source
3407
+ }
3408
+ })).filter((message) => message.text.trim().length > 0);
3409
+ return {
3410
+ target: {
3411
+ source: "telegram",
3412
+ accountId,
3413
+ roomId,
3414
+ channelId,
3415
+ threadId: parts.threadId?.toString()
3416
+ },
3417
+ label: room?.name || (chat ? getTelegramChatDisplayName(chat, String(parts.chatId)) : channelId),
3418
+ summary: chat ? `Telegram ${chat.type}` : void 0,
3419
+ recentMessages,
3420
+ metadata: {
3421
+ accountId,
3422
+ telegramChatId: String(parts.chatId),
3423
+ telegramThreadId: parts.threadId,
3424
+ telegramChatType: chat?.type
3425
+ }
3426
+ };
3427
+ }
3428
+ async getConnectorUserContext(entityId, context) {
3429
+ const accountId = normalizeTelegramAccountId(
3430
+ context.target?.accountId ?? context.accountId ?? context.account?.accountId ?? this.defaultAccountId
3431
+ );
3432
+ const entity = typeof context.runtime.getEntityById === "function" ? await context.runtime.getEntityById(String(entityId)) : null;
3433
+ const telegramMetadata = entity?.metadata?.telegram && typeof entity.metadata.telegram === "object" ? entity.metadata.telegram : null;
3434
+ const telegramId = typeof telegramMetadata?.id === "number" || typeof telegramMetadata?.id === "string" ? telegramMetadata.id : TELEGRAM_CHAT_ID_PATTERN.test(String(entityId)) ? entityId : null;
3435
+ if (!telegramId) {
1551
3436
  return null;
1552
3437
  }
3438
+ const chat = await this.getTelegramChatForTarget(telegramId, accountId);
3439
+ const aliases = [
3440
+ entity?.names?.[0],
3441
+ chat && "username" in chat ? chat.username : void 0,
3442
+ chat && "first_name" in chat ? chat.first_name : void 0,
3443
+ chat && "last_name" in chat ? chat.last_name : void 0
3444
+ ].filter((value) => Boolean(value));
3445
+ return {
3446
+ entityId,
3447
+ label: aliases[0] ?? String(telegramId),
3448
+ aliases,
3449
+ handles: { telegram: String(telegramId) },
3450
+ metadata: {
3451
+ accountId,
3452
+ telegramId: String(telegramId),
3453
+ telegramChatType: chat?.type,
3454
+ username: chat && "username" in chat ? chat.username : void 0
3455
+ }
3456
+ };
1553
3457
  }
1554
3458
  static registerSendHandlers(runtime, serviceInstance) {
1555
- if (serviceInstance && serviceInstance.bot) {
1556
- runtime.registerSendHandler(
1557
- "telegram",
1558
- serviceInstance.handleSendMessage.bind(serviceInstance)
3459
+ if (serviceInstance?.bot) {
3460
+ const registerConnector = (accountId) => {
3461
+ const normalizedAccountId = accountId ? normalizeTelegramAccountId(accountId) : void 0;
3462
+ const state = normalizedAccountId ? serviceInstance.getAccountState(normalizedAccountId) : serviceInstance.getDefaultAccountState();
3463
+ const sendHandler = async (handlerRuntime, target, content) => {
3464
+ await serviceInstance.handleSendMessage(
3465
+ handlerRuntime,
3466
+ normalizedAccountId && !target.accountId ? { ...target, accountId: normalizedAccountId } : target,
3467
+ content
3468
+ );
3469
+ return void 0;
3470
+ };
3471
+ const withContextAccount = (context) => normalizedAccountId && !context.accountId ? {
3472
+ ...context,
3473
+ accountId: normalizedAccountId,
3474
+ account: context.account ?? {
3475
+ source: "telegram",
3476
+ accountId: normalizedAccountId,
3477
+ label: state?.account.name ?? normalizedAccountId
3478
+ }
3479
+ } : context;
3480
+ const registration = {
3481
+ source: "telegram",
3482
+ ...normalizedAccountId ? { accountId: normalizedAccountId } : {},
3483
+ ...normalizedAccountId ? {
3484
+ account: {
3485
+ source: "telegram",
3486
+ accountId: normalizedAccountId,
3487
+ label: state?.account.name ?? normalizedAccountId,
3488
+ authMethod: "BOT_TOKEN"
3489
+ }
3490
+ } : {},
3491
+ label: state?.account.name ? `Telegram (${state.account.name})` : "Telegram",
3492
+ description: "Telegram connector for sending messages to chats, topics, and users.",
3493
+ capabilities: [...TELEGRAM_CONNECTOR_CAPABILITIES],
3494
+ supportedTargetKinds: ["channel", "group", "thread", "user"],
3495
+ contexts: [...TELEGRAM_CONNECTOR_CONTEXTS],
3496
+ metadata: {
3497
+ service: TELEGRAM_SERVICE_NAME,
3498
+ ...normalizedAccountId ? { accountId: normalizedAccountId } : {}
3499
+ },
3500
+ resolveTargets: (query, context) => serviceInstance.resolveConnectorTargets(
3501
+ query,
3502
+ withContextAccount(context)
3503
+ ),
3504
+ listRecentTargets: (context) => serviceInstance.listRecentConnectorTargets(
3505
+ withContextAccount(context)
3506
+ ),
3507
+ listRooms: (context) => serviceInstance.listConnectorRooms(withContextAccount(context)),
3508
+ fetchMessages: (context, params) => {
3509
+ const readParams = params ?? {};
3510
+ return serviceInstance.fetchConnectorMessages(
3511
+ withContextAccount(context),
3512
+ {
3513
+ ...readParams,
3514
+ target: normalizedAccountId && readParams.target && !readParams.target.accountId ? {
3515
+ ...readParams.target,
3516
+ accountId: normalizedAccountId
3517
+ } : readParams.target
3518
+ }
3519
+ );
3520
+ },
3521
+ searchMessages: (context, params) => serviceInstance.searchConnectorMessages(
3522
+ withContextAccount(context),
3523
+ {
3524
+ ...params,
3525
+ target: normalizedAccountId && params.target && !params.target.accountId ? {
3526
+ ...params.target,
3527
+ accountId: normalizedAccountId
3528
+ } : params.target
3529
+ }
3530
+ ),
3531
+ getChatContext: (target, context) => serviceInstance.getConnectorChatContext(
3532
+ normalizedAccountId && !target.accountId ? { ...target, accountId: normalizedAccountId } : target,
3533
+ withContextAccount(context)
3534
+ ),
3535
+ getUserContext: (entityId, context) => serviceInstance.getConnectorUserContext(
3536
+ entityId,
3537
+ withContextAccount(context)
3538
+ ),
3539
+ getUser: async (handlerRuntime, params) => {
3540
+ const userParams = params;
3541
+ const entityId = String(
3542
+ userParams.entityId ?? userParams.userId ?? userParams.username ?? userParams.handle ?? ""
3543
+ ).trim();
3544
+ if (!entityId) {
3545
+ return null;
3546
+ }
3547
+ const entity = typeof handlerRuntime.getEntityById === "function" ? await handlerRuntime.getEntityById(entityId).catch(() => null) : null;
3548
+ if (entity) {
3549
+ return entity;
3550
+ }
3551
+ const context = await serviceInstance.getConnectorUserContext(
3552
+ entityId,
3553
+ {
3554
+ runtime: handlerRuntime,
3555
+ accountId: normalizedAccountId
3556
+ }
3557
+ );
3558
+ if (!context) {
3559
+ return null;
3560
+ }
3561
+ return {
3562
+ id: createUniqueUuid2(
3563
+ handlerRuntime,
3564
+ serviceInstance.scopedTelegramKey(
3565
+ `telegram:${context.handles?.telegram ?? entityId}`,
3566
+ normalizedAccountId
3567
+ )
3568
+ ),
3569
+ names: context.aliases?.length ? context.aliases : [context.label ?? entityId],
3570
+ agentId: handlerRuntime.agentId,
3571
+ metadata: {
3572
+ ...context.metadata,
3573
+ ...normalizedAccountId ? { accountId: normalizedAccountId } : {}
3574
+ }
3575
+ };
3576
+ },
3577
+ sendHandler
3578
+ };
3579
+ runtime.registerMessageConnector(registration);
3580
+ };
3581
+ if (typeof runtime.registerMessageConnector === "function") {
3582
+ registerConnector();
3583
+ for (const accountId of serviceInstance.getAccountIds()) {
3584
+ registerConnector(accountId);
3585
+ }
3586
+ } else {
3587
+ runtime.registerSendHandler(
3588
+ "telegram",
3589
+ serviceInstance.handleSendMessage.bind(serviceInstance)
3590
+ );
3591
+ }
3592
+ logger4.info(
3593
+ { src: "plugin:telegram", agentId: runtime.agentId },
3594
+ "Registered Telegram message connector"
1559
3595
  );
1560
- logger3.info({ src: "plugin:telegram", agentId: runtime.agentId }, "Registered send handler");
1561
3596
  } else {
1562
- logger3.warn({ src: "plugin:telegram", agentId: runtime.agentId }, "Cannot register send handler, bot not initialized");
3597
+ logger4.warn(
3598
+ { src: "plugin:telegram", agentId: runtime.agentId },
3599
+ "Cannot register send handler, bot not initialized"
3600
+ );
1563
3601
  }
1564
3602
  }
1565
3603
  async handleSendMessage(runtime, target, content) {
1566
- if (!this.bot || !this.messageManager) {
1567
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId }, "Bot not initialized, cannot send messages");
1568
- throw new Error("Telegram bot is not initialized. Please provide TELEGRAM_BOT_TOKEN.");
3604
+ const accountId = await this.resolveAccountIdForTarget(runtime, target);
3605
+ const accountState = this.getAccountState(accountId);
3606
+ const messageManager = accountState?.messageManager ?? this.messageManager;
3607
+ const bot = accountState?.bot ?? this.bot;
3608
+ if (!bot || !messageManager) {
3609
+ logger4.error(
3610
+ { src: "plugin:telegram", agentId: runtime.agentId, accountId },
3611
+ "Bot not initialized, cannot send messages"
3612
+ );
3613
+ throw new Error(
3614
+ "Telegram bot is not initialized. Please provide TELEGRAM_BOT_TOKEN."
3615
+ );
1569
3616
  }
1570
3617
  let chatId;
3618
+ let threadId;
1571
3619
  if (target.channelId) {
1572
- chatId = target.channelId;
3620
+ const parts = parseTelegramTargetParts(target.channelId, target.threadId);
3621
+ chatId = parts.chatId;
3622
+ threadId = parts.threadId;
1573
3623
  } else if (target.roomId) {
1574
3624
  const room = await runtime.getRoom(target.roomId);
1575
- chatId = room?.channelId;
1576
- if (!chatId)
1577
- throw new Error(`Could not resolve Telegram chat ID from roomId ${target.roomId}`);
3625
+ const metadata = room?.metadata;
3626
+ const metadataThreadId = typeof metadata?.threadId === "string" ? metadata.threadId : void 0;
3627
+ if (room?.channelId) {
3628
+ const parts = parseTelegramTargetParts(
3629
+ room.channelId,
3630
+ metadataThreadId
3631
+ );
3632
+ chatId = parts.chatId;
3633
+ threadId = parts.threadId;
3634
+ }
3635
+ if (!chatId) {
3636
+ throw new Error(
3637
+ `Could not resolve Telegram chat ID from roomId ${target.roomId}`
3638
+ );
3639
+ }
1578
3640
  } else if (target.entityId) {
1579
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId, entityId: target.entityId }, "Sending DMs via entityId not implemented");
1580
- throw new Error("Sending DMs via entityId is not yet supported for Telegram.");
3641
+ const entity = await runtime.getEntityById(target.entityId);
3642
+ if (!entity) {
3643
+ throw new Error(`Entity ${target.entityId} not found`);
3644
+ }
3645
+ const telegramMeta = entity.metadata?.telegram;
3646
+ const entityAccountId = typeof entity.metadata?.accountId === "string" ? entity.metadata.accountId : typeof telegramMeta?.accountId === "string" ? telegramMeta.accountId : void 0;
3647
+ if (entityAccountId && normalizeTelegramAccountId(entityAccountId) !== accountId) {
3648
+ throw new Error(
3649
+ `Entity ${target.entityId} is linked to Telegram account ${entityAccountId}, not ${accountId}`
3650
+ );
3651
+ }
3652
+ const telegramId = telegramMeta?.id;
3653
+ if (!telegramId) {
3654
+ logger4.error(
3655
+ {
3656
+ src: "plugin:telegram",
3657
+ agentId: runtime.agentId,
3658
+ accountId,
3659
+ entityId: target.entityId
3660
+ },
3661
+ "Entity has no telegram.id in metadata \u2014 cannot send DM without Telegram user ID"
3662
+ );
3663
+ throw new Error(
3664
+ `Entity ${target.entityId} has no telegram.id in metadata \u2014 cannot send DM without Telegram user ID`
3665
+ );
3666
+ }
3667
+ chatId = telegramId;
3668
+ if (target.threadId && /^\d+$/.test(target.threadId)) {
3669
+ threadId = Number.parseInt(target.threadId, 10);
3670
+ }
1581
3671
  } else {
1582
- throw new Error("Telegram SendHandler requires channelId, roomId, or entityId.");
3672
+ throw new Error(
3673
+ "Telegram SendHandler requires channelId, roomId, or entityId."
3674
+ );
1583
3675
  }
1584
3676
  if (!chatId) {
1585
3677
  throw new Error(
@@ -1587,17 +3679,189 @@ var TelegramService = class _TelegramService extends Service {
1587
3679
  );
1588
3680
  }
1589
3681
  try {
1590
- await this.messageManager.sendMessage(chatId, content);
1591
- logger3.info({ src: "plugin:telegram", agentId: runtime.agentId, chatId }, "Message sent");
3682
+ await messageManager.sendMessage(
3683
+ chatId,
3684
+ {
3685
+ ...content,
3686
+ metadata: {
3687
+ ...content.metadata && typeof content.metadata === "object" ? content.metadata : {},
3688
+ accountId
3689
+ }
3690
+ },
3691
+ void 0,
3692
+ threadId
3693
+ );
3694
+ logger4.info(
3695
+ {
3696
+ src: "plugin:telegram",
3697
+ agentId: runtime.agentId,
3698
+ accountId,
3699
+ chatId,
3700
+ threadId
3701
+ },
3702
+ "Message sent"
3703
+ );
1592
3704
  } catch (error) {
1593
- logger3.error({ src: "plugin:telegram", agentId: runtime.agentId, chatId, error: error instanceof Error ? error.message : String(error) }, "Error sending message");
3705
+ logger4.error(
3706
+ {
3707
+ src: "plugin:telegram",
3708
+ agentId: runtime.agentId,
3709
+ accountId,
3710
+ chatId,
3711
+ error: error instanceof Error ? error.message : String(error)
3712
+ },
3713
+ "Error sending message"
3714
+ );
1594
3715
  throw error;
1595
3716
  }
1596
3717
  }
1597
3718
  };
1598
3719
 
3720
+ // src/setup-routes.ts
3721
+ import { logger as logger5 } from "@elizaos/core";
3722
+ var TELEGRAM_API_BASE = "https://api.telegram.org";
3723
+ function isConnectorSetupService2(service) {
3724
+ if (!service || typeof service !== "object") {
3725
+ return false;
3726
+ }
3727
+ const candidate = service;
3728
+ return typeof candidate.getConfig === "function" && typeof candidate.updateConfig === "function" && typeof candidate.persistConfig === "function" && typeof candidate.registerEscalationChannel === "function" && typeof candidate.setOwnerContact === "function";
3729
+ }
3730
+ function getSetupService2(runtime) {
3731
+ const service = runtime.getService("connector-setup");
3732
+ return isConnectorSetupService2(service) ? service : null;
3733
+ }
3734
+ async function readJsonBody(req) {
3735
+ return req.body ?? null;
3736
+ }
3737
+ async function handleValidateToken(req, res, runtime) {
3738
+ const body = await readJsonBody(req);
3739
+ const token = typeof body?.token === "string" ? body.token.trim() : "";
3740
+ if (!token) {
3741
+ res.status(200).json({ ok: false, error: "token is required" });
3742
+ return;
3743
+ }
3744
+ if (!/^\d+:[A-Za-z0-9_-]{30,}$/.test(token)) {
3745
+ res.status(200).json({
3746
+ ok: false,
3747
+ error: "Token format invalid. Expected format: 123456:ABC-DEF..."
3748
+ });
3749
+ return;
3750
+ }
3751
+ try {
3752
+ const apiRes = await fetch(`${TELEGRAM_API_BASE}/bot${token}/getMe`, {
3753
+ signal: AbortSignal.timeout(1e4)
3754
+ });
3755
+ if (!apiRes.ok) {
3756
+ res.status(200).json({
3757
+ ok: false,
3758
+ error: `Telegram API returned ${apiRes.status}. Check that the token is correct.`
3759
+ });
3760
+ return;
3761
+ }
3762
+ const data = await apiRes.json();
3763
+ if (!data.ok || !data.result) {
3764
+ res.status(200).json({
3765
+ ok: false,
3766
+ error: "Telegram API returned unexpected response"
3767
+ });
3768
+ return;
3769
+ }
3770
+ const bot = data.result;
3771
+ const setupService = getSetupService2(runtime);
3772
+ if (setupService) {
3773
+ setupService.updateConfig((config) => {
3774
+ if (!config.connectors) {
3775
+ config.connectors = {};
3776
+ }
3777
+ const connectors = config.connectors;
3778
+ if (!connectors.telegram || typeof connectors.telegram !== "object") {
3779
+ connectors.telegram = {};
3780
+ }
3781
+ connectors.telegram.botToken = token;
3782
+ });
3783
+ setupService.setOwnerContact({
3784
+ source: "telegram",
3785
+ channelId: String(bot.id)
3786
+ });
3787
+ setupService.registerEscalationChannel("telegram");
3788
+ } else {
3789
+ logger5.warn(
3790
+ "[telegram-setup] connector-setup service not available \u2014 token saved to runtime only"
3791
+ );
3792
+ }
3793
+ res.status(200).json({
3794
+ ok: true,
3795
+ bot: {
3796
+ id: bot.id,
3797
+ username: bot.username,
3798
+ firstName: bot.first_name
3799
+ }
3800
+ });
3801
+ } catch (err) {
3802
+ const message = err instanceof Error ? err.message : String(err);
3803
+ res.status(200).json({
3804
+ ok: false,
3805
+ error: `Failed to reach Telegram API: ${message}`
3806
+ });
3807
+ }
3808
+ }
3809
+ async function handleStatus2(_req, res, runtime) {
3810
+ const setupService = getSetupService2(runtime);
3811
+ let hasToken = false;
3812
+ if (setupService) {
3813
+ const config = setupService.getConfig();
3814
+ const connectors = config.connectors ?? {};
3815
+ const tgConfig = connectors.telegram;
3816
+ hasToken = Boolean(tgConfig?.botToken);
3817
+ }
3818
+ if (!hasToken) {
3819
+ hasToken = Boolean(runtime.getSetting("TELEGRAM_BOT_TOKEN"));
3820
+ }
3821
+ const service = runtime.getService("telegram");
3822
+ const connected = Boolean(service);
3823
+ res.status(200).json({
3824
+ available: true,
3825
+ hasToken,
3826
+ connected
3827
+ });
3828
+ }
3829
+ async function handleDisconnect2(_req, res, runtime) {
3830
+ const setupService = getSetupService2(runtime);
3831
+ if (setupService) {
3832
+ setupService.updateConfig((config) => {
3833
+ const connectors = config.connectors ?? {};
3834
+ const tgConfig = connectors.telegram;
3835
+ if (tgConfig) {
3836
+ delete tgConfig.botToken;
3837
+ }
3838
+ });
3839
+ }
3840
+ res.status(200).json({ ok: true });
3841
+ }
3842
+ var telegramSetupRoutes = [
3843
+ {
3844
+ type: "POST",
3845
+ path: "/api/telegram-setup/validate-token",
3846
+ handler: handleValidateToken,
3847
+ rawPath: true
3848
+ },
3849
+ {
3850
+ type: "GET",
3851
+ path: "/api/telegram-setup/status",
3852
+ handler: handleStatus2,
3853
+ rawPath: true
3854
+ },
3855
+ {
3856
+ type: "POST",
3857
+ path: "/api/telegram-setup/disconnect",
3858
+ handler: handleDisconnect2,
3859
+ rawPath: true
3860
+ }
3861
+ ];
3862
+
1599
3863
  // src/tests.ts
1600
- import { logger as logger4 } from "@elizaos/core";
3864
+ import { logger as logger6 } from "@elizaos/core";
1601
3865
  var TEST_IMAGE_URL = "https://github.com/elizaOS/awesome-eliza/blob/main/assets/eliza-logo.jpg?raw=true";
1602
3866
  var TelegramTestSuite = class {
1603
3867
  name = "telegram";
@@ -1666,7 +3930,7 @@ var TelegramTestSuite = class {
1666
3930
  throw new Error("Bot is not initialized.");
1667
3931
  }
1668
3932
  const chat = await this.bot.telegram.getChat(chatId);
1669
- logger4.debug({ src: "plugin:telegram", chatId }, "Fetched real chat");
3933
+ logger6.debug({ src: "plugin:telegram", chatId }, "Fetched real chat");
1670
3934
  return chat;
1671
3935
  } catch (error) {
1672
3936
  throw new Error(`Error fetching real Telegram chat: ${error}`);
@@ -1674,29 +3938,41 @@ var TelegramTestSuite = class {
1674
3938
  }
1675
3939
  async testCreatingTelegramBot(runtime) {
1676
3940
  this.telegramClient = runtime.getService("telegram");
1677
- if (!this.telegramClient || !this.telegramClient.messageManager) {
3941
+ if (!this.telegramClient?.messageManager) {
1678
3942
  throw new Error(
1679
3943
  "Telegram service or message manager not initialized - check TELEGRAM_BOT_TOKEN"
1680
3944
  );
1681
3945
  }
1682
3946
  this.bot = this.telegramClient.messageManager.bot;
1683
3947
  this.messageManager = this.telegramClient.messageManager;
1684
- logger4.debug({ src: "plugin:telegram" }, "Telegram bot initialized successfully");
3948
+ logger6.debug(
3949
+ { src: "plugin:telegram" },
3950
+ "Telegram bot initialized successfully"
3951
+ );
1685
3952
  }
1686
3953
  async testSendingTextMessage(runtime) {
1687
3954
  try {
1688
- if (!this.bot) throw new Error("Bot not initialized.");
3955
+ if (!this.bot) {
3956
+ throw new Error("Bot not initialized.");
3957
+ }
1689
3958
  const chatId = this.validateChatId(runtime);
1690
3959
  await this.bot.telegram.sendMessage(chatId, "Testing Telegram message!");
1691
- logger4.debug({ src: "plugin:telegram", chatId }, "Message sent successfully");
3960
+ logger6.debug(
3961
+ { src: "plugin:telegram", chatId },
3962
+ "Message sent successfully"
3963
+ );
1692
3964
  } catch (error) {
1693
3965
  throw new Error(`Error sending Telegram message: ${error}`);
1694
3966
  }
1695
3967
  }
1696
3968
  async testSendingMessageWithAttachment(runtime) {
1697
3969
  try {
1698
- if (!this.messageManager) throw new Error("MessageManager not initialized.");
1699
- if (!this.bot) throw new Error("Bot not initialized.");
3970
+ if (!this.messageManager) {
3971
+ throw new Error("MessageManager not initialized.");
3972
+ }
3973
+ if (!this.bot) {
3974
+ throw new Error("Bot not initialized.");
3975
+ }
1700
3976
  const chat = await this.getChatInfo(runtime);
1701
3977
  const mockContext = {
1702
3978
  chat,
@@ -1721,15 +3997,24 @@ var TelegramTestSuite = class {
1721
3997
  mockContext,
1722
3998
  messageContent
1723
3999
  );
1724
- logger4.success({ src: "plugin:telegram" }, "Message with image attachment sent successfully");
4000
+ logger6.success(
4001
+ { src: "plugin:telegram" },
4002
+ "Message with image attachment sent successfully"
4003
+ );
1725
4004
  } catch (error) {
1726
- throw new Error(`Error sending Telegram message with attachment: ${error}`);
4005
+ throw new Error(
4006
+ `Error sending Telegram message with attachment: ${error}`
4007
+ );
1727
4008
  }
1728
4009
  }
1729
4010
  async testHandlingMessage(runtime) {
1730
4011
  try {
1731
- if (!this.bot) throw new Error("Bot not initialized.");
1732
- if (!this.messageManager) throw new Error("MessageManager not initialized.");
4012
+ if (!this.bot) {
4013
+ throw new Error("Bot not initialized.");
4014
+ }
4015
+ if (!this.messageManager) {
4016
+ throw new Error("MessageManager not initialized.");
4017
+ }
1733
4018
  const chat = await this.getChatInfo(runtime);
1734
4019
  const mockContext = {
1735
4020
  chat,
@@ -1741,7 +4026,7 @@ var TelegramTestSuite = class {
1741
4026
  last_name: "User"
1742
4027
  },
1743
4028
  message: {
1744
- message_id: void 0,
4029
+ message_id: 12345,
1745
4030
  text: `@${this.bot.botInfo?.username}! Hello!`,
1746
4031
  date: Math.floor(Date.now() / 1e3),
1747
4032
  chat
@@ -1759,8 +4044,12 @@ var TelegramTestSuite = class {
1759
4044
  }
1760
4045
  async testProcessingImages(runtime) {
1761
4046
  try {
1762
- if (!this.bot) throw new Error("Bot not initialized.");
1763
- if (!this.messageManager) throw new Error("MessageManager not initialized.");
4047
+ if (!this.bot) {
4048
+ throw new Error("Bot not initialized.");
4049
+ }
4050
+ if (!this.messageManager) {
4051
+ throw new Error("MessageManager not initialized.");
4052
+ }
1764
4053
  const chatId = this.validateChatId(runtime);
1765
4054
  const fileId = await this.getFileId(String(chatId), TEST_IMAGE_URL);
1766
4055
  const mockMessage = {
@@ -1777,12 +4066,19 @@ var TelegramTestSuite = class {
1777
4066
  ],
1778
4067
  text: `@${this.bot.botInfo?.username}!`
1779
4068
  };
1780
- const result = await this.messageManager.processImage(mockMessage);
1781
- if (!result || !result.description) {
1782
- throw new Error("Error processing Telegram image or description not found");
4069
+ const result = await this.messageManager.processImage(
4070
+ mockMessage
4071
+ );
4072
+ if (!result?.description) {
4073
+ throw new Error(
4074
+ "Error processing Telegram image or description not found"
4075
+ );
1783
4076
  }
1784
4077
  const { description } = result;
1785
- logger4.debug({ src: "plugin:telegram", description }, "Processing Telegram image successfully");
4078
+ logger6.debug(
4079
+ { src: "plugin:telegram", description },
4080
+ "Processing Telegram image successfully"
4081
+ );
1786
4082
  } catch (error) {
1787
4083
  throw new Error(`Error processing Telegram image: ${error}`);
1788
4084
  }
@@ -1793,12 +4089,19 @@ var TelegramTestSuite = class {
1793
4089
  throw new Error("Bot is not initialized.");
1794
4090
  }
1795
4091
  const message = await this.bot.telegram.sendPhoto(chatId, imageUrl);
1796
- if (!message.photo || message.photo.length === 0) {
4092
+ if (message.photo.length === 0) {
1797
4093
  throw new Error("No photo received in the message response.");
1798
4094
  }
1799
4095
  return message.photo[message.photo.length - 1].file_id;
1800
4096
  } catch (error) {
1801
- logger4.error({ src: "plugin:telegram", chatId, error: error instanceof Error ? error.message : String(error) }, "Error sending image");
4097
+ logger6.error(
4098
+ {
4099
+ src: "plugin:telegram",
4100
+ chatId,
4101
+ error: error instanceof Error ? error.message : String(error)
4102
+ },
4103
+ "Error sending image"
4104
+ );
1802
4105
  throw error;
1803
4106
  }
1804
4107
  }
@@ -1808,13 +4111,57 @@ var TelegramTestSuite = class {
1808
4111
  var telegramPlugin = {
1809
4112
  name: TELEGRAM_SERVICE_NAME,
1810
4113
  description: "Telegram client plugin",
1811
- services: [TelegramService],
1812
- tests: [new TelegramTestSuite()]
4114
+ // TelegramService must come before TelegramOwnerPairingServiceImpl so the
4115
+ // bot instance exists when the pairing service registers its command.
4116
+ services: [TelegramService, TelegramOwnerPairingServiceImpl],
4117
+ routes: [...telegramSetupRoutes, ...telegramAccountRoutes],
4118
+ tests: [new TelegramTestSuite()],
4119
+ // Self-declared auto-enable: activate when the "telegram" connector is
4120
+ // configured in eliza.json / eliza.json. The hardcoded CONNECTOR_PLUGINS
4121
+ // map in plugin-auto-enable.ts still serves as a fallback.
4122
+ autoEnable: {
4123
+ connectorKeys: ["telegram"]
4124
+ },
4125
+ init: async (_config, runtime) => {
4126
+ try {
4127
+ const manager = getConnectorAccountManager(runtime);
4128
+ manager.registerProvider(createTelegramConnectorAccountProvider(runtime));
4129
+ } catch (err) {
4130
+ logger7.warn(
4131
+ {
4132
+ src: "plugin:telegram",
4133
+ err: err instanceof Error ? err.message : String(err)
4134
+ },
4135
+ "Failed to register Telegram provider with ConnectorAccountManager"
4136
+ );
4137
+ }
4138
+ }
1813
4139
  };
1814
4140
  var index_default = telegramPlugin;
1815
4141
  export {
4142
+ DEFAULT_ACCOUNT_ID,
1816
4143
  MessageManager,
4144
+ TELEGRAM_OWNER_PAIRING_SERVICE_TYPE,
4145
+ TelegramAccountAuthSession,
4146
+ TelegramOwnerPairingServiceImpl,
1817
4147
  TelegramService,
1818
- index_default as default
4148
+ clearTelegramAccountAuthState,
4149
+ clearTelegramAccountSession,
4150
+ createTelegramConnectorAccountProvider,
4151
+ index_default as default,
4152
+ defaultTelegramAccountDeviceModel,
4153
+ defaultTelegramAccountSystemVersion,
4154
+ getTelegramMultiAccountConfig,
4155
+ listEnabledTelegramAccounts,
4156
+ listTelegramAccountIds,
4157
+ loadTelegramAccountSessionString,
4158
+ normalizeTelegramAccountId,
4159
+ resolveDefaultTelegramAccountId,
4160
+ resolveTelegramAccount,
4161
+ resolveTelegramAccountSessionFile,
4162
+ saveTelegramAccountSessionString,
4163
+ stopTelegramAccountAuthSession,
4164
+ telegramAccountAuthStateExists,
4165
+ telegramAccountSessionExists
1819
4166
  };
1820
4167
  //# sourceMappingURL=index.js.map