teleton 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +28 -11
  2. package/dist/{chunk-U56QTM46.js → chunk-3S4GGLLR.js} +28 -26
  3. package/dist/{chunk-NUGDTPE4.js → chunk-4L66JHQE.js} +2 -1
  4. package/dist/{chunk-H36RFKRI.js → chunk-5FNWBZ5K.js} +476 -143
  5. package/dist/{chunk-SD4NLLYG.js → chunk-7U7BOHCL.js} +80 -33
  6. package/dist/{chunk-QVBSUYVX.js → chunk-AYWEJCDB.js} +11 -3
  7. package/dist/{chunk-RQBAMUCV.js → chunk-CGOXE4WP.js} +1235 -201
  8. package/dist/{chunk-TVRZJIZX.js → chunk-KVXV7EF7.js} +3 -3
  9. package/dist/{chunk-WIKM24GZ.js → chunk-QBHRXLZS.js} +5 -0
  10. package/dist/{chunk-P36I6OIV.js → chunk-QV2GLOTK.js} +12 -1
  11. package/dist/{chunk-JHYZYFZJ.js → chunk-S6PHGKOC.js} +8 -1
  12. package/dist/{chunk-IJBWWQE4.js → chunk-UP55PXFH.js} +4 -0
  13. package/dist/cli/index.js +17 -16
  14. package/dist/{client-LNZTDQSA.js → client-MPHPIZB6.js} +2 -2
  15. package/dist/{get-my-gifts-OMGKOEPM.js → get-my-gifts-CC6HAVWB.js} +1 -1
  16. package/dist/index.js +11 -11
  17. package/dist/{memory-AS7WKGTW.js → memory-UBHM7ILG.js} +4 -4
  18. package/dist/{migrate-POHWYEIW.js → migrate-UBBEJ5BL.js} +4 -4
  19. package/dist/{server-H3QA252W.js → server-3FHI2SEB.js} +392 -51
  20. package/dist/{setup-server-QXED3D2L.js → setup-server-32XGDPE6.js} +157 -7
  21. package/dist/{store-GAFULOOX.js → store-M5IMUQCL.js} +5 -5
  22. package/dist/{task-dependency-resolver-3FIKQ7Z6.js → task-dependency-resolver-RR2O5S7B.js} +2 -2
  23. package/dist/{task-executor-RUTFG6VG.js → task-executor-6W5HRX5C.js} +2 -2
  24. package/dist/{tasks-BEZ4QRI2.js → tasks-WQIKXDX5.js} +1 -1
  25. package/dist/{tool-index-H3SHOJC3.js → tool-index-PMAOXWUA.js} +8 -5
  26. package/dist/{transcript-IMNE6KU3.js → transcript-NGDPSNIH.js} +1 -1
  27. package/dist/web/assets/index-BfYCdwLI.js +80 -0
  28. package/dist/web/assets/{index-BrVqauzj.css → index-DmlyQVhR.css} +1 -1
  29. package/dist/web/assets/{index.es-DkU1GvWU.js → index.es-DitvF-9H.js} +1 -1
  30. package/dist/web/index.html +2 -2
  31. package/package.json +11 -4
  32. 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-QBHRXLZS.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-CGOXE4WP.js";
51
54
  import {
52
55
  getCachedTonClient,
53
56
  getKeyPair,
@@ -58,14 +61,14 @@ import {
58
61
  loadTemplate,
59
62
  loadWallet,
60
63
  setToncenterApiKey
61
- } from "./chunk-JHYZYFZJ.js";
64
+ } from "./chunk-S6PHGKOC.js";
62
65
  import {
63
66
  getErrorMessage
64
67
  } from "./chunk-XBE4JB7C.js";
65
68
  import {
66
69
  getEffectiveApiKey,
67
70
  getProviderModel
68
- } from "./chunk-QVBSUYVX.js";
71
+ } from "./chunk-AYWEJCDB.js";
69
72
  import {
70
73
  getProviderMetadata
71
74
  } from "./chunk-PHSAHTK4.js";
@@ -81,7 +84,7 @@ import {
81
84
  initializeMemory,
82
85
  migrateFromMainDb,
83
86
  openModuleDb
84
- } from "./chunk-SD4NLLYG.js";
87
+ } from "./chunk-7U7BOHCL.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-UP55PXFH.js";
111
114
  import {
112
115
  fetchWithTimeout
113
116
  } from "./chunk-XQUHC3JZ.js";
@@ -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,15 +427,21 @@ 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) => {
430
- if ((update instanceof Api.UpdateNewMessage || update instanceof Api.UpdateNewChannelMessage) && update.message instanceof Api.MessageService) {
438
+ if ((update instanceof Api.UpdateNewMessage || update instanceof Api.UpdateNewChannelMessage) && // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS update.message lacks proper typing
439
+ update.message instanceof Api.MessageService) {
431
440
  await handler(update.message);
432
441
  }
433
442
  });
434
443
  }
