teleton 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QMN6ZOA5.js → chunk-2X4PCE7V.js} +5 -1
- package/dist/{chunk-WMIN6AGX.js → chunk-DAMFGHXV.js} +1 -1
- package/dist/{chunk-TBIMVWQZ.js → chunk-DR6WM6B5.js} +2 -2
- package/dist/{chunk-KU4Z3TYC.js → chunk-KS7B2CVM.js} +418 -123
- package/dist/{chunk-LJXYESJJ.js → chunk-LCMHAUNK.js} +7 -1
- package/dist/cli/index.js +9 -13
- package/dist/index.js +6 -6
- package/dist/{memory-OEOLPEXP.js → memory-PDEJIPK6.js} +4 -4
- package/dist/{migrate-7XOO67O5.js → migrate-6BQZVOBN.js} +4 -4
- package/dist/{scraper-DSAYK6QJ.js → scraper-2O6Z3ZHT.js} +4 -4
- package/dist/{task-dependency-resolver-CWG6DTU4.js → task-dependency-resolver-WNYOTWWM.js} +4 -2
- package/dist/{task-executor-MNI4VIZL.js → task-executor-4SVB72GR.js} +1 -1
- package/dist/timeouts-ZAK6NELA.js +63 -0
- package/package.json +4 -1
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Mi,
|
|
3
|
+
Mn,
|
|
4
|
+
br,
|
|
5
|
+
dt,
|
|
6
|
+
le,
|
|
7
|
+
qn,
|
|
8
|
+
ut,
|
|
9
|
+
ye
|
|
10
|
+
} from "./chunk-U7FQYCBQ.js";
|
|
1
11
|
import {
|
|
2
12
|
initScraperDb
|
|
3
13
|
} from "./chunk-DUW5VBAZ.js";
|
|
@@ -14,12 +24,13 @@ import {
|
|
|
14
24
|
MessageStore,
|
|
15
25
|
USED_TRANSACTIONS_SCHEMA,
|
|
16
26
|
UserStore,
|
|
27
|
+
closeDatabase,
|
|
17
28
|
createDbWrapper,
|
|
18
29
|
getDatabase,
|
|
19
30
|
initializeMemory,
|
|
20
31
|
migrateFromMainDb,
|
|
21
32
|
openModuleDb
|
|
22
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-DR6WM6B5.js";
|
|
23
34
|
import {
|
|
24
35
|
COINGECKO_API_URL,
|
|
25
36
|
ELEVENLABS_TTS_URL,
|
|
@@ -29,7 +40,7 @@ import {
|
|
|
29
40
|
fetchWithTimeout,
|
|
30
41
|
setTonapiKey,
|
|
31
42
|
tonapiFetch
|
|
32
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-DAMFGHXV.js";
|
|
33
44
|
import {
|
|
34
45
|
COMPACTION_KEEP_RECENT,
|
|
35
46
|
COMPACTION_MAX_MESSAGES,
|
|
@@ -42,8 +53,10 @@ import {
|
|
|
42
53
|
DEBOUNCE_MAX_BUFFER_SIZE,
|
|
43
54
|
DEBOUNCE_MAX_MULTIPLIER,
|
|
44
55
|
DEFAULT_GIFTS_QUERY_LIMIT,
|
|
56
|
+
MAX_DEPENDENTS_PER_TASK,
|
|
45
57
|
MAX_POLL_QUESTION_LENGTH,
|
|
46
58
|
MAX_TOOL_RESULT_SIZE,
|
|
59
|
+
MAX_WRITE_SIZE,
|
|
47
60
|
PAYMENT_TOLERANCE_RATIO,
|
|
48
61
|
PENDING_HISTORY_MAX_AGE_MS,
|
|
49
62
|
PENDING_HISTORY_MAX_PER_CHAT,
|
|
@@ -52,7 +65,14 @@ import {
|
|
|
52
65
|
TELEGRAM_CONNECTION_RETRIES,
|
|
53
66
|
TELEGRAM_FLOOD_SLEEP_THRESHOLD,
|
|
54
67
|
TELEGRAM_MAX_MESSAGE_LENGTH
|
|
55
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-2X4PCE7V.js";
|
|
69
|
+
import {
|
|
70
|
+
ALLOWED_EXTENSIONS,
|
|
71
|
+
MAX_FILE_SIZES,
|
|
72
|
+
TELETON_ROOT,
|
|
73
|
+
WORKSPACE_PATHS,
|
|
74
|
+
WORKSPACE_ROOT
|
|
75
|
+
} from "./chunk-EYWNOHMJ.js";
|
|
56
76
|
import {
|
|
57
77
|
GRAMJS_RETRY_DELAY_MS,
|
|
58
78
|
MESSAGE_HANDLER_LOCK_TIMEOUT_MS,
|
|
@@ -63,29 +83,13 @@ import {
|
|
|
63
83
|
RETRY_DEFAULT_MAX_ATTEMPTS,
|
|
64
84
|
RETRY_DEFAULT_MAX_DELAY_MS,
|
|
65
85
|
RETRY_DEFAULT_TIMEOUT_MS,
|
|
86
|
+
TOOL_EXECUTION_TIMEOUT_MS,
|
|
66
87
|
TTS_TIMEOUT_MS
|
|
67
|
-
} from "./chunk-
|
|
68
|
-
import {
|
|
69
|
-
ALLOWED_EXTENSIONS,
|
|
70
|
-
MAX_FILE_SIZES,
|
|
71
|
-
TELETON_ROOT,
|
|
72
|
-
WORKSPACE_PATHS,
|
|
73
|
-
WORKSPACE_ROOT
|
|
74
|
-
} from "./chunk-EYWNOHMJ.js";
|
|
88
|
+
} from "./chunk-LCMHAUNK.js";
|
|
75
89
|
import {
|
|
76
90
|
telegramGetMyGiftsExecutor,
|
|
77
91
|
telegramGetMyGiftsTool
|
|
78
92
|
} from "./chunk-B2PRMXOH.js";
|
|
79
|
-
import {
|
|
80
|
-
Mi,
|
|
81
|
-
Mn,
|
|
82
|
-
br,
|
|
83
|
-
dt,
|
|
84
|
-
le,
|
|
85
|
-
qn,
|
|
86
|
-
ut,
|
|
87
|
-
ye
|
|
88
|
-
} from "./chunk-U7FQYCBQ.js";
|
|
89
93
|
import {
|
|
90
94
|
__commonJS,
|
|
91
95
|
__toESM
|
|
@@ -3408,7 +3412,13 @@ ${statsContext}`;
|
|
|
3408
3412
|
const providerMeta = getProviderMetadata(
|
|
3409
3413
|
this.config.agent.provider || "anthropic"
|
|
3410
3414
|
);
|
|
3411
|
-
const
|
|
3415
|
+
const isAdmin = toolContext?.config?.telegram.admin_ids.includes(toolContext.senderId) ?? false;
|
|
3416
|
+
const tools23 = this.toolRegistry?.getForContext(
|
|
3417
|
+
isGroup ?? false,
|
|
3418
|
+
providerMeta.toolLimit,
|
|
3419
|
+
chatId,
|
|
3420
|
+
isAdmin
|
|
3421
|
+
);
|
|
3412
3422
|
const maxIterations = this.config.agent.max_agentic_iterations || 5;
|
|
3413
3423
|
let iteration = 0;
|
|
3414
3424
|
let overflowResets = 0;
|
|
@@ -3623,22 +3633,6 @@ ${statsContext}`;
|
|
|
3623
3633
|
*/
|
|
3624
3634
|
clearHistory(chatId) {
|
|
3625
3635
|
const db3 = getDatabase().getDb();
|
|
3626
|
-
db3.prepare(
|
|
3627
|
-
`
|
|
3628
|
-
DELETE FROM tg_messages_fts
|
|
3629
|
-
WHERE rowid IN (
|
|
3630
|
-
SELECT rowid FROM tg_messages WHERE chat_id = ?
|
|
3631
|
-
)
|
|
3632
|
-
`
|
|
3633
|
-
).run(chatId);
|
|
3634
|
-
db3.prepare(
|
|
3635
|
-
`
|
|
3636
|
-
DELETE FROM tg_messages_vec
|
|
3637
|
-
WHERE id IN (
|
|
3638
|
-
SELECT id FROM tg_messages WHERE chat_id = ?
|
|
3639
|
-
)
|
|
3640
|
-
`
|
|
3641
|
-
).run(chatId);
|
|
3642
3636
|
db3.prepare(`DELETE FROM tg_messages WHERE chat_id = ?`).run(chatId);
|
|
3643
3637
|
resetSession(chatId);
|
|
3644
3638
|
console.log(`\u{1F5D1}\uFE0F Cleared history for chat ${chatId}`);
|
|
@@ -4839,7 +4833,21 @@ import { mnemonicNew, mnemonicToPrivateKey, mnemonicValidate } from "@ton/crypto
|
|
|
4839
4833
|
import { WalletContractV5R1, TonClient, fromNano } from "@ton/ton";
|
|
4840
4834
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync8, mkdirSync as mkdirSync6, chmodSync as chmodSync2 } from "fs";
|
|
4841
4835
|
import { join as join6, dirname as dirname5 } from "path";
|
|
4836
|
+
|
|
4837
|
+
// src/ton/endpoint.ts
|
|
4842
4838
|
import { getHttpEndpoint } from "@orbs-network/ton-access";
|
|
4839
|
+
var ENDPOINT_CACHE_TTL_MS = 6e4;
|
|
4840
|
+
var _cache = null;
|
|
4841
|
+
async function getCachedHttpEndpoint() {
|
|
4842
|
+
if (_cache && Date.now() - _cache.ts < ENDPOINT_CACHE_TTL_MS) {
|
|
4843
|
+
return _cache.url;
|
|
4844
|
+
}
|
|
4845
|
+
const url = await getHttpEndpoint({ network: "mainnet" });
|
|
4846
|
+
_cache = { url, ts: Date.now() };
|
|
4847
|
+
return url;
|
|
4848
|
+
}
|
|
4849
|
+
|
|
4850
|
+
// src/ton/wallet-service.ts
|
|
4843
4851
|
var WALLET_FILE = join6(TELETON_ROOT, "wallet.json");
|
|
4844
4852
|
async function generateWallet() {
|
|
4845
4853
|
const mnemonic = await mnemonicNew(24);
|
|
@@ -4905,7 +4913,7 @@ function getWalletAddress() {
|
|
|
4905
4913
|
}
|
|
4906
4914
|
async function getWalletBalance(address4) {
|
|
4907
4915
|
try {
|
|
4908
|
-
const endpoint = await
|
|
4916
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
4909
4917
|
const client = new TonClient({ endpoint });
|
|
4910
4918
|
const { Address: Address19 } = await import("@ton/core");
|
|
4911
4919
|
const addressObj = Address19.parse(address4);
|
|
@@ -4999,15 +5007,20 @@ function initDealsConfig(yaml) {
|
|
|
4999
5007
|
// src/telegram/admin.ts
|
|
5000
5008
|
var VALID_DM_POLICIES = ["open", "allowlist", "pairing", "disabled"];
|
|
5001
5009
|
var VALID_GROUP_POLICIES = ["open", "allowlist", "disabled"];
|
|
5010
|
+
var VALID_MODULE_LEVELS = ["open", "admin", "disabled"];
|
|
5002
5011
|
var AdminHandler = class {
|
|
5003
5012
|
bridge;
|
|
5004
5013
|
config;
|
|
5005
5014
|
agent;
|
|
5006
5015
|
paused = false;
|
|
5007
|
-
|
|
5016
|
+
permissions;
|
|
5017
|
+
registry;
|
|
5018
|
+
constructor(bridge, config, agent, permissions, registry) {
|
|
5008
5019
|
this.bridge = bridge;
|
|
5009
5020
|
this.config = config;
|
|
5010
5021
|
this.agent = agent;
|
|
5022
|
+
this.permissions = permissions ?? null;
|
|
5023
|
+
this.registry = registry ?? null;
|
|
5011
5024
|
}
|
|
5012
5025
|
/**
|
|
5013
5026
|
* Check if user is admin
|
|
@@ -5042,7 +5055,7 @@ var AdminHandler = class {
|
|
|
5042
5055
|
/**
|
|
5043
5056
|
* Handle admin command
|
|
5044
5057
|
*/
|
|
5045
|
-
async handleCommand(command, chatId, senderId) {
|
|
5058
|
+
async handleCommand(command, chatId, senderId, isGroup) {
|
|
5046
5059
|
if (!this.isAdmin(senderId)) {
|
|
5047
5060
|
return "\u26D4 Admin access required";
|
|
5048
5061
|
}
|
|
@@ -5073,6 +5086,8 @@ var AdminHandler = class {
|
|
|
5073
5086
|
return await this.handleStopCommand();
|
|
5074
5087
|
case "verbose":
|
|
5075
5088
|
return this.handleVerboseCommand();
|
|
5089
|
+
case "modules":
|
|
5090
|
+
return this.handleModulesCommand(command, isGroup ?? false);
|
|
5076
5091
|
case "help":
|
|
5077
5092
|
return this.handleHelpCommand();
|
|
5078
5093
|
case "ping":
|
|
@@ -5285,6 +5300,124 @@ Usage:
|
|
|
5285
5300
|
setVerbose(next);
|
|
5286
5301
|
return next ? "\u{1F50A} Verbose logging **ON**" : "\u{1F507} Verbose logging **OFF**";
|
|
5287
5302
|
}
|
|
5303
|
+
/**
|
|
5304
|
+
* /modules - Manage per-group module permissions
|
|
5305
|
+
*/
|
|
5306
|
+
handleModulesCommand(command, isGroup) {
|
|
5307
|
+
if (!this.permissions || !this.registry) {
|
|
5308
|
+
return "\u274C Module permissions non disponible";
|
|
5309
|
+
}
|
|
5310
|
+
if (!isGroup) {
|
|
5311
|
+
return "\u274C /modules est uniquement disponible dans les groupes";
|
|
5312
|
+
}
|
|
5313
|
+
const chatId = command.chatId;
|
|
5314
|
+
const sub = command.args[0]?.toLowerCase();
|
|
5315
|
+
if (!sub) {
|
|
5316
|
+
return this.listModules(chatId);
|
|
5317
|
+
}
|
|
5318
|
+
switch (sub) {
|
|
5319
|
+
case "set":
|
|
5320
|
+
return this.setModuleLevel(chatId, command.args[1], command.args[2], command.senderId);
|
|
5321
|
+
case "info":
|
|
5322
|
+
return this.showModuleInfo(command.args[1], chatId);
|
|
5323
|
+
case "reset":
|
|
5324
|
+
return this.resetModules(chatId, command.args[1]);
|
|
5325
|
+
default:
|
|
5326
|
+
return `\u274C Sous-commande inconnue: "${sub}"
|
|
5327
|
+
|
|
5328
|
+
Usage: /modules | /modules set <module> <level> | /modules info <module> | /modules reset [module]`;
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
listModules(chatId) {
|
|
5332
|
+
const modules = this.registry.getAvailableModules();
|
|
5333
|
+
const overrides = this.permissions.getOverrides(chatId);
|
|
5334
|
+
const lines = ["\u{1F9E9} **Modules** (ce groupe)\n"];
|
|
5335
|
+
for (const mod of modules) {
|
|
5336
|
+
const count = this.registry.getModuleToolCount(mod);
|
|
5337
|
+
const level = overrides.get(mod) ?? "open";
|
|
5338
|
+
const isProtected = this.permissions.isProtected(mod);
|
|
5339
|
+
let icon;
|
|
5340
|
+
switch (level) {
|
|
5341
|
+
case "open":
|
|
5342
|
+
icon = "\u2705";
|
|
5343
|
+
break;
|
|
5344
|
+
case "admin":
|
|
5345
|
+
icon = "\u{1F510}";
|
|
5346
|
+
break;
|
|
5347
|
+
case "disabled":
|
|
5348
|
+
icon = "\u274C";
|
|
5349
|
+
break;
|
|
5350
|
+
}
|
|
5351
|
+
const toolWord = count === 1 ? "tool" : "tools";
|
|
5352
|
+
const protectedMark = isProtected ? " \u{1F512}" : "";
|
|
5353
|
+
lines.push(` ${icon} **${mod}** ${count} ${toolWord} ${level}${protectedMark}`);
|
|
5354
|
+
}
|
|
5355
|
+
lines.push("");
|
|
5356
|
+
lines.push("Niveaux: `open` | `admin` | `disabled`");
|
|
5357
|
+
lines.push("Usage: `/modules set <module> <level>`");
|
|
5358
|
+
return lines.join("\n");
|
|
5359
|
+
}
|
|
5360
|
+
setModuleLevel(chatId, module, level, senderId) {
|
|
5361
|
+
if (!module || !level) {
|
|
5362
|
+
return "\u274C Usage: /modules set <module> <level>";
|
|
5363
|
+
}
|
|
5364
|
+
module = module.toLowerCase();
|
|
5365
|
+
level = level.toLowerCase();
|
|
5366
|
+
const available = this.registry.getAvailableModules();
|
|
5367
|
+
if (!available.includes(module)) {
|
|
5368
|
+
return `\u274C Module inconnu: "${module}"`;
|
|
5369
|
+
}
|
|
5370
|
+
if (this.permissions.isProtected(module)) {
|
|
5371
|
+
return `\u26D4 Module "${module}" est prot\xE9g\xE9`;
|
|
5372
|
+
}
|
|
5373
|
+
if (!VALID_MODULE_LEVELS.includes(level)) {
|
|
5374
|
+
return `\u274C Niveau invalide: "${level}". Valide: ${VALID_MODULE_LEVELS.join(", ")}`;
|
|
5375
|
+
}
|
|
5376
|
+
const oldLevel = this.permissions.getLevel(chatId, module);
|
|
5377
|
+
this.permissions.setLevel(chatId, module, level, senderId);
|
|
5378
|
+
const icons = { open: "\u2705", admin: "\u{1F510}", disabled: "\u274C" };
|
|
5379
|
+
return `${icons[level]} **${module}**: ${oldLevel} \u2192 ${level}`;
|
|
5380
|
+
}
|
|
5381
|
+
showModuleInfo(module, chatId) {
|
|
5382
|
+
if (!module) {
|
|
5383
|
+
return "\u274C Usage: /modules info <module>";
|
|
5384
|
+
}
|
|
5385
|
+
module = module.toLowerCase();
|
|
5386
|
+
const available = this.registry.getAvailableModules();
|
|
5387
|
+
if (!available.includes(module)) {
|
|
5388
|
+
return `\u274C Module inconnu: "${module}"`;
|
|
5389
|
+
}
|
|
5390
|
+
const tools23 = this.registry.getModuleTools(module);
|
|
5391
|
+
const count = tools23.length;
|
|
5392
|
+
const toolWord = count === 1 ? "tool" : "tools";
|
|
5393
|
+
const level = this.permissions.getLevel(chatId, module);
|
|
5394
|
+
const isProtected = this.permissions.isProtected(module);
|
|
5395
|
+
const protectedMark = isProtected ? " \u{1F512}" : "";
|
|
5396
|
+
const lines = [
|
|
5397
|
+
`\u{1F4E6} Module "**${module}**" \u2014 ${level}${protectedMark} (${count} ${toolWord})
|
|
5398
|
+
`
|
|
5399
|
+
];
|
|
5400
|
+
for (const t of tools23) {
|
|
5401
|
+
lines.push(` ${t.name} ${t.scope}`);
|
|
5402
|
+
}
|
|
5403
|
+
return lines.join("\n");
|
|
5404
|
+
}
|
|
5405
|
+
resetModules(chatId, module) {
|
|
5406
|
+
if (module) {
|
|
5407
|
+
module = module.toLowerCase();
|
|
5408
|
+
const available = this.registry.getAvailableModules();
|
|
5409
|
+
if (!available.includes(module)) {
|
|
5410
|
+
return `\u274C Module inconnu: "${module}"`;
|
|
5411
|
+
}
|
|
5412
|
+
if (this.permissions.isProtected(module)) {
|
|
5413
|
+
return `\u26D4 Module "${module}" est prot\xE9g\xE9 (d\xE9j\xE0 open)`;
|
|
5414
|
+
}
|
|
5415
|
+
this.permissions.resetModule(chatId, module);
|
|
5416
|
+
return `\u2705 **${module}** \u2192 open`;
|
|
5417
|
+
}
|
|
5418
|
+
this.permissions.resetAll(chatId);
|
|
5419
|
+
return "\u2705 Tous les modules remis \xE0 **open**";
|
|
5420
|
+
}
|
|
5288
5421
|
/**
|
|
5289
5422
|
* /help - Show available commands
|
|
5290
5423
|
*/
|
|
@@ -5306,6 +5439,9 @@ Change access policy
|
|
|
5306
5439
|
**/strategy** [buy|sell <percent>]
|
|
5307
5440
|
View or change trading thresholds
|
|
5308
5441
|
|
|
5442
|
+
**/modules** [set|info|reset]
|
|
5443
|
+
Manage per-group module permissions
|
|
5444
|
+
|
|
5309
5445
|
**/wallet**
|
|
5310
5446
|
Check TON wallet balance
|
|
5311
5447
|
|
|
@@ -5457,6 +5593,8 @@ import { validateToolCall } from "@mariozechner/pi-ai";
|
|
|
5457
5593
|
var ToolRegistry = class {
|
|
5458
5594
|
tools = /* @__PURE__ */ new Map();
|
|
5459
5595
|
scopes = /* @__PURE__ */ new Map();
|
|
5596
|
+
toolModules = /* @__PURE__ */ new Map();
|
|
5597
|
+
permissions = null;
|
|
5460
5598
|
/**
|
|
5461
5599
|
* Register a new tool with optional scope
|
|
5462
5600
|
*/
|
|
@@ -5468,6 +5606,42 @@ var ToolRegistry = class {
|
|
|
5468
5606
|
if (scope && scope !== "always") {
|
|
5469
5607
|
this.scopes.set(tool.name, scope);
|
|
5470
5608
|
}
|
|
5609
|
+
this.toolModules.set(tool.name, tool.name.split("_")[0]);
|
|
5610
|
+
}
|
|
5611
|
+
/**
|
|
5612
|
+
* Set the module permissions manager
|
|
5613
|
+
*/
|
|
5614
|
+
setPermissions(mp) {
|
|
5615
|
+
this.permissions = mp;
|
|
5616
|
+
}
|
|
5617
|
+
/**
|
|
5618
|
+
* Get sorted unique module names derived from registered tools
|
|
5619
|
+
*/
|
|
5620
|
+
getAvailableModules() {
|
|
5621
|
+
const modules = new Set(this.toolModules.values());
|
|
5622
|
+
return Array.from(modules).sort();
|
|
5623
|
+
}
|
|
5624
|
+
/**
|
|
5625
|
+
* Get the number of tools in a module
|
|
5626
|
+
*/
|
|
5627
|
+
getModuleToolCount(module) {
|
|
5628
|
+
let count = 0;
|
|
5629
|
+
for (const mod of this.toolModules.values()) {
|
|
5630
|
+
if (mod === module) count++;
|
|
5631
|
+
}
|
|
5632
|
+
return count;
|
|
5633
|
+
}
|
|
5634
|
+
/**
|
|
5635
|
+
* Get tools belonging to a module with their scope
|
|
5636
|
+
*/
|
|
5637
|
+
getModuleTools(module) {
|
|
5638
|
+
const result = [];
|
|
5639
|
+
for (const [name, mod] of this.toolModules) {
|
|
5640
|
+
if (mod === module) {
|
|
5641
|
+
result.push({ name, scope: this.scopes.get(name) ?? "always" });
|
|
5642
|
+
}
|
|
5643
|
+
}
|
|
5644
|
+
return result.sort((a, b) => a.name.localeCompare(b.name));
|
|
5471
5645
|
}
|
|
5472
5646
|
/**
|
|
5473
5647
|
* Get all registered tools for pi-ai
|
|
@@ -5499,9 +5673,43 @@ var ToolRegistry = class {
|
|
|
5499
5673
|
error: `Tool "${toolCall.name}" is only available in group chats`
|
|
5500
5674
|
};
|
|
5501
5675
|
}
|
|
5676
|
+
if (context.isGroup && this.permissions) {
|
|
5677
|
+
const module = this.toolModules.get(toolCall.name);
|
|
5678
|
+
if (module) {
|
|
5679
|
+
const level = this.permissions.getLevel(context.chatId, module);
|
|
5680
|
+
if (level === "disabled") {
|
|
5681
|
+
return {
|
|
5682
|
+
success: false,
|
|
5683
|
+
error: `Module "${module}" is disabled in this group`
|
|
5684
|
+
};
|
|
5685
|
+
}
|
|
5686
|
+
if (level === "admin") {
|
|
5687
|
+
const isAdmin = context.config?.telegram.admin_ids.includes(context.senderId) ?? false;
|
|
5688
|
+
if (!isAdmin) {
|
|
5689
|
+
return {
|
|
5690
|
+
success: false,
|
|
5691
|
+
error: `Module "${module}" is restricted to admins in this group`
|
|
5692
|
+
};
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
}
|
|
5502
5697
|
try {
|
|
5503
5698
|
const validatedArgs = validateToolCall(this.getAll(), toolCall);
|
|
5504
|
-
|
|
5699
|
+
let timeoutHandle;
|
|
5700
|
+
const result = await Promise.race([
|
|
5701
|
+
registered.executor(validatedArgs, context),
|
|
5702
|
+
new Promise((_, reject) => {
|
|
5703
|
+
timeoutHandle = setTimeout(
|
|
5704
|
+
() => reject(
|
|
5705
|
+
new Error(
|
|
5706
|
+
`Tool "${toolCall.name}" timed out after ${TOOL_EXECUTION_TIMEOUT_MS / 1e3}s`
|
|
5707
|
+
)
|
|
5708
|
+
),
|
|
5709
|
+
TOOL_EXECUTION_TIMEOUT_MS
|
|
5710
|
+
);
|
|
5711
|
+
})
|
|
5712
|
+
]).finally(() => clearTimeout(timeoutHandle));
|
|
5505
5713
|
return result;
|
|
5506
5714
|
} catch (error) {
|
|
5507
5715
|
console.error(`Error executing tool ${toolCall.name}:`, error);
|
|
@@ -5525,13 +5733,25 @@ var ToolRegistry = class {
|
|
|
5525
5733
|
return all.slice(0, toolLimit);
|
|
5526
5734
|
}
|
|
5527
5735
|
/**
|
|
5528
|
-
* Get tools filtered by chat context (DM vs group) and provider limit.
|
|
5736
|
+
* Get tools filtered by chat context (DM vs group), module permissions, and provider limit.
|
|
5529
5737
|
* - In groups: excludes "dm-only" tools (financial, private)
|
|
5530
5738
|
* - In DMs: excludes "group-only" tools (moderation)
|
|
5739
|
+
* - In groups with permissions: excludes disabled modules, admin-only modules for non-admins
|
|
5531
5740
|
*/
|
|
5532
|
-
getForContext(isGroup, toolLimit) {
|
|
5741
|
+
getForContext(isGroup, toolLimit, chatId, isAdmin) {
|
|
5533
5742
|
const excluded = isGroup ? "dm-only" : "group-only";
|
|
5534
|
-
const filtered = Array.from(this.tools.values()).filter((rt) =>
|
|
5743
|
+
const filtered = Array.from(this.tools.values()).filter((rt) => {
|
|
5744
|
+
if (this.scopes.get(rt.tool.name) === excluded) return false;
|
|
5745
|
+
if (isGroup && chatId && this.permissions) {
|
|
5746
|
+
const module = this.toolModules.get(rt.tool.name);
|
|
5747
|
+
if (module) {
|
|
5748
|
+
const level = this.permissions.getLevel(chatId, module);
|
|
5749
|
+
if (level === "disabled") return false;
|
|
5750
|
+
if (level === "admin" && !isAdmin) return false;
|
|
5751
|
+
}
|
|
5752
|
+
}
|
|
5753
|
+
return true;
|
|
5754
|
+
}).map((rt) => rt.tool);
|
|
5535
5755
|
if (toolLimit !== null && filtered.length > toolLimit) {
|
|
5536
5756
|
console.warn(
|
|
5537
5757
|
`\u26A0\uFE0F Provider tool limit: ${toolLimit}, after scope filter: ${filtered.length}. Truncating to ${toolLimit} tools.`
|
|
@@ -10006,18 +10226,20 @@ function getDeal(db3, dealId) {
|
|
|
10006
10226
|
}
|
|
10007
10227
|
function acceptDeal(db3, dealId) {
|
|
10008
10228
|
const newExpiry = Math.floor(Date.now() / 1e3) + DEAL_VERIFICATION_WINDOW_SECONDS;
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10229
|
+
const r3 = db3.prepare(
|
|
10230
|
+
`UPDATE deals SET status = 'accepted', expires_at = ? WHERE id = ? AND status = 'proposed'`
|
|
10231
|
+
).run(newExpiry, dealId);
|
|
10232
|
+
return r3.changes === 1;
|
|
10013
10233
|
}
|
|
10014
10234
|
function declineDeal(db3, dealId) {
|
|
10015
|
-
db3.prepare(`UPDATE deals SET status = 'declined' WHERE id =
|
|
10235
|
+
const r3 = db3.prepare(`UPDATE deals SET status = 'declined' WHERE id = ? AND status = 'proposed'`).run(dealId);
|
|
10236
|
+
return r3.changes === 1;
|
|
10016
10237
|
}
|
|
10017
10238
|
function claimPayment(db3, dealId) {
|
|
10018
|
-
db3.prepare(
|
|
10019
|
-
`UPDATE deals SET status = 'payment_claimed', payment_claimed_at = unixepoch() WHERE id =
|
|
10239
|
+
const r3 = db3.prepare(
|
|
10240
|
+
`UPDATE deals SET status = 'payment_claimed', payment_claimed_at = unixepoch() WHERE id = ? AND status = 'accepted'`
|
|
10020
10241
|
).run(dealId);
|
|
10242
|
+
return r3.changes === 1;
|
|
10021
10243
|
}
|
|
10022
10244
|
function setInlineMessageId(db3, dealId, inlineMessageId) {
|
|
10023
10245
|
db3.prepare(`UPDATE deals SET inline_message_id = ? WHERE id = ?`).run(inlineMessageId, dealId);
|
|
@@ -10027,7 +10249,10 @@ function isDealExpired(deal) {
|
|
|
10027
10249
|
return now > deal.expiresAt;
|
|
10028
10250
|
}
|
|
10029
10251
|
function expireDeal(db3, dealId) {
|
|
10030
|
-
|
|
10252
|
+
const r3 = db3.prepare(
|
|
10253
|
+
`UPDATE deals SET status = 'expired' WHERE id = ? AND status IN ('proposed', 'accepted')`
|
|
10254
|
+
).run(dealId);
|
|
10255
|
+
return r3.changes === 1;
|
|
10031
10256
|
}
|
|
10032
10257
|
function getDealsAwaitingVerification(db3) {
|
|
10033
10258
|
const rows = db3.prepare(
|
|
@@ -10520,19 +10745,6 @@ var GramJSBotClient = class {
|
|
|
10520
10745
|
import { TonClient as TonClient2, fromNano as fromNano2 } from "@ton/ton";
|
|
10521
10746
|
import { Address } from "@ton/core";
|
|
10522
10747
|
|
|
10523
|
-
// src/ton/endpoint.ts
|
|
10524
|
-
import { getHttpEndpoint as getHttpEndpoint2 } from "@orbs-network/ton-access";
|
|
10525
|
-
var ENDPOINT_CACHE_TTL_MS = 6e4;
|
|
10526
|
-
var _cache = null;
|
|
10527
|
-
async function getCachedHttpEndpoint() {
|
|
10528
|
-
if (_cache && Date.now() - _cache.ts < ENDPOINT_CACHE_TTL_MS) {
|
|
10529
|
-
return _cache.url;
|
|
10530
|
-
}
|
|
10531
|
-
const url = await getHttpEndpoint2({ network: "mainnet" });
|
|
10532
|
-
_cache = { url, ts: Date.now() };
|
|
10533
|
-
return url;
|
|
10534
|
-
}
|
|
10535
|
-
|
|
10536
10748
|
// src/casino/retry.ts
|
|
10537
10749
|
var DEFAULT_OPTIONS = {
|
|
10538
10750
|
maxAttempts: RETRY_DEFAULT_MAX_ATTEMPTS,
|
|
@@ -10767,7 +10979,6 @@ If you already sent, wait a moment and try again.`
|
|
|
10767
10979
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey2 } from "@ton/crypto";
|
|
10768
10980
|
import { WalletContractV5R1 as WalletContractV5R12, TonClient as TonClient3, toNano, internal } from "@ton/ton";
|
|
10769
10981
|
import { Address as Address2, SendMode } from "@ton/core";
|
|
10770
|
-
import { getHttpEndpoint as getHttpEndpoint3 } from "@orbs-network/ton-access";
|
|
10771
10982
|
async function sendTon(params) {
|
|
10772
10983
|
try {
|
|
10773
10984
|
const { toAddress: toAddress2, amount, comment = "", bounce = false } = params;
|
|
@@ -10788,7 +10999,7 @@ async function sendTon(params) {
|
|
|
10788
10999
|
workchain: 0,
|
|
10789
11000
|
publicKey: keyPair.publicKey
|
|
10790
11001
|
});
|
|
10791
|
-
const endpoint = await
|
|
11002
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
10792
11003
|
const client = new TonClient3({ endpoint });
|
|
10793
11004
|
const contract = client.open(wallet);
|
|
10794
11005
|
const seqno = await contract.getSeqno();
|
|
@@ -11477,12 +11688,16 @@ var VerificationPoller = class {
|
|
|
11477
11688
|
* Handle verification timeout
|
|
11478
11689
|
*/
|
|
11479
11690
|
async handleTimeout(deal) {
|
|
11480
|
-
this.db.prepare(
|
|
11691
|
+
const r3 = this.db.prepare(
|
|
11481
11692
|
`UPDATE deals SET
|
|
11482
11693
|
status = 'failed',
|
|
11483
11694
|
notes = 'Payment verification timeout'
|
|
11484
|
-
WHERE id =
|
|
11695
|
+
WHERE id = ? AND status = 'payment_claimed'`
|
|
11485
11696
|
).run(deal.dealId);
|
|
11697
|
+
if (r3.changes !== 1) {
|
|
11698
|
+
this.retryMap.delete(deal.dealId);
|
|
11699
|
+
return;
|
|
11700
|
+
}
|
|
11486
11701
|
if (deal.inlineMessageId) {
|
|
11487
11702
|
const { text, buttons } = buildFailedMessage(
|
|
11488
11703
|
deal,
|
|
@@ -11944,6 +12159,7 @@ function openDealsDb() {
|
|
|
11944
12159
|
CREATE INDEX IF NOT EXISTS idx_deals_chat ON deals(chat_id);
|
|
11945
12160
|
CREATE INDEX IF NOT EXISTS idx_deals_inline_msg ON deals(inline_message_id) WHERE inline_message_id IS NOT NULL;
|
|
11946
12161
|
CREATE INDEX IF NOT EXISTS idx_deals_payment_claimed ON deals(payment_claimed_at) WHERE payment_claimed_at IS NOT NULL;
|
|
12162
|
+
CREATE INDEX IF NOT EXISTS idx_deals_expires ON deals(expires_at) WHERE status IN ('proposed', 'accepted');
|
|
11947
12163
|
|
|
11948
12164
|
CREATE TABLE IF NOT EXISTS user_trade_stats (
|
|
11949
12165
|
telegram_id INTEGER PRIMARY KEY,
|
|
@@ -14364,7 +14580,6 @@ var telegramCreateScheduledTaskExecutor = async (params, context) => {
|
|
|
14364
14580
|
}
|
|
14365
14581
|
const { getTaskStore } = await import("./tasks-M3QDPTGY.js");
|
|
14366
14582
|
const taskStore = getTaskStore(context.db);
|
|
14367
|
-
const MAX_DEPENDENTS_PER_TASK = 10;
|
|
14368
14583
|
if (dependsOn && dependsOn.length > 0) {
|
|
14369
14584
|
for (const parentId of dependsOn) {
|
|
14370
14585
|
const existingDependents = taskStore.getDependents(parentId);
|
|
@@ -14867,7 +15082,6 @@ import { Type as Type75 } from "@sinclair/typebox";
|
|
|
14867
15082
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey3 } from "@ton/crypto";
|
|
14868
15083
|
import { WalletContractV5R1 as WalletContractV5R13, TonClient as TonClient4, toNano as toNano2, internal as internal2 } from "@ton/ton";
|
|
14869
15084
|
import { Address as Address3, SendMode as SendMode2 } from "@ton/core";
|
|
14870
|
-
import { getHttpEndpoint as getHttpEndpoint4 } from "@orbs-network/ton-access";
|
|
14871
15085
|
var tonSendTool = {
|
|
14872
15086
|
name: "ton_send",
|
|
14873
15087
|
description: "Send TON cryptocurrency to an address. Requires wallet to be initialized. Amount is in TON (not nanoTON). Example: amount 1.5 = 1.5 TON. Always confirm the transaction details before sending.",
|
|
@@ -14909,7 +15123,7 @@ var tonSendExecutor = async (params, context) => {
|
|
|
14909
15123
|
workchain: 0,
|
|
14910
15124
|
publicKey: keyPair.publicKey
|
|
14911
15125
|
});
|
|
14912
|
-
const endpoint = await
|
|
15126
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
14913
15127
|
const client = new TonClient4({ endpoint });
|
|
14914
15128
|
const contract = client.open(wallet);
|
|
14915
15129
|
const seqno = await contract.getSeqno();
|
|
@@ -14949,7 +15163,6 @@ var tonSendExecutor = async (params, context) => {
|
|
|
14949
15163
|
import { Type as Type76 } from "@sinclair/typebox";
|
|
14950
15164
|
import { TonClient as TonClient5, fromNano as fromNano3 } from "@ton/ton";
|
|
14951
15165
|
import { Address as Address4 } from "@ton/core";
|
|
14952
|
-
import { getHttpEndpoint as getHttpEndpoint5 } from "@orbs-network/ton-access";
|
|
14953
15166
|
var OP_CODES = {
|
|
14954
15167
|
COMMENT: 0,
|
|
14955
15168
|
JETTON_TRANSFER: 260734629,
|
|
@@ -15025,7 +15238,7 @@ var tonGetTransactionsExecutor = async (params, context) => {
|
|
|
15025
15238
|
error: `Invalid address: ${address4}`
|
|
15026
15239
|
};
|
|
15027
15240
|
}
|
|
15028
|
-
const endpoint = await
|
|
15241
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
15029
15242
|
const client = new TonClient5({ endpoint });
|
|
15030
15243
|
const transactions = await client.getTransactions(addressObj, {
|
|
15031
15244
|
limit: Math.min(limit, 50)
|
|
@@ -15169,7 +15382,6 @@ var tonGetTransactionsExecutor = async (params, context) => {
|
|
|
15169
15382
|
import { Type as Type77 } from "@sinclair/typebox";
|
|
15170
15383
|
import { TonClient as TonClient6, fromNano as fromNano4 } from "@ton/ton";
|
|
15171
15384
|
import { Address as Address5 } from "@ton/core";
|
|
15172
|
-
import { getHttpEndpoint as getHttpEndpoint6 } from "@orbs-network/ton-access";
|
|
15173
15385
|
var OP_CODES2 = {
|
|
15174
15386
|
COMMENT: 0,
|
|
15175
15387
|
JETTON_TRANSFER: 260734629,
|
|
@@ -15241,7 +15453,7 @@ var tonMyTransactionsExecutor = async (params, context) => {
|
|
|
15241
15453
|
};
|
|
15242
15454
|
}
|
|
15243
15455
|
const addressObj = Address5.parse(walletData.address);
|
|
15244
|
-
const endpoint = await
|
|
15456
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
15245
15457
|
const client = new TonClient6({ endpoint });
|
|
15246
15458
|
const transactions = await client.getTransactions(addressObj, {
|
|
15247
15459
|
limit: Math.min(limit, 50)
|
|
@@ -15647,7 +15859,6 @@ import { Type as Type81 } from "@sinclair/typebox";
|
|
|
15647
15859
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey4 } from "@ton/crypto";
|
|
15648
15860
|
import { WalletContractV5R1 as WalletContractV5R14, TonClient as TonClient7, toNano as toNano3, internal as internal3, beginCell } from "@ton/ton";
|
|
15649
15861
|
import { Address as Address6, SendMode as SendMode3 } from "@ton/core";
|
|
15650
|
-
import { getHttpEndpoint as getHttpEndpoint7 } from "@orbs-network/ton-access";
|
|
15651
15862
|
var DNS_COLLECTION = "EQC3dNlesgVD8YbAazcauIrXBPfiVhMMr5YYk2in0Mtsz0Bz";
|
|
15652
15863
|
var dnsStartAuctionTool = {
|
|
15653
15864
|
name: "dns_start_auction",
|
|
@@ -15690,7 +15901,7 @@ var dnsStartAuctionExecutor = async (params, context) => {
|
|
|
15690
15901
|
workchain: 0,
|
|
15691
15902
|
publicKey: keyPair.publicKey
|
|
15692
15903
|
});
|
|
15693
|
-
const endpoint = await
|
|
15904
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
15694
15905
|
const client = new TonClient7({ endpoint });
|
|
15695
15906
|
const contract = client.open(wallet);
|
|
15696
15907
|
const seqno = await contract.getSeqno();
|
|
@@ -15735,7 +15946,6 @@ import { Type as Type82 } from "@sinclair/typebox";
|
|
|
15735
15946
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey5 } from "@ton/crypto";
|
|
15736
15947
|
import { WalletContractV5R1 as WalletContractV5R15, TonClient as TonClient8, toNano as toNano4, internal as internal4 } from "@ton/ton";
|
|
15737
15948
|
import { Address as Address7, SendMode as SendMode4 } from "@ton/core";
|
|
15738
|
-
import { getHttpEndpoint as getHttpEndpoint8 } from "@orbs-network/ton-access";
|
|
15739
15949
|
var dnsBidTool = {
|
|
15740
15950
|
name: "dns_bid",
|
|
15741
15951
|
description: "Place a bid on an existing .ton domain auction. Bid must be at least 5% higher than current bid. The domain must already be in auction (use dns_check first to verify status and get current bid).",
|
|
@@ -15808,7 +16018,7 @@ var dnsBidExecutor = async (params, context) => {
|
|
|
15808
16018
|
workchain: 0,
|
|
15809
16019
|
publicKey: keyPair.publicKey
|
|
15810
16020
|
});
|
|
15811
|
-
const endpoint = await
|
|
16021
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
15812
16022
|
const client = new TonClient8({ endpoint });
|
|
15813
16023
|
const contract = client.open(wallet);
|
|
15814
16024
|
const seqno = await contract.getSeqno();
|
|
@@ -15853,7 +16063,6 @@ import { Type as Type83 } from "@sinclair/typebox";
|
|
|
15853
16063
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey6 } from "@ton/crypto";
|
|
15854
16064
|
import { WalletContractV5R1 as WalletContractV5R16, TonClient as TonClient9, toNano as toNano5, internal as internal5, beginCell as beginCell2 } from "@ton/ton";
|
|
15855
16065
|
import { Address as Address8, SendMode as SendMode5 } from "@ton/core";
|
|
15856
|
-
import { getHttpEndpoint as getHttpEndpoint9 } from "@orbs-network/ton-access";
|
|
15857
16066
|
var DNS_CHANGE_RECORD_OP = 1320284409;
|
|
15858
16067
|
var DNS_SMC_ADDRESS_PREFIX = 40915;
|
|
15859
16068
|
var WALLET_RECORD_KEY = BigInt(
|
|
@@ -15935,7 +16144,7 @@ var dnsLinkExecutor = async (params, context) => {
|
|
|
15935
16144
|
workchain: 0,
|
|
15936
16145
|
publicKey: keyPair.publicKey
|
|
15937
16146
|
});
|
|
15938
|
-
const endpoint = await
|
|
16147
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
15939
16148
|
const client = new TonClient9({ endpoint });
|
|
15940
16149
|
const contract = client.open(wallet);
|
|
15941
16150
|
const seqno = await contract.getSeqno();
|
|
@@ -15981,7 +16190,6 @@ import { Type as Type84 } from "@sinclair/typebox";
|
|
|
15981
16190
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey7 } from "@ton/crypto";
|
|
15982
16191
|
import { WalletContractV5R1 as WalletContractV5R17, TonClient as TonClient10, toNano as toNano6, internal as internal6, beginCell as beginCell3 } from "@ton/ton";
|
|
15983
16192
|
import { Address as Address9, SendMode as SendMode6 } from "@ton/core";
|
|
15984
|
-
import { getHttpEndpoint as getHttpEndpoint10 } from "@orbs-network/ton-access";
|
|
15985
16193
|
var DNS_CHANGE_RECORD_OP2 = 1320284409;
|
|
15986
16194
|
var WALLET_RECORD_KEY2 = BigInt(
|
|
15987
16195
|
"0xe8d44050873dba865aa7c170ab4cce64d90839a34dcfd6cf71d14e0205443b1b"
|
|
@@ -16048,7 +16256,7 @@ var dnsUnlinkExecutor = async (params, context) => {
|
|
|
16048
16256
|
workchain: 0,
|
|
16049
16257
|
publicKey: keyPair.publicKey
|
|
16050
16258
|
});
|
|
16051
|
-
const endpoint = await
|
|
16259
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
16052
16260
|
const client = new TonClient10({ endpoint });
|
|
16053
16261
|
const contract = client.open(wallet);
|
|
16054
16262
|
const seqno = await contract.getSeqno();
|
|
@@ -16208,7 +16416,6 @@ import { Type as Type86 } from "@sinclair/typebox";
|
|
|
16208
16416
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey8 } from "@ton/crypto";
|
|
16209
16417
|
import { WalletContractV5R1 as WalletContractV5R18, TonClient as TonClient11, toNano as toNano19, internal as internal7 } from "@ton/ton";
|
|
16210
16418
|
import { SendMode as SendMode7 } from "@ton/core";
|
|
16211
|
-
import { getHttpEndpoint as getHttpEndpoint11 } from "@orbs-network/ton-access";
|
|
16212
16419
|
|
|
16213
16420
|
// node_modules/@ston-fi/sdk/dist/chunk-HNMPFVZW.js
|
|
16214
16421
|
import { Address as Address10, address } from "@ton/ton";
|
|
@@ -19579,7 +19786,7 @@ var jettonSwapExecutor = async (params, context) => {
|
|
|
19579
19786
|
error: `Invalid to_asset address: ${toAddress2}`
|
|
19580
19787
|
};
|
|
19581
19788
|
}
|
|
19582
|
-
const endpoint = await
|
|
19789
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
19583
19790
|
const tonClient = new TonClient11({ endpoint });
|
|
19584
19791
|
const stonApiClient = new StonApiClient();
|
|
19585
19792
|
console.log(`Simulating swap: ${amount} ${fromAddress} \u2192 ${toAddress2}`);
|
|
@@ -19668,7 +19875,6 @@ import { Type as Type87 } from "@sinclair/typebox";
|
|
|
19668
19875
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey9 } from "@ton/crypto";
|
|
19669
19876
|
import { WalletContractV5R1 as WalletContractV5R19, TonClient as TonClient12, toNano as toNano20, internal as internal8 } from "@ton/ton";
|
|
19670
19877
|
import { Address as Address13, SendMode as SendMode8, beginCell as beginCell15 } from "@ton/core";
|
|
19671
|
-
import { getHttpEndpoint as getHttpEndpoint12 } from "@orbs-network/ton-access";
|
|
19672
19878
|
var JETTON_TRANSFER_OP = 260734629;
|
|
19673
19879
|
var jettonSendTool = {
|
|
19674
19880
|
name: "jetton_send",
|
|
@@ -19748,7 +19954,7 @@ var jettonSendExecutor = async (params, context) => {
|
|
|
19748
19954
|
workchain: 0,
|
|
19749
19955
|
publicKey: keyPair.publicKey
|
|
19750
19956
|
});
|
|
19751
|
-
const endpoint = await
|
|
19957
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
19752
19958
|
const client = new TonClient12({ endpoint });
|
|
19753
19959
|
const walletContract = client.open(wallet);
|
|
19754
19960
|
const seqno = await walletContract.getSeqno();
|
|
@@ -20610,7 +20816,7 @@ var jettonPoolsExecutor = async (params, context) => {
|
|
|
20610
20816
|
|
|
20611
20817
|
// src/agent/tools/jetton/index.ts
|
|
20612
20818
|
var tools18 = [
|
|
20613
|
-
{ tool: jettonSwapTool, executor: jettonSwapExecutor
|
|
20819
|
+
{ tool: jettonSwapTool, executor: jettonSwapExecutor },
|
|
20614
20820
|
{ tool: jettonSendTool, executor: jettonSendExecutor, scope: "dm-only" },
|
|
20615
20821
|
{ tool: jettonBalancesTool, executor: jettonBalancesExecutor },
|
|
20616
20822
|
{ tool: jettonInfoTool, executor: jettonInfoExecutor },
|
|
@@ -20627,7 +20833,6 @@ var tools18 = [
|
|
|
20627
20833
|
import { Type as Type96 } from "@sinclair/typebox";
|
|
20628
20834
|
import { TonClient as TonClient13, toNano as toNano22, fromNano as fromNano5 } from "@ton/ton";
|
|
20629
20835
|
import { Address as Address14 } from "@ton/core";
|
|
20630
|
-
import { getHttpEndpoint as getHttpEndpoint13 } from "@orbs-network/ton-access";
|
|
20631
20836
|
import { Factory, Asset, PoolType, ReadinessStatus } from "@dedust/sdk";
|
|
20632
20837
|
|
|
20633
20838
|
// src/agent/tools/dedust/constants.ts
|
|
@@ -20701,7 +20906,7 @@ var dedustQuoteExecutor = async (params, context) => {
|
|
|
20701
20906
|
};
|
|
20702
20907
|
}
|
|
20703
20908
|
}
|
|
20704
|
-
const endpoint = await
|
|
20909
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
20705
20910
|
const tonClient = new TonClient13({ endpoint });
|
|
20706
20911
|
const factory = tonClient.open(
|
|
20707
20912
|
Factory.createFromAddress(Address14.parse(DEDUST_FACTORY_MAINNET))
|
|
@@ -20785,7 +20990,6 @@ import { Type as Type97 } from "@sinclair/typebox";
|
|
|
20785
20990
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey10 } from "@ton/crypto";
|
|
20786
20991
|
import { WalletContractV5R1 as WalletContractV5R110, TonClient as TonClient14, toNano as toNano23, fromNano as fromNano6 } from "@ton/ton";
|
|
20787
20992
|
import { Address as Address15 } from "@ton/core";
|
|
20788
|
-
import { getHttpEndpoint as getHttpEndpoint14 } from "@orbs-network/ton-access";
|
|
20789
20993
|
import { Factory as Factory2, Asset as Asset2, PoolType as PoolType2, ReadinessStatus as ReadinessStatus2, JettonRoot, VaultJetton } from "@dedust/sdk";
|
|
20790
20994
|
var dedustSwapTool = {
|
|
20791
20995
|
name: "dedust_swap",
|
|
@@ -20849,7 +21053,7 @@ var dedustSwapExecutor = async (params, context) => {
|
|
|
20849
21053
|
};
|
|
20850
21054
|
}
|
|
20851
21055
|
}
|
|
20852
|
-
const endpoint = await
|
|
21056
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
20853
21057
|
const tonClient = new TonClient14({ endpoint });
|
|
20854
21058
|
const factory = tonClient.open(
|
|
20855
21059
|
Factory2.createFromAddress(Address15.parse(DEDUST_FACTORY_MAINNET))
|
|
@@ -21079,7 +21283,7 @@ var dedustPoolsExecutor = async (params, context) => {
|
|
|
21079
21283
|
|
|
21080
21284
|
// src/agent/tools/dedust/index.ts
|
|
21081
21285
|
var tools19 = [
|
|
21082
|
-
{ tool: dedustSwapTool, executor: dedustSwapExecutor
|
|
21286
|
+
{ tool: dedustSwapTool, executor: dedustSwapExecutor },
|
|
21083
21287
|
{ tool: dedustQuoteTool, executor: dedustQuoteExecutor },
|
|
21084
21288
|
{ tool: dedustPoolsTool, executor: dedustPoolsExecutor }
|
|
21085
21289
|
];
|
|
@@ -21088,7 +21292,6 @@ var tools19 = [
|
|
|
21088
21292
|
import { Type as Type99 } from "@sinclair/typebox";
|
|
21089
21293
|
import { TonClient as TonClient15, toNano as toNano24, fromNano as fromNano7 } from "@ton/ton";
|
|
21090
21294
|
import { Address as Address16 } from "@ton/core";
|
|
21091
|
-
import { getHttpEndpoint as getHttpEndpoint15 } from "@orbs-network/ton-access";
|
|
21092
21295
|
import { Factory as Factory3, Asset as Asset3, PoolType as PoolType3, ReadinessStatus as ReadinessStatus3 } from "@dedust/sdk";
|
|
21093
21296
|
var dexQuoteTool = {
|
|
21094
21297
|
name: "dex_quote",
|
|
@@ -21235,7 +21438,7 @@ async function getDedustQuote(fromAsset, toAsset, amount, slippage, tonClient) {
|
|
|
21235
21438
|
var dexQuoteExecutor = async (params, context) => {
|
|
21236
21439
|
try {
|
|
21237
21440
|
const { from_asset, to_asset, amount, slippage = 0.01 } = params;
|
|
21238
|
-
const endpoint = await
|
|
21441
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
21239
21442
|
const tonClient = new TonClient15({ endpoint });
|
|
21240
21443
|
const [stonfiQuote, dedustQuote] = await Promise.all([
|
|
21241
21444
|
getStonfiQuote(from_asset, to_asset, amount, slippage),
|
|
@@ -21347,7 +21550,6 @@ import { Type as Type100 } from "@sinclair/typebox";
|
|
|
21347
21550
|
import { mnemonicToPrivateKey as mnemonicToPrivateKey11 } from "@ton/crypto";
|
|
21348
21551
|
import { WalletContractV5R1 as WalletContractV5R111, TonClient as TonClient16, toNano as toNano25, fromNano as fromNano8 } from "@ton/ton";
|
|
21349
21552
|
import { Address as Address17, SendMode as SendMode9, internal as internal9 } from "@ton/core";
|
|
21350
|
-
import { getHttpEndpoint as getHttpEndpoint16 } from "@orbs-network/ton-access";
|
|
21351
21553
|
import { Factory as Factory4, Asset as Asset4, PoolType as PoolType4, ReadinessStatus as ReadinessStatus4, JettonRoot as JettonRoot2, VaultJetton as VaultJetton2 } from "@dedust/sdk";
|
|
21352
21554
|
var dexSwapTool = {
|
|
21353
21555
|
name: "dex_swap",
|
|
@@ -21569,7 +21771,7 @@ var dexSwapExecutor = async (params, context) => {
|
|
|
21569
21771
|
if (!isTonOutput && !to_asset.match(/^[EUe][Qq][A-Za-z0-9_-]{46}$/)) {
|
|
21570
21772
|
return { success: false, error: `Invalid to_asset address: ${to_asset}` };
|
|
21571
21773
|
}
|
|
21572
|
-
const endpoint = await
|
|
21774
|
+
const endpoint = await getCachedHttpEndpoint();
|
|
21573
21775
|
const tonClient = new TonClient16({ endpoint });
|
|
21574
21776
|
let stonfiQuote = null;
|
|
21575
21777
|
let dedustQuote = null;
|
|
@@ -21683,7 +21885,7 @@ var dexSwapExecutor = async (params, context) => {
|
|
|
21683
21885
|
|
|
21684
21886
|
// src/agent/tools/dex/index.ts
|
|
21685
21887
|
var tools20 = [
|
|
21686
|
-
{ tool: dexSwapTool, executor: dexSwapExecutor
|
|
21888
|
+
{ tool: dexSwapTool, executor: dexSwapExecutor },
|
|
21687
21889
|
{ tool: dexQuoteTool, executor: dexQuoteExecutor }
|
|
21688
21890
|
];
|
|
21689
21891
|
|
|
@@ -22302,7 +22504,6 @@ var workspaceWriteExecutor = async (params, _context) => {
|
|
|
22302
22504
|
writeContent = content;
|
|
22303
22505
|
}
|
|
22304
22506
|
const contentSize = Buffer.byteLength(writeContent);
|
|
22305
|
-
const MAX_WRITE_SIZE = 50 * 1024 * 1024;
|
|
22306
22507
|
if (contentSize > MAX_WRITE_SIZE) {
|
|
22307
22508
|
return {
|
|
22308
22509
|
success: false,
|
|
@@ -22918,10 +23119,10 @@ async function sendPayout(playerAddress, amount, message) {
|
|
|
22918
23119
|
const endpoint = await getCachedHttpEndpoint();
|
|
22919
23120
|
const client = new TonClient17({ endpoint });
|
|
22920
23121
|
const contract = client.open(wallet);
|
|
22921
|
-
const seqno = await withBlockchainRetry(() =>
|
|
22922
|
-
|
|
22923
|
-
|
|
22924
|
-
seqno,
|
|
23122
|
+
const seqno = await withBlockchainRetry(async () => {
|
|
23123
|
+
const seq = await contract.getSeqno();
|
|
23124
|
+
await contract.sendTransfer({
|
|
23125
|
+
seqno: seq,
|
|
22925
23126
|
secretKey: keyPair.secretKey,
|
|
22926
23127
|
sendMode: SendMode10.PAY_GAS_SEPARATELY,
|
|
22927
23128
|
messages: [
|
|
@@ -22932,9 +23133,9 @@ async function sendPayout(playerAddress, amount, message) {
|
|
|
22932
23133
|
bounce: false
|
|
22933
23134
|
})
|
|
22934
23135
|
]
|
|
22935
|
-
})
|
|
22936
|
-
|
|
22937
|
-
);
|
|
23136
|
+
});
|
|
23137
|
+
return seq;
|
|
23138
|
+
}, "payout");
|
|
22938
23139
|
const walletAddr = wallet.address.toString({ bounceable: false });
|
|
22939
23140
|
const walletShort = walletAddr.slice(-8);
|
|
22940
23141
|
const timestamp = Date.now();
|
|
@@ -23586,7 +23787,7 @@ var MarketScraperService = class {
|
|
|
23586
23787
|
this.isScrapingInProgress = true;
|
|
23587
23788
|
console.log("\u{1F504} Starting full market scrape...");
|
|
23588
23789
|
try {
|
|
23589
|
-
const { runScraper } = await import("./scraper-
|
|
23790
|
+
const { runScraper } = await import("./scraper-2O6Z3ZHT.js");
|
|
23590
23791
|
const result = await runScraper({
|
|
23591
23792
|
workers: 4,
|
|
23592
23793
|
limit: 0
|
|
@@ -23930,6 +24131,85 @@ function loadModules(registry, config, db3) {
|
|
|
23930
24131
|
return loaded;
|
|
23931
24132
|
}
|
|
23932
24133
|
|
|
24134
|
+
// src/agent/tools/module-permissions.ts
|
|
24135
|
+
var PROTECTED_MODULES = /* @__PURE__ */ new Set(["telegram", "memory"]);
|
|
24136
|
+
var ModulePermissions = class {
|
|
24137
|
+
db;
|
|
24138
|
+
/** chatId → module → level */
|
|
24139
|
+
cache = /* @__PURE__ */ new Map();
|
|
24140
|
+
constructor(db3) {
|
|
24141
|
+
this.db = db3;
|
|
24142
|
+
this.ensureTable();
|
|
24143
|
+
this.loadAll();
|
|
24144
|
+
}
|
|
24145
|
+
ensureTable() {
|
|
24146
|
+
this.db.exec(`
|
|
24147
|
+
CREATE TABLE IF NOT EXISTS group_modules (
|
|
24148
|
+
chat_id TEXT NOT NULL,
|
|
24149
|
+
module TEXT NOT NULL,
|
|
24150
|
+
level TEXT NOT NULL CHECK(level IN ('open', 'admin', 'disabled')),
|
|
24151
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
24152
|
+
updated_by INTEGER,
|
|
24153
|
+
PRIMARY KEY (chat_id, module)
|
|
24154
|
+
)
|
|
24155
|
+
`);
|
|
24156
|
+
}
|
|
24157
|
+
loadAll() {
|
|
24158
|
+
const rows = this.db.prepare("SELECT chat_id, module, level FROM group_modules").all();
|
|
24159
|
+
for (const row of rows) {
|
|
24160
|
+
let chatMap = this.cache.get(row.chat_id);
|
|
24161
|
+
if (!chatMap) {
|
|
24162
|
+
chatMap = /* @__PURE__ */ new Map();
|
|
24163
|
+
this.cache.set(row.chat_id, chatMap);
|
|
24164
|
+
}
|
|
24165
|
+
chatMap.set(row.module, row.level);
|
|
24166
|
+
}
|
|
24167
|
+
}
|
|
24168
|
+
/** Get the effective level for a module in a chat. Default: "open". */
|
|
24169
|
+
getLevel(chatId, module) {
|
|
24170
|
+
return this.cache.get(chatId)?.get(module) ?? "open";
|
|
24171
|
+
}
|
|
24172
|
+
/** Set the level for a module in a chat. Throws if module is protected. */
|
|
24173
|
+
setLevel(chatId, module, level, userId) {
|
|
24174
|
+
if (PROTECTED_MODULES.has(module)) {
|
|
24175
|
+
throw new Error(`Module "${module}" est prot\xE9g\xE9`);
|
|
24176
|
+
}
|
|
24177
|
+
if (level === "open") {
|
|
24178
|
+
this.db.prepare("DELETE FROM group_modules WHERE chat_id = ? AND module = ?").run(chatId, module);
|
|
24179
|
+
this.cache.get(chatId)?.delete(module);
|
|
24180
|
+
} else {
|
|
24181
|
+
this.db.prepare(
|
|
24182
|
+
`INSERT OR REPLACE INTO group_modules (chat_id, module, level, updated_at, updated_by)
|
|
24183
|
+
VALUES (?, ?, ?, unixepoch(), ?)`
|
|
24184
|
+
).run(chatId, module, level, userId ?? null);
|
|
24185
|
+
let chatMap = this.cache.get(chatId);
|
|
24186
|
+
if (!chatMap) {
|
|
24187
|
+
chatMap = /* @__PURE__ */ new Map();
|
|
24188
|
+
this.cache.set(chatId, chatMap);
|
|
24189
|
+
}
|
|
24190
|
+
chatMap.set(module, level);
|
|
24191
|
+
}
|
|
24192
|
+
}
|
|
24193
|
+
/** Reset a single module to default ("open"). */
|
|
24194
|
+
resetModule(chatId, module) {
|
|
24195
|
+
this.db.prepare("DELETE FROM group_modules WHERE chat_id = ? AND module = ?").run(chatId, module);
|
|
24196
|
+
this.cache.get(chatId)?.delete(module);
|
|
24197
|
+
}
|
|
24198
|
+
/** Reset all modules for a chat to default ("open"). */
|
|
24199
|
+
resetAll(chatId) {
|
|
24200
|
+
this.db.prepare("DELETE FROM group_modules WHERE chat_id = ?").run(chatId);
|
|
24201
|
+
this.cache.delete(chatId);
|
|
24202
|
+
}
|
|
24203
|
+
/** Get all non-default overrides for a chat. */
|
|
24204
|
+
getOverrides(chatId) {
|
|
24205
|
+
return this.cache.get(chatId) ?? /* @__PURE__ */ new Map();
|
|
24206
|
+
}
|
|
24207
|
+
/** Check if a module is protected (always open, cannot be changed). */
|
|
24208
|
+
isProtected(module) {
|
|
24209
|
+
return PROTECTED_MODULES.has(module);
|
|
24210
|
+
}
|
|
24211
|
+
};
|
|
24212
|
+
|
|
23933
24213
|
// src/index.ts
|
|
23934
24214
|
var TonnetApp = class {
|
|
23935
24215
|
config;
|
|
@@ -23977,6 +24257,8 @@ var TonnetApp = class {
|
|
|
23977
24257
|
});
|
|
23978
24258
|
const db3 = getDatabase().getDb();
|
|
23979
24259
|
this.modules = loadModules(this.toolRegistry, this.config, db3);
|
|
24260
|
+
const modulePermissions = new ModulePermissions(db3);
|
|
24261
|
+
this.toolRegistry.setPermissions(modulePermissions);
|
|
23980
24262
|
this.toolCount = this.toolRegistry.count;
|
|
23981
24263
|
this.messageHandler = new MessageHandler(
|
|
23982
24264
|
this.bridge,
|
|
@@ -23989,7 +24271,13 @@ var TonnetApp = class {
|
|
|
23989
24271
|
this.config
|
|
23990
24272
|
// Pass full config for vision tool API key access
|
|
23991
24273
|
);
|
|
23992
|
-
this.adminHandler = new AdminHandler(
|
|
24274
|
+
this.adminHandler = new AdminHandler(
|
|
24275
|
+
this.bridge,
|
|
24276
|
+
this.config.telegram,
|
|
24277
|
+
this.agent,
|
|
24278
|
+
modulePermissions,
|
|
24279
|
+
this.toolRegistry
|
|
24280
|
+
);
|
|
23993
24281
|
}
|
|
23994
24282
|
/**
|
|
23995
24283
|
* Start the agent
|
|
@@ -24028,7 +24316,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24028
24316
|
`\u26A0\uFE0F Tool count (${this.toolCount}) exceeds ${providerMeta.displayName} limit (${providerMeta.toolLimit})`
|
|
24029
24317
|
);
|
|
24030
24318
|
}
|
|
24031
|
-
const { migrateSessionsToDb } = await import("./migrate-
|
|
24319
|
+
const { migrateSessionsToDb } = await import("./migrate-6BQZVOBN.js");
|
|
24032
24320
|
migrateSessionsToDb();
|
|
24033
24321
|
const { cleanupOldTranscripts } = await import("./transcript-DF2Y6CFY.js");
|
|
24034
24322
|
cleanupOldTranscripts(30);
|
|
@@ -24149,7 +24437,8 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24149
24437
|
const response = await this.adminHandler.handleCommand(
|
|
24150
24438
|
adminCmd,
|
|
24151
24439
|
message.chatId,
|
|
24152
|
-
message.senderId
|
|
24440
|
+
message.senderId,
|
|
24441
|
+
message.isGroup
|
|
24153
24442
|
);
|
|
24154
24443
|
await this.bridge.sendMessage({
|
|
24155
24444
|
chatId: message.chatId,
|
|
@@ -24177,8 +24466,8 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24177
24466
|
}
|
|
24178
24467
|
const taskId = match[1];
|
|
24179
24468
|
const { getTaskStore } = await import("./tasks-M3QDPTGY.js");
|
|
24180
|
-
const { executeScheduledTask } = await import("./task-executor-
|
|
24181
|
-
const { getDatabase: getDatabase2 } = await import("./memory-
|
|
24469
|
+
const { executeScheduledTask } = await import("./task-executor-4SVB72GR.js");
|
|
24470
|
+
const { getDatabase: getDatabase2 } = await import("./memory-PDEJIPK6.js");
|
|
24182
24471
|
const db3 = getDatabase2().getDb();
|
|
24183
24472
|
const taskStore = getTaskStore(db3);
|
|
24184
24473
|
const task = taskStore.getTask(taskId);
|
|
@@ -24244,7 +24533,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24244
24533
|
taskStore.completeTask(taskId, response.content);
|
|
24245
24534
|
console.log(`\u2705 Executed scheduled task ${taskId}: ${task.description}`);
|
|
24246
24535
|
if (!this.dependencyResolver) {
|
|
24247
|
-
const { TaskDependencyResolver } = await import("./task-dependency-resolver-
|
|
24536
|
+
const { TaskDependencyResolver } = await import("./task-dependency-resolver-WNYOTWWM.js");
|
|
24248
24537
|
this.dependencyResolver = new TaskDependencyResolver(taskStore, this.bridge);
|
|
24249
24538
|
}
|
|
24250
24539
|
await this.dependencyResolver.onTaskComplete(taskId);
|
|
@@ -24252,8 +24541,8 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24252
24541
|
console.error("Error handling scheduled task:", error);
|
|
24253
24542
|
try {
|
|
24254
24543
|
const { getTaskStore } = await import("./tasks-M3QDPTGY.js");
|
|
24255
|
-
const { TaskDependencyResolver } = await import("./task-dependency-resolver-
|
|
24256
|
-
const { getDatabase: getDatabase2 } = await import("./memory-
|
|
24544
|
+
const { TaskDependencyResolver } = await import("./task-dependency-resolver-WNYOTWWM.js");
|
|
24545
|
+
const { getDatabase: getDatabase2 } = await import("./memory-PDEJIPK6.js");
|
|
24257
24546
|
const db3 = getDatabase2().getDb();
|
|
24258
24547
|
const taskStore = getTaskStore(db3);
|
|
24259
24548
|
const match = message.text.match(/^\[TASK:([^\]]+)\]/);
|
|
@@ -24281,6 +24570,7 @@ ${blue} \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u250
|
|
|
24281
24570
|
await mod.stop?.();
|
|
24282
24571
|
}
|
|
24283
24572
|
await this.bridge.disconnect();
|
|
24573
|
+
closeDatabase();
|
|
24284
24574
|
}
|
|
24285
24575
|
};
|
|
24286
24576
|
async function main(configPath) {
|
|
@@ -24292,14 +24582,19 @@ async function main(configPath) {
|
|
|
24292
24582
|
console.error("\u{1F4A5} Uncaught exception:", error);
|
|
24293
24583
|
process.exit(1);
|
|
24294
24584
|
});
|
|
24295
|
-
|
|
24296
|
-
await
|
|
24297
|
-
|
|
24298
|
-
|
|
24299
|
-
|
|
24585
|
+
const gracefulShutdown = async () => {
|
|
24586
|
+
const { SHUTDOWN_TIMEOUT_MS } = await import("./timeouts-ZAK6NELA.js");
|
|
24587
|
+
const forceExit = setTimeout(() => {
|
|
24588
|
+
console.error("\u26A0\uFE0F Shutdown timed out, forcing exit");
|
|
24589
|
+
process.exit(1);
|
|
24590
|
+
}, SHUTDOWN_TIMEOUT_MS);
|
|
24591
|
+
forceExit.unref();
|
|
24300
24592
|
await app.stop();
|
|
24593
|
+
clearTimeout(forceExit);
|
|
24301
24594
|
process.exit(0);
|
|
24302
|
-
}
|
|
24595
|
+
};
|
|
24596
|
+
process.on("SIGINT", gracefulShutdown);
|
|
24597
|
+
process.on("SIGTERM", gracefulShutdown);
|
|
24303
24598
|
await app.start();
|
|
24304
24599
|
}
|
|
24305
24600
|
if (import.meta.url === `file://${process.argv[1]}`) {
|