@mastra/telegram 0.1.3 → 0.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -19375,7 +19375,7 @@ function isUint8Array(value) {
19375
19375
  return Boolean(value && typeof value === "object" && "byteLength" in value && "byteOffset" in value);
19376
19376
  }
19377
19377
  //#endregion
19378
- //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/bf8128214e5ca45222a909d8e82dc4a6bbc779eb9b510d06add2841f98f9c957/node_modules/chat/dist/chunk-VB76CUI4.js
19378
+ //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/812501c7a15f847e73b05ce99c81d2d9c3310ee4f208ad61509a2d1b4aae4089/node_modules/chat/dist/chunk-VB76CUI4.js
19379
19379
  function isListNode(node) {
19380
19380
  return node.type === "list";
19381
19381
  }
@@ -20276,7 +20276,7 @@ var vn = (n, r) => {
20276
20276
  };
20277
20277
  var $e = vn;
20278
20278
  //#endregion
20279
- //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/bf8128214e5ca45222a909d8e82dc4a6bbc779eb9b510d06add2841f98f9c957/node_modules/chat/dist/chunk-BKACWYIW.js
20279
+ //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/812501c7a15f847e73b05ce99c81d2d9c3310ee4f208ad61509a2d1b4aae4089/node_modules/chat/dist/chunk-BKACWYIW.js
20280
20280
  var adapterMap = /* @__PURE__ */ new WeakMap();
