teleton 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +28 -11
  2. package/dist/{chunk-H36RFKRI.js → chunk-2IZU3REP.js} +572 -174
  3. package/dist/chunk-3UFPFWYP.js +12 -0
  4. package/dist/{chunk-NUGDTPE4.js → chunk-4L66JHQE.js} +2 -1
  5. package/dist/{chunk-TVRZJIZX.js → chunk-55SKE6YH.js} +4 -4
  6. package/dist/{setup-server-QXED3D2L.js → chunk-57URFK6M.js} +161 -210
  7. package/dist/chunk-5SEMA47R.js +75 -0
  8. package/dist/{chunk-JHYZYFZJ.js → chunk-7YKSXOQQ.js} +17 -2
  9. package/dist/{chunk-IJBWWQE4.js → chunk-C4NKJT2Z.js} +12 -0
  10. package/dist/{chunk-RQBAMUCV.js → chunk-GGXJLMOH.js} +1451 -743
  11. package/dist/{chunk-WIKM24GZ.js → chunk-H7MFXJZK.js} +7 -2
  12. package/dist/{chunk-U56QTM46.js → chunk-HEDJCLA6.js} +85 -44
  13. package/dist/{chunk-QVBSUYVX.js → chunk-J73TA3UM.js} +17 -9
  14. package/dist/{chunk-P36I6OIV.js → chunk-LC4TV3KL.js} +13 -2
  15. package/dist/{chunk-RCMD3U65.js → chunk-NQ6FZKCE.js} +13 -0
  16. package/dist/{chunk-SD4NLLYG.js → chunk-VYKW7FMV.js} +224 -93
  17. package/dist/chunk-W25Z7CM6.js +487 -0
  18. package/dist/{chunk-OJCLKU5Z.js → chunk-WFTC3JJW.js} +16 -0
  19. package/dist/{server-H3QA252W.js → chunk-XBSCYMKM.js} +369 -374
  20. package/dist/{chunk-PHSAHTK4.js → chunk-YOSUPUAJ.js} +75 -7
  21. package/dist/cli/index.js +67 -22
  22. package/dist/{client-LNZTDQSA.js → client-YOOHI776.js} +4 -4
  23. package/dist/{get-my-gifts-OMGKOEPM.js → get-my-gifts-Y7EN7RK4.js} +3 -3
  24. package/dist/index.js +15 -14
  25. package/dist/{memory-AS7WKGTW.js → memory-Q6EWGK2S.js} +7 -5
  26. package/dist/memory-hook-WUXJNVT5.js +18 -0
  27. package/dist/{migrate-POHWYEIW.js → migrate-WFU6COBN.js} +5 -5
  28. package/dist/server-GYZXKIKU.js +787 -0
  29. package/dist/server-YODFBZKG.js +392 -0
  30. package/dist/setup-server-IZBUOJRU.js +215 -0
  31. package/dist/{store-GAFULOOX.js → store-7M4XV6M5.js} +6 -6
  32. package/dist/{task-dependency-resolver-3FIKQ7Z6.js → task-dependency-resolver-L6UUMTHK.js} +3 -3
  33. package/dist/{task-executor-RUTFG6VG.js → task-executor-XBNJLUCS.js} +3 -3
  34. package/dist/{tasks-BEZ4QRI2.js → tasks-WQIKXDX5.js} +1 -1
  35. package/dist/{tool-adapter-IH5VGBOO.js → tool-adapter-IVX2XQJE.js} +1 -1
  36. package/dist/{tool-index-H3SHOJC3.js → tool-index-NYH57UWP.js} +9 -6
  37. package/dist/{transcript-IMNE6KU3.js → transcript-IM7G25OS.js} +2 -2
  38. package/dist/web/assets/index-BfYCdwLI.js +80 -0
  39. package/dist/web/assets/{index-BrVqauzj.css → index-DmlyQVhR.css} +1 -1
  40. package/dist/web/assets/{index.es-DkU1GvWU.js → index.es-DitvF-9H.js} +1 -1
  41. package/dist/web/index.html +2 -2
  42. package/package.json +14 -5
  43. package/dist/chunk-XBE4JB7C.js +0 -8
  44. package/dist/web/assets/index-DYeEkvJ6.js +0 -72
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  telegramGetMyGiftsExecutor,
3
3
  telegramGetMyGiftsTool
4
- } from "./chunk-WIKM24GZ.js";
4
+ } from "./chunk-H7MFXJZK.js";
5
5
  import {
6
6
  AgentRuntime,
7
7
  DEDUST_API_URL,
@@ -20,13 +20,16 @@ import {
20
20
  findAssetBySymbol,
21
21
  formatTransactions,
22
22
  fromUnits,
23
+ getBlocklistConfig,
23
24
  getDecimals,
24
25
  getDefaultConfigPath,
26
+ getTriggersConfig,
25
27
  hasStyledButtons,
26
28
  listPluginSecretKeys,
27
29
  loadConfig,
28
30
  loadEnhancedPlugins,
29
31
  loadSoul,
32
+ module_default,
30
33
  parseHtml,
31
34
  randomLong,
32
35
  readRawConfig,
@@ -47,7 +50,7 @@ import {
47
50
  withTxLock,
48
51
  writePluginSecret,
49
52
  writeRawConfig
50
- } from "./chunk-RQBAMUCV.js";
53
+ } from "./chunk-GGXJLMOH.js";
51
54
  import {
52
55
  getCachedTonClient,
53
56
  getKeyPair,
@@ -58,17 +61,17 @@ import {
58
61
  loadTemplate,
59
62
  loadWallet,
60
63
  setToncenterApiKey
61
- } from "./chunk-JHYZYFZJ.js";
64
+ } from "./chunk-7YKSXOQQ.js";
62
65
  import {
63
66
  getErrorMessage
64
- } from "./chunk-XBE4JB7C.js";
67
+ } from "./chunk-3UFPFWYP.js";
65
68
  import {
66
69
  getEffectiveApiKey,
67
70
  getProviderModel
68
- } from "./chunk-QVBSUYVX.js";
71
+ } from "./chunk-J73TA3UM.js";
69
72
  import {
70
73
  getProviderMetadata
71
- } from "./chunk-PHSAHTK4.js";
74
+ } from "./chunk-YOSUPUAJ.js";
72
75
  import {
73
76
  ChatStore,
74
77
  JOURNAL_SCHEMA,
@@ -81,7 +84,7 @@ import {
81
84
  initializeMemory,
82
85
  migrateFromMainDb,
83
86
  openModuleDb
84
- } from "./chunk-SD4NLLYG.js";
87
+ } from "./chunk-VYKW7FMV.js";
85
88
  import {
86
89
  ELEVENLABS_TTS_URL,
87
90
  GECKOTERMINAL_API_URL,
@@ -107,7 +110,7 @@ import {
107
110
  TELEGRAM_MAX_MESSAGE_LENGTH,
108
111
  WEB_FETCH_MAX_TEXT_LENGTH,
109
112
  WEB_SEARCH_MAX_RESULTS
110
- } from "./chunk-IJBWWQE4.js";
113
+ } from "./chunk-C4NKJT2Z.js";
111
114
  import {
112
115
  fetchWithTimeout
113
116
  } from "./chunk-XQUHC3JZ.js";
@@ -130,7 +133,7 @@ import {
130
133
  initLoggerFromConfig,
131
134
  isVerbose,
132
135
  setVerbose
133
- } from "./chunk-RCMD3U65.js";
136
+ } from "./chunk-NQ6FZKCE.js";
134
137
 
135
138
  // src/telegram/client.ts
136
139
  import { TelegramClient, Api } from "telegram";