444
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS raw update event
435
445
  addCallbackQueryHandler(handler) {
436
446
  this.client.addEventHandler(async (update) => {
437
447
  if (update.className === "UpdateBotCallbackQuery" || update.className === "UpdateInlineBotCallbackQuery") {
@@ -459,13 +469,16 @@ var TelegramUserClient = class {
459
469
  const parseMode = options.parseMode ?? "html";
460
470
  const formattedMessage = parseMode === "html" ? markdownToTelegramHtml(options.message) : options.message;
461
471
  return withFloodRetry(
462
- () => this.client.sendMessage(entity, {
463
- message: formattedMessage,
464
- replyTo: options.replyTo,
465
- silent: options.silent,
466
- parseMode: parseMode === "none" ? void 0 : parseMode,
467
- linkPreview: false
468
- })
472
+ () => (
473
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS sendMessage accepts string | Entity
474
+ this.client.sendMessage(entity, {
475
+ message: formattedMessage,
476
+ replyTo: options.replyTo,
477
+ silent: options.silent,
478
+ parseMode: parseMode === "none" ? void 0 : parseMode,
479
+ linkPreview: false
480
+ })
481
+ )
469
482
  );
470
483
  }
471
484
  async getMessages(entity, options) {
@@ -729,7 +742,7 @@ var TelegramBridge = class {
729
742
  if (sender instanceof Api2.User) {
730
743
  isBot = sender.bot ?? false;
731
744
  }
732
- } catch (e) {
745
+ } catch {
733
746
  }
734
747
  const hasMedia = !!(msg.photo || msg.document || msg.video || msg.audio || msg.voice || msg.sticker);
735
748
  let mediaType;
@@ -1221,7 +1234,6 @@ var MessageHandler = class _MessageHandler {
1221
1234
  fullConfig;
1222
1235
  agent;
1223
1236
  rateLimiter;
1224
- lastProcessedMessageId;
1225
1237
  messageStore;
1226
1238
  chatStore;
1227
1239
  userStore;
@@ -1246,7 +1258,6 @@ var MessageHandler = class _MessageHandler {
1246
1258
  this.chatStore = new ChatStore(db2);
1247
1259
  this.userStore = new UserStore(db2);
1248
1260
  this.pendingHistory = new PendingHistory();
1249
- this.lastProcessedMessageId = 0;
1250
1261
  }
1251
1262
  setOwnUserId(userId) {
1252
1263
  this.ownUserId = userId;
@@ -1358,10 +1369,11 @@ var MessageHandler = class _MessageHandler {
1358
1369
  * Process and respond to a message
1359
1370
  */
1360
1371
  async handleMessage(message) {
1361
- if (this.recentMessageIds.has(message.id)) {
1372
+ const dedupKey = `${message.chatId}:${message.id}`;
1373
+ if (this.recentMessageIds.has(dedupKey)) {
1362
1374
  return;
1363
1375
  }
1364
- this.recentMessageIds.add(message.id);
1376
+ this.recentMessageIds.add(dedupKey);
1365
1377
  if (this.recentMessageIds.size > _MessageHandler.DEDUP_MAX_SIZE) {
1366
1378
  const ids = [...this.recentMessageIds];
1367
1379
  this.recentMessageIds = new Set(ids.slice(ids.length >> 1));
@@ -1452,10 +1464,11 @@ var MessageHandler = class _MessageHandler {
1452
1464
  config: this.fullConfig
1453
1465
  }
1454
1466
  );
1455
- if (transcribeResult.success && transcribeResult.data?.text) {
1456
- transcriptionText = transcribeResult.data.text;
1467
+ const transcribeData = transcribeResult.data;
1468
+ if (transcribeResult.success && transcribeData?.text) {
1469
+ transcriptionText = transcribeData.text;
1457
1470
  log6.info(
1458
- `\u{1F3A4} Auto-transcribed voice msg ${message.id}: "${transcriptionText.substring(0, 80)}..."`
1471
+ `\u{1F3A4} Auto-transcribed voice msg ${message.id}: "${transcriptionText?.substring(0, 80)}..."`
1459
1472
  );
1460
1473
  }
1461
1474
  } catch (err) {
@@ -1561,12 +1574,6 @@ ${message.text}` : ""}` : message.text;
1561
1574
  log6.error({ err: error }, "Error storing message to feed");
1562
1575
  }
1563
1576
  }
1564
- /**
1565
- * Get last processed message ID
1566
- */
1567
- getLastProcessedMessageId() {
1568
- return this.lastProcessedMessageId;
1569
- }
1570
1577
  };
1571
1578
 
1572
1579
  // src/telegram/admin.ts
@@ -1696,7 +1703,7 @@ var AdminHandler = class {
1696
1703
  Use /help for available commands.`;
1697
1704
  }
1698
1705
  }
1699
- async handleStatusCommand(command) {
1706
+ async handleStatusCommand(_command) {
1700
1707
  const activeChatIds = this.agent.getActiveChatIds();
1701
1708
  const chatCount = activeChatIds.length;
1702
1709
  const cfg = this.agent.getConfig();
@@ -1907,6 +1914,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1907
1914
  }
1908
1915
  }
1909
1916
  listModules(chatId) {
1917
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1910
1918
  const modules = this.registry.getAvailableModules();
1911
1919
  const overrides = this.permissions.getOverrides(chatId);
1912
1920
  const lines = ["\u{1F9E9} **Modules** (this group)\n"];
@@ -1941,6 +1949,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1941
1949
  }
1942
1950
  module = module.toLowerCase();
1943
1951
  level = level.toLowerCase();
1952
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1944
1953
  const available = this.registry.getAvailableModules();
1945
1954
  if (!available.includes(module)) {
1946
1955
  return `\u274C Unknown module: "${module}"`;
@@ -1961,6 +1970,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1961
1970
  return "\u274C Usage: /modules info <module>";
1962
1971
  }
1963
1972
  module = module.toLowerCase();
1973
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1964
1974
  const available = this.registry.getAvailableModules();
1965
1975
  if (!available.includes(module)) {
1966
1976
  return `\u274C Unknown module: "${module}"`;
@@ -1981,6 +1991,7 @@ Usage: /modules | /modules set <module> <level> | /modules info <module> | /modu
1981
1991
  return lines.join("\n");
1982
1992
  }
1983
1993
  resetModules(chatId, module) {
1994
+ if (!this.registry || !this.permissions) return "\u274C Module permissions not available";
1984
1995
  if (module) {
1985
1996
  module = module.toLowerCase();
1986
1997
  const available = this.registry.getAvailableModules();
@@ -2550,7 +2561,7 @@ var ToolRegistry = class {
2550
2561
  }
2551
2562
  this.toolArrayCache = null;
2552
2563
  if (names.length > 0) {
2553
- const addedTools = names.map((n) => this.tools.get(n).tool);
2564
+ const addedTools = names.map((n) => this.tools.get(n)?.tool).filter((t) => !!t);
2554
2565
  this.notifyToolsChanged([], addedTools);
2555
2566
  }
2556
2567
  return names.length;
@@ -2593,7 +2604,7 @@ var ToolRegistry = class {
2593
2604
  }
2594
2605
  this.toolArrayCache = null;
2595
2606
  const removedNames = [...previousNames].filter((n) => !names.includes(n));
2596
- const addedTools = names.map((n) => this.tools.get(n).tool);
2607
+ const addedTools = names.map((n) => this.tools.get(n)?.tool).filter((t) => !!t);
2597
2608
  if (removedNames.length > 0 || addedTools.length > 0) {
2598
2609
  this.notifyToolsChanged(removedNames, addedTools);
2599
2610
  }
@@ -2868,7 +2879,7 @@ var telegramForwardMessageExecutor = async (params, context) => {
2868
2879
  try {
2869
2880
  const { fromChatId, toChatId, messageIds, silent = false, background = false } = params;
2870
2881
  const gramJsClient = context.bridge.getClient().getClient();
2871
- const result = await gramJsClient.invoke(
2882
+ const _result = await gramJsClient.invoke(
2872
2883
  new Api5.messages.ForwardMessages({
2873
2884
  fromPeer: fromChatId,
2874
2885
  toPeer: toChatId,
@@ -3274,6 +3285,7 @@ var telegramGetRepliesExecutor = async (params, context) => {
3274
3285
  limit,
3275
3286
  maxId: 0,
3276
3287
  minId: 0,
3288
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
3277
3289
  hash: 0n
3278
3290
  })
3279
3291
  );
@@ -3369,6 +3381,7 @@ var telegramGetScheduledMessagesExecutor = async (params, context) => {
3369
3381
  const result = await gramJsClient.invoke(
3370
3382
  new Api11.messages.GetScheduledHistory({
3371
3383
  peer: entity,
3384
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
3372
3385
  hash: 0n
3373
3386
  })
3374
3387
  );
@@ -3766,7 +3779,7 @@ async function generatePiperTTS(text, voice) {
3766
3779
  });
3767
3780
  });
3768
3781
  unlinkSync(wavPath);
3769
- } catch (err) {
3782
+ } catch {
3770
3783
  return {
3771
3784
  filePath: wavPath,
3772
3785
  provider: "piper",
@@ -4053,7 +4066,7 @@ var telegramSendVoiceExecutor = async (params, context) => {
4053
4066
  if (generatedFile) {
4054
4067
  try {
4055
4068
  unlinkSync2(generatedFile);
4056
- } catch (e) {
4069
+ } catch {
4057
4070
  }
4058
4071
  }
4059
4072
  }
@@ -4109,6 +4122,7 @@ var telegramSendStickerExecutor = async (params, context) => {
4109
4122
  const stickerSet = await gramJsClient.invoke(
4110
4123
  new Api15.messages.GetStickerSet({
4111
4124
  stickerset: new Api15.InputStickerSetShortName({
4125
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasSetInfo check
4112
4126
  shortName: stickerSetShortName
4113
4127
  }),
4114
4128
  hash: 0
@@ -4127,7 +4141,7 @@ var telegramSendStickerExecutor = async (params, context) => {
4127
4141
  };
4128
4142
  }
4129
4143
  const stickerDoc = stickerSet.documents[stickerIndex];
4130
- const result2 = await gramJsClient.invoke(
4144
+ const _result = await gramJsClient.invoke(
4131
4145
  new Api15.messages.SendMedia({
4132
4146
  peer: chatId,
4133
4147
  media: new Api15.InputMediaDocument({
@@ -4234,10 +4248,12 @@ var telegramSendGifExecutor = async (params, context) => {
4234
4248
  }
4235
4249
  const gramJsClient = context.bridge.getClient().getClient();
4236
4250
  if (hasInlineResult) {
4237
- const result2 = await gramJsClient.invoke(
4251
+ const _result = await gramJsClient.invoke(
4238
4252
  new Api16.messages.SendInlineBotResult({
4239
4253
  peer: chatId,
4254
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasInlineResult check
4240
4255
  queryId: toLong(BigInt(queryId)),
4256
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- guarded by hasInlineResult check
4241
4257
  id: resultId,
4242
4258
  randomId: randomLong(),
4243
4259
  replyTo: replyToId ? new Api16.InputReplyToMessage({ replyToMsgId: replyToId }) : void 0
@@ -4530,6 +4546,7 @@ var visionAnalyzeExecutor = async (params, context) => {
4530
4546
  log27.info(`\u{1F4F7} Downloading image from message ${messageId}...`);
4531
4547
  const gramJsClient = context.bridge.getClient().getClient();
4532
4548
  const messages = await gramJsClient.getMessages(chatId, {
4549
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- messageId guaranteed in this branch
4533
4550
  ids: [messageId]
4534
4551
  });
4535
4552
  if (!messages || messages.length === 0) {
@@ -4812,7 +4829,7 @@ var telegramGetChatInfoExecutor = async (params, context) => {
4812
4829
  let entity;
4813
4830
  try {
4814
4831
  entity = await gramJsClient.getEntity(chatId);
4815
- } catch (error) {
4832
+ } catch {
4816
4833
  return {
4817
4834
  success: false,
4818
4835
  error: `Could not find chat "${chatId}"`
@@ -4878,7 +4895,7 @@ var telegramGetChatInfoExecutor = async (params, context) => {
4878
4895
  isDeactivated: chat.deactivated || false
4879
4896
  };
4880
4897
  }
4881
- } catch (error) {
4898
+ } catch {
4882
4899
  chatInfo = {
4883
4900
  ...chatInfo,
4884
4901
  title: entity instanceof Api18.Channel ? entity.title : entity instanceof Api18.Chat ? entity.title : null,
@@ -4929,7 +4946,7 @@ var telegramMarkAsReadExecutor = async (params, context) => {
4929
4946
  let entity;
4930
4947
  try {
4931
4948
  entity = await gramJsClient.getEntity(chatId);
4932
- } catch (error) {
4949
+ } catch {
4933
4950
  return {
4934
4951
  success: false,
4935
4952
  error: `Could not find chat "${chatId}"`
@@ -5122,7 +5139,7 @@ var telegramLeaveChannelExecutor = async (params, context) => {
5122
5139
  let channelEntity;
5123
5140
  try {
5124
5141
  channelEntity = await gramJsClient.getEntity(channel);
5125
- } catch (error) {
5142
+ } catch {
5126
5143
  return {
5127
5144
  success: false,
5128
5145
  error: `Could not find channel "${channel}". Make sure it exists and you have access to it.`
@@ -5416,7 +5433,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5416
5433
  } else {
5417
5434
  failed.push(`${userId} (not a user)`);
5418
5435
  }
5419
- } catch (error) {
5436
+ } catch {
5420
5437
  failed.push(`${userId} (not found)`);
5421
5438
  }
5422
5439
  }
@@ -5436,7 +5453,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5436
5453
  } else {
5437
5454
  failed.push(`@${cleanUsername} (not a user)`);
5438
5455
  }
5439
- } catch (error) {
5456
+ } catch {
5440
5457
  failed.push(`@${username.replace("@", "")} (not found)`);
5441
5458
  }
5442
5459
  }
@@ -5446,7 +5463,7 @@ var telegramInviteToChannelExecutor = async (params, context) => {
5446
5463
  error: `Could not resolve any users to invite. Failed: ${failed.join(", ")}`
5447
5464
  };
5448
5465
  }
5449
- const result = await gramJsClient.invoke(
5466
+ const _result = await gramJsClient.invoke(
5450
5467
  new Api23.channels.InviteToChannel({
5451
5468
  channel,
5452
5469
  users
@@ -6416,7 +6433,7 @@ var telegramCreatePollExecutor = async (params, context) => {
6416
6433
  closePeriod,
6417
6434
  closeDate
6418
6435
  });
6419
- const result = await gramJsClient.invoke(
6436
+ const _result = await gramJsClient.invoke(
6420
6437
  new Api31.messages.SendMedia({
6421
6438
  peer: chatId,
6422
6439
  media: new Api31.InputMediaPoll({
@@ -6525,7 +6542,7 @@ var telegramCreateQuizExecutor = async (params, context) => {
6525
6542
  closePeriod,
6526
6543
  closeDate
6527
6544
  });
6528
- const result = await gramJsClient.invoke(
6545
+ const _result = await gramJsClient.invoke(
6529
6546
  new Api32.messages.SendMedia({
6530
6547
  peer: chatId,
6531
6548
  media: new Api32.InputMediaPoll({
@@ -7048,6 +7065,7 @@ var telegramGetFoldersExecutor = async (_params, context) => {
7048
7065
  const filterList = dialogFilters.filters ?? [];
7049
7066
  const folders = filterList.filter((filter) => filter.className === "DialogFilter").map((filter) => ({
7050
7067
  id: filter.id,
7068
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
7051
7069
  title: filter.title?.text ?? filter.title,
7052
7070
  emoji: filter.emoticon || null,
7053
7071
  pinnedPeersCount: filter.pinnedPeers?.length || 0,
@@ -7211,7 +7229,7 @@ var telegramAddChatToFolderExecutor = async (params, context) => {
7211
7229
  error: `Folder with ID ${folderId} not found`
7212
7230
  };
7213
7231
  }
7214
- const chatEntity = await gramJsClient.getEntity(chatId);
7232
+ const _chatEntity = await gramJsClient.getEntity(chatId);
7215
7233
  const inputPeer = await gramJsClient.getInputEntity(chatId);
7216
7234
  const updatedIncludePeers = [...folder.includePeers || []];
7217
7235
  updatedIncludePeers.push(inputPeer);
@@ -7290,7 +7308,7 @@ var telegramUpdateProfileExecutor = async (params, context) => {
7290
7308
  const gramJsClient = context.bridge.getClient().getClient();
7291
7309
  const updates = {};
7292
7310
  if (firstName !== void 0 || lastName !== void 0) {
7293
- const nameResult = await gramJsClient.invoke(
7311
+ const _nameResult = await gramJsClient.invoke(
7294
7312
  new Api42.account.UpdateProfile({
7295
7313
  firstName,
7296
7314
  lastName
@@ -7396,7 +7414,7 @@ var telegramSetUsernameExecutor = async (params, context) => {
7396
7414
  }
7397
7415
  }
7398
7416
  const gramJsClient = context.bridge.getClient().getClient();
7399
- const result = await gramJsClient.invoke(
7417
+ const _result = await gramJsClient.invoke(
7400
7418
  new Api44.account.UpdateUsername({
7401
7419
  username: username || ""
7402
7420
  })
@@ -8074,14 +8092,18 @@ function decodeInlineMessageId(encoded) {
8074
8092
  if (buf.length === 20) {
8075
8093
  return new Api49.InputBotInlineMessageID({
8076
8094
  dcId: buf.readInt32LE(0),
8095
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS BigInteger compat
8077
8096
  id: buf.readBigInt64LE(4),
8097
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS BigInteger compat
8078
8098
  accessHash: buf.readBigInt64LE(12)
8079
8099
  });
8080
8100
  } else if (buf.length === 24) {
8081
8101
  return new Api49.InputBotInlineMessageID64({
8082
8102
  dcId: buf.readInt32LE(0),
8103
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS BigInteger compat
8083
8104
  ownerId: buf.readBigInt64LE(4),
8084
8105
  id: buf.readInt32LE(12),
8106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS BigInteger compat
8085
8107
  accessHash: buf.readBigInt64LE(16)
8086
8108
  });
8087
8109
  }
@@ -8841,7 +8863,7 @@ var VerificationPoller = class {
8841
8863
  const me = this.bridge.getClient().getMe();
8842
8864
  if (!me) return { verified: false };
8843
8865
  const botUserId = Number(me.id);
8844
- const { telegramGetMyGiftsExecutor: telegramGetMyGiftsExecutor2 } = await import("./get-my-gifts-OMGKOEPM.js");
8866
+ const { telegramGetMyGiftsExecutor: telegramGetMyGiftsExecutor2 } = await import("./get-my-gifts-CC6HAVWB.js");
8845
8867
  const toolContext = {
8846
8868
  bridge: this.bridge,
8847
8869
  db: this.db,
@@ -9066,9 +9088,10 @@ var DealBot = class {
9066
9088
  await this.editViaGramJS(inlineMessageId, text, buttons);
9067
9089
  edited = true;
9068
9090
  } catch (error) {
9091
+ const errMsg = error?.errorMessage;
9069
9092
  log68.warn(
9070
9093
  { err: error },
9071
- `[Bot] chosen_inline_result GramJS edit failed: ${error?.errorMessage || error}`
9094
+ `[Bot] chosen_inline_result GramJS edit failed: ${errMsg || error}`
9072
9095
  );
9073
9096
  }
9074
9097
  }
@@ -9081,9 +9104,10 @@ var DealBot = class {
9081
9104
  reply_markup: keyboard
9082
9105
  });
9083
9106
  } catch (error) {
9107
+ const errDesc = error?.description;
9084
9108
  log68.error(
9085
9109
  { err: error },
9086
- `[Bot] chosen_inline_result Grammy fallback failed: ${error?.description || error}`
9110
+ `[Bot] chosen_inline_result Grammy fallback failed: ${errDesc || error}`
9087
9111
  );
9088
9112
  }
9089
9113
  }
@@ -9245,10 +9269,11 @@ var DealBot = class {
9245
9269
  await this.editViaGramJS(inlineMsgId, text, buttons);
9246
9270
  return;
9247
9271
  } catch (error) {
9248
- if (error?.errorMessage === "MESSAGE_NOT_MODIFIED") return;
9272
+ const errMsg = error?.errorMessage;
9273
+ if (errMsg === "MESSAGE_NOT_MODIFIED") return;
9249
9274
  log68.warn(
9250
9275
  { err: error },
9251
- `[Bot] GramJS edit failed, falling back to Grammy: ${error?.errorMessage || error}`
9276
+ `[Bot] GramJS edit failed, falling back to Grammy: ${errMsg || error}`
9252
9277
  );
9253
9278
  }
9254
9279
  }
@@ -9260,7 +9285,8 @@ var DealBot = class {
9260
9285
  reply_markup: keyboard
9261
9286
  });
9262
9287
  } catch (error) {
9263
- if (error?.description?.includes("message is not modified")) return;
9288
+ const desc = error?.description;
9289
+ if (desc?.includes("message is not modified")) return;
9264
9290
  log68.error({ err: error }, "[Bot] Failed to edit inline message");
9265
9291
  }
9266
9292
  }
@@ -9270,10 +9296,11 @@ var DealBot = class {
9270
9296
  await this.editViaGramJS(inlineMessageId, text, buttons);
9271
9297
  return;
9272
9298
  } catch (error) {
9273
- if (error?.errorMessage === "MESSAGE_NOT_MODIFIED") return;
9299
+ const errMsg = error?.errorMessage;
9300
+ if (errMsg === "MESSAGE_NOT_MODIFIED") return;
9274
9301
  log68.warn(
9275
9302
  { err: error },
9276
- `[Bot] GramJS edit failed, falling back to Grammy: ${error?.errorMessage || error}`
9303
+ `[Bot] GramJS edit failed, falling back to Grammy: ${errMsg || error}`
9277
9304
  );
9278
9305
  }
9279
9306
  }
@@ -10362,7 +10389,7 @@ var dealsModule = {
10362
10389
  closeDealsDb();
10363
10390
  }
10364
10391
  };
10365
- var module_default = dealsModule;
10392
+ var module_default2 = dealsModule;
10366
10393
  function hasVerifiedDeal(giftId, userId) {
10367
10394
  const dealsDb = getDealsDb();
10368
10395
  if (!dealsDb) return false;
@@ -10417,6 +10444,7 @@ var telegramSendGiftExecutor = async (params, context) => {
10417
10444
  const user = await gramJsClient.getInputEntity(userId);
10418
10445
  const invoiceData = {
10419
10446
  peer: user,
10447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10420
10448
  giftId: BigInt(giftId),
10421
10449
  hideName: anonymous,
10422
10450
  message: message ? new Api51.TextWithEntities({ text: message, entities: [] }) : void 0
@@ -10603,6 +10631,7 @@ var telegramSetCollectiblePriceExecutor = async (params, context) => {
10603
10631
  new Api53.payments.UpdateStarGiftPrice({
10604
10632
  stargift: new Api53.InputSavedStarGiftUser({ msgId }),
10605
10633
  resellAmount: new Api53.StarsAmount({
10634
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10606
10635
  amount: BigInt(isListing ? price : 0),
10607
10636
  nanos: 0
10608
10637
  })
@@ -10681,6 +10710,7 @@ var telegramGetResaleGiftsExecutor = async (params, context) => {
10681
10710
  }
10682
10711
  const result = await gramJsClient.invoke(
10683
10712
  new Api54.payments.GetResaleStarGifts({
10713
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10684
10714
  giftId: BigInt(giftId),
10685
10715
  offset: "",
10686
10716
  limit,
@@ -10704,6 +10734,7 @@ var telegramGetResaleGiftsExecutor = async (params, context) => {
10704
10734
  ownerName: gift.ownerName || void 0,
10705
10735
  priceStars: starsPrice ? starsPrice.amount?.toString() : void 0,
10706
10736
  priceTon: tonPrice ? tonPrice.amount?.toString() : void 0,
10737
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10707
10738
  attributes: (gift.attributes || []).map((attr) => ({
10708
10739
  type: attr.className?.replace("StarGiftAttribute", "").toLowerCase(),
10709
10740
  name: attr.name
@@ -10835,6 +10866,7 @@ var telegramSetGiftStatusExecutor = async (params, context) => {
10835
10866
  emojiStatus = new Api56.EmojiStatusEmpty();
10836
10867
  } else {
10837
10868
  emojiStatus = new Api56.InputEmojiStatusCollectible({
10869
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10838
10870
  collectibleId: BigInt(collectibleId)
10839
10871
  });
10840
10872
  }
@@ -10955,11 +10987,13 @@ var telegramGetUniqueGiftExecutor = async (params, context) => {
10955
10987
  lastName: ownerUser?.lastName || void 0
10956
10988
  },
10957
10989
  giftAddress: gift.giftAddress || void 0,
10990
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10958
10991
  attributes: (gift.attributes || []).map((attr) => ({
10959
10992
  type: attr.className?.replace("StarGiftAttribute", "").toLowerCase(),
10960
10993
  name: attr.name,
10961
10994
  rarityPercent: attr.rarityPermille ? attr.rarityPermille / 10 : void 0
10962
10995
  })),
10996
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
10963
10997
  resellPrices: (gift.resellAmount || []).map((a) => ({
10964
10998
  amount: a.amount?.toString(),
10965
10999
  isTon: !!a.ton
@@ -11070,6 +11104,7 @@ var telegramSendGiftOfferExecutor = async (params, context) => {
11070
11104
  new Api60.payments.SendStarGiftOffer({
11071
11105
  peer,
11072
11106
  slug,
11107
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- GramJS API response is untyped
11073
11108
  price: new Api60.StarsAmount({ amount: BigInt(price), nanos: 0 }),
11074
11109
  duration,
11075
11110
  randomId: randomLong()
@@ -11378,7 +11413,7 @@ var telegramGetUserInfoExecutor = async (params, context) => {
11378
11413
  } else {
11379
11414
  entity = await gramJsClient.getEntity(userId);
11380
11415
  }
11381
- } catch (error) {
11416
+ } catch {
11382
11417
  return {
11383
11418
  success: false,
11384
11419
  error: `User not found: ${username || userId}`
@@ -12092,7 +12127,7 @@ var telegramCreateScheduledTaskExecutor = async (params, context) => {
12092
12127
  };
12093
12128
  }
12094
12129
  }
12095
- } catch (e) {
12130
+ } catch {
12096
12131
  return {
12097
12132
  success: false,
12098
12133
  error: "Invalid JSON payload"
@@ -12105,7 +12140,7 @@ var telegramCreateScheduledTaskExecutor = async (params, context) => {
12105
12140
  error: "Database not available"
12106
12141
  };
12107
12142
  }
12108
- const { getTaskStore } = await import("./tasks-BEZ4QRI2.js");
12143
+ const { getTaskStore } = await import("./tasks-WQIKXDX5.js");
12109
12144
  const taskStore = getTaskStore(context.db);
12110
12145
  if (dependsOn && dependsOn.length > 0) {
12111
12146
  for (const parentId of dependsOn) {
@@ -12212,7 +12247,7 @@ var tonGetAddressTool = {
12212
12247
  description: "Return your TON wallet address in EQ format. No parameters needed.",
12213
12248
  parameters: Type81.Object({})
12214
12249
  };
12215
- var tonGetAddressExecutor = async (params, context) => {
12250
+ var tonGetAddressExecutor = async (_params, _context) => {
12216
12251
  try {
12217
12252
  const address = getWalletAddress();
12218
12253
  if (!address) {
@@ -12247,7 +12282,7 @@ var tonGetBalanceTool = {
12247
12282
  parameters: Type82.Object({}),
12248
12283
  category: "data-bearing"
12249
12284
  };
12250
- var tonGetBalanceExecutor = async (params, context) => {
12285
+ var tonGetBalanceExecutor = async (_params, _context) => {
12251
12286
  try {
12252
12287
  const address = getWalletAddress();
12253
12288
  if (!address) {
@@ -12291,7 +12326,7 @@ var tonPriceTool = {
12291
12326
  category: "data-bearing",
12292
12327
  parameters: Type83.Object({})
12293
12328
  };
12294
- var tonPriceExecutor = async (params, context) => {
12329
+ var tonPriceExecutor = async (_params, _context) => {
12295
12330
  try {
12296
12331
  const priceData = await getTonPrice();
12297
12332
  if (!priceData) {
@@ -12406,13 +12441,13 @@ var tonGetTransactionsTool = {
12406
12441
  )
12407
12442
  })
12408
12443
  };
12409
- var tonGetTransactionsExecutor = async (params, context) => {
12444
+ var tonGetTransactionsExecutor = async (params, _context) => {
12410
12445
  try {
12411
12446
  const { address, limit = 10 } = params;
12412
12447
  let addressObj;
12413
12448
  try {
12414
12449
  addressObj = Address5.parse(address);
12415
- } catch (e) {
12450
+ } catch {
12416
12451
  return {
12417
12452
  success: false,
12418
12453
  error: `Invalid address: ${address}`
@@ -12457,7 +12492,7 @@ var tonMyTransactionsTool = {
12457
12492
  )
12458
12493
  })
12459
12494
  };
12460
- var tonMyTransactionsExecutor = async (params, context) => {
12495
+ var tonMyTransactionsExecutor = async (params, _context) => {
12461
12496
  try {
12462
12497
  const { limit = 10 } = params;
12463
12498
  const walletData = loadWallet();
@@ -12517,7 +12552,7 @@ var PERIOD_CONFIG = {
12517
12552
  "90d": { seconds: 7776e3, points: 180 },
12518
12553
  "1y": { seconds: 31536e3, points: 200 }
12519
12554
  };
12520
- var tonChartExecutor = async (params, context) => {
12555
+ var tonChartExecutor = async (params, _context) => {
12521
12556
  try {
12522
12557
  const token = params.token || "ton";
12523
12558
  const period = params.period || "7d";
@@ -12621,7 +12656,7 @@ var nftListTool = {
12621
12656
  }),
12622
12657
  category: "data-bearing"
12623
12658
  };
12624
- var nftListExecutor = async (params, context) => {
12659
+ var nftListExecutor = async (params, _context) => {
12625
12660
  try {
12626
12661
  const address = params.address || getWalletAddress();
12627
12662
  if (!address) {
@@ -12735,7 +12770,7 @@ var jettonSendTool = {
12735
12770
  )
12736
12771
  })
12737
12772
  };
12738
- var jettonSendExecutor = async (params, context) => {
12773
+ var jettonSendExecutor = async (params, _context) => {
12739
12774
  try {
12740
12775
  const { jetton_address, to, amount, comment } = params;
12741
12776
  const walletData = loadWallet();
@@ -12854,7 +12889,7 @@ var jettonBalancesTool = {
12854
12889
  parameters: Type90.Object({}),
12855
12890
  category: "data-bearing"
12856
12891
  };
12857
- var jettonBalancesExecutor = async (params, context) => {
12892
+ var jettonBalancesExecutor = async (_params, _context) => {
12858
12893
  try {
12859
12894
  const walletData = loadWallet();
12860
12895
  if (!walletData) {
@@ -12964,7 +12999,7 @@ var jettonInfoTool = {
12964
12999
  })
12965
13000
  })
12966
13001
  };
12967
- var jettonInfoExecutor = async (params, context) => {
13002
+ var jettonInfoExecutor = async (params, _context) => {
12968
13003
  try {
12969
13004
  const { jetton_address } = params;
12970
13005
  const response = await tonapiFetch(`/jettons/${jetton_address}`);
@@ -13061,7 +13096,7 @@ var jettonPriceTool = {
13061
13096
  })
13062
13097
  })
13063
13098
  };
13064
- var jettonPriceExecutor = async (params, context) => {
13099
+ var jettonPriceExecutor = async (params, _context) => {
13065
13100
  try {
13066
13101
  const { jetton_address } = params;
13067
13102
  const response = await tonapiFetch(
@@ -13169,7 +13204,7 @@ var jettonHoldersTool = {
13169
13204
  )
13170
13205
  })
13171
13206
  };
13172
- var jettonHoldersExecutor = async (params, context) => {
13207
+ var jettonHoldersExecutor = async (params, _context) => {
13173
13208
  try {
13174
13209
  const { jetton_address, limit = 10 } = params;
13175
13210
  const response = await tonapiFetch(
@@ -13212,7 +13247,8 @@ var jettonHoldersExecutor = async (params, context) => {
13212
13247
  isWallet: h.owner?.is_wallet || false
13213
13248
  };
13214
13249
  });
13215
- const totalTop = holders.reduce(
13250
+ const _totalTop = holders.reduce(
13251
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TON API response is untyped
13216
13252
  (sum, h) => sum + parseFloat(h.balance.replace(/,/g, "")),
13217
13253
  0
13218
13254
  );
@@ -13258,7 +13294,7 @@ var jettonHistoryTool = {
13258
13294
  })
13259
13295
  })
13260
13296
  };
13261
- var jettonHistoryExecutor = async (params, context) => {
13297
+ var jettonHistoryExecutor = async (params, _context) => {
13262
13298
  try {
13263
13299
  const { jetton_address } = params;
13264
13300
  const ratesResponse = await tonapiFetch(
@@ -13524,7 +13560,7 @@ async function getDedustQuote(fromAsset, toAsset, amount, slippage, tonClient) {
13524
13560
  };
13525
13561
  }
13526
13562
  }
13527
- var dexQuoteExecutor = async (params, context) => {
13563
+ var dexQuoteExecutor = async (params, _context) => {
13528
13564
  try {
13529
13565
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
13530
13566
  const tonClient = await getCachedTonClient();
@@ -13671,7 +13707,7 @@ function estimateMinPrice(length) {
13671
13707
  if (length >= 6 && length <= 10) return "~5-10 TON";
13672
13708
  return "~1 TON";
13673
13709
  }
13674
- var dnsCheckExecutor = async (params, context) => {
13710
+ var dnsCheckExecutor = async (params, _context) => {
13675
13711
  try {
13676
13712
  let { domain } = params;
13677
13713
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -13790,7 +13826,7 @@ var dnsAuctionsTool = {
13790
13826
  )
13791
13827
  })
13792
13828
  };
13793
- var dnsAuctionsExecutor = async (params, context) => {
13829
+ var dnsAuctionsExecutor = async (params, _context) => {
13794
13830
  try {
13795
13831
  const { limit = 20 } = params;
13796
13832
  const response = await tonapiFetch(`/dns/auctions?tld=ton`);
@@ -13824,6 +13860,7 @@ var dnsAuctionsExecutor = async (params, context) => {
13824
13860
  };
13825
13861
  });
13826
13862
  const summary = formattedAuctions.map(
13863
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TON DNS API response is untyped
13827
13864
  (a, i) => `${i + 1}. ${a.domain} - ${a.currentBid} (${a.bids} bids) - Ends: ${a.endDate}`
13828
13865
  ).join("\n");
13829
13866
  return {
@@ -13860,7 +13897,7 @@ var dnsResolveTool = {
13860
13897
  })
13861
13898
  })
13862
13899
  };
13863
- var dnsResolveExecutor = async (params, context) => {
13900
+ var dnsResolveExecutor = async (params, _context) => {
13864
13901
  try {
13865
13902
  let { domain } = params;
13866
13903
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -13931,9 +13968,10 @@ var dnsStartAuctionTool = {
13931
13968
  })
13932
13969
  })
13933
13970
  };
13934
- var dnsStartAuctionExecutor = async (params, context) => {
13971
+ var dnsStartAuctionExecutor = async (params, _context) => {
13935
13972
  try {
13936
- let { domain, amount } = params;
13973
+ let { domain } = params;
13974
+ const { amount } = params;
13937
13975
  domain = domain.toLowerCase().replace(/\.ton$/, "");
13938
13976
  if (domain.length < 4 || domain.length > 126) {
13939
13977
  return {
@@ -14021,9 +14059,10 @@ var dnsBidTool = {
14021
14059
  })
14022
14060
  })
14023
14061
  };
14024
- var dnsBidExecutor = async (params, context) => {
14062
+ var dnsBidExecutor = async (params, _context) => {
14025
14063
  try {
14026
- let { domain, amount } = params;
14064
+ let { domain } = params;
14065
+ const { amount } = params;
14027
14066
  domain = domain.toLowerCase().replace(/\.ton$/, "");
14028
14067
  const fullDomain = `${domain}.ton`;
14029
14068
  const dnsResponse = await tonapiFetch(`/dns/${fullDomain}`);
@@ -14148,9 +14187,10 @@ var dnsLinkTool = {
14148
14187
  )
14149
14188
  })
14150
14189
  };
14151
- var dnsLinkExecutor = async (params, context) => {
14190
+ var dnsLinkExecutor = async (params, _context) => {
14152
14191
  try {
14153
- let { domain, wallet_address } = params;
14192
+ let { domain } = params;
14193
+ const { wallet_address } = params;
14154
14194
  domain = domain.toLowerCase().replace(/\.ton$/, "");
14155
14195
  const fullDomain = `${domain}.ton`;
14156
14196
  const walletData = loadWallet();
@@ -14273,7 +14313,7 @@ var dnsUnlinkTool = {
14273
14313
  })
14274
14314
  })
14275
14315
  };
14276
- var dnsUnlinkExecutor = async (params, context) => {
14316
+ var dnsUnlinkExecutor = async (params, _context) => {
14277
14317
  try {
14278
14318
  let { domain } = params;
14279
14319
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -14391,7 +14431,7 @@ var dnsSetSiteTool = {
14391
14431
  })
14392
14432
  })
14393
14433
  };
14394
- var dnsSetSiteExecutor = async (params, context) => {
14434
+ var dnsSetSiteExecutor = async (params, _context) => {
14395
14435
  try {
14396
14436
  let { domain, adnl_address } = params;
14397
14437
  domain = domain.toLowerCase().replace(/\.ton$/, "");
@@ -14537,7 +14577,7 @@ var stonfiSwapTool = {
14537
14577
  )
14538
14578
  })
14539
14579
  };
14540
- var stonfiSwapExecutor = async (params, context) => {
14580
+ var stonfiSwapExecutor = async (params, _context) => {
14541
14581
  try {
14542
14582
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
14543
14583
  const walletData = loadWallet();
@@ -14711,7 +14751,7 @@ var stonfiQuoteTool = {
14711
14751
  )
14712
14752
  })
14713
14753
  };
14714
- var stonfiQuoteExecutor = async (params, context) => {
14754
+ var stonfiQuoteExecutor = async (params, _context) => {
14715
14755
  try {
14716
14756
  const { from_asset, to_asset, amount, slippage = 0.01 } = params;
14717
14757
  const isTonInput = from_asset.toLowerCase() === "ton" || from_asset === NATIVE_TON_ADDRESS3;
@@ -14817,7 +14857,7 @@ var stonfiSearchTool = {
14817
14857
  )
14818
14858
  })
14819
14859
  };
14820
- var stonfiSearchExecutor = async (params, context) => {
14860
+ var stonfiSearchExecutor = async (params, _context) => {
14821
14861
  try {
14822
14862
  const { query, limit = 10 } = params;
14823
14863
  const searchQuery = query.toLowerCase().trim();
@@ -14880,7 +14920,7 @@ var stonfiSearchExecutor = async (params, context) => {
14880
14920
  }
14881
14921
  results.sort((a, b) => b.score - a.score);
14882
14922
  const topResults = results.slice(0, Math.min(limit, 50));
14883
- const cleanResults = topResults.map(({ score, ...rest }) => rest);
14923
+ const cleanResults = topResults.map(({ score: _score, ...rest }) => rest);
14884
14924
  let message = "";
14885
14925
  if (cleanResults.length === 0) {
14886
14926
  message = `No jettons found matching "${query}". Try a different search term.`;
@@ -14934,7 +14974,7 @@ var stonfiTrendingTool = {
14934
14974
  )
14935
14975
  })
14936
14976
  };
14937
- var stonfiTrendingExecutor = async (params, context) => {
14977
+ var stonfiTrendingExecutor = async (params, _context) => {
14938
14978
  try {
14939
14979
  const { limit = 10 } = params;
14940
14980
  const response = await fetchWithTimeout(`${STONFI_API_BASE_URL}/assets`, {
@@ -15014,7 +15054,7 @@ var stonfiPoolsTool = {
15014
15054
  )
15015
15055
  })
15016
15056
  };
15017
- var stonfiPoolsExecutor = async (params, context) => {
15057
+ var stonfiPoolsExecutor = async (params, _context) => {
15018
15058
  try {
15019
15059
  const { jetton_address, limit = 10 } = params;
15020
15060
  const response = await fetchWithTimeout(`${STONFI_API_BASE_URL}/pools`, {
@@ -15037,6 +15077,7 @@ var stonfiPoolsExecutor = async (params, context) => {
15037
15077
  });
15038
15078
  }
15039
15079
  pools = pools.filter((p) => !p.deprecated).sort(
15080
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- DEX API response is untyped
15040
15081
  (a, b) => parseFloat(b.volume_24h_usd || "0") - parseFloat(a.volume_24h_usd || "0")
15041
15082
  ).slice(0, limit);
15042
15083
  const assetMap = {};
@@ -15149,7 +15190,7 @@ var dedustQuoteTool = {
15149
15190
  )
15150
15191
  })
15151
15192
  };
15152
- var dedustQuoteExecutor = async (params, context) => {
15193
+ var dedustQuoteExecutor = async (params, _context) => {
15153
15194
  try {
15154
15195
  const { from_asset, to_asset, amount, pool_type = "volatile", slippage = 0.01 } = params;
15155
15196
  const isTonInput = from_asset.toLowerCase() === "ton";
@@ -15159,7 +15200,7 @@ var dedustQuoteExecutor = async (params, context) => {
15159
15200
  if (!isTonInput) {
15160
15201
  try {
15161
15202
  fromAssetAddr = Address15.parse(from_asset).toString();
15162
- } catch (error) {
15203
+ } catch {
15163
15204
  return {
15164
15205
  success: false,
15165
15206
  error: `Invalid from_asset address: ${from_asset}`
@@ -15169,7 +15210,7 @@ var dedustQuoteExecutor = async (params, context) => {
15169
15210
  if (!isTonOutput) {
15170
15211
  try {
15171
15212
  toAssetAddr = Address15.parse(to_asset).toString();
15172
- } catch (error) {
15213
+ } catch {
15173
15214
  return {
15174
15215
  success: false,
15175
15216
  error: `Invalid to_asset address: ${to_asset}`
@@ -15290,7 +15331,7 @@ var dedustSwapTool = {
15290
15331
  )
15291
15332
  })
15292
15333
  };
15293
- var dedustSwapExecutor = async (params, context) => {
15334
+ var dedustSwapExecutor = async (params, _context) => {
15294
15335
  try {
15295
15336
  const { from_asset, to_asset, amount, pool_type = "volatile", slippage = 0.01 } = params;
15296
15337
  const walletData = loadWallet();
@@ -15307,7 +15348,7 @@ var dedustSwapExecutor = async (params, context) => {
15307
15348
  if (!isTonInput) {
15308
15349
  try {
15309
15350
  fromAssetAddr = Address16.parse(from_asset).toString();
15310
- } catch (error) {
15351
+ } catch {
15311
15352
  return {
15312
15353
  success: false,
15313
15354
  error: `Invalid from_asset address: ${from_asset}`
@@ -15317,7 +15358,7 @@ var dedustSwapExecutor = async (params, context) => {
15317
15358
  if (!isTonOutput) {
15318
15359
  try {
15319
15360
  toAssetAddr = Address16.parse(to_asset).toString();
15320
- } catch (error) {
15361
+ } catch {
15321
15362
  return {
15322
15363
  success: false,
15323
15364
  error: `Invalid to_asset address: ${to_asset}`
@@ -15472,7 +15513,7 @@ var dedustPoolsTool = {
15472
15513
  )
15473
15514
  })
15474
15515
  };
15475
- var dedustPoolsExecutor = async (params, context) => {
15516
+ var dedustPoolsExecutor = async (params, _context) => {
15476
15517
  try {
15477
15518
  const { jetton_address, pool_type, limit = 20 } = params;
15478
15519
  const response = await fetchWithTimeout(`${DEDUST_API_URL}/pools`);
@@ -16146,7 +16187,7 @@ function listDir(dirPath, recursive, filter) {
16146
16187
  results.push(...listDir(fullPath, recursive, filter));
16147
16188
  }
16148
16189
  }
16149
- } catch (error) {
16190
+ } catch {
16150
16191
  }
16151
16192
  return results;
16152
16193
  }
@@ -16881,6 +16922,116 @@ function registerAllTools(registry) {
16881
16922
  }
16882
16923
  }
16883
16924
 
16925
+ // src/sdk/hooks/runner.ts
16926
+ var DEFAULT_TIMEOUT_MS = 5e3;
16927
+ async function withTimeout(fn, ms, label, _log) {
16928
+ let timer;
16929
+ try {
16930
+ await Promise.race([
16931
+ Promise.resolve(fn()),
16932
+ new Promise((_, reject) => {
16933
+ timer = setTimeout(() => reject(new Error(`Hook timeout: ${label}`)), ms);
16934
+ })
16935
+ ]);
16936
+ } finally {
16937
+ if (timer !== void 0) clearTimeout(timer);
16938
+ }
16939
+ }
16940
+ var BLOCKABLE_HOOKS = /* @__PURE__ */ new Set([
16941
+ "tool:before",
16942
+ "message:receive",
16943
+ "response:before"
16944
+ ]);
16945
+ function createHookRunner(registry, opts) {
16946
+ let hookDepth = 0;
16947
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
16948
+ const catchErrors = opts.catchErrors ?? true;
16949
+ async function runModifyingHook(name, event) {
16950
+ if (!registry.hasHooks(name) || hookDepth > 0) {
16951
+ if (hookDepth > 0) {
16952
+ opts.logger.debug(`Skipping ${name} hooks (reentrancy depth=${hookDepth})`);
16953
+ }
16954
+ return;
16955
+ }
16956
+ const hooks = registry.getHooks(name);
16957
+ hookDepth++;
16958
+ try {
16959
+ for (const hook of hooks) {
16960
+ const label = `${hook.pluginId}:${name}`;
16961
+ const t0 = Date.now();
16962
+ try {
16963
+ await withTimeout(
16964
+ () => hook.handler(event),
16965
+ timeoutMs,
16966
+ label,
16967
+ opts.logger
16968
+ );
16969
+ } catch (err) {
16970
+ if (catchErrors) {
16971
+ opts.logger.error(
16972
+ `Hook error [${label}]: ${getErrorMessage(err)} (after ${Date.now() - t0}ms)`
16973
+ );
16974
+ } else {
16975
+ throw err;
16976
+ }
16977
+ }
16978
+ if (BLOCKABLE_HOOKS.has(name) && event.block) {
16979
+ break;
16980
+ }
16981
+ }
16982
+ } finally {
16983
+ hookDepth--;
16984
+ }
16985
+ }
16986
+ async function runObservingHook(name, event) {
16987
+ if (!registry.hasHooks(name) || hookDepth > 0) {
16988
+ if (hookDepth > 0) {
16989
+ opts.logger.debug(`Skipping ${name} hooks (reentrancy depth=${hookDepth})`);
16990
+ }
16991
+ return;
16992
+ }
16993
+ const hooks = registry.getHooks(name);
16994
+ hookDepth++;
16995
+ try {
16996
+ const results = await Promise.allSettled(
16997
+ hooks.map(async (hook) => {
16998
+ const label = `${hook.pluginId}:${name}`;
16999
+ const t0 = Date.now();
17000
+ try {
17001
+ await withTimeout(
17002
+ () => hook.handler(event),
17003
+ timeoutMs,
17004
+ label,
17005
+ opts.logger
17006
+ );
17007
+ } catch (err) {
17008
+ if (catchErrors) {
17009
+ opts.logger.error(
17010
+ `Hook error [${label}]: ${getErrorMessage(err)} (after ${Date.now() - t0}ms)`
17011
+ );
17012
+ } else {
17013
+ throw err;
17014
+ }
17015
+ }
17016
+ })
17017
+ );
17018
+ if (!catchErrors) {
17019
+ const firstRejected = results.find((r) => r.status === "rejected");
17020
+ if (firstRejected) throw firstRejected.reason;
17021
+ }
17022
+ } finally {
17023
+ hookDepth--;
17024
+ }
17025
+ }
17026
+ return {
17027
+ runModifyingHook,
17028
+ runObservingHook,
17029
+ get depth() {
17030
+ return hookDepth;
17031
+ }
17032
+ };
17033
+ }
17034
+
16884
17035
  // src/agent/tools/exec/run.ts
16885
17036
  import { Type as Type126 } from "@sinclair/typebox";
16886
17037
 
@@ -16901,6 +17052,7 @@ function runCommand(command, options) {
16901
17052
  detached: true,
16902
17053
  stdio: ["ignore", "pipe", "pipe"],
16903
17054
  encoding: "utf8"
17055
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Node.js spawn options type doesn't include encoding
16904
17056
  });
16905
17057
  const finish = (exitCode, signal) => {
16906
17058
  if (resolved) return;
@@ -16917,9 +17069,9 @@ function runCommand(command, options) {
16917
17069
  timedOut
16918
17070
  });
16919
17071
  };
16920
- child.stdout.setEncoding("utf8");
16921
- child.stderr.setEncoding("utf8");
16922
- child.stdout.on("data", (chunk) => {
17072
+ child.stdout?.setEncoding("utf8");
17073
+ child.stderr?.setEncoding("utf8");
17074
+ child.stdout?.on("data", (chunk) => {
16923
17075
  if (stdout.length < maxOutput) {
16924
17076
  stdout += chunk;
16925
17077
  if (stdout.length > maxOutput) {
@@ -16928,7 +17080,7 @@ function runCommand(command, options) {
16928
17080
  }
16929
17081
  }
16930
17082
  });
16931
- child.stderr.on("data", (chunk) => {
17083
+ child.stderr?.on("data", (chunk) => {
16932
17084
  if (stderr.length < maxOutput) {
16933
17085
  stderr += chunk;
16934
17086
  if (stderr.length > maxOutput) {
@@ -16949,10 +17101,10 @@ function runCommand(command, options) {
16949
17101
  const timeoutTimer = setTimeout(() => {
16950
17102
  timedOut = true;
16951
17103
  log131.warn({ command, timeout }, "Command timed out, sending SIGTERM");
16952
- killProcessGroup(child.pid, "SIGTERM");
17104
+ if (child.pid) killProcessGroup(child.pid, "SIGTERM");
16953
17105
  killTimer = setTimeout(() => {
16954
17106
  log131.warn({ command }, "Grace period expired, sending SIGKILL");
16955
- killProcessGroup(child.pid, "SIGKILL");
17107
+ if (child.pid) killProcessGroup(child.pid, "SIGKILL");
16956
17108
  }, KILL_GRACE_MS);
16957
17109
  }, timeout);
16958
17110
  });
@@ -17314,11 +17466,11 @@ var execModule = {
17314
17466
  log132.info({ mode: moduleConfig.mode, scope: moduleConfig.scope }, "Exec capability active");
17315
17467
  }
17316
17468
  };
17317
- var module_default2 = execModule;
17469
+ var module_default3 = execModule;
17318
17470
 
17319
17471
  // src/agent/tools/module-loader.ts
17320
17472
  var log133 = createLogger("ModuleLoader");
17321
- var BUILTIN_MODULES = [module_default, module_default2];
17473
+ var BUILTIN_MODULES = [module_default2, module_default, module_default3];
17322
17474
  function loadModules(registry, config, db2) {
17323
17475
  const loaded = [];
17324
17476
  for (const mod of BUILTIN_MODULES) {
@@ -17623,7 +17775,7 @@ function parseCommand(config) {
17623
17775
  return { command: parts[0], args: parts.slice(1) };
17624
17776
  }
17625
17777
  function extractText(content) {
17626
- return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n");
17778
+ return content.filter((c) => c.type === "text" && c.text).map((c) => c.text ?? "").join("\n");
17627
17779
  }
17628
17780
  async function loadMcpServers(config) {
17629
17781
  const entries = Object.entries(config.servers).filter(([, cfg]) => cfg.enabled !== false);
@@ -17635,7 +17787,7 @@ async function loadMcpServers(config) {
17635
17787
  const { command, args } = parseCommand(serverConfig);
17636
17788
  const safeEnv = {};
17637
17789
  for (const key of ["PATH", "HOME", "NODE_PATH", "LANG", "TERM"]) {
17638
- if (process.env[key]) safeEnv[key] = process.env[key];
17790
+ if (process.env[key]) safeEnv[key] = process.env[key] ?? "";
17639
17791
  }
17640
17792
  const BLOCKED_ENV_KEYS = /* @__PURE__ */ new Set([
17641
17793
  "LD_PRELOAD",
@@ -17729,10 +17881,23 @@ async function registerMcpTools(connections, registry) {
17729
17881
  const prefixedName = `mcp_${conn.serverName}_${mcpTool.name}`;
17730
17882
  const executor = async (params) => {
17731
17883
  try {
17732
- const result = await conn.client.callTool({
17733
- name: mcpTool.name,
17734
- arguments: params
17735
- });
17884
+ let timeoutHandle;
17885
+ const result = await Promise.race([
17886
+ conn.client.callTool({
17887
+ name: mcpTool.name,
17888
+ arguments: params
17889
+ }),
17890
+ new Promise((_, reject) => {
17891
+ timeoutHandle = setTimeout(
17892
+ () => reject(
17893
+ new Error(
17894
+ `MCP tool "${mcpTool.name}" timed out after ${TOOL_EXECUTION_TIMEOUT_MS / 1e3}s`
17895
+ )
17896
+ ),
17897
+ TOOL_EXECUTION_TIMEOUT_MS
17898
+ );
17899
+ })
17900
+ ]).finally(() => clearTimeout(timeoutHandle));
17736
17901
  if (result.isError) {
17737
17902
  const errorText = extractText(
17738
17903
  result.content
@@ -17795,6 +17960,101 @@ async function closeMcpServers(connections) {
17795
17960
  );
17796
17961
  }
17797
17962
 
17963
+ // src/agent/hooks/user-hook-evaluator.ts
17964
+ var ZERO_WIDTH_RE = /[\u200B-\u200D\uFEFF\u00AD]/g;
17965
+ var TOKEN_SPLIT_RE = /[\s,.!?;:'"()\[\]{}<>/\\|@#$%^&*+=~`]+/;
17966
+ function normalize(text) {
17967
+ return text.toLowerCase().normalize("NFKC").replace(ZERO_WIDTH_RE, "");
17968
+ }
17969
+ function tokenize(text) {
17970
+ return normalize(text).split(TOKEN_SPLIT_RE).filter(Boolean);
17971
+ }
17972
+ function matchesMultiWord(messageTokens, keywordTokens) {
17973
+ if (keywordTokens.length > messageTokens.length) return false;
17974
+ for (let i = 0; i <= messageTokens.length - keywordTokens.length; i++) {
17975
+ let match = true;
17976
+ for (let j = 0; j < keywordTokens.length; j++) {
17977
+ if (messageTokens[i + j] !== keywordTokens[j]) {
17978
+ match = false;
17979
+ break;
17980
+ }
17981
+ }
17982
+ if (match) return true;
17983
+ }
17984
+ return false;
17985
+ }
17986
+ var UserHookEvaluator = class {
17987
+ constructor(db2) {
17988
+ this.db = db2;
17989
+ this.reload();
17990
+ }
17991
+ blocklistEnabled = false;
17992
+ singleKeywords = /* @__PURE__ */ new Set();
17993
+ multiKeywords = [];
17994
+ blockMessage = "";
17995
+ triggers = [];
17996
+ /** Reload config from DB — called on startup and after WebUI changes */
17997
+ reload() {
17998
+ const blocklist = getBlocklistConfig(this.db);
17999
+ this.blocklistEnabled = blocklist.enabled;
18000
+ this.blockMessage = blocklist.message;
18001
+ this.singleKeywords.clear();
18002
+ this.multiKeywords = [];
18003
+ for (const kw of blocklist.keywords) {
18004
+ const tokens = tokenize(kw);
18005
+ if (tokens.length === 0) continue;
18006
+ if (tokens.length === 1) {
18007
+ this.singleKeywords.add(tokens[0]);
18008
+ } else {
18009
+ this.multiKeywords.push(tokens);
18010
+ }
18011
+ }
18012
+ const triggers = getTriggersConfig(this.db);
18013
+ this.triggers = triggers.map((t) => ({
18014
+ ...t,
18015
+ keywordTokens: tokenize(t.keyword)
18016
+ }));
18017
+ }
18018
+ /** Evaluate a message — returns { blocked, blockMessage, additionalContext } */
18019
+ evaluate(text) {
18020
+ const tokens = tokenize(text);
18021
+ if (this.blocklistEnabled) {
18022
+ for (const token of tokens) {
18023
+ if (this.singleKeywords.has(token)) {
18024
+ return {
18025
+ blocked: true,
18026
+ blockMessage: this.blockMessage || void 0,
18027
+ additionalContext: ""
18028
+ };
18029
+ }
18030
+ }
18031
+ for (const kwTokens of this.multiKeywords) {
18032
+ if (matchesMultiWord(tokens, kwTokens)) {
18033
+ return {
18034
+ blocked: true,
18035
+ blockMessage: this.blockMessage || void 0,
18036
+ additionalContext: ""
18037
+ };
18038
+ }
18039
+ }
18040
+ }
18041
+ const contexts = [];
18042
+ const seen = /* @__PURE__ */ new Set();
18043
+ for (const trigger of this.triggers) {
18044
+ if (!trigger.enabled || trigger.keywordTokens.length === 0) continue;
18045
+ const matched = trigger.keywordTokens.length === 1 ? tokens.includes(trigger.keywordTokens[0]) : matchesMultiWord(tokens, trigger.keywordTokens);
18046
+ if (matched && !seen.has(trigger.context)) {
18047
+ seen.add(trigger.context);
18048
+ contexts.push(trigger.context);
18049
+ }
18050
+ }
18051
+ return {
18052
+ blocked: false,
18053
+ additionalContext: contexts.join("\n\n")
18054
+ };
18055
+ }
18056
+ };
18057
+
17798
18058
  // src/agent/lifecycle.ts
17799
18059
  import { EventEmitter } from "events";
17800
18060
  var log136 = createLogger("Lifecycle");
@@ -17840,7 +18100,7 @@ var AgentLifecycle = class extends EventEmitter {
17840
18100
  return;
17841
18101
  }
17842
18102
  if (this.state === "starting") {
17843
- return this.startPromise;
18103
+ return this.startPromise ?? Promise.resolve();
17844
18104
  }
17845
18105
  if (this.state === "stopping") {
17846
18106
  throw new Error("Cannot start while agent is stopping");
@@ -17879,7 +18139,7 @@ var AgentLifecycle = class extends EventEmitter {
17879
18139
  return;
17880
18140
  }
17881
18141
  if (this.state === "stopping") {
17882
- return this.stopPromise;
18142
+ return this.stopPromise ?? Promise.resolve();
17883
18143
  }
17884
18144
  if (this.state === "starting" && this.startPromise) {
17885
18145
  try {
@@ -17967,17 +18227,19 @@ var TeletonApp = class {
17967
18227
  debouncer = null;
17968
18228
  toolCount = 0;
17969
18229
  toolRegistry;
17970
- dependencyResolver;
17971
- // TaskDependencyResolver, imported lazily
18230
+ dependencyResolver = null;
17972
18231
  modules = [];
17973
18232
  memory;
17974
18233
  sdkDeps;
17975
18234
  webuiServer = null;
17976
- // WebUIServer, imported lazily
17977
18235
  pluginWatcher = null;
17978
18236
  mcpConnections = [];
17979
18237
  callbackHandlerRegistered = false;
17980
18238
  lifecycle = new AgentLifecycle();
18239
+ hookRunner;
18240
+ userHookEvaluator = null;
18241
+ startTime = 0;
18242
+ messagesProcessed = 0;
17981
18243
  configPath;
17982
18244
  constructor(configPath) {
17983
18245
  this.configPath = configPath ?? getDefaultConfigPath();
@@ -18017,6 +18279,8 @@ var TeletonApp = class {
18017
18279
  workspaceDir: join9(TELETON_ROOT)
18018
18280
  });
18019
18281
  const db2 = getDatabase().getDb();
18282
+ this.userHookEvaluator = new UserHookEvaluator(db2);
18283
+ this.agent.setUserHookEvaluator(this.userHookEvaluator);
18020
18284
  this.sdkDeps = { bridge: this.bridge };
18021
18285
  this.modules = loadModules(this.toolRegistry, this.config, db2);
18022
18286
  const modulePermissions = new ModulePermissions(db2);
@@ -18068,7 +18332,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18068
18332
  );
18069
18333
  if (this.config.webui.enabled) {
18070
18334
  try {
18071
- const { WebUIServer } = await import("./server-H3QA252W.js");
18335
+ const { WebUIServer } = await import("./server-3FHI2SEB.js");
18072
18336
  const mcpServers = () => Object.entries(this.config.mcp.servers).map(([name, serverConfig]) => {
18073
18337
  const type = serverConfig.command ? "stdio" : serverConfig.url ? "streamable-http" : "sse";
18074
18338
  const target = serverConfig.command ?? serverConfig.url ?? "";
@@ -18110,7 +18374,8 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18110
18374
  pluginContext,
18111
18375
  loadedModuleNames: builtinNames,
18112
18376
  rewireHooks: () => this.wirePluginEventHooks()
18113
- }
18377
+ },
18378
+ userHookEvaluator: this.userHookEvaluator
18114
18379
  });
18115
18380
  await this.webuiServer.start();
18116
18381
  } catch (error) {
@@ -18129,7 +18394,12 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18129
18394
  async startAgent() {
18130
18395
  const moduleNames = this.modules.filter((m) => m.tools(this.config).length > 0).map((m) => m.name);
18131
18396
  const builtinNames = this.modules.map((m) => m.name);
18132
- const externalModules = await loadEnhancedPlugins(this.config, builtinNames, this.sdkDeps);
18397
+ const { modules: externalModules, hookRegistry } = await loadEnhancedPlugins(
18398
+ this.config,
18399
+ builtinNames,
18400
+ this.sdkDeps,
18401
+ getDatabase().getDb()
18402
+ );
18133
18403
  let pluginToolCount = 0;
18134
18404
  const pluginNames = [];
18135
18405
  for (const mod of externalModules) {
@@ -18167,7 +18437,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18167
18437
  }
18168
18438
  this.toolRegistry.loadConfigFromDB(getDatabase().getDb());
18169
18439
  if (this.config.tool_rag.enabled) {
18170
- const { ToolIndex } = await import("./tool-index-H3SHOJC3.js");
18440
+ const { ToolIndex } = await import("./tool-index-PMAOXWUA.js");
18171
18441
  const toolIndex2 = new ToolIndex(
18172
18442
  getDatabase().getDb(),
18173
18443
  this.memory.embedder,
@@ -18195,18 +18465,21 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18195
18465
  `\u26A0\uFE0F Tool count (${this.toolCount}) exceeds ${providerMeta.displayName} limit (${providerMeta.toolLimit})`
18196
18466
  );
18197
18467
  }
18198
- const { migrateSessionsToDb } = await import("./migrate-POHWYEIW.js");
18468
+ const { migrateSessionsToDb } = await import("./migrate-UBBEJ5BL.js");
18199
18469
  migrateSessionsToDb();
18200
- const { cleanupOldTranscripts } = await import("./transcript-IMNE6KU3.js");
18470
+ const { cleanupOldTranscripts } = await import("./transcript-NGDPSNIH.js");
18201
18471
  cleanupOldTranscripts(30);
18202
- const { pruneOldSessions } = await import("./store-GAFULOOX.js");
18472
+ const { pruneOldSessions } = await import("./store-M5IMUQCL.js");
18203
18473
  pruneOldSessions(30);
18204
18474
  if (this.memory.embedder.warmup) {
18205
18475
  await this.memory.embedder.warmup();
18206
18476
  }
18207
18477
  const indexResult = await this.memory.knowledge.indexAll();
18208
18478
  const db2 = getDatabase();
18209
- const ftsResult = db2.rebuildFtsIndexes();
18479
+ let ftsResult = { knowledge: 0, messages: 0 };
18480
+ if (indexResult.indexed > 0) {
18481
+ ftsResult = db2.rebuildFtsIndexes();
18482
+ }
18210
18483
  const toolIndex = this.toolRegistry.getToolIndex();
18211
18484
  if (toolIndex) {
18212
18485
  const t0 = Date.now();
@@ -18216,7 +18489,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18216
18489
  this.agent.initializeContextBuilder(this.memory.embedder, db2.isVectorSearchReady());
18217
18490
  if (this.config.agent.provider === "cocoon") {
18218
18491
  try {
18219
- const { registerCocoonModels } = await import("./client-LNZTDQSA.js");
18492
+ const { registerCocoonModels } = await import("./client-MPHPIZB6.js");
18220
18493
  const port = this.config.cocoon?.port ?? 1e4;
18221
18494
  const models = await registerCocoonModels(port);
18222
18495
  if (models.length === 0) {
@@ -18238,7 +18511,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18238
18511
  }
18239
18512
  if (this.config.agent.provider === "local" && this.config.agent.base_url) {
18240
18513
  try {
18241
- const { registerLocalModels } = await import("./client-LNZTDQSA.js");
18514
+ const { registerLocalModels } = await import("./client-MPHPIZB6.js");
18242
18515
  const models = await registerLocalModels(this.config.agent.base_url);
18243
18516
  if (models.length > 0) {
18244
18517
  log137.info(`Discovered ${models.length} local model(s): ${models.join(", ")}`);
@@ -18303,6 +18576,28 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18303
18576
  inlineRouter.setGramJSBot(activeDealBot.getGramJSBot());
18304
18577
  log137.info("\u{1F50C} Bot SDK: inline router installed");
18305
18578
  }
18579
+ if (hookRegistry.hasAnyHooks()) {
18580
+ const hookRunner = createHookRunner(hookRegistry, { logger: log137 });
18581
+ this.agent.setHookRunner(hookRunner);
18582
+ this.hookRunner = hookRunner;
18583
+ const activeHooks = [
18584
+ "tool:before",
18585
+ "tool:after",
18586
+ "tool:error",
18587
+ "prompt:before",
18588
+ "prompt:after",
18589
+ "session:start",
18590
+ "session:end",
18591
+ "message:receive",
18592
+ "response:before",
18593
+ "response:after",
18594
+ "response:error",
18595
+ "agent:start",
18596
+ "agent:stop"
18597
+ ];
18598
+ const active = activeHooks.filter((n) => hookRegistry.hasHooks(n));
18599
+ log137.info(`\u{1FA9D} Hook runner created (${active.join(", ")})`);
18600
+ }
18306
18601
  this.wirePluginEventHooks();
18307
18602
  if (this.config.dev.hot_reload) {
18308
18603
  this.pluginWatcher = new PluginWatcher({
@@ -18331,6 +18626,26 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18331
18626
  `
18332
18627
  );
18333
18628
  log137.info("Teleton Agent is running! Press Ctrl+C to stop.");
18629
+ this.startTime = Date.now();
18630
+ this.messagesProcessed = 0;
18631
+ if (this.hookRunner) {
18632
+ let version = "0.0.0";
18633
+ try {
18634
+ const { createRequire } = await import("module");
18635
+ const req = createRequire(import.meta.url);
18636
+ version = req("../package.json").version;
18637
+ } catch {
18638
+ }
18639
+ const agentStartEvent = {
18640
+ version,
18641
+ provider,
18642
+ model: this.config.agent.model,
18643
+ pluginCount: pluginNames.length,
18644
+ toolCount: this.toolCount,
18645
+ timestamp: Date.now()
18646
+ };
18647
+ await this.hookRunner.runObservingHook("agent:start", agentStartEvent);
18648
+ }
18334
18649
  this.debouncer = new MessageDebouncer(
18335
18650
  {
18336
18651
  debounceMs: this.config.telegram.debounce_ms
@@ -18422,6 +18737,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
18422
18737
  * Handle a single message (extracted for debouncer callback)
18423
18738
  */
18424
18739
  async handleSingleMessage(message) {
18740
+ this.messagesProcessed++;
18425
18741
  try {
18426
18742
  const ownUserId = this.bridge.getOwnUserId();
18427
18743
  if (ownUserId && message.senderId === Number(ownUserId) && message.text.startsWith("[TASK:")) {
@@ -18488,10 +18804,10 @@ Task: "${taskDescription}"`;
18488
18804
  * Handle scheduled task message
18489
18805
  */
18490
18806
  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");
18807
+ const { getTaskStore } = await import("./tasks-WQIKXDX5.js");
18808
+ const { executeScheduledTask } = await import("./task-executor-6W5HRX5C.js");
18809
+ const { TaskDependencyResolver } = await import("./task-dependency-resolver-RR2O5S7B.js");
18810
+ const { getDatabase: getDatabase2 } = await import("./memory-UBHM7ILG.js");
18495
18811
  const db2 = getDatabase2().getDb();
18496
18812
  const taskStore = getTaskStore(db2);
18497
18813
  const match = message.text.match(/^\[TASK:([^\]]+)\]/);
@@ -18572,7 +18888,7 @@ Task: "${taskDescription}"`;
18572
18888
  this.dependencyResolver = new TaskDependencyResolver(taskStore, this.bridge);
18573
18889
  }
18574
18890
  await this.dependencyResolver.onTaskFail(taskId);
18575
- } catch (e) {
18891
+ } catch {
18576
18892
  }
18577
18893
  }
18578
18894
  }
@@ -18604,14 +18920,18 @@ Task: "${taskDescription}"`;
18604
18920
  }
18605
18921
  if (!this.callbackHandlerRegistered) {
18606
18922
  this.bridge.getClient().addCallbackQueryHandler(async (update) => {
18607
- const queryId = update.queryId;
18608
- const data = update.data?.toString() || "";
18923
+ if (!update || typeof update !== "object") {
18924
+ return;
18925
+ }
18926
+ const callbackUpdate = update;
18927
+ const queryId = callbackUpdate.queryId;
18928
+ const data = typeof callbackUpdate.data === "string" ? callbackUpdate.data : callbackUpdate.data?.toString() || "";
18609
18929
  const parts = data.split(":");
18610
18930
  const action = parts[0];
18611
18931
  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);
18932
+ const chatId = callbackUpdate.peer?.channelId?.toString() ?? callbackUpdate.peer?.chatId?.toString() ?? callbackUpdate.peer?.userId?.toString() ?? "";
18933
+ const messageId = typeof callbackUpdate.msgId === "number" ? callbackUpdate.msgId : Number(callbackUpdate.msgId || 0);
18934
+ const userId = Number(callbackUpdate.userId);
18615
18935
  const answer = async (text, alert = false) => {
18616
18936
  try {
18617
18937
  await this.bridge.getClient().answerCallbackQuery(queryId, { message: text, alert });
@@ -18676,6 +18996,19 @@ Task: "${taskDescription}"`;
18676
18996
  * Called by lifecycle.stop() — do NOT call directly.
18677
18997
  */
18678
18998
  async stopAgent() {
18999
+ if (this.hookRunner) {
19000
+ try {
19001
+ const agentStopEvent = {
19002
+ reason: "manual",
19003
+ uptimeMs: this.startTime > 0 ? Date.now() - this.startTime : 0,
19004
+ messagesProcessed: this.messagesProcessed,
19005
+ timestamp: Date.now()
19006
+ };
19007
+ await this.hookRunner.runObservingHook("agent:stop", agentStopEvent);
19008
+ } catch (e) {
19009
+ log137.error({ err: e }, "\u26A0\uFE0F agent:stop hook failed");
19010
+ }
19011
+ }
18679
19012
  if (this.pluginWatcher) {
18680
19013
  try {
18681
19014
  await this.pluginWatcher.stop();