20281
20281
  var Message = class _Message {
20282
20282
  /** Unique message ID */
@@ -20687,7 +20687,7 @@ function wrapTablesForAppend(text2, closeFences = false) {
20687
20687
  new AbortController().signal;
20688
20688
  new async_hooks.AsyncLocalStorage();
20689
20689
  //#endregion
20690
- //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/bf8128214e5ca45222a909d8e82dc4a6bbc779eb9b510d06add2841f98f9c957/node_modules/chat/dist/index.js
20690
+ //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/chat/4.40.0/812501c7a15f847e73b05ce99c81d2d9c3310ee4f208ad61509a2d1b4aae4089/node_modules/chat/dist/index.js
20691
20691
  var emojiRegistry = /* @__PURE__ */ new Map();
20692
20692
  function getEmoji(name) {
20693
20693
  let emojiValue = emojiRegistry.get(name);
@@ -21353,7 +21353,7 @@ createEmoji();
21353
21353
  var cardChildToFallbackText2 = cardChildToFallbackText;
21354
21354
  var isCardElement2 = isCardElement;
21355
21355
  //#endregion
21356
- //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@chat-adapter/shared/4.40.0/b8d1ffb3606d5fbc146955d209d67d901e1ac7e62c614258eabf21f6794389e3/node_modules/@chat-adapter/shared/dist/index.js
21356
+ //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@chat-adapter/shared/4.40.0/fce4918c61c1df207adfd85bd40413a154f91b156c76778268cca9eac6100664/node_modules/@chat-adapter/shared/dist/index.js
21357
21357
  function extractCard(message) {
21358
21358
  if (isCardElement2(message)) return message;
21359
21359
  if (typeof message === "object" && message !== null && "card" in message) return message.card;
@@ -21493,7 +21493,7 @@ function blocklist(ranges, family) {
21493
21493
  blocklist(IPV4, "ipv4");
21494
21494
  blocklist(IPV6, "ipv6");
21495
21495
  //#endregion
21496
- //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@chat-adapter/telegram/4.40.0/117ee55721c79f2050c97f5568d59cc1a8a9476541dcbc8fcd32561f0bae25c7/node_modules/@chat-adapter/telegram/dist/index.js
21496
+ //#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@chat-adapter/telegram/4.40.0/2ef492177ff8ab13f86cb97c925417d9e41f7412cd1657efee41ac94fe25b285/node_modules/@chat-adapter/telegram/dist/index.js
21497
21497
  var CALLBACK_DATA_PREFIX = "chat:";
21498
21498
  var TELEGRAM_CALLBACK_DATA_LIMIT_BYTES = 64;
21499
21499
  function convertLabel(label) {
@@ -24340,6 +24340,7 @@ var TelegramInstallStore = class {
24340
24340
  #toRecord(install) {
24341
24341
  const data = {
24342
24342
  botToken: this.#enc(install.botToken),
24343
+ botUserId: install.botUserId,
24343
24344
  secretToken: this.#enc(install.secretToken),
24344
24345
  username: install.username,
24345
24346
  webhookUrl: install.webhookUrl,
@@ -24364,6 +24365,7 @@ var TelegramInstallStore = class {
24364
24365
  webhookId: record.webhookId ?? "",
24365
24366
  status: record.status === "active" ? "active" : "pending",
24366
24367
  botToken: this.#dec(data.botToken),
24368
+ botUserId: data.botUserId,
24367
24369
  secretToken: this.#dec(data.secretToken),
24368
24370
  username: data.username,
24369
24371
  webhookUrl: data.webhookUrl,
@@ -24434,6 +24436,7 @@ var TelegramProvider = class {
24434
24436
  #initPromise = null;
24435
24437
  #connectingBotTokens = /* @__PURE__ */ new Set();
24436
24438
  constructor(config = {}) {
24439
+ if ("tokenResolver" in config && config.tokenResolver && "botToken" in config && config.botToken) throw new Error("TelegramProvider cannot be constructed with both `botToken` and `tokenResolver` — pick one credential mode (self-managed or delegated).");
24437
24440
  this.#config = config;
24438
24441
  }
24439
24442
  /**
@@ -24508,15 +24511,73 @@ var TelegramProvider = class {
24508
24511
  }
24509
24512
  }
24510
24513
  async #doInitialize() {
24511
- const active = (await (await this.#getStore()).list()).filter((i) => i.status === "active");
24514
+ const store = await this.#getStore();
24515
+ const active = (await store.list()).filter((i) => i.status === "active");
24512
24516
  this.#configured = active.length > 0;
24513
24517
  for (const installation of active) try {
24514
- await this.#activateInstallation(installation);
24518
+ const prepared = await this.#migrateInstallation(installation, store);
24519
+ if (!prepared) continue;
24520
+ await this.#activateInstallation(prepared);
24515
24521
  } catch (err) {
24516
24522
  console.error(`[Telegram] Failed to restore installation "${installation.id}":`, err);
24517
24523
  }
24518
24524
  }
24519
24525
  /**
24526
+ * Bring a stored installation up to the provider's current credential mode.
24527
+ *
24528
+ * When {@link TelegramProviderConfig.tokenResolver} is configured but the
24529
+ * record was written under self-managed mode, the record still carries a
24530
+ * `botToken` and may be missing `botUserId`. Left as-is, the adapter would
24531
+ * keep using that stale token (bypassing rotation) and duplicate detection
24532
+ * would fall back to token comparison. Resolve the current token, verify it
24533
+ * points at the same bot, populate `botUserId` if missing, and drop the
24534
+ * persisted token so future rotations flow through the resolver.
24535
+ *
24536
+ * For a legacy record with no `botUserId`, the "same bot" check needs an
24537
+ * expected identity — so we `getMe` the stored `botToken` first and compare
24538
+ * that identity to the resolver's. A stored-token lookup failure leaves the
24539
+ * record untouched (we cannot prove it's still the same bot, and silently
24540
+ * assigning `me.id` would let a repointed resolver retarget the install and
24541
+ * orphan the old bot's webhook).
24542
+ *
24543
+ * A resolver failure — or an identity mismatch — is not fatal here: we log
24544
+ * and leave the record untouched, so the operator can investigate before
24545
+ * connect/disconnect on that installation.
24546
+ */
24547
+ async #migrateInstallation(installation, store) {
24548
+ if (!this.#config.tokenResolver) return installation;
24549
+ const needsMigration = installation.botToken !== void 0 || installation.botUserId === void 0;
24550
+ const needsIdentityCheck = installation.botUserId !== void 0;
24551
+ if (!needsMigration && !needsIdentityCheck) return installation;
24552
+ try {
24553
+ const resolved = await this.#config.tokenResolver();
24554
+ if (!resolved) return installation;
24555
+ const me = await getMe(resolved, this.#apiBaseUrl());
24556
+ let expectedBotUserId = installation.botUserId;
24557
+ if (expectedBotUserId === void 0 && installation.botToken) try {
24558
+ expectedBotUserId = (await getMe(installation.botToken, this.#apiBaseUrl())).id;
24559
+ } catch (err) {
24560
+ console.warn(`[Telegram] Could not verify stored bot identity for installation "${installation.id}" during delegated-mode migration; leaving the record untouched.`, err);
24561
+ return installation;
24562
+ }
24563
+ if (expectedBotUserId !== void 0 && expectedBotUserId !== me.id) {
24564
+ console.warn(`[Telegram] Delegated credential for installation "${installation.id}" now resolves to bot ${me.id} but was bot ${expectedBotUserId}. Disconnect and reconnect the agent to adopt the new bot.`);
24565
+ return null;
24566
+ }
24567
+ if (!needsMigration) return installation;
24568
+ const { botToken: _dropped, ...rest } = installation;
24569
+ const migrated = {
24570
+ ...rest,
24571
+ botUserId: me.id
24572
+ };
24573
+ await store.save(migrated);
24574
+ return migrated;
24575
+ } catch (err) {
24576
+ console.warn(`[Telegram] Delegated-mode migration failed for installation "${installation.id}":`, err);
24577
+ return installation;
24578
+ }
24579
+ }
24580
+ /**
24520
24581
  * Update runtime provider settings. Pass `botToken` to change the default
24521
24582
  * bot token new {@link connect} calls fall back to when none is supplied
24522
24583
  * per-agent (matching {@link SlackProvider.configure}'s rotation pattern);
@@ -24525,6 +24586,7 @@ var TelegramProvider = class {
24525
24586
  * via {@link connect}/{@link disconnect}.
24526
24587
  */
24527
24588
  async configure(credentials) {
24589
+ if (this.#config.tokenResolver && credentials?.botToken !== void 0) throw new Error("TelegramProvider was constructed with a tokenResolver — bot tokens are managed externally. Remove the tokenResolver to manage credentials manually via configure().");
24528
24590
  if (credentials === null) {
24529
24591
  this.#config = {
24530
24592
  ...this.#config,
@@ -24561,7 +24623,13 @@ var TelegramProvider = class {
24561
24623
  const store = await this.#getStore();
24562
24624
  const existing = await store.getByAgent(agentId);
24563
24625
  if (existing?.status === "active") throw new Error(`Agent "${agentId}" is already connected to Telegram. Disconnect first to reconnect.`);
24564
- const botToken = options.botToken ?? this.#config.botToken;
24626
+ if (this.#config.tokenResolver && options.botToken !== void 0) throw new Error("TelegramProvider was constructed with a tokenResolver — bot tokens are managed externally and cannot be supplied per connect() call.");
24627
+ let botToken;
24628
+ if (this.#config.tokenResolver) {
24629
+ const resolved = await this.#config.tokenResolver();
24630
+ if (!resolved) throw new Error("TelegramProvider tokenResolver returned an empty bot token. Attach a Telegram bot credential upstream before connecting an agent.");
24631
+ botToken = resolved;
24632
+ } else botToken = options.botToken ?? this.#config.botToken;
24565
24633
  if (!botToken) {
24566
24634
  const installationId = existing?.id ?? (0, crypto$1.randomUUID)();
24567
24635
  await store.save({
@@ -24585,11 +24653,11 @@ var TelegramProvider = class {
24585
24653
  this.#connectingBotTokens.add(botToken);
24586
24654
  }
24587
24655
  try {
24656
+ const me = await getMe(botToken, this.#apiBaseUrl());
24588
24657
  if (mode === "webhook") {
24589
- const duplicate = (await store.list()).find((i) => i.status === "active" && i.botToken === botToken);
24658
+ const duplicate = (await store.list()).find((i) => i.status === "active" && i.agentId !== agentId && (i.botUserId !== void 0 ? i.botUserId === me.id : i.botToken === botToken));
24590
24659
  if (duplicate) throw new Error(`This Telegram bot is already connected to agent "${duplicate.agentId}". Disconnect it before connecting another agent.`);
24591
24660
  }
24592
- const me = await getMe(botToken, this.#apiBaseUrl());
24593
24661
  const installationId = existing?.id ?? (0, crypto$1.randomUUID)();
24594
24662
  const webhookId = existing?.webhookId ?? (0, crypto$1.randomUUID)();
24595
24663
  const webhookUrl = mode === "webhook" ? `${baseUrl}/${PLATFORM}/events/${webhookId}` : void 0;
@@ -24599,15 +24667,16 @@ var TelegramProvider = class {
24599
24667
  agentId,
24600
24668
  webhookId,
24601
24669
  status: "active",
24602
- botToken,
24670
+ ...this.#config.tokenResolver ? {} : { botToken },
24671
+ botUserId: me.id,
24603
24672
  secretToken: generateSecretToken(),
24604
24673
  username: options.name ?? me.username ?? me.first_name,
24605
24674
  webhookUrl,
24606
24675
  commands: commands.length ? commands : void 0,
24607
24676
  installedAt: existing?.installedAt ?? /* @__PURE__ */ new Date()
24608
24677
  };
24609
- await this.#registerTransport(installation, mode);
24610
- await this.#registerCommands(installation);
24678
+ await this.#registerTransport(installation, mode, botToken);
24679
+ await this.#registerCommands(installation, botToken);
24611
24680
  await store.save(installation);
24612
24681
  await this.#activateInstallation(installation);
24613
24682
  this.#configured = true;
@@ -24631,8 +24700,18 @@ var TelegramProvider = class {
24631
24700
  } catch (err) {
24632
24701
  console.warn(`[Telegram] Failed to stop polling for agent "${agentId}":`, err);
24633
24702
  }
24634
- if (existing.botToken) try {
24635
- await deleteWebhook(existing.botToken, true, this.#apiBaseUrl());
24703
+ try {
24704
+ let botToken;
24705
+ if (existing.botToken) botToken = existing.botToken;
24706
+ else if (this.#config.tokenResolver) {
24707
+ const resolved = await this.#config.tokenResolver();
24708
+ if (resolved && existing.botUserId !== void 0) {
24709
+ const me = await getMe(resolved, this.#apiBaseUrl());
24710
+ if (me.id !== existing.botUserId) console.warn(`[Telegram] Skipping deleteWebhook for agent "${agentId}": resolver now points at bot ${me.id} but this installation was bot ${existing.botUserId}.`);
24711
+ else botToken = resolved;
24712
+ } else if (resolved) botToken = resolved;
24713
+ }
24714
+ if (botToken) await deleteWebhook(botToken, true, this.#apiBaseUrl());
24636
24715
  } catch (err) {
24637
24716
  console.warn(`[Telegram] Failed to delete webhook for agent "${agentId}":`, err);
24638
24717
  }
@@ -24706,22 +24785,25 @@ var TelegramProvider = class {
24706
24785
  if (mode === "auto") return baseUrl ? "webhook" : "polling";
24707
24786
  return mode;
24708
24787
  }
24709
- /** Register (or clear) the receive transport for a bot, enforcing the exclusion. */
24710
- async #registerTransport(installation, mode) {
24711
- if (!installation.botToken) return;
24712
- if (mode === "webhook" && installation.webhookUrl && installation.secretToken) await setWebhook(installation.botToken, {
24788
+ /**
24789
+ * Register (or clear) the receive transport for a bot, enforcing the
24790
+ * exclusion. The token is passed explicitly — delegated-mode installations
24791
+ * do not persist one.
24792
+ */
24793
+ async #registerTransport(installation, mode, botToken) {
24794
+ if (mode === "webhook" && installation.webhookUrl && installation.secretToken) await setWebhook(botToken, {
24713
24795
  url: installation.webhookUrl,
24714
24796
  secretToken: installation.secretToken,
24715
24797
  allowedUpdates: this.#config.allowedUpdates ?? [...DEFAULT_ALLOWED_UPDATES],
24716
24798
  dropPendingUpdates: true
24717
24799
  }, this.#apiBaseUrl());
24718
- else await deleteWebhook(installation.botToken, true, this.#apiBaseUrl());
24800
+ else await deleteWebhook(botToken, true, this.#apiBaseUrl());
24719
24801
  }
24720
24802
  /** Publish the bot's command list (best-effort — a failure won't block connect). */
24721
- async #registerCommands(installation) {
24722
- if (!installation.botToken || !installation.commands?.length) return;
24803
+ async #registerCommands(installation, botToken) {
24804
+ if (!installation.commands?.length) return;
24723
24805
  try {
24724
- await setMyCommands(installation.botToken, {
24806
+ await setMyCommands(botToken, {
24725
24807
  commands: installation.commands,
24726
24808
  scope: this.#config.commandScope
24727
24809
  }, this.#apiBaseUrl());
@@ -24733,7 +24815,7 @@ var TelegramProvider = class {
24733
24815
  const existing = this.#adapters.get(installation.id);
24734
24816
  if (existing) return existing;
24735
24817
  const adapter = createTelegramAdapter({
24736
- botToken: installation.botToken,
24818
+ botToken: installation.botToken ?? this.#config.tokenResolver,
24737
24819
  secretToken: installation.secretToken,
24738
24820
  userName: installation.username,
24739
24821
  apiBaseUrl: this.#apiBaseUrl(),