@@ -349,14 +352,15 @@ var TelegramUserClient = class {
349
352
  authenticated = true;
350
353
  break;
351
354
  } catch (err) {
352
- if (err.errorMessage === "PHONE_CODE_INVALID") {
355
+ const errObj = err;
356
+ if (errObj.errorMessage === "PHONE_CODE_INVALID") {
353
357
  const remaining = maxAttempts - attempt - 1;
354
358
  if (remaining > 0) {
355
359
  console.log(`Invalid code. ${remaining} attempt(s) remaining.`);
356
360
  } else {
357
361
  throw new Error("Authentication failed: too many invalid code attempts");
358
362
  }
359
- } else if (err.errorMessage === "SESSION_PASSWORD_NEEDED") {
363
+ } else if (errObj.errorMessage === "SESSION_PASSWORD_NEEDED") {
360
364
  const pwd = await promptInput("2FA password: ");
361
365
  const { computeCheck } = await import("telegram/Password.js");
362
366
  const srpResult = await this.client.invoke(new Api.account.GetPassword());
@@ -423,7 +427,11 @@ var TelegramUserClient = class {
423
427
  }
424
428
  await handler(event);
425
429
  };
426
- this.client.addEventHandler(wrappedHandler, new NewMessage(filters ?? {}));
430
+ this.client.addEventHandler(
431
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises -- GramJS event handler accepts async
432
+ wrappedHandler,
433
+ new NewMessage(filters ?? {})
434
+ );
427
435
  }
428
436
  addServiceMessageHandler(handler) {
429
437
  this.client.addEventHandler(async (update) => {
@@ -729,7 +737,7 @@ var TelegramBridge = class {
729
737
  if (sender instanceof Api2.User) {
730
738
  isBot = sender.bot ?? false;
731
739
  }
732
- } catch (e) {
740
+ } catch {
733
741
  }
734
742
  const hasMedia = !!(msg.photo || msg.document || msg.video || msg.audio || msg.voice || msg.sticker);
735
743
  let mediaType;
@@ -810,12 +818,11 @@ var TelegramBridge = class {
810
818
  let text = "";
811
819
  if (action instanceof Api2.MessageActionStarGiftPurchaseOffer) {
812
820
  const gift = action.gift;
813
- const price = action.price;
814
- const isUnique = gift.className === "StarGiftUnique";
821
+ const isUnique = gift instanceof Api2.StarGiftUnique;
815
822
  const title = gift.title || "Unknown Gift";
816
823
  const slug = isUnique ? gift.slug : void 0;
817
824
  const num = isUnique ? gift.num : void 0;
818
- const priceStars = price?.amount?.toString() || "?";
825
+ const priceStars = action.price.amount?.toString() || "?";
819
826
  const status = action.accepted ? "accepted" : action.declined ? "declined" : "pending";
820
827
  const expires = action.expiresAt ? new Date(action.expiresAt * 1e3).toISOString() : "unknown";
821
828
  text = `[Gift Offer Received]
@@ -834,12 +841,11 @@ var TelegramBridge = class {
834
841
  );
835
842
  } else if (action instanceof Api2.MessageActionStarGiftPurchaseOfferDeclined) {
836
843
  const gift = action.gift;
837
- const price = action.price;
838
- const isUnique = gift.className === "StarGiftUnique";
844
+ const isUnique = gift instanceof Api2.StarGiftUnique;
839
845
  const title = gift.title || "Unknown Gift";
840
846
  const slug = isUnique ? gift.slug : void 0;
841
847
  const num = isUnique ? gift.num : void 0;
842
- const priceStars = price?.amount?.toString() || "?";
848
+ const priceStars = action.price.amount?.toString() || "?";
843
849
  const reason = action.expired ? "expired" : "declined";
844
850
  text = `[Gift Offer ${action.expired ? "Expired" : "Declined"}]
845
851
  `;
@@ -848,7 +854,7 @@ var TelegramBridge = class {
848
854
  } else if (action instanceof Api2.MessageActionStarGift) {
849
855
  const gift = action.gift;
850
856
  const title = gift.title || "Unknown Gift";
851
- const stars = gift.stars?.toString() || "?";
857
+ const stars = gift instanceof Api2.StarGift ? gift.stars?.toString() || "?" : "?";
852
858
  const giftMessage = action.message?.text || "";
853
859
  const fromAnonymous = action.nameHidden;
854
860
  text = `[Gift Received]
@@ -1221,7 +1227,6 @@ var MessageHandler = class _MessageHandler {
1221
1227
  fullConfig;
1222
1228
  agent;
1223
1229
  rateLimiter;
1224
- lastProcessedMessageId;
1225
1230
  messageStore;
1226
1231
  chatStore;
1227
1232
  userStore;
@@ -1246,7 +1251,6 @@ var MessageHandler = class _MessageHandler {
1246
1251
  this.chatStore = new ChatStore(db2);
1247
1252
  this.userStore = new UserStore(db2);
1248
1253
  this.pendingHistory = new PendingHistory();
1249
- this.lastProcessedMessageId = 0;
1250
1254
  }
1251
1255
  setOwnUserId(userId) {
1252
1256
  this.ownUserId = userId;
@@ -1358,10 +1362,11 @@ var MessageHandler = class _MessageHandler {
1358
1362
  * Process and respond to a message
1359
1363
  */
1360
1364
  async handleMessage(message) {
1361
- if (this.recentMessageIds.has(message.id)) {
1365
+ const dedupKey = `${message.chatId}:${message.id}`;
1366
+ if (this.recentMessageIds.has(dedupKey)) {
1362
1367
  return;
1363
1368
  }
1364
- this.recentMessageIds.add(message.id);
1369
+ this.recentMessageIds.add(dedupKey);
1365
1370
  if (this.recentMessageIds.size > _MessageHandler.DEDUP_MAX_SIZE) {
1366
1371
  const ids = [...this.recentMessageIds];
1367
1372
  this.recentMessageIds = new Set(ids.slice(ids.length >> 1));
@@ -1452,10 +1457,11 @@ var MessageHandler = class _MessageHandler {
1452
1457
  config: this.fullConfig
1453
1458
  }
1454
1459
  );
1455
- if (transcribeResult.success && transcribeResult.data?.text) {
1456
- transcriptionText = transcribeResult.data.text;
1460
+ const transcribeData = transcribeResult.data;
1461
+ if (transcribeResult.success && transcribeData?.text) {
1462
+ transcriptionText = transcribeData.text;
1457
1463
  log6.info(
1458
- `\u{1F3A4} Auto-transcribed voice msg ${message.id}: "${transcriptionText.substring(0, 80)}..."`
1464
+ `\u{1F3A4} Auto-transcribed voice msg ${message.id}: "${transcriptionText?.substring(0, 80)}..."`
1459
1465
  );
1460
1466
  }
1461
1467
  } catch (err) {
@@ -1561,12 +1567,6 @@ ${message.text}` : ""}` : message.text;
1561
1567
  log6.error({ err: error }, "Error storing message to feed");
1562
1568
  }
1563
1569
  }
1564
- /**
1565
- * Get last processed message ID
1566
- */
1567
- getLastProcessedMessageId() {
1568
- return this.lastProcessedMessageId;
1569
- }
1570
1570
  };
1571
1571
 
1572
1572
  // src/telegram/admin.ts
@@ -1696,7 +1696,7 @@ var AdminHandler = class {
1696
1696
  Use /help for available commands.`;
1697
1697
  }
1698
1698
  }
1699
- async handleStatusCommand(command) {
1699
+ async handleStatusCommand(_command) {
1700
1700
  const activeChatIds = this.agent.getActiveChatIds();
1701
1701
  const chatCount = activeChatIds.length;
1702
1702
  const cfg = this.agent.getConfig();
@@ -1907,6 +1907,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1907
1907
  }
1908
1908
  }
1909
1909
  listModules(chatId) {
1910
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1910
1911
  const modules = this.registry.getAvailableModules();
1911
1912
  const overrides = this.permissions.getOverrides(chatId);
1912
1913
  const lines = ["\u{1F9E9} **Modules** (this group)\n"];
@@ -1941,6 +1942,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1941
1942
  }
1942
1943
  module = module.toLowerCase();
1943
1944
  level = level.toLowerCase();
1945
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1944
1946
  const available = this.registry.getAvailableModules();
1945
1947
  if (!available.includes(module)) {
1946
1948
  return `\u274C Unknown module: "${module}"`;
@@ -1961,6 +1963,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1961
1963
  return "\u274C Usage: /modules info <module>";
1962
1964
  }
1963
1965
  module = module.toLowerCase();
1966
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1964
1967
  const available = this.registry.getAvailableModules();
1965
1968
  if (!available.includes(module)) {
1966
1969
  return `\u274C Unknown module: "${module}"`;
@@ -1981,6 +1984,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1981
1984
  return lines.join("\n");
1982
1985
  }
1983
1986
  resetModules(chatId, module) {
1987
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1984
1988
  if (module) {
1985
1989
  module = module.toLowerCase();
1986
1990
  const available = this.registry.getAvailableModules();
@@ -2550,7 +2554,7 @@ var ToolRegistry = class {
2550
2554
  }
2551
2555
  this.toolArrayCache = null;
2552
2556
  if (names.length > 0) {
2553
- const addedTools = names.map((n) => this.tools.get(n).tool);
2557
+ const addedTools = names.map((n) => this.tools.get(n)?.tool).filter((t) => !!t);
2554
2558
  this.notifyToolsChanged([], addedTools);
2555
2559
  }
2556
2560
  return names.length;
@@ -2593,7 +2597,7 @@ var ToolRegistry = class {
2593
2597
  }
2594
2598
  this.toolArrayCache = null;
2595
2599
  const removedNames = [...previousNames].filter((n) => !names.includes(n));
2596
- const addedTools = names.map((n) => this.tools.get(n).tool);
2600
+ const addedTools = names.map((n) => this.tools.get(n)?.tool).filter((t) => !!t);
2597
2601
  if (removedNames.length > 0 || addedTools.length > 0) {
2598
2602
  this.notifyToolsChanged(removedNames, addedTools);
2599
2603
  }
@@ -2868,7 +2872,7 @@ var telegramForwardMessageExecutor = async (params, context) => {
2868
2872
  try {
2869
2873
  const { fromChatId, toChatId, messageIds, silent = false, background = false } = params;
2870
2874
  const gramJsClient = context.bridge.getClient().getClient();
2871
- const result = await gramJsClient.invoke(
2875
+ const _result = await gramJsClient.invoke(
2872
2876
  new Api5.messages.ForwardMessages({
2873
2877
  fromPeer: fromChatId,
2874
2878
  toPeer: toChatId,
@@ -3274,7 +3278,7 @@ var telegramGetRepliesExecutor = async (params, context) => {
3274
3278
  limit,
3275
3279
  maxId: 0,
3276
3280
  minId: 0,
3277
- hash: 0n
3281
+ hash: toLong(0n)
3278
3282
  })
3279
3283
  );
3280
3284
  const messages = [];
@@ -3369,7 +3373,7 @@ var telegramGetScheduledMessagesExecutor = async (params, context) => {
3369
3373
  const result = await gramJsClient.invoke(
3370
3374
  new Api11.messages.GetScheduledHistory({
3371
3375
  peer: entity,
3372
- hash: 0n
3376
+ hash: toLong(0n)
3373
3377
  })
3374
3378
  );
3375
3379
  const messages = "messages" in result ? result.messages : [];
@@ -3766,7 +3770,7 @@ async function generatePiperTTS(text, voice) {
3766
3770
  });
3767
3771
  });
3768
3772
  unlinkSync(wavPath);
3769
- } catch (err) {
3773
+ } catch {
3770
3774
  return {
3771
3775
  filePath: wavPath,
3772
3776
  provider: "piper",
@@ -4053,7 +4057,7 @@ var telegramSendVoiceExecutor = async (params, context) => {
4053
4057
  if (generatedFile) {
4054
4058
  try {
4055
4059
  unlinkSync2(generatedFile);
4056
- } catch (e) {
4060
+ } catch {
4057
4061
  }
4058
4062
  }
4059
4063
  }
@@ -4109,6 +4113,7 @@ var telegramSendStickerExecutor = async (params, context) => {
4109
4113
  const stickerSet = await gramJsClient.invoke(
4110
4114
  new Api15.messages.GetStickerSet({
4111
4115
  stickerset: new Api15.InputStickerSetShortName({
4116
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasSetInfo check
4112
4117
  shortName: stickerSetShortName
4113
4118
  }),
4114
4119
  hash: 0
@@ -4127,7 +4132,7 @@ var telegramSendStickerExecutor = async (params, context) => {
4127
4132
  };
4128
4133
  }
4129
4134
  const stickerDoc = stickerSet.documents[stickerIndex];
4130
- const result2 = await gramJsClient.invoke(
4135
+ const _result = await gramJsClient.invoke(
4131
4136
  new Api15.messages.SendMedia({
4132
4137
  peer: chatId,
4133
4138
  media: new Api15.InputMediaDocument({
@@ -4234,10 +4239,12 @@ var telegramSendGifExecutor = async (params, context) => {
4234
4239
  }
4235
4240
  const gramJsClient = context.bridge.getClient().getClient();
4236
4241
  if (hasInlineResult) {
4237
- const result2 = await gramJsClient.invoke(
4242
+ const _result = await gramJsClient.invoke(
4238
4243
  new Api16.messages.SendInlineBotResult({
4239
4244
  peer: chatId,
4245
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasInlineResult check
4240
4246
  queryId: toLong(BigInt(queryId)),
4247
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasInlineResult check
4241
4248
  id: resultId,
4242
4249
  randomId: randomLong(),
4243
4250
  replyTo: replyToId ? new Api16.InputReplyToMessage({ replyToMsgId: replyToId }) : void 0
@@ -4530,6 +4537,7 @@ var visionAnalyzeExecutor = async (params, context) => {
4530
4537
  log27.info(`\u{1F4F7} Downloading image from message ${messageId}...`);
4531
4538
  const gramJsClient = context.bridge.getClient().getClient();
4532
4539
  const messages = await gramJsClient.getMessages(chatId, {
4540
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- messageId guaranteed in this branch
4533
4541
  ids: [messageId]
4534
4542
  });
4535
4543
  if (!messages || messages.length === 0) {
@@ -4812,7 +4820,7 @@ var telegramGetChatInfoExecutor = async (params, context) => {
4812
4820
  let entity;
4813
4821
  try {
4814
4822
  entity = await gramJsClient.getEntity(chatId);
4815
- } catch (error) {
4823
+ } catch {
4816
4824
  return {
4817
4825
  success: false,
4818
4826
  error: `Could not find chat "${chatId}"`
@@ -4878,7 +4886,7 @@ var telegramGetChatInfoExecutor = async (params, context) => {
4878
4886
  isDeactivated: chat.deactivated || false
4879
4887
  };
4880
4888
  }
4881
- } catch (error) {
4889
+ } catch {
4882
4890
  chatInfo = {
4883
4891
  ...chatInfo,
4884
4892
  title: entity instanceof Api18.Channel ? entity.title : entity instanceof Api18.Chat ? entity.title : null,
@@ -4929,7 +4937,7 @@ var telegramMarkAsReadExecutor = async (params, context) => {
4929
4937
  let entity;
4930
4938
  try {
4931
4939
  entity = await gramJsClient.getEntity(chatId);
4932
- } catch (error) {
4940
+ } catch {
4933
4941
  return {
4934
4942
  success: false,
4935
4943
  error: `Could not find chat "${chatId}"`
@@ -5122,7 +5130,7 @@ var telegramLeaveChannelExecutor = async (params, context) => {
5122
5130
  let channelEntity;
5123
5131
  try {
5124
5132
  channelEntity = await gramJsClient.getEntity(channel);
5125
- } catch (error) {
5133
+ } catch {
5126
5134
  return {
5127
5135
  success: false,
5128
5136
  error: `Could not find channel "${channel}". Make sure it exists and you have access to it.`
@@ -5416,7 +5424,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5416
5424
  } else {
5417
5425
  failed.push(`${userId} (not a user)`);
5418
5426
  }
5419
- } catch (error) {
5427
+ } catch {
5420
5428
  failed.push(`${userId} (not found)`);
5421
5429
  }
5422
5430
  }
@@ -5436,7 +5444,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5436
5444
  } else {
5437
5445
  failed.push(`@${cleanUsername} (not a user)`);
5438
5446
  }
5439
- } catch (error) {
5447
+ } catch {
5440
5448
  failed.push(`@${username.replace("@", "")} (not found)`);
5441
5449
  }
5442
5450
  }
@@ -5446,7 +5454,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5446
5454
  error: `Could not resolve any users to invite. Failed: ${failed.join(", ")}`
5447
5455
  };
5448
5456
  }
5449
- const result = await gramJsClient.invoke(
5457
+ const _result = await gramJsClient.invoke(
5450
5458
  new Api23.channels.InviteToChannel({
5451
5459
  channel,
5452
5460
  users
@@ -6416,7 +6424,7 @@ var telegramCreatePollExecutor = async (params, context) => {
6416
6424
  closePeriod,
6417
6425
  closeDate
6418
6426
  });
6419
- const result = await gramJsClient.invoke(
6427
+ const _result = await gramJsClient.invoke(
6420
6428
  new Api31.messages.SendMedia({
6421
6429
  peer: chatId,
6422
6430
  media: new Api31.InputMediaPoll({
@@ -6525,7 +6533,7 @@ var telegramCreateQuizExecutor = async (params, context) => {
6525
6533
  closePeriod,
6526
6534
  closeDate
6527
6535
  });
6528
- const result = await gramJsClient.invoke(
6536
+ const _result = await gramJsClient.invoke(
6529
6537
  new Api32.messages.SendMedia({
6530
6538
  peer: chatId,
6531
6539
  media: new Api32.InputMediaPoll({
@@ -7048,7 +7056,7 @@ var telegramGetFoldersExecutor = async (_params, context) => {
7048
7056
  const filterList = dialogFilters.filters ?? [];
7049
7057
  const folders = filterList.filter((filter) => filter.className === "DialogFilter").map((filter) => ({
7050
7058
  id: filter.id,
7051
- title: filter.title?.text ?? filter.title,
7059
+ title: filter.title.text,
7052
7060
  emoji: filter.emoticon || null,
7053
7061
  pinnedPeersCount: filter.pinnedPeers?.length || 0,
7054
7062
  includedPeersCount: filter.includePeers?.length || 0,
@@ -7211,7 +7219,7 @@ var telegramAddChatToFolderExecutor = async (params, context) => {
7211
7219
  error: `Folder with ID ${folderId} not found`
7212
7220
  };
7213
7221
  }
7214
- const chatEntity = await gramJsClient.getEntity(chatId);
7222
+ const _chatEntity = await gramJsClient.getEntity(chatId);
7215
7223
  const inputPeer = await gramJsClient.getInputEntity(chatId);
7216
7224
  const updatedIncludePeers = [...folder.includePeers || []];
7217
7225
  updatedIncludePeers.push(inputPeer);
@@ -7290,7 +7298,7 @@ var telegramUpdateProfileExecutor = async (params, context) => {
7290
7298
  const gramJsClient = context.bridge.getClient().getClient();
7291
7299
  const updates = {};
7292
7300
  if (firstName !== void 0 || lastName !== void 0) {
7293
- const nameResult = await gramJsClient.invoke(
7301
+ const _nameResult = await gramJsClient.invoke(
7294
7302
  new Api42.account.UpdateProfile({
7295
7303
  firstName,
7296
7304
  lastName
@@ -7396,7 +7404,7 @@ var telegramSetUsernameExecutor = async (params, context) => {
7396
7404
  }
7397
7405
  }
7398
7406
  const gramJsClient = context.bridge.getClient().getClient();
7399
- const result = await gramJsClient.invoke(
7407
+ const _result = await gramJsClient.invoke(
7400
7408
  new Api44.account.UpdateUsername({
7401
7409
  username: username || ""
7402
7410
  })
@@ -8074,15 +8082,15 @@ function decodeInlineMessageId(encoded) {
8074
8082
  if (buf.length === 20) {
8075
8083
  return new Api49.InputBotInlineMessageID({
8076
8084
  dcId: buf.readInt32LE(0),
8077
- id: buf.readBigInt64LE(4),
8078
- accessHash: buf.readBigInt64LE(12)
8085
+ id: toLong(buf.readBigInt64LE(4)),
8086
+ accessHash: toLong(buf.readBigInt64LE(12))
8079
8087
  });
8080
8088
  } else if (buf.length === 24) {
8081
8089
  return new Api49.InputBotInlineMessageID64({
8082
8090
  dcId: buf.readInt32LE(0),
8083
- ownerId: buf.readBigInt64LE(4),
8091
+ ownerId: toLong(buf.readBigInt64LE(4)),
8084
8092
  id: buf.readInt32LE(12),
8085
- accessHash: buf.readBigInt64LE(16)
8093
+ accessHash: toLong(buf.readBigInt64LE(16))
8086
8094
  });
8087
8095
  }
8088
8096
  throw new Error(`Unknown inline_message_id format (${buf.length} bytes)`);
@@ -8841,7 +8849,7 @@ var VerificationPoller = class {
8841
8849
  const me = this.bridge.getClient().getMe();
8842
8850
  if (!me) return { verified: false };
8843
8851
  const botUserId = Number(me.id);
8844
- const { telegramGetMyGiftsExecutor: telegramGetMyGiftsExecutor2 } = await import("./get-my-gifts-OMGKOEPM.js");
8852
+ const { telegramGetMyGiftsExecutor: telegramGetMyGiftsExecutor2 } = await import("./get-my-gifts-Y7EN7RK4.js");
8845
8853
  const toolContext = {
8846
8854
  bridge: this.bridge,
8847
8855
  db: this.db,
@@ -8856,7 +8864,8 @@ var VerificationPoller = class {
8856
8864
  if (!result.success || !result.data) {
8857
8865
  return { verified: false };
8858
8866
  }
8859
- const gifts = result.data.gifts || [];
8867
+ const verifyData = result.data;
8868
+ const gifts = verifyData.gifts || [];
8860
8869
  const matchingGift = gifts.find(
8861
8870
  (g) => g.slug === deal.userGivesGiftSlug && Number(g.fromId) === deal.userId && g.date && g.date >= deal.createdAt
8862
8871
  );
@@ -9066,9 +9075,10 @@ var DealBot = class {
9066
9075
  await this.editViaGramJS(inlineMessageId, text, buttons);
9067
9076
  edited = true;
9068
9077
  } catch (error) {
9078
+ const errMsg = error?.errorMessage;
9069
9079
  log68.warn(
9070
9080
  { err: error },
9071
- `[Bot] chosen_inline_result GramJS edit failed: ${error?.errorMessage || error}`
9081
+ `[Bot] chosen_inline_result GramJS edit failed: ${errMsg || error}`
9072
9082
  );
9073
9083
  }
9074
9084
  }
@@ -9081,9 +9091,10 @@ var DealBot = class {
9081
9091
  reply_markup: keyboard
9082
9092
  });
9083
9093
  } catch (error) {
9094
+ const errDesc = error?.description;
9084
9095
  log68.error(
9085
9096
  { err: error },
9086
- `[Bot] chosen_inline_result Grammy fallback failed: ${error?.description || error}`
9097
+ `[Bot] chosen_inline_result Grammy fallback failed: ${errDesc || error}`
9087
9098
  );
9088
9099
  }
9089
9100
  }
@@ -9245,10 +9256,11 @@ var DealBot = class {
9245
9256
  await this.editViaGramJS(inlineMsgId, text, buttons);
9246
9257
  return;
9247
9258
  } catch (error) {
9248
- if (error?.errorMessage === "MESSAGE_NOT_MODIFIED") return;
9259
+ const errMsg = error?.errorMessage;
9260
+ if (errMsg === "MESSAGE_NOT_MODIFIED") return;
9249
9261
  log68.warn(
9250
9262
  { err: error },
9251
- `[Bot] GramJS edit failed, falling back to Grammy: ${error?.errorMessage || error}`
9263
+ `[Bot] GramJS edit failed, falling back to Grammy: ${errMsg || error}`
9252
9264
  );
9253
9265
  }
9254
9266
  }
@@ -9260,7 +9272,8 @@ var DealBot = class {
9260
9272
  reply_markup: keyboard
9261
9273
  });
9262
9274
  } catch (error) {
9263
- if (error?.description?.includes("message is not modified")) return;
9275
+ const desc = error?.description;
9276
+ if (desc?.includes("message is not modified")) return;
9264
9277
  log68.error({ err: error }, "[Bot] Failed to edit inline message");
9265
9278
  }
9266
9279
  }
@@ -9270,10 +9283,11 @@ var DealBot = class {
9270
9283
  await this.editViaGramJS(inlineMessageId, text, buttons);
9271
9284
  return;
9272
9285
  } catch (error) {
9273
- if (error?.errorMessage === "MESSAGE_NOT_MODIFIED") return;
9286
+ const errMsg = error?.errorMessage;
9287
+ if (errMsg === "MESSAGE_NOT_MODIFIED") return;
9274
9288
  log68.warn(
9275
9289
  { err: error },
9276
- `[Bot] GramJS edit failed, falling back to Grammy: ${error?.errorMessage || error}`
9290
+ `[Bot] GramJS edit failed, falling back to Grammy: ${errMsg || error}`
9277
9291
  );
9278
9292
  }
9279
9293
  }
@@ -9732,7 +9746,8 @@ var GiftDetector = class {
9732
9746
  if (!result.success || !result.data) {
9733
9747
  return [];
9734
9748
  }
9735
- const gifts = result.data.gifts || [];
9749
+ const data = result.data;
9750
+ const gifts = data.gifts || [];
9736
9751
  const seenSet = this.seenGifts.get(userId) || /* @__PURE__ */ new Set();
9737
9752
  const newGifts = [];
9738
9753
  const currentMsgIds = /* @__PURE__ */ new Set();
@@ -10362,7 +10377,7 @@ var dealsModule = {
10362
10377
  closeDealsDb();
10363
10378
  }
10364
10379
  };
10365
- var module_default = dealsModule;
10380
+ var module_default2 = dealsModule;
10366
10381
  function hasVerifiedDeal(giftId, userId) {
10367
10382
  const dealsDb = getDealsDb();
10368
10383
  if (!dealsDb) return false;
@@ -10417,7 +10432,7 @@ var telegramSendGiftExecutor = async (params, context) => {
10417
10432
  const user = await gramJsClient.getInputEntity(userId);
10418
10433
  const invoiceData = {
10419
10434
  peer: user,
10420
- giftId: BigInt(giftId),
10435
+ giftId: toLong(giftId),
10421
10436
  hideName: anonymous,
10422
10437
  message: message ? new Api51.TextWithEntities({ text: message, entities: [] }) : void 0
10423
10438
  };
@@ -10603,7 +10618,7 @@ var telegramSetCollectiblePriceExecutor = async (params, context) => {
10603
10618
  new Api53.payments.UpdateStarGiftPrice({
10604
10619
  stargift: new Api53.InputSavedStarGiftUser({ msgId }),
10605
10620
  resellAmount: new Api53.StarsAmount({
10606
- amount: BigInt(isListing ? price : 0),
10621
+ amount: toLong(isListing ? price : 0),
10607
10622
  nanos: 0
10608
10623
  })
10609
10624
  })
@@ -10681,7 +10696,7 @@ var telegramGetResaleGiftsExecutor = async (params, context) => {
10681
10696
  }
10682
10697
  const result = await gramJsClient.invoke(
10683
10698
  new Api54.payments.GetResaleStarGifts({
10684
- giftId: BigInt(giftId),
10699
+ giftId: toLong(giftId),
10685
10700
  offset: "",
10686
10701
  limit,
10687
10702
  sortByPrice
@@ -10704,6 +10719,7 @@ var telegramGetResaleGiftsExecutor = async (params, context) => {
10704
10719
  ownerName: gift.ownerName || void 0,
10705
10720
  priceStars: starsPrice ? starsPrice.amount?.toString() : void 0,
10706
10721
  priceTon: tonPrice ? tonPrice.amount?.toString() : void 0,
10722
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10707
10723
  attributes: (gift.attributes || []).map((attr) => ({
10708
10724
  type: attr.className?.replace("StarGiftAttribute", "").toLowerCase(),
10709
10725
  name: attr.name
@@ -10835,7 +10851,7 @@ var telegramSetGiftStatusExecutor = async (params, context) => {
10835
10851
  emojiStatus = new Api56.EmojiStatusEmpty();
10836
10852
  } else {
10837
10853
  emojiStatus = new Api56.InputEmojiStatusCollectible({
10838
- collectibleId: BigInt(collectibleId)
10854
+ collectibleId: toLong(collectibleId)
10839
10855
  });
10840
10856
  }
10841
10857
  await gramJsClient.invoke(
@@ -10955,11 +10971,13 @@ var telegramGetUniqueGiftExecutor = async (params, context) => {
10955
10971
  lastName: ownerUser?.lastName || void 0
10956
10972
  },
10957
10973
  giftAddress: gift.giftAddress || void 0,
10974
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10958
10975
  attributes: (gift.attributes || []).map((attr) => ({
10959
10976
  type: attr.className?.replace("StarGiftAttribute", "").toLowerCase(),
10960
10977
  name: attr.name,
10961
10978
  rarityPercent: attr.rarityPermille ? attr.rarityPermille / 10 : void 0
10962
10979
  })),
10980
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10963
10981
  resellPrices: (gift.resellAmount || []).map((a) => ({
10964
10982
  amount: a.amount?.toString(),
10965
10983
  isTon: !!a.ton
@@ -11070,7 +11088,7 @@ var telegramSendGiftOfferExecutor = async (params, context) => {
11070
11088
  new Api60.payments.SendStarGiftOffer({
11071
11089
  peer,
11072
11090
  slug,
11073
- price: new Api60.StarsAmount({ amount: BigInt(price), nanos: 0 }),
11091
+ price: new Api60.StarsAmount({ amount: toLong(price), nanos: 0 }),
11074
11092
  duration,
11075
11093
  randomId: randomLong()
11076
11094
  })
@@ -11378,7 +11396,7 @@ var telegramGetUserInfoExecutor = async (params, context) => {
11378
11396
  } else {
11379
11397
  entity = await gramJsClient.getEntity(userId);
11380
11398
  }
11381
- } catch (error) {
11399
+ } catch {
11382
11400
  return {
11383
11401
  success: false,
11384
11402
  error: `User not found: ${username || userId}`
@@ -12092,7 +12110,7 @@ var telegramCreateScheduledTaskExecutor = async (params, context) => {
12092
12110
  };
12093
12111
  }
12094
12112
  }
12095
- } catch (e) {
12113
+ } catch {
12096
12114
  return {
12097
12115
  success: false,
12098
12116
  error: "Invalid JSON payload"
@@ -12105,7 +12123,7 @@ var telegramCreateScheduledTaskExecutor = async (params, context) => {
12105
12123
  error: "Database not available"
12106
12124
  };
12107
12125
  }
12108
- const { getTaskStore } = await import("./tasks-BEZ4QRI2.js");
12126
+ const { getTaskStore } = await import("./tasks-WQIKXDX5.js");
12109
12127
  const taskStore = getTaskStore(context.db);
12110
12128
  if (dependsOn && dependsOn.length > 0) {
12111
12129
  for (const parentId of dependsOn) {
@@ -12212,7 +12230,7 @@ var tonGetAddressTool = {
12212
12230
  description: "Return your TON wallet address in EQ format. No parameters needed.",
12213
12231
  parameters: Type81.Object({})
12214
12232
  };
12215
- var tonGetAddressExecutor = async (params, context) => {
12233
+ var tonGetAddressExecutor = async (_params, _context) => {
12216
12234
  try {
12217
12235
  const address = getWalletAddress();
12218
12236
  if (!address) {
@@ -12247,7 +12265,7 @@ var tonGetBalanceTool = {
12247
12265
  parameters: Type82.Object({}),
12248
12266
  category: "data-bearing"
12249
12267
  };
12250
- var tonGetBalanceExecutor = async (params, context) => {
12268
+ var tonGetBalanceExecutor = async (_params, _context) => {
12251
12269
  try {
12252
12270
  const address = getWalletAddress();
12253
12271
  if (!address) {
@@ -12291,7 +12309,7 @@ var tonPriceTool = {
12291
12309
  category: "data-bearing",
12292
12310
  parameters: Type83.Object({})
12293
12311
  };
12294
- var tonPriceExecutor = async (params, context) => {
12312
+ var tonPriceExecutor = async (_params, _context) => {
12295
12313
  try {
12296
12314
  const priceData = await getTonPrice();
12297
12315
  if (!priceData) {
@@ -12406,13 +12424,13 @@ var tonGetTransactionsTool = {
12406
12424
  )
12407
12425
  })
12408
12426
  };
12409
- var tonGetTransactionsExecutor = async (params, context) => {
12427
+ var tonGetTransactionsExecutor = async (params, _context) => {
12410
12428
  try {
12411
12429
  const { address, limit = 10 } = params;
12412
12430
  let addressObj;
12413
12431
  try {
12414
12432
  addressObj = Address5.parse(address);
12415
- } catch (e) {
12433
+ } catch {
12416
12434
  return {
12417
12435
  success: false,
12418
12436
  error: `Invalid address: ${address}`
@@ -12457,7 +12475,7 @@ var tonMyTransactionsTool = {
12457
12475
  )
12458
12476
  })
12459
12477
  };
12460
- var tonMyTransactionsExecutor = async (params, context) => {
12478
+ var tonMyTransactionsExecutor = async (params, _context) => {
12461
12479
  try {
12462
12480
  const { limit = 10 } = params;
12463
12481
  const walletData = loadWallet();
@@ -12517,7 +12535,7 @@ var PERIOD_CONFIG = {
12517
12535
  "90d": { seconds: 7776e3, points: 180 },
12518
12536
  "1y": { seconds: 31536e3, points: 200 }
12519
12537
  };
12520
- var tonChartExecutor = async (params, context) => {
12538
+ var tonChartExecutor = async (params, _context) => {
12521
12539
  try {
12522
12540
  const token = params.token || "ton";
12523
12541
  const period = params.period || "7d";
@@ -12621,7 +12639,7 @@ var nftListTool = {
12621
12639
  }),
12622
12640
  category: "data-bearing"
12623
12641
  };
12624
- var nftListExecutor = async (params, context) => {
12642
+ var nftListExecutor = async (params, _context) => {
12625
12643
  try {
12626
12644
  const address = params.address || getWalletAddress();
12627
12645
  if (!address) {
@@ -12735,7 +12753,7 @@ var jettonSendTool = {
12735
12753
  )
12736
12754
  })
12737
12755
  };
12738
- var jettonSendExecutor = async (params, context) => {
12756
+ var jettonSendExecutor = async (params, _context) => {
12739
12757
  try {
12740
12758
  const { jetton_address, to, amount, comment } = params;
12741
12759
  const walletData = loadWallet();
@@ -12854,7 +12872,7 @@ var jettonBalancesTool = {
12854
12872
  parameters: Type90.Object({}),
12855
12873
  category: "data-bearing"
12856
12874
  };
12857
- var jettonBalancesExecutor = async (params, context) => {
12875
+ var jettonBalancesExecutor = async (_params, _context) => {
12858
12876
  try {
12859
12877
  const walletData = loadWallet();
12860
12878
  if (!walletData) {
@@ -12964,7 +12982,7 @@ var jettonInfoTool = {
12964
12982
  })
12965
12983
  })
12966
12984
  };
12967
- var jettonInfoExecutor = async (params, context) => {
12985
+ var jettonInfoExecutor = async (params, _context) => {
12968
12986
  try {
12969
12987
  const { jetton_address } = params;
12970
12988
  const response = await tonapiFetch(`/jettons/${jetton_address}`);
@@ -13061,7 +13079,7 @@ var jettonPriceTool = {
13061
13079
  })
13062
13080
  })
13063
13081
  };
13064
- var jettonPriceExecutor = async (params, context) => {
13082
+ var jettonPriceExecutor = async (params, _context) => {
13065
13083
  try {
13066
13084
  const { jetton_address } = params;
13067
13085
  const response = await tonapiFetch(
@@ -13169,7 +13187,7 @@ var jettonHoldersTool = {
13169
13187
  )
13170
13188
  })
13171
13189
  };
13172
- var jettonHoldersExecutor = async (params, context) => {
13190
+ var jettonHoldersExecutor = async (params, _context) => {
13173
13191
  try {
13174
13192
  const { jetton_address, limit = 10 } = params;
13175
13193
  const response = await tonapiFetch(
@@ -13212,7 +13230,8 @@ var jettonHoldersExecutor = async (params, context) => {
13212
13230
  isWallet: h.owner?.is_wallet || false
13213
13231
  };
13214
13232
  });
13215
- const totalTop = holders.reduce(
13233
+ const _totalTop = holders.reduce(
13234
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TON API response is untyped
13216
13235
  (sum, h) => sum + parseFloat(h.balance.replace(/,/g, "")),
13217
13236
  0
13218
13237
  );
@@ -13258,7 +13277,7 @@ var jettonHistoryTool = {
13258
13277
  })
13259
13278
  })
13260
13279
  };
13261
- var jettonHistoryExecutor = async (params, context) => {
13280
+ var jettonHistoryExecutor = async (params, _context) => {
13262
13281
  try {
13263
13282
  const { jetton_address } = params;
13264
13283
  const ratesResponse = await tonapiFetch(
@@ -13524,7 +13543,7 @@ async function getDedustQuote(fromAsset, toAsset, amount, slippage, tonClient) {
13524
13543
  };
13525
13544
  }
13526
13545
  }
13527
- var dexQuoteExecutor = async (params, context) => {
13546
+ var dexQuoteExecutor = async (params, _context) => {
13528
13547
  try {
13529
13548
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
13530
13549
  const tonClient = await getCachedTonClient();
@@ -13671,7 +13690,7 @@ function estimateMinPrice(length) {
13671
13690
  if (length >= 6 && length <= 10) return "~5-10 TON";
13672
13691
  return "~1 TON";
13673
13692
  }
13674
- var dnsCheckExecutor = async (params, context) => {
13693
+ var dnsCheckExecutor = async (params, _context) => {
13675
13694
  try {
13676
13695
  let { domain } = params;
13677
13696
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -13790,7 +13809,7 @@ var dnsAuctionsTool = {
13790
13809
  )
13791
13810
  })
13792
13811
  };
13793
- var dnsAuctionsExecutor = async (params, context) => {
13812
+ var dnsAuctionsExecutor = async (params, _context) => {
13794
13813
  try {
13795
13814
  const { limit = 20 } = params;
13796
13815
  const response = await tonapiFetch(`/dns/auctions?tld=ton`);
@@ -13824,6 +13843,7 @@ var dnsAuctionsExecutor = async (params, context) => {
13824
13843
  };
13825
13844
  });
13826
13845
  const summary = formattedAuctions.map(
13846
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TON DNS API response is untyped
13827
13847
  (a, i) => `${i + 1}. ${a.domain} - ${a.currentBid} (${a.bids} bids) - Ends: ${a.endDate}`
13828
13848
  ).join("\n");
13829
13849
  return {
@@ -13860,7 +13880,7 @@ var dnsResolveTool = {
13860
13880
  })
13861
13881
  })
13862
13882
  };
13863
- var dnsResolveExecutor = async (params, context) => {
13883
+ var dnsResolveExecutor = async (params, _context) => {
13864
13884
  try {
13865
13885
  let { domain } = params;
13866
13886
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -13931,9 +13951,10 @@ var dnsStartAuctionTool = {
13931
13951
  })
13932
13952
  })
13933
13953
  };
13934
- var dnsStartAuctionExecutor = async (params, context) => {
13954
+ var dnsStartAuctionExecutor = async (params, _context) => {
13935
13955
  try {
13936
- let { domain, amount } = params;
13956
+ let { domain } = params;
13957
+ const { amount } = params;
13937
13958
  domain = domain.toLowerCase().replace(/\.ton$/, "");
13938
13959
  if (domain.length < 4 || domain.length > 126) {
13939
13960
  return {
@@ -14021,9 +14042,10 @@ var dnsBidTool = {
14021
14042
  })
14022
14043
  })
14023
14044
  };
14024
- var dnsBidExecutor = async (params, context) => {
14045
+ var dnsBidExecutor = async (params, _context) => {
14025
14046
  try {
14026
- let { domain, amount } = params;
14047
+ let { domain } = params;
14048
+ const { amount } = params;
14027
14049
  domain = domain.toLowerCase().replace(/\.ton$/, "");
14028
14050
  const fullDomain = `${domain}.ton`;
14029
14051
  const dnsResponse = await tonapiFetch(`/dns/${fullDomain}`);
@@ -14148,9 +14170,10 @@ var dnsLinkTool = {
14148
14170
  )
14149
14171
  })
14150
14172
  };
14151
- var dnsLinkExecutor = async (params, context) => {
14173
+ var dnsLinkExecutor = async (params, _context) => {
14152
14174
  try {
14153
- let { domain, wallet_address } = params;
14175
+ let { domain } = params;
14176
+ const { wallet_address } = params;
14154
14177
  domain = domain.toLowerCase().replace(/\.ton$/, "");
14155
14178
  const fullDomain = `${domain}.ton`;
14156
14179
  const walletData = loadWallet();
@@ -14273,7 +14296,7 @@ var dnsUnlinkTool = {
14273
14296
  })
14274
14297
  })
14275
14298
  };
14276
- var dnsUnlinkExecutor = async (params, context) => {
14299
+ var dnsUnlinkExecutor = async (params, _context) => {
14277
14300
  try {
14278
14301
  let { domain } = params;
14279
14302
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -14391,7 +14414,7 @@ var dnsSetSiteTool = {
14391
14414
  })
14392
14415
  })
14393
14416
  };
14394
- var dnsSetSiteExecutor = async (params, context) => {
14417
+ var dnsSetSiteExecutor = async (params, _context) => {
14395
14418
  try {
14396
14419
  let { domain, adnl_address } = params;
14397
14420
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -14537,7 +14560,7 @@ var stonfiSwapTool = {
14537
14560
  )
14538
14561
  })
14539
14562
  };
14540
- var stonfiSwapExecutor = async (params, context) => {
14563
+ var stonfiSwapExecutor = async (params, _context) => {
14541
14564
  try {
14542
14565
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
14543
14566
  const walletData = loadWallet();
@@ -14711,7 +14734,7 @@ var stonfiQuoteTool = {
14711
14734
  )
14712
14735
  })
14713
14736
  };
14714
- var stonfiQuoteExecutor = async (params, context) => {
14737
+ var stonfiQuoteExecutor = async (params, _context) => {
14715
14738
  try {
14716
14739
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
14717
14740
  const isTonInput = from_asset.toLowerCase() === "ton" || from_asset === NATIVE_TON_ADDRESS3;
@@ -14817,7 +14840,7 @@ var stonfiSearchTool = {
14817
14840
  )
14818
14841
  })
14819
14842
  };
14820
- var stonfiSearchExecutor = async (params, context) => {
14843
+ var stonfiSearchExecutor = async (params, _context) => {
14821
14844
  try {
14822
14845
  const { query, limit = 10 } = params;
14823
14846
  const searchQuery = query.toLowerCase().trim();
@@ -14880,7 +14903,7 @@ var stonfiSearchExecutor = async (params, context) => {
14880
14903
  }
14881
14904
  results.sort((a, b) => b.score - a.score);
14882
14905
  const topResults = results.slice(0, Math.min(limit, 50));
14883
- const cleanResults = topResults.map(({ score, ...rest }) => rest);
14906
+ const cleanResults = topResults.map(({ score: _score, ...rest }) => rest);
14884
14907
  let message = "";
14885
14908
  if (cleanResults.length === 0) {
14886
14909
  message = `No jettons found matching "${query}". Try a different search term.`;
@@ -14934,7 +14957,7 @@ var stonfiTrendingTool = {
14934
14957
  )
14935
14958
  })
14936
14959
  };
14937
- var stonfiTrendingExecutor = async (params, context) => {
14960
+ var stonfiTrendingExecutor = async (params, _context) => {
14938
14961
  try {
14939
14962
  const { limit = 10 } = params;
14940
14963
  const response = await fetchWithTimeout(`${STONFI_API_BASE_URL}/assets`, {
@@ -15014,7 +15037,7 @@ var stonfiPoolsTool = {
15014
15037
  )
15015
15038
  })
15016
15039
  };
15017
- var stonfiPoolsExecutor = async (params, context) => {
15040
+ var stonfiPoolsExecutor = async (params, _context) => {
15018
15041
  try {
15019
15042
  const { jetton_address, limit = 10 } = params;
15020
15043
  const response = await fetchWithTimeout(`${STONFI_API_BASE_URL}/pools`, {
@@ -15037,6 +15060,7 @@ var stonfiPoolsExecutor = async (params, context) => {
15037
15060
  });
15038
15061
  }
15039
15062
  pools = pools.filter((p) => !p.deprecated).sort(
15063
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- DEX API response is untyped
15040
15064
  (a, b) => parseFloat(b.volume_24h_usd || "0") - parseFloat(a.volume_24h_usd || "0")
15041
15065
  ).slice(0, limit);
15042
15066
  const assetMap = {};
@@ -15149,7 +15173,7 @@ var dedustQuoteTool = {
15149
15173
  )
15150
15174
  })
15151
15175
  };
15152
- var dedustQuoteExecutor = async (params, context) => {
15176
+ var dedustQuoteExecutor = async (params, _context) => {
15153
15177
  try {
15154
15178
  const { from_asset, to_asset, amount, pool_type = "volatile", slippage = 0.01 } = params;
15155
15179
  const isTonInput = from_asset.toLowerCase() === "ton";
@@ -15159,7 +15183,7 @@ var dedustQuoteExecutor = async (params, context) => {
15159
15183
  if (!isTonInput) {
15160
15184
  try {
15161
15185
  fromAssetAddr = Address15.parse(from_asset).toString();
15162
- } catch (error) {
15186
+ } catch {
15163
15187
  return {
15164
15188
  success: false,
15165
15189
  error: `Invalid from_asset address: ${from_asset}`
@@ -15169,7 +15193,7 @@ var dedustQuoteExecutor = async (params, context) => {
15169
15193
  if (!isTonOutput) {
15170
15194
  try {
15171
15195
  toAssetAddr = Address15.parse(to_asset).toString();
15172
- } catch (error) {
15196
+ } catch {
15173
15197
  return {
15174
15198
  success: false,
15175
15199
  error: `Invalid to_asset address: ${to_asset}`
@@ -15290,7 +15314,7 @@ var dedustSwapTool = {
15290
15314
  )
15291
15315
  })
15292
15316
  };
15293
- var dedustSwapExecutor = async (params, context) => {
15317
+ var dedustSwapExecutor = async (params, _context) => {
15294
15318
  try {
15295
15319
  const { from_asset, to_asset, amount, pool_type = "volatile", slippage = 0.01 } = params;
15296
15320
  const walletData = loadWallet();
@@ -15307,7 +15331,7 @@ var dedustSwapExecutor = async (params, context) => {
15307
15331
  if (!isTonInput) {
15308
15332
  try {
15309
15333
  fromAssetAddr = Address16.parse(from_asset).toString();
15310
- } catch (error) {
15334
+ } catch {
15311
15335
  return {
15312
15336
  success: false,
15313
15337
  error: `Invalid from_asset address: ${from_asset}`
@@ -15317,7 +15341,7 @@ var dedustSwapExecutor = async (params, context) => {
15317
15341
  if (!isTonOutput) {
15318
15342
  try {
15319
15343
  toAssetAddr = Address16.parse(to_asset).toString();
15320
- } catch (error) {
15344
+ } catch {
15321
15345
  return {
15322
15346
  success: false,
15323
15347
  error: `Invalid to_asset address: ${to_asset}`
@@ -15472,7 +15496,7 @@ var dedustPoolsTool = {
15472
15496
  )
15473
15497
  })
15474
15498
  };
15475
- var dedustPoolsExecutor = async (params, context) => {
15499
+ var dedustPoolsExecutor = async (params, _context) => {
15476
15500
  try {
15477
15501
  const { jetton_address, pool_type, limit = 20 } = params;
15478
15502
  const response = await fetchWithTimeout(`${DEDUST_API_URL}/pools`);
@@ -16146,7 +16170,7 @@ function listDir(dirPath, recursive, filter) {
16146
16170
  results.push(...listDir(fullPath, recursive, filter));
16147
16171
  }
16148
16172
  }
16149
- } catch (error) {
16173
+ } catch {
16150
16174
  }
16151
16175
  return results;
16152
16176
  }
@@ -16881,6 +16905,116 @@ function registerAllTools(registry) {
16881
16905
  }
16882
16906
  }
16883
16907
 
16908
+ // src/sdk/hooks/runner.ts
16909
+ var DEFAULT_TIMEOUT_MS = 5e3;
16910
+ async function withTimeout(fn, ms, label, _log) {
16911
+ let timer;
16912
+ try {
16913
+ await Promise.race([
16914
+ Promise.resolve(fn()),
16915
+ new Promise((_, reject) => {
16916
+ timer = setTimeout(() => reject(new Error(`Hook timeout: ${label}`)), ms);
16917
+ })
16918
+ ]);
16919
+ } finally {
16920
+ if (timer !== void 0) clearTimeout(timer);
16921
+ }
16922
+ }
16923
+ var BLOCKABLE_HOOKS = /* @__PURE__ */ new Set([
16924
+ "tool:before",
16925
+ "message:receive",
16926
+ "response:before"
16927
+ ]);
16928
+ function createHookRunner(registry, opts) {
16929
+ let hookDepth = 0;
16930
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
16931
+ const catchErrors = opts.catchErrors ?? true;
16932
+ async function runModifyingHook(name, event) {
16933
+ if (!registry.hasHooks(name) || hookDepth > 0) {
16934
+ if (hookDepth > 0) {
16935
+ opts.logger.debug(`Skipping ${name} hooks (reentrancy depth=${hookDepth})`);
16936
+ }
16937
+ return;
16938
+ }
16939
+ const hooks = registry.getHooks(name);
16940
+ hookDepth++;
16941
+ try {
16942
+ for (const hook of hooks) {
16943
+ const label = `${hook.pluginId}:${name}`;
16944
+ const t0 = Date.now();
16945
+ try {
16946
+ await withTimeout(
16947
+ () => hook.handler(event),
16948
+ timeoutMs,
16949
+ label,
16950
+ opts.logger
16951
+ );
16952
+ } catch (err) {
16953
+ if (catchErrors) {
16954
+ opts.logger.error(
16955
+ `Hook error [${label}]: ${getErrorMessage(err)} (after ${Date.now() - t0}ms)`
16956
+ );
16957
+ } else {
16958
+ throw err;
16959
+ }
16960
+ }
16961
+ if (BLOCKABLE_HOOKS.has(name) && event.block) {
16962
+ break;
16963
+ }
16964
+ }
16965
+ } finally {
16966
+ hookDepth--;
16967
+ }
16968
+ }
16969
+ async function runObservingHook(name, event) {
16970
+ if (!registry.hasHooks(name) || hookDepth > 0) {
16971
+ if (hookDepth > 0) {
16972
+ opts.logger.debug(`Skipping ${name} hooks (reentrancy depth=${hookDepth})`);
16973
+ }
16974
+ return;
16975
+ }
16976
+ const hooks = registry.getHooks(name);
16977
+ hookDepth++;
16978
+ try {
16979
+ const results = await Promise.allSettled(
16980
+ hooks.map(async (hook) => {
16981
+ const label = `${hook.pluginId}:${name}`;
16982
+ const t0 = Date.now();
16983
+ try {
16984
+ await withTimeout(
16985
+ () => hook.handler(event),
16986
+ timeoutMs,
16987
+ label,
16988
+ opts.logger
16989
+ );
16990
+ } catch (err) {
16991
+ if (catchErrors) {
16992
+ opts.logger.error(
16993
+ `Hook error [${label}]: ${getErrorMessage(err)} (after ${Date.now() - t0}ms)`
16994
+ );
16995
+ } else {
16996
+ throw err;
16997
+ }
16998
+ }
16999
+ })
17000
+ );
17001
+ if (!catchErrors) {
17002
+ const firstRejected = results.find((r) => r.status === "rejected");
17003
+ if (firstRejected) throw firstRejected.reason;
17004
+ }
17005
+ } finally {
17006
+ hookDepth--;
17007
+ }
17008
+ }
17009
+ return {
17010
+ runModifyingHook,
17011
+ runObservingHook,
17012
+ get depth() {
17013
+ return hookDepth;
17014
+ }
17015
+ };
17016
+ }
17017
+
16884
17018
  // src/agent/tools/exec/run.ts
16885
17019
  import { Type as Type126 } from "@sinclair/typebox";
16886
17020
 
@@ -16917,9 +17051,9 @@ function runCommand(command, options) {
16917
17051
  timedOut
16918
17052
  });
16919
17053
  };
16920
- child.stdout.setEncoding("utf8");
16921
- child.stderr.setEncoding("utf8");
16922
- child.stdout.on("data", (chunk) => {
17054
+ child.stdout?.setEncoding("utf8");
17055
+ child.stderr?.setEncoding("utf8");
17056
+ child.stdout?.on("data", (chunk) => {
16923
17057
  if (stdout.length < maxOutput) {
16924
17058
  stdout += chunk;
16925
17059
  if (stdout.length > maxOutput) {
@@ -16928,7 +17062,7 @@ function runCommand(command, options) {
16928
17062
  }
16929
17063
  }
16930
17064
  });
16931
- child.stderr.on("data", (chunk) => {
17065
+ child.stderr?.on("data", (chunk) => {
16932
17066
  if (stderr.length < maxOutput) {
16933
17067
  stderr += chunk;
16934
17068
  if (stderr.length > maxOutput) {
@@ -16949,10 +17083,10 @@ function runCommand(command, options) {
16949
17083
  const timeoutTimer = setTimeout(() => {
16950
17084
  timedOut = true;
16951
17085
  log131.warn({ command, timeout }, "Command timed out, sending SIGTERM");
16952
- killProcessGroup(child.pid, "SIGTERM");
17086
+ if (child.pid) killProcessGroup(child.pid, "SIGTERM");
16953
17087
  killTimer = setTimeout(() => {
16954
17088
  log131.warn({ command }, "Grace period expired, sending SIGKILL");
16955
- killProcessGroup(child.pid, "SIGKILL");
17089
+ if (child.pid) killProcessGroup(child.pid, "SIGKILL");
16956
17090
  }, KILL_GRACE_MS);
16957
17091
  }, timeout);
16958
17092
  });
@@ -17314,11 +17448,11 @@ var execModule = {
17314
17448
  log132.info({ mode: moduleConfig.mode, scope: moduleConfig.scope }, "Exec capability active");
17315
17449
  }
17316
17450
  };
17317
- var module_default2 = execModule;
17451
+ var module_default3 = execModule;
17318
17452
 
17319
17453
  // src/agent/tools/module-loader.ts
17320
17454
  var log133 = createLogger("ModuleLoader");
17321
- var BUILTIN_MODULES = [module_default, module_default2];
17455
+ var BUILTIN_MODULES = [module_default2, module_default, module_default3];
17322
17456
  function loadModules(registry, config, db2) {
17323
17457
  const loaded = [];
17324
17458
  for (const mod of BUILTIN_MODULES) {
@@ -17623,7 +17757,7 @@ function parseCommand(config) {
17623
17757
  return { command: parts[0], args: parts.slice(1) };
17624
17758
  }
17625
17759
  function extractText(content) {
17626
- return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n");
17760
+ return content.filter((c) => c.type === "text" && c.text).map((c) => c.text ?? "").join("\n");
17627
17761
  }
17628
17762
  async function loadMcpServers(config) {
17629
17763
  const entries = Object.entries(config.servers).filter(([, cfg]) => cfg.enabled !== false);
@@ -17635,7 +17769,7 @@ async function loadMcpServers(config) {
17635
17769
  const { command, args } = parseCommand(serverConfig);
17636
17770
  const safeEnv = {};
17637
17771
  for (const key of ["PATH", "HOME", "NODE_PATH", "LANG", "TERM"]) {
17638
- if (process.env[key]) safeEnv[key] = process.env[key];
17772
+ if (process.env[key]) safeEnv[key] = process.env[key] ?? "";
17639
17773
  }
17640
17774
  const BLOCKED_ENV_KEYS = /* @__PURE__ */ new Set([
17641
17775
  "LD_PRELOAD",
@@ -17729,10 +17863,23 @@ async function registerMcpTools(connections, registry) {
17729
17863
  const prefixedName = `mcp_${conn.serverName}_${mcpTool.name}`;
17730
17864
  const executor = async (params) => {
17731
17865
  try {
17732
- const result = await conn.client.callTool({
17733
- name: mcpTool.name,
17734
- arguments: params
17735
- });
17866
+ let timeoutHandle;
17867
+ const result = await Promise.race([
17868
+ conn.client.callTool({
17869
+ name: mcpTool.name,
17870
+ arguments: params
17871
+ }),
17872
+ new Promise((_, reject) => {
17873
+ timeoutHandle = setTimeout(
17874
+ () => reject(
17875
+ new Error(
17876
+ `MCP tool "${mcpTool.name}" timed out after ${TOOL_EXECUTION_TIMEOUT_MS / 1e3}s`
17877
+ )
17878
+ ),
17879
+ TOOL_EXECUTION_TIMEOUT_MS
17880
+ );
17881
+ })
17882
+ ]).finally(() => clearTimeout(timeoutHandle));
17736
17883
  if (result.isError) {
17737
17884
  const errorText = extractText(
17738
17885
  result.content
@@ -17795,6 +17942,101 @@ async function closeMcpServers(connections) {
17795
17942
  );
17796
17943
  }
17797
17944
 
17945
+ // src/agent/hooks/user-hook-evaluator.ts
17946
+ var ZERO_WIDTH_RE = /[\u200B-\u200D\uFEFF\u00AD]/g;
17947
+ var TOKEN_SPLIT_RE = /[\s,.!?;:'"()\[\]{}<>/\\|@#$%^&*+=~`]+/;
17948
+ function normalize(text) {
17949
+ return text.toLowerCase().normalize("NFKC").replace(ZERO_WIDTH_RE, "");
17950
+ }
17951
+ function tokenize(text) {
17952
+ return normalize(text).split(TOKEN_SPLIT_RE).filter(Boolean);
17953
+ }
17954
+ function matchesMultiWord(messageTokens, keywordTokens) {
17955
+ if (keywordTokens.length > messageTokens.length) return false;
17956
+ for (let i = 0; i <= messageTokens.length - keywordTokens.length; i++) {
17957
+ let match = true;
17958
+ for (let j = 0; j < keywordTokens.length; j++) {
17959
+ if (messageTokens[i + j] !== keywordTokens[j]) {
17960
+ match = false;
17961
+ break;
17962
+ }
17963
+ }
17964
+ if (match) return true;
17965
+ }
17966
+ return false;
17967
+ }
17968
+ var UserHookEvaluator = class {
17969
+ constructor(db2) {
17970
+ this.db = db2;
17971
+ this.reload();
17972
+ }
17973
+ blocklistEnabled = false;
17974
+ singleKeywords = /* @__PURE__ */ new Set();
17975
+ multiKeywords = [];
17976
+ blockMessage = "";
17977
+ triggers = [];
17978
+ /** Reload config from DB — called on startup and after WebUI changes */
17979
+ reload() {
17980
+ const blocklist = getBlocklistConfig(this.db);
17981
+ this.blocklistEnabled = blocklist.enabled;
17982
+ this.blockMessage = blocklist.message;
17983
+ this.singleKeywords.clear();
17984
+ this.multiKeywords = [];
17985
+ for (const kw of blocklist.keywords) {
17986
+ const tokens = tokenize(kw);
17987
+ if (tokens.length === 0) continue;
17988
+ if (tokens.length === 1) {
17989
+ this.singleKeywords.add(tokens[0]);
17990
+ } else {
17991
+ this.multiKeywords.push(tokens);
17992
+ }
17993
+ }
17994
+ const triggers = getTriggersConfig(this.db);
17995
+ this.triggers = triggers.map((t) => ({
17996
+ ...t,
17997
+ keywordTokens: tokenize(t.keyword)
17998
+ }));
17999
+ }
18000
+ /** Evaluate a message — returns { blocked, blockMessage, additionalContext } */
18001
+ evaluate(text) {
18002
+ const tokens = tokenize(text);
18003
+ if (this.blocklistEnabled) {
18004
+ for (const token of tokens) {
18005
+ if (this.singleKeywords.has(token)) {
18006
+ return {
18007
+ blocked: true,
18008
+ blockMessage: this.blockMessage || void 0,
18009
+ additionalContext: ""
18010
+ };
18011
+ }
18012
+ }
18013
+ for (const kwTokens of this.multiKeywords) {
18014
+ if (matchesMultiWord(tokens, kwTokens)) {
18015
+ return {
18016
+ blocked: true,
18017
+ blockMessage: this.blockMessage || void 0,
18018
+ additionalContext: ""
18019
+ };
18020
+ }
18021
+ }
18022
+ }
18023
+ const contexts = [];
18024
+ const seen = /* @__PURE__ */ new Set();
18025
+ for (const trigger of this.triggers) {
18026
+ if (!trigger.enabled || trigger.keywordTokens.length === 0) continue;
18027
+ const matched = trigger.keywordTokens.length === 1 ? tokens.includes(trigger.keywordTokens[0]) : matchesMultiWord(tokens, trigger.keywordTokens);
18028
+ if (matched && !seen.has(trigger.context)) {
18029
+ seen.add(trigger.context);
18030
+ contexts.push(trigger.context);
18031
+ }
18032
+ }
18033
+ return {
18034
+ blocked: false,
18035
+ additionalContext: contexts.join("\n\n")
18036
+ };
18037
+ }
18038
+ };
18039
+
17798
18040
  // src/agent/lifecycle.ts
17799
18041
  import { EventEmitter } from "events";
17800
18042
  var log136 = createLogger("Lifecycle");
@@ -17840,7 +18082,7 @@ var AgentLifecycle = class extends EventEmitter {
17840
18082
  return;
17841
18083
  }
17842
18084
  if (this.state === "starting") {
17843
- return this.startPromise;
18085
+ return this.startPromise ?? Promise.resolve();
17844
18086
  }
17845
18087
  if (this.state === "stopping") {
17846
18088
  throw new Error("Cannot start while agent is stopping");
@@ -17879,7 +18121,7 @@ var AgentLifecycle = class extends EventEmitter {
17879
18121
  return;
17880
18122
  }
17881
18123
  if (this.state === "stopping") {
17882
- return this.stopPromise;
18124
+ return this.stopPromise ?? Promise.resolve();
17883
18125
  }
17884
18126
  if (this.state === "starting" && this.startPromise) {
17885
18127
  try {
@@ -17967,17 +18209,21 @@ var TeletonApp = class {
17967
18209
  debouncer = null;
17968
18210
  toolCount = 0;
17969
18211
  toolRegistry;
17970
- dependencyResolver;
17971
- // TaskDependencyResolver, imported lazily
18212
+ dependencyResolver = null;
17972
18213
  modules = [];
17973
18214
  memory;
17974
18215
  sdkDeps;
17975
18216
  webuiServer = null;
17976
- // WebUIServer, imported lazily
18217
+ apiServer = null;
17977
18218
  pluginWatcher = null;
17978
18219
  mcpConnections = [];
17979
18220
  callbackHandlerRegistered = false;
18221
+ messageHandlersRegistered = false;
17980
18222
  lifecycle = new AgentLifecycle();
18223
+ hookRunner;
18224
+ userHookEvaluator = null;
18225
+ startTime = 0;
18226
+ messagesProcessed = 0;
17981
18227
  configPath;
17982
18228
  constructor(configPath) {
17983
18229
  this.configPath = configPath ?? getDefaultConfigPath();
@@ -18017,6 +18263,8 @@ var TeletonApp = class {
18017
18263
  workspaceDir: join9(TELETON_ROOT)
18018
18264
  });
18019
18265
  const db2 = getDatabase().getDb();
18266
+ this.userHookEvaluator = new UserHookEvaluator(db2);
18267
+ this.agent.setUserHookEvaluator(this.userHookEvaluator);
18020
18268
  this.sdkDeps = { bridge: this.bridge };
18021
18269
  this.modules = loadModules(this.toolRegistry, this.config, db2);
18022
18270
  const modulePermissions = new ModulePermissions(db2);
@@ -18068,7 +18316,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18068
18316
  );
18069
18317
  if (this.config.webui.enabled) {
18070
18318
  try {
18071
- const { WebUIServer } = await import("./server-H3QA252W.js");
18319
+ const { WebUIServer } = await import("./server-YODFBZKG.js");
18072
18320
  const mcpServers = () => Object.entries(this.config.mcp.servers).map(([name, serverConfig]) => {
18073
18321
  const type = serverConfig.command ? "stdio" : serverConfig.url ? "streamable-http" : "sse";
18074
18322
  const target = serverConfig.command ?? serverConfig.url ?? "";
@@ -18110,7 +18358,8 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18110
18358
  pluginContext,
18111
18359
  loadedModuleNames: builtinNames,
18112
18360
  rewireHooks: () => this.wirePluginEventHooks()
18113
- }
18361
+ },
18362
+ userHookEvaluator: this.userHookEvaluator
18114
18363
  });
18115
18364
  await this.webuiServer.start();
18116
18365
  } catch (error) {
@@ -18118,6 +18367,66 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18118
18367
  log137.warn("\u26A0\uFE0F Continuing without WebUI...");
18119
18368
  }
18120
18369
  }
18370
+ if (this.config.api?.enabled) {
18371
+ try {
18372
+ const { ApiServer: ApiServerClass } = await import("./server-GYZXKIKU.js");
18373
+ const mcpServers = () => Object.entries(this.config.mcp.servers).map(([name, serverConfig]) => {
18374
+ const type = serverConfig.command ? "stdio" : serverConfig.url ? "streamable-http" : "sse";
18375
+ const target = serverConfig.command ?? serverConfig.url ?? "";
18376
+ const connected = this.mcpConnections.some((c) => c.serverName === name);
18377
+ const moduleName = `mcp_${name}`;
18378
+ const moduleTools = this.toolRegistry.getModuleTools(moduleName);
18379
+ return {
18380
+ name,
18381
+ type,
18382
+ target,
18383
+ scope: serverConfig.scope ?? "always",
18384
+ enabled: serverConfig.enabled ?? true,
18385
+ connected,
18386
+ toolCount: moduleTools.length,
18387
+ tools: moduleTools.map((t) => t.name),
18388
+ envKeys: Object.keys(serverConfig.env ?? {})
18389
+ };
18390
+ });
18391
+ const builtinNames = this.modules.map((m) => m.name);
18392
+ const pluginContext = {
18393
+ bridge: this.bridge,
18394
+ db: getDatabase().getDb(),
18395
+ config: this.config
18396
+ };
18397
+ this.apiServer = new ApiServerClass(
18398
+ {
18399
+ agent: this.agent,
18400
+ bridge: this.bridge,
18401
+ memory: this.memory,
18402
+ toolRegistry: this.toolRegistry,
18403
+ plugins: this.modules.filter((m) => this.toolRegistry.isPluginModule(m.name)).map((m) => ({ name: m.name, version: m.version ?? "0.0.0" })),
18404
+ mcpServers,
18405
+ config: this.config.webui,
18406
+ configPath: this.configPath,
18407
+ lifecycle: this.lifecycle,
18408
+ marketplace: {
18409
+ modules: this.modules,
18410
+ config: this.config,
18411
+ sdkDeps: this.sdkDeps,
18412
+ pluginContext,
18413
+ loadedModuleNames: builtinNames,
18414
+ rewireHooks: () => this.wirePluginEventHooks()
18415
+ },
18416
+ userHookEvaluator: this.userHookEvaluator
18417
+ },
18418
+ this.config.api
18419
+ );
18420
+ await this.apiServer.start();
18421
+ if (process.env.TELETON_JSON_CREDENTIALS === "true") {
18422
+ const creds = this.apiServer.getCredentials();
18423
+ process.stdout.write(JSON.stringify(creds) + "\n");
18424
+ }
18425
+ } catch (error) {
18426
+ log137.error({ err: error }, "Failed to start Management API server");
18427
+ log137.warn("Continuing without Management API...");
18428
+ }
18429
+ }
18121
18430
  await this.lifecycle.start(() => this.startAgent());
18122
18431
  await new Promise(() => {
18123
18432
  });
@@ -18129,7 +18438,12 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18129
18438
  async startAgent() {
18130
18439
  const moduleNames = this.modules.filter((m) => m.tools(this.config).length > 0).map((m) => m.name);
18131
18440
  const builtinNames = this.modules.map((m) => m.name);
18132
- const externalModules = await loadEnhancedPlugins(this.config, builtinNames, this.sdkDeps);
18441
+ const { modules: externalModules, hookRegistry } = await loadEnhancedPlugins(
18442
+ this.config,
18443
+ builtinNames,
18444
+ this.sdkDeps,
18445
+ getDatabase().getDb()
18446
+ );
18133
18447
  let pluginToolCount = 0;
18134
18448
  const pluginNames = [];
18135
18449
  for (const mod of externalModules) {
@@ -18167,7 +18481,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18167
18481
  }
18168
18482
  this.toolRegistry.loadConfigFromDB(getDatabase().getDb());
18169
18483
  if (this.config.tool_rag.enabled) {
18170
- const { ToolIndex } = await import("./tool-index-H3SHOJC3.js");
18484
+ const { ToolIndex } = await import("./tool-index-NYH57UWP.js");
18171
18485
  const toolIndex2 = new ToolIndex(
18172
18486
  getDatabase().getDb(),
18173
18487
  this.memory.embedder,
@@ -18195,18 +18509,32 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18195
18509
  `\u26A0\uFE0F Tool count (${this.toolCount}) exceeds ${providerMeta.displayName} limit (${providerMeta.toolLimit})`
18196
18510
  );
18197
18511
  }
18198
- const { migrateSessionsToDb } = await import("./migrate-POHWYEIW.js");
18512
+ const { migrateSessionsToDb } = await import("./migrate-WFU6COBN.js");
18199
18513
  migrateSessionsToDb();
18200
- const { cleanupOldTranscripts } = await import("./transcript-IMNE6KU3.js");
18514
+ const { cleanupOldTranscripts } = await import("./transcript-IM7G25OS.js");
18201
18515
  cleanupOldTranscripts(30);
18202
- const { pruneOldSessions } = await import("./store-GAFULOOX.js");
18516
+ const { pruneOldSessions } = await import("./store-7M4XV6M5.js");
18203
18517
  pruneOldSessions(30);
18204
18518
  if (this.memory.embedder.warmup) {
18205
18519
  await this.memory.embedder.warmup();
18206
18520
  }
18207
- const indexResult = await this.memory.knowledge.indexAll();
18208
18521
  const db2 = getDatabase();
18209
- const ftsResult = db2.rebuildFtsIndexes();
18522
+ const forceReindex = db2.didDimensionsChange();
18523
+ const indexResult = await this.memory.knowledge.indexAll({ force: forceReindex });
18524
+ let ftsResult = { knowledge: 0, messages: 0 };
18525
+ if (indexResult.indexed > 0) {
18526
+ ftsResult = db2.rebuildFtsIndexes();
18527
+ }
18528
+ import("./memory-hook-WUXJNVT5.js").then(
18529
+ ({ consolidateOldMemoryFiles }) => consolidateOldMemoryFiles({
18530
+ apiKey: this.config.agent.api_key,
18531
+ provider: this.config.agent.provider,
18532
+ utilityModel: this.config.agent.utility_model
18533
+ })
18534
+ ).then((r) => {
18535
+ if (r.consolidated > 0)
18536
+ log137.info(`\u{1F9F9} Consolidated ${r.consolidated} old session memory files`);
18537
+ }).catch((error) => log137.warn({ err: error }, "Memory consolidation skipped"));
18210
18538
  const toolIndex = this.toolRegistry.getToolIndex();
18211
18539
  if (toolIndex) {
18212
18540
  const t0 = Date.now();
@@ -18216,7 +18544,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18216
18544
  this.agent.initializeContextBuilder(this.memory.embedder, db2.isVectorSearchReady());
18217
18545
  if (this.config.agent.provider === "cocoon") {
18218
18546
  try {
18219
- const { registerCocoonModels } = await import("./client-LNZTDQSA.js");
18547
+ const { registerCocoonModels } = await import("./client-YOOHI776.js");
18220
18548
  const port = this.config.cocoon?.port ?? 1e4;
18221
18549
  const models = await registerCocoonModels(port);
18222
18550
  if (models.length === 0) {
@@ -18238,7 +18566,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18238
18566
  }
18239
18567
  if (this.config.agent.provider === "local" && this.config.agent.base_url) {
18240
18568
  try {
18241
- const { registerLocalModels } = await import("./client-LNZTDQSA.js");
18569
+ const { registerLocalModels } = await import("./client-YOOHI776.js");
18242
18570
  const models = await registerLocalModels(this.config.agent.base_url);
18243
18571
  if (models.length > 0) {
18244
18572
  log137.info(`Discovered ${models.length} local model(s): ${models.join(", ")}`);
@@ -18303,6 +18631,28 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18303
18631
  inlineRouter.setGramJSBot(activeDealBot.getGramJSBot());
18304
18632
  log137.info("\u{1F50C} Bot SDK: inline router installed");
18305
18633
  }
18634
+ if (hookRegistry.hasAnyHooks()) {
18635
+ const hookRunner = createHookRunner(hookRegistry, { logger: log137 });
18636
+ this.agent.setHookRunner(hookRunner);
18637
+ this.hookRunner = hookRunner;
18638
+ const activeHooks = [
18639
+ "tool:before",
18640
+ "tool:after",
18641
+ "tool:error",
18642
+ "prompt:before",
18643
+ "prompt:after",
18644
+ "session:start",
18645
+ "session:end",
18646
+ "message:receive",
18647
+ "response:before",
18648
+ "response:after",
18649
+ "response:error",
18650
+ "agent:start",
18651
+ "agent:stop"
18652
+ ];
18653
+ const active = activeHooks.filter((n) => hookRegistry.hasHooks(n));
18654
+ log137.info(`\u{1FA9D} Hook runner created (${active.join(", ")})`);
18655
+ }
18306
18656
  this.wirePluginEventHooks();
18307
18657
  if (this.config.dev.hot_reload) {
18308
18658
  this.pluginWatcher = new PluginWatcher({
@@ -18331,6 +18681,26 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18331
18681
  `
18332
18682
  );
18333
18683
  log137.info("Teleton Agent is running! Press Ctrl+C to stop.");
18684
+ this.startTime = Date.now();
18685
+ this.messagesProcessed = 0;
18686
+ if (this.hookRunner) {
18687
+ let version = "0.0.0";
18688
+ try {
18689
+ const { createRequire } = await import("module");
18690
+ const req = createRequire(import.meta.url);
18691
+ version = req("../package.json").version;
18692
+ } catch {
18693
+ }
18694
+ const agentStartEvent = {
18695
+ version,
18696
+ provider,
18697
+ model: this.config.agent.model,
18698
+ pluginCount: pluginNames.length,
18699
+ toolCount: this.toolCount,
18700
+ timestamp: Date.now()
18701
+ };
18702
+ await this.hookRunner.runObservingHook("agent:start", agentStartEvent);
18703
+ }
18334
18704
  this.debouncer = new MessageDebouncer(
18335
18705
  {
18336
18706
  debounceMs: this.config.telegram.debounce_ms
@@ -18354,20 +18724,23 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18354
18724
  log137.error({ err: error }, `Error processing batch of ${messages.length} messages`);
18355
18725
  }
18356
18726
  );
18357
- this.bridge.onNewMessage(async (message) => {
18358
- try {
18359
- await this.debouncer.enqueue(message);
18360
- } catch (error) {
18361
- log137.error({ err: error }, "Error enqueueing message");
18362
- }
18363
- });
18364
- this.bridge.onServiceMessage(async (message) => {
18365
- try {
18366
- await this.debouncer.enqueue(message);
18367
- } catch (error) {
18368
- log137.error({ err: error }, "Error enqueueing service message");
18369
- }
18370
- });
18727
+ if (!this.messageHandlersRegistered) {
18728
+ this.bridge.onNewMessage(async (message) => {
18729
+ try {
18730
+ await this.debouncer.enqueue(message);
18731
+ } catch (error) {
18732
+ log137.error({ err: error }, "Error enqueueing message");
18733
+ }
18734
+ });
18735
+ this.bridge.onServiceMessage(async (message) => {
18736
+ try {
18737
+ await this.debouncer.enqueue(message);
18738
+ } catch (error) {
18739
+ log137.error({ err: error }, "Error enqueueing service message");
18740
+ }
18741
+ });
18742
+ this.messageHandlersRegistered = true;
18743
+ }
18371
18744
  }
18372
18745
  /**
18373
18746
  * Resolve owner name and username from Telegram API if not already configured.
@@ -18422,6 +18795,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18422
18795
  * Handle a single message (extracted for debouncer callback)
18423
18796
  */
18424
18797
  async handleSingleMessage(message) {
18798
+ this.messagesProcessed++;
18425
18799
  try {
18426
18800
  const ownUserId = this.bridge.getOwnUserId();
18427
18801
  if (ownUserId && message.senderId === Number(ownUserId) && message.text.startsWith("[TASK:")) {
@@ -18488,10 +18862,10 @@ Task: "${taskDescription}"`;
18488
18862
  * Handle scheduled task message
18489
18863
  */
18490
18864
  async handleScheduledTask(message) {
18491
- const { getTaskStore } = await import("./tasks-BEZ4QRI2.js");
18492
- const { executeScheduledTask } = await import("./task-executor-RUTFG6VG.js");
18493
- const { TaskDependencyResolver } = await import("./task-dependency-resolver-3FIKQ7Z6.js");
18494
- const { getDatabase: getDatabase2 } = await import("./memory-AS7WKGTW.js");
18865
+ const { getTaskStore } = await import("./tasks-WQIKXDX5.js");
18866
+ const { executeScheduledTask } = await import("./task-executor-XBNJLUCS.js");
18867
+ const { TaskDependencyResolver } = await import("./task-dependency-resolver-L6UUMTHK.js");
18868
+ const { getDatabase: getDatabase2 } = await import("./memory-Q6EWGK2S.js");
18495
18869
  const db2 = getDatabase2().getDb();
18496
18870
  const taskStore = getTaskStore(db2);
18497
18871
  const match = message.text.match(/^\[TASK:([^\]]+)\]/);
@@ -18572,7 +18946,7 @@ Task: "${taskDescription}"`;
18572
18946
  this.dependencyResolver = new TaskDependencyResolver(taskStore, this.bridge);
18573
18947
  }
18574
18948
  await this.dependencyResolver.onTaskFail(taskId);
18575
- } catch (e) {
18949
+ } catch {
18576
18950
  }
18577
18951
  }
18578
18952
  }
@@ -18604,14 +18978,18 @@ Task: "${taskDescription}"`;
18604
18978
  }
18605
18979
  if (!this.callbackHandlerRegistered) {
18606
18980
  this.bridge.getClient().addCallbackQueryHandler(async (update) => {
18607
- const queryId = update.queryId;
18608
- const data = update.data?.toString() || "";
18981
+ if (!update || typeof update !== "object") {
18982
+ return;
18983
+ }
18984
+ const callbackUpdate = update;
18985
+ const queryId = callbackUpdate.queryId;
18986
+ const data = typeof callbackUpdate.data === "string" ? callbackUpdate.data : callbackUpdate.data?.toString() || "";
18609
18987
  const parts = data.split(":");
18610
18988
  const action = parts[0];
18611
18989
  const params = parts.slice(1);
18612
- const chatId = update.peer?.channelId?.toString() ?? update.peer?.chatId?.toString() ?? update.peer?.userId?.toString() ?? "";
18613
- const messageId = update.msgId || 0;
18614
- const userId = Number(update.userId);
18990
+ const chatId = callbackUpdate.peer?.channelId?.toString() ?? callbackUpdate.peer?.chatId?.toString() ?? callbackUpdate.peer?.userId?.toString() ?? "";
18991
+ const messageId = typeof callbackUpdate.msgId === "number" ? callbackUpdate.msgId : Number(callbackUpdate.msgId || 0);
18992
+ const userId = Number(callbackUpdate.userId);
18615
18993
  const answer = async (text, alert = false) => {
18616
18994
  try {
18617
18995
  await this.bridge.getClient().answerCallbackQuery(queryId, { message: text, alert });
@@ -18665,6 +19043,13 @@ Task: "${taskDescription}"`;
18665
19043
  log137.error({ err: e }, "\u26A0\uFE0F WebUI stop failed");
18666
19044
  }
18667
19045
  }
19046
+ if (this.apiServer) {
19047
+ try {
19048
+ await this.apiServer.stop();
19049
+ } catch (e) {
19050
+ log137.error({ err: e }, "\u26A0\uFE0F Management API stop failed");
19051
+ }
19052
+ }
18668
19053
  try {
18669
19054
  closeDatabase();
18670
19055
  } catch (e) {
@@ -18676,6 +19061,19 @@ Task: "${taskDescription}"`;
18676
19061
  * Called by lifecycle.stop() — do NOT call directly.
18677
19062
  */
18678
19063
  async stopAgent() {
19064
+ if (this.hookRunner) {
19065
+ try {
19066
+ const agentStopEvent = {
19067
+ reason: "manual",
19068
+ uptimeMs: this.startTime > 0 ? Date.now() - this.startTime : 0,
19069
+ messagesProcessed: this.messagesProcessed,
19070
+ timestamp: Date.now()
19071
+ };
19072
+ await this.hookRunner.runObservingHook("agent:stop", agentStopEvent);
19073
+ } catch (e) {
19074
+ log137.error({ err: e }, "\u26A0\uFE0F agent:stop hook failed");
19075
+ }
19076
+ }
18679
19077
  if (this.pluginWatcher) {
18680
19078
  try {
18681
19079
  await this.pluginWatcher.stop();