teleton 0.8.2 → 0.8.3
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/bootstrap-DDFVEMYI.js +128 -0
- package/dist/{chunk-XBSCYMKM.js → chunk-2ERTYRHA.js} +6 -6
- package/dist/{chunk-2IZU3REP.js → chunk-33Z47EXI.js} +139 -214
- package/dist/{chunk-HEDJCLA6.js → chunk-35MX4ZUI.js} +2 -122
- package/dist/{chunk-YOSUPUAJ.js → chunk-6OOHHJ4N.js} +1 -174
- package/dist/{chunk-GGXJLMOH.js → chunk-7MWKT67G.js} +295 -416
- package/dist/chunk-AEHTQI3H.js +142 -0
- package/dist/{chunk-7YKSXOQQ.js → chunk-AERHOXGC.js} +78 -320
- package/dist/{chunk-W25Z7CM6.js → chunk-ALKAAG4O.js} +3 -3
- package/dist/chunk-CUE4UZXR.js +129 -0
- package/dist/chunk-FUNF6H4W.js +251 -0
- package/dist/{chunk-VYKW7FMV.js → chunk-GHMXWAXI.js} +1 -1
- package/dist/{chunk-J73TA3UM.js → chunk-LVTKJQ7O.js} +7 -5
- package/dist/chunk-NVKBBTI6.js +128 -0
- package/dist/{chunk-57URFK6M.js → chunk-OIMAE24Q.js} +51 -13
- package/dist/chunk-WTDAICGT.js +175 -0
- package/dist/{chunk-55SKE6YH.js → chunk-XDZDOKIF.js} +1 -1
- package/dist/cli/index.js +42 -22
- package/dist/{client-YOOHI776.js → client-5KD25NOP.js} +4 -3
- package/dist/index.js +15 -10
- package/dist/local-IHKJFQJS.js +9 -0
- package/dist/{memory-Q6EWGK2S.js → memory-QMJRM3XJ.js} +5 -3
- package/dist/{memory-hook-WUXJNVT5.js → memory-hook-VUNWZ3NY.js} +5 -4
- package/dist/{migrate-WFU6COBN.js → migrate-5VBAP52B.js} +3 -2
- package/dist/{server-GYZXKIKU.js → server-JF6FX772.js} +39 -13
- package/dist/{server-YODFBZKG.js → server-N4T7E25M.js} +14 -10
- package/dist/{setup-server-IZBUOJRU.js → setup-server-IX3BFPPH.js} +5 -3
- package/dist/{store-7M4XV6M5.js → store-BY7S6IFN.js} +4 -3
- package/dist/{tool-index-NYH57UWP.js → tool-index-FTERJSZK.js} +2 -1
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ConfigSchema,
|
|
3
2
|
getCachedTonClient,
|
|
4
3
|
getKeyPair,
|
|
5
4
|
getTonPrice,
|
|
@@ -7,7 +6,13 @@ import {
|
|
|
7
6
|
getWalletBalance,
|
|
8
7
|
invalidateTonClientCache,
|
|
9
8
|
loadWallet
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FUNF6H4W.js";
|
|
10
|
+
import {
|
|
11
|
+
expandPath
|
|
12
|
+
} from "./chunk-AEHTQI3H.js";
|
|
13
|
+
import {
|
|
14
|
+
ConfigSchema
|
|
15
|
+
} from "./chunk-AERHOXGC.js";
|
|
11
16
|
import {
|
|
12
17
|
getOrCreateSession,
|
|
13
18
|
getSession,
|
|
@@ -15,11 +20,18 @@ import {
|
|
|
15
20
|
resetSessionWithPolicy,
|
|
16
21
|
shouldResetSession,
|
|
17
22
|
updateSession
|
|
18
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-XDZDOKIF.js";
|
|
24
|
+
import {
|
|
25
|
+
ContextBuilder,
|
|
26
|
+
createDbWrapper,
|
|
27
|
+
getDatabase,
|
|
28
|
+
migrateFromMainDb,
|
|
29
|
+
openModuleDb
|
|
30
|
+
} from "./chunk-GHMXWAXI.js";
|
|
19
31
|
import {
|
|
20
32
|
saveSessionMemory,
|
|
21
33
|
summarizeWithFallback
|
|
22
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-ALKAAG4O.js";
|
|
23
35
|
import {
|
|
24
36
|
getErrorMessage,
|
|
25
37
|
isHttpError
|
|
@@ -34,28 +46,6 @@ import {
|
|
|
34
46
|
ut,
|
|
35
47
|
ye
|
|
36
48
|
} from "./chunk-7TECSLJ4.js";
|
|
37
|
-
import {
|
|
38
|
-
chatWithContext,
|
|
39
|
-
getEffectiveApiKey,
|
|
40
|
-
getProviderModel,
|
|
41
|
-
loadContextFromTranscript
|
|
42
|
-
} from "./chunk-J73TA3UM.js";
|
|
43
|
-
import {
|
|
44
|
-
getProviderMetadata,
|
|
45
|
-
getSupportedProviders
|
|
46
|
-
} from "./chunk-YOSUPUAJ.js";
|
|
47
|
-
import {
|
|
48
|
-
appendToTranscript,
|
|
49
|
-
archiveTranscript,
|
|
50
|
-
transcriptExists
|
|
51
|
-
} from "./chunk-LC4TV3KL.js";
|
|
52
|
-
import {
|
|
53
|
-
ContextBuilder,
|
|
54
|
-
createDbWrapper,
|
|
55
|
-
getDatabase,
|
|
56
|
-
migrateFromMainDb,
|
|
57
|
-
openModuleDb
|
|
58
|
-
} from "./chunk-VYKW7FMV.js";
|
|
59
49
|
import {
|
|
60
50
|
GECKOTERMINAL_API_URL,
|
|
61
51
|
tonapiFetch
|
|
@@ -84,6 +74,16 @@ import {
|
|
|
84
74
|
SERVER_ERROR_MAX_RETRIES,
|
|
85
75
|
TOOL_CONCURRENCY_LIMIT
|
|
86
76
|
} from "./chunk-C4NKJT2Z.js";
|
|
77
|
+
import {
|
|
78
|
+
chatWithContext,
|
|
79
|
+
getEffectiveApiKey,
|
|
80
|
+
getProviderModel,
|
|
81
|
+
loadContextFromTranscript
|
|
82
|
+
} from "./chunk-LVTKJQ7O.js";
|
|
83
|
+
import {
|
|
84
|
+
getProviderMetadata,
|
|
85
|
+
getSupportedProviders
|
|
86
|
+
} from "./chunk-6OOHHJ4N.js";
|
|
87
87
|
import {
|
|
88
88
|
fetchWithTimeout
|
|
89
89
|
} from "./chunk-XQUHC3JZ.js";
|
|
@@ -96,6 +96,11 @@ import {
|
|
|
96
96
|
RETRY_DEFAULT_MAX_DELAY_MS,
|
|
97
97
|
RETRY_DEFAULT_TIMEOUT_MS
|
|
98
98
|
} from "./chunk-R4YSJ4EY.js";
|
|
99
|
+
import {
|
|
100
|
+
appendToTranscript,
|
|
101
|
+
archiveTranscript,
|
|
102
|
+
transcriptExists
|
|
103
|
+
} from "./chunk-LC4TV3KL.js";
|
|
99
104
|
import {
|
|
100
105
|
ALLOWED_EXTENSIONS,
|
|
101
106
|
TELETON_ROOT,
|
|
@@ -106,140 +111,17 @@ import {
|
|
|
106
111
|
createLogger
|
|
107
112
|
} from "./chunk-NQ6FZKCE.js";
|
|
108
113
|
|
|
109
|
-
// src/config/loader.ts
|
|
110
|
-
import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
|
|
111
|
-
import { parse, stringify } from "yaml";
|
|
112
|
-
import { homedir } from "os";
|
|
113
|
-
import { dirname, join } from "path";
|
|
114
|
-
var log = createLogger("Config");
|
|
115
|
-
var DEFAULT_CONFIG_PATH = join(TELETON_ROOT, "config.yaml");
|
|
116
|
-
function expandPath(path) {
|
|
117
|
-
if (path.startsWith("~")) {
|
|
118
|
-
return join(homedir(), path.slice(1));
|
|
119
|
-
}
|
|
120
|
-
return path;
|
|
121
|
-
}
|
|
122
|
-
function loadConfig(configPath = DEFAULT_CONFIG_PATH) {
|
|
123
|
-
const fullPath = expandPath(configPath);
|
|
124
|
-
if (!existsSync(fullPath)) {
|
|
125
|
-
throw new Error(`Config file not found: ${fullPath}
|
|
126
|
-
Run 'teleton setup' to create one.`);
|
|
127
|
-
}
|
|
128
|
-
let content;
|
|
129
|
-
try {
|
|
130
|
-
content = readFileSync(fullPath, "utf-8");
|
|
131
|
-
} catch (error) {
|
|
132
|
-
throw new Error(`Cannot read config file ${fullPath}: ${error.message}`);
|
|
133
|
-
}
|
|
134
|
-
let raw;
|
|
135
|
-
try {
|
|
136
|
-
raw = parse(content);
|
|
137
|
-
} catch (error) {
|
|
138
|
-
throw new Error(`Invalid YAML in ${fullPath}: ${error.message}`);
|
|
139
|
-
}
|
|
140
|
-
if (raw && typeof raw === "object" && "market" in raw) {
|
|
141
|
-
log.warn("config.market is deprecated and ignored. Use market-api plugin instead.");
|
|
142
|
-
delete raw.market;
|
|
143
|
-
}
|
|
144
|
-
const result = ConfigSchema.safeParse(raw);
|
|
145
|
-
if (!result.success) {
|
|
146
|
-
throw new Error(`Invalid config: ${result.error.message}`);
|
|
147
|
-
}
|
|
148
|
-
const config = result.data;
|
|
149
|
-
const provider = config.agent.provider;
|
|
150
|
-
if (provider !== "anthropic" && provider !== "claude-code" && !raw.agent?.model) {
|
|
151
|
-
const meta = getProviderMetadata(provider);
|
|
152
|
-
config.agent.model = meta.defaultModel;
|
|
153
|
-
}
|
|
154
|
-
config.telegram.session_path = expandPath(config.telegram.session_path);
|
|
155
|
-
config.storage.sessions_file = expandPath(config.storage.sessions_file);
|
|
156
|
-
config.storage.memory_file = expandPath(config.storage.memory_file);
|
|
157
|
-
if (process.env.TELETON_API_KEY) {
|
|
158
|
-
config.agent.api_key = process.env.TELETON_API_KEY;
|
|
159
|
-
}
|
|
160
|
-
if (process.env.TELETON_TG_API_ID) {
|
|
161
|
-
const apiId = parseInt(process.env.TELETON_TG_API_ID, 10);
|
|
162
|
-
if (isNaN(apiId)) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
`Invalid TELETON_TG_API_ID environment variable: "${process.env.TELETON_TG_API_ID}" is not a valid integer`
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
config.telegram.api_id = apiId;
|
|
168
|
-
}
|
|
169
|
-
if (process.env.TELETON_TG_API_HASH) {
|
|
170
|
-
config.telegram.api_hash = process.env.TELETON_TG_API_HASH;
|
|
171
|
-
}
|
|
172
|
-
if (process.env.TELETON_TG_PHONE) {
|
|
173
|
-
config.telegram.phone = process.env.TELETON_TG_PHONE;
|
|
174
|
-
}
|
|
175
|
-
if (process.env.TELETON_WEBUI_ENABLED) {
|
|
176
|
-
config.webui.enabled = process.env.TELETON_WEBUI_ENABLED === "true";
|
|
177
|
-
}
|
|
178
|
-
if (process.env.TELETON_WEBUI_PORT) {
|
|
179
|
-
const port = parseInt(process.env.TELETON_WEBUI_PORT, 10);
|
|
180
|
-
if (!isNaN(port) && port >= 1024 && port <= 65535) {
|
|
181
|
-
config.webui.port = port;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if (process.env.TELETON_WEBUI_HOST) {
|
|
185
|
-
config.webui.host = process.env.TELETON_WEBUI_HOST;
|
|
186
|
-
if (!["127.0.0.1", "localhost", "::1"].includes(config.webui.host)) {
|
|
187
|
-
log.warn(
|
|
188
|
-
{ host: config.webui.host },
|
|
189
|
-
"WebUI bound to non-loopback address \u2014 ensure auth_token is set"
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
if (process.env.TELETON_API_ENABLED) {
|
|
194
|
-
if (!config.api) config.api = { enabled: false, port: 7778, key_hash: "", allowed_ips: [] };
|
|
195
|
-
config.api.enabled = process.env.TELETON_API_ENABLED === "true";
|
|
196
|
-
}
|
|
197
|
-
if (process.env.TELETON_API_PORT) {
|
|
198
|
-
const port = parseInt(process.env.TELETON_API_PORT, 10);
|
|
199
|
-
if (!isNaN(port) && port >= 1024 && port <= 65535) {
|
|
200
|
-
if (!config.api) config.api = { enabled: false, port: 7778, key_hash: "", allowed_ips: [] };
|
|
201
|
-
config.api.port = port;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (process.env.TELETON_BASE_URL) {
|
|
205
|
-
try {
|
|
206
|
-
new URL(process.env.TELETON_BASE_URL);
|
|
207
|
-
config.agent.base_url = process.env.TELETON_BASE_URL;
|
|
208
|
-
} catch {
|
|
209
|
-
throw new Error(
|
|
210
|
-
`Invalid TELETON_BASE_URL: "${process.env.TELETON_BASE_URL}" is not a valid URL`
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (process.env.TELETON_TAVILY_API_KEY) {
|
|
215
|
-
config.tavily_api_key = process.env.TELETON_TAVILY_API_KEY;
|
|
216
|
-
}
|
|
217
|
-
if (process.env.TELETON_TONAPI_KEY) {
|
|
218
|
-
config.tonapi_key = process.env.TELETON_TONAPI_KEY;
|
|
219
|
-
}
|
|
220
|
-
if (process.env.TELETON_TONCENTER_API_KEY) {
|
|
221
|
-
config.toncenter_api_key = process.env.TELETON_TONCENTER_API_KEY;
|
|
222
|
-
}
|
|
223
|
-
return config;
|
|
224
|
-
}
|
|
225
|
-
function configExists(configPath = DEFAULT_CONFIG_PATH) {
|
|
226
|
-
return existsSync(expandPath(configPath));
|
|
227
|
-
}
|
|
228
|
-
function getDefaultConfigPath() {
|
|
229
|
-
return DEFAULT_CONFIG_PATH;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
114
|
// src/soul/loader.ts
|
|
233
|
-
import { readFileSync as
|
|
115
|
+
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "fs";
|
|
234
116
|
|
|
235
117
|
// src/memory/daily-logs.ts
|
|
236
|
-
import { existsSync as
|
|
237
|
-
import { join
|
|
118
|
+
import { existsSync as existsSync2, mkdirSync, appendFileSync, readFileSync } from "fs";
|
|
119
|
+
import { join } from "path";
|
|
238
120
|
|
|
239
121
|
// src/workspace/validator.ts
|
|
240
|
-
import { existsSync
|
|
122
|
+
import { existsSync, lstatSync, readdirSync } from "fs";
|
|
241
123
|
import { resolve, normalize, relative, extname, basename } from "path";
|
|
242
|
-
import { homedir
|
|
124
|
+
import { homedir } from "os";
|
|
243
125
|
var WorkspaceSecurityError = class extends Error {
|
|
244
126
|
constructor(message, attemptedPath) {
|
|
245
127
|
super(message);
|
|
@@ -273,7 +155,7 @@ function validatePath(inputPath, allowCreate = false) {
|
|
|
273
155
|
if (decodedPath.startsWith("/")) {
|
|
274
156
|
absolutePath = resolve(normalize(decodedPath));
|
|
275
157
|
} else if (decodedPath.startsWith("~/")) {
|
|
276
|
-
const expanded = decodedPath.replace(/^~(?=$|[\\/])/,
|
|
158
|
+
const expanded = decodedPath.replace(/^~(?=$|[\\/])/, homedir());
|
|
277
159
|
absolutePath = resolve(expanded);
|
|
278
160
|
} else {
|
|
279
161
|
absolutePath = resolve(WORKSPACE_ROOT, normalize(decodedPath));
|
|
@@ -285,7 +167,7 @@ function validatePath(inputPath, allowCreate = false) {
|
|
|
285
167
|
inputPath
|
|
286
168
|
);
|
|
287
169
|
}
|
|
288
|
-
const exists =
|
|
170
|
+
const exists = existsSync(absolutePath);
|
|
289
171
|
if (!exists && !allowCreate) {
|
|
290
172
|
throw new WorkspaceSecurityError(
|
|
291
173
|
`File not found: '${inputPath}' does not exist in workspace.`,
|
|
@@ -349,7 +231,7 @@ function validateDirectory(inputPath) {
|
|
|
349
231
|
}
|
|
350
232
|
|
|
351
233
|
// src/memory/daily-logs.ts
|
|
352
|
-
var
|
|
234
|
+
var log = createLogger("Memory");
|
|
353
235
|
var MEMORY_DIR = WORKSPACE_PATHS.MEMORY_DIR;
|
|
354
236
|
function formatDate(date) {
|
|
355
237
|
const year = date.getFullYear();
|
|
@@ -358,11 +240,11 @@ function formatDate(date) {
|
|
|
358
240
|
return `${year}-${month}-${day}`;
|
|
359
241
|
}
|
|
360
242
|
function getDailyLogPath(date = /* @__PURE__ */ new Date()) {
|
|
361
|
-
return
|
|
243
|
+
return join(MEMORY_DIR, `${formatDate(date)}.md`);
|
|
362
244
|
}
|
|
363
245
|
function ensureMemoryDir() {
|
|
364
|
-
if (!
|
|
365
|
-
|
|
246
|
+
if (!existsSync2(MEMORY_DIR)) {
|
|
247
|
+
mkdirSync(MEMORY_DIR, { recursive: true });
|
|
366
248
|
}
|
|
367
249
|
}
|
|
368
250
|
function appendToDailyLog(content, date = /* @__PURE__ */ new Date()) {
|
|
@@ -370,7 +252,7 @@ function appendToDailyLog(content, date = /* @__PURE__ */ new Date()) {
|
|
|
370
252
|
ensureMemoryDir();
|
|
371
253
|
const logPath = getDailyLogPath(date);
|
|
372
254
|
const timestamp = date.toLocaleTimeString("en-US", { hour12: false });
|
|
373
|
-
if (!
|
|
255
|
+
if (!existsSync2(logPath)) {
|
|
374
256
|
const header = `# Daily Log - ${formatDate(date)}
|
|
375
257
|
|
|
376
258
|
`;
|
|
@@ -384,16 +266,16 @@ ${content}
|
|
|
384
266
|
|
|
385
267
|
`;
|
|
386
268
|
appendFileSync(logPath, entry, "utf-8");
|
|
387
|
-
|
|
269
|
+
log.info(`Daily log updated: ${logPath}`);
|
|
388
270
|
} catch (error) {
|
|
389
|
-
|
|
271
|
+
log.error({ err: error }, "Failed to write daily log");
|
|
390
272
|
}
|
|
391
273
|
}
|
|
392
274
|
function readDailyLog(date = /* @__PURE__ */ new Date()) {
|
|
393
275
|
try {
|
|
394
276
|
const logPath = getDailyLogPath(date);
|
|
395
|
-
if (!
|
|
396
|
-
return
|
|
277
|
+
if (!existsSync2(logPath)) return null;
|
|
278
|
+
return readFileSync(logPath, "utf-8");
|
|
397
279
|
} catch {
|
|
398
280
|
return null;
|
|
399
281
|
}
|
|
@@ -474,7 +356,7 @@ function cachedReadFile(path) {
|
|
|
474
356
|
if (cached && now < cached.expiry) return cached.content;
|
|
475
357
|
let content = null;
|
|
476
358
|
try {
|
|
477
|
-
if (
|
|
359
|
+
if (existsSync3(path)) content = readFileSync2(path, "utf-8");
|
|
478
360
|
} catch {
|
|
479
361
|
}
|
|
480
362
|
fileCache.set(path, { content, expiry: now + FILE_CACHE_TTL });
|
|
@@ -757,7 +639,7 @@ var DEFAULT_COMPACTION_CONFIG = {
|
|
|
757
639
|
memoryFlushEnabled: true,
|
|
758
640
|
softThresholdTokens: DEFAULT_SOFT_THRESHOLD_TOKENS
|
|
759
641
|
};
|
|
760
|
-
var
|
|
642
|
+
var log2 = createLogger("Memory");
|
|
761
643
|
function estimateContextTokens(context) {
|
|
762
644
|
let charCount = 0;
|
|
763
645
|
if (context.systemPrompt) {
|
|
@@ -789,7 +671,7 @@ function shouldFlushMemory(context, config, tokenCount) {
|
|
|
789
671
|
const tokens = tokenCount ?? estimateContextTokens(context);
|
|
790
672
|
const softThreshold = config.softThresholdTokens ?? FALLBACK_SOFT_THRESHOLD_TOKENS;
|
|
791
673
|
if (tokens >= softThreshold) {
|
|
792
|
-
|
|
674
|
+
log2.info(`Memory flush needed: ~${tokens} tokens (soft threshold: ${softThreshold})`);
|
|
793
675
|
return true;
|
|
794
676
|
}
|
|
795
677
|
return false;
|
|
@@ -811,7 +693,7 @@ function flushMemoryToDailyLog(context) {
|
|
|
811
693
|
}
|
|
812
694
|
}
|
|
813
695
|
writeSummaryToDailyLog(summary.join("\n"));
|
|
814
|
-
|
|
696
|
+
log2.info(`Memory flushed to daily log`);
|
|
815
697
|
}
|
|
816
698
|
function shouldCompact(context, config, tokenCount) {
|
|
817
699
|
if (!config.enabled) {
|
|
@@ -819,13 +701,13 @@ function shouldCompact(context, config, tokenCount) {
|
|
|
819
701
|
}
|
|
820
702
|
const messageCount = context.messages.length;
|
|
821
703
|
if (config.maxMessages && messageCount >= config.maxMessages) {
|
|
822
|
-
|
|
704
|
+
log2.info(`Compaction needed: ${messageCount} messages (max: ${config.maxMessages})`);
|
|
823
705
|
return true;
|
|
824
706
|
}
|
|
825
707
|
if (config.maxTokens) {
|
|
826
708
|
const tokens = tokenCount ?? estimateContextTokens(context);
|
|
827
709
|
if (tokens >= config.maxTokens) {
|
|
828
|
-
|
|
710
|
+
log2.info(`Compaction needed: ~${tokens} tokens (max: ${config.maxTokens})`);
|
|
829
711
|
return true;
|
|
830
712
|
}
|
|
831
713
|
}
|
|
@@ -871,12 +753,12 @@ async function compactContext(context, config, apiKey, provider, utilityModel) {
|
|
|
871
753
|
iterations++;
|
|
872
754
|
}
|
|
873
755
|
if (hasOrphanedToolResults(context.messages.slice(cutIndex))) {
|
|
874
|
-
|
|
756
|
+
log2.warn(`Compaction: couldn't find clean cut point, keeping all messages`);
|
|
875
757
|
return context;
|
|
876
758
|
}
|
|
877
759
|
const recentMessages = context.messages.slice(cutIndex);
|
|
878
760
|
const oldMessages = context.messages.slice(0, cutIndex);
|
|
879
|
-
|
|
761
|
+
log2.info(
|
|
880
762
|
`Compacting ${oldMessages.length} old messages, keeping ${recentMessages.length} recent (cut at clean boundary)`
|
|
881
763
|
);
|
|
882
764
|
try {
|
|
@@ -906,7 +788,7 @@ Keep each section concise. Omit a section if empty. Preserve specific names, num
|
|
|
906
788
|
provider,
|
|
907
789
|
utilityModel
|
|
908
790
|
});
|
|
909
|
-
|
|
791
|
+
log2.info(`AI Summary: ${result.tokensUsed} tokens, ${result.chunksProcessed} chunks processed`);
|
|
910
792
|
const summaryText = `[Auto-compacted ${oldMessages.length} messages]
|
|
911
793
|
|
|
912
794
|
${result.summary}`;
|
|
@@ -920,7 +802,7 @@ ${result.summary}`;
|
|
|
920
802
|
messages: [summaryMessage, ...recentMessages]
|
|
921
803
|
};
|
|
922
804
|
} catch (error) {
|
|
923
|
-
|
|
805
|
+
log2.error({ err: error }, "AI summarization failed, using fallback");
|
|
924
806
|
const summaryText = `[Auto-compacted: ${oldMessages.length} earlier messages from this conversation]`;
|
|
925
807
|
const summaryMessage = {
|
|
926
808
|
role: "user",
|
|
@@ -935,7 +817,7 @@ ${result.summary}`;
|
|
|
935
817
|
}
|
|
936
818
|
async function compactAndSaveTranscript(sessionId, context, config, apiKey, chatId, provider, utilityModel) {
|
|
937
819
|
const newSessionId = randomUUID();
|
|
938
|
-
|
|
820
|
+
log2.info(`Creating compacted transcript: ${sessionId} \u2192 ${newSessionId}`);
|
|
939
821
|
if (chatId) {
|
|
940
822
|
await saveSessionMemory({
|
|
941
823
|
oldSessionId: sessionId,
|
|
@@ -969,7 +851,7 @@ var CompactionManager = class {
|
|
|
969
851
|
if (this.config.memoryFlushEnabled) {
|
|
970
852
|
flushMemoryToDailyLog(context);
|
|
971
853
|
}
|
|
972
|
-
|
|
854
|
+
log2.info(`Auto-compacting session ${sessionId}`);
|
|
973
855
|
const newSessionId = await compactAndSaveTranscript(
|
|
974
856
|
sessionId,
|
|
975
857
|
context,
|
|
@@ -979,7 +861,7 @@ var CompactionManager = class {
|
|
|
979
861
|
provider,
|
|
980
862
|
utilityModel
|
|
981
863
|
);
|
|
982
|
-
|
|
864
|
+
log2.info(`Compaction complete: ${newSessionId}`);
|
|
983
865
|
return newSessionId;
|
|
984
866
|
}
|
|
985
867
|
updateConfig(config) {
|
|
@@ -1111,7 +993,7 @@ function maskOldToolResults(messages, options) {
|
|
|
1111
993
|
}
|
|
1112
994
|
|
|
1113
995
|
// src/agent/runtime.ts
|
|
1114
|
-
var
|
|
996
|
+
var log3 = createLogger("Agent");
|
|
1115
997
|
var globalTokenUsage = { totalTokens: 0, totalCost: 0 };
|
|
1116
998
|
function getTokenUsage() {
|
|
1117
999
|
return { ...globalTokenUsage };
|
|
@@ -1224,7 +1106,7 @@ var AgentRuntime = class {
|
|
|
1224
1106
|
if (this.userHookEvaluator) {
|
|
1225
1107
|
const hookResult = this.userHookEvaluator.evaluate(userMessage);
|
|
1226
1108
|
if (hookResult.blocked) {
|
|
1227
|
-
|
|
1109
|
+
log3.info("Message blocked by keyword filter");
|
|
1228
1110
|
return { content: hookResult.blockMessage ?? "", toolCalls: [] };
|
|
1229
1111
|
}
|
|
1230
1112
|
if (hookResult.additionalContext) {
|
|
@@ -1250,7 +1132,7 @@ var AgentRuntime = class {
|
|
|
1250
1132
|
};
|
|
1251
1133
|
await this.hookRunner.runModifyingHook("message:receive", msgEvent);
|
|
1252
1134
|
if (msgEvent.block) {
|
|
1253
|
-
|
|
1135
|
+
log3.info(`\u{1F6AB} Message blocked by hook: ${msgEvent.blockReason || "no reason"}`);
|
|
1254
1136
|
return { content: "", toolCalls: [] };
|
|
1255
1137
|
}
|
|
1256
1138
|
effectiveMessage = sanitizeForContext(msgEvent.text);
|
|
@@ -1262,7 +1144,7 @@ var AgentRuntime = class {
|
|
|
1262
1144
|
const now = timestamp ?? Date.now();
|
|
1263
1145
|
const resetPolicy = this.config.agent.session_reset_policy;
|
|
1264
1146
|
if (shouldResetSession(session, resetPolicy)) {
|
|
1265
|
-
|
|
1147
|
+
log3.info(`\u{1F504} Auto-resetting session based on policy`);
|
|
1266
1148
|
if (this.hookRunner) {
|
|
1267
1149
|
await this.hookRunner.runObservingHook("session:end", {
|
|
1268
1150
|
sessionId: session.sessionId,
|
|
@@ -1272,7 +1154,7 @@ var AgentRuntime = class {
|
|
|
1272
1154
|
}
|
|
1273
1155
|
if (transcriptExists(session.sessionId)) {
|
|
1274
1156
|
try {
|
|
1275
|
-
|
|
1157
|
+
log3.info(`\u{1F4BE} Saving memory before daily reset...`);
|
|
1276
1158
|
const oldContext = loadContextFromTranscript(session.sessionId);
|
|
1277
1159
|
await saveSessionMemory({
|
|
1278
1160
|
oldSessionId: session.sessionId,
|
|
@@ -1283,9 +1165,9 @@ var AgentRuntime = class {
|
|
|
1283
1165
|
provider: this.config.agent.provider,
|
|
1284
1166
|
utilityModel: this.config.agent.utility_model
|
|
1285
1167
|
});
|
|
1286
|
-
|
|
1168
|
+
log3.info(`\u2705 Memory saved before reset`);
|
|
1287
1169
|
} catch (error) {
|
|
1288
|
-
|
|
1170
|
+
log3.warn({ err: error }, `\u26A0\uFE0F Failed to save memory before reset`);
|
|
1289
1171
|
}
|
|
1290
1172
|
}
|
|
1291
1173
|
session = resetSessionWithPolicy(chatId, resetPolicy);
|
|
@@ -1293,9 +1175,9 @@ var AgentRuntime = class {
|
|
|
1293
1175
|
let context = loadContextFromTranscript(session.sessionId);
|
|
1294
1176
|
const isNewSession = context.messages.length === 0;
|
|
1295
1177
|
if (!isNewSession) {
|
|
1296
|
-
|
|
1178
|
+
log3.info(`\u{1F4D6} Loading existing session: ${session.sessionId}`);
|
|
1297
1179
|
} else {
|
|
1298
|
-
|
|
1180
|
+
log3.info(`\u{1F195} Starting new session: ${session.sessionId}`);
|
|
1299
1181
|
}
|
|
1300
1182
|
if (this.hookRunner) {
|
|
1301
1183
|
await this.hookRunner.runObservingHook("session:start", {
|
|
@@ -1324,13 +1206,13 @@ var AgentRuntime = class {
|
|
|
1324
1206
|
formattedMessage = `${pendingContext}
|
|
1325
1207
|
|
|
1326
1208
|
${formattedMessage}`;
|
|
1327
|
-
|
|
1209
|
+
log3.debug(`\u{1F4CB} Including ${pendingContext.split("\n").length - 1} pending messages`);
|
|
1328
1210
|
}
|
|
1329
|
-
|
|
1211
|
+
log3.debug(`\u{1F4E8} Formatted message: ${formattedMessage.substring(0, 100)}...`);
|
|
1330
1212
|
const preview = formattedMessage.slice(0, 50).replace(/\n/g, " ");
|
|
1331
1213
|
const who = senderUsername ? `@${senderUsername}` : userName;
|
|
1332
1214
|
const msgType = isGroup ? `Group ${chatId} ${who}` : `DM ${who}`;
|
|
1333
|
-
|
|
1215
|
+
log3.info(`\u{1F4E8} ${msgType}: "${preview}${formattedMessage.length > 50 ? "..." : ""}"`);
|
|
1334
1216
|
let relevantContext = "";
|
|
1335
1217
|
let queryEmbedding;
|
|
1336
1218
|
const isNonTrivial = !isTrivialMessage(effectiveMessage);
|
|
@@ -1349,7 +1231,7 @@ ${formattedMessage}`;
|
|
|
1349
1231
|
searchQuery.slice(0, EMBEDDING_QUERY_MAX_CHARS)
|
|
1350
1232
|
);
|
|
1351
1233
|
} catch (error) {
|
|
1352
|
-
|
|
1234
|
+
log3.warn({ err: error }, "Embedding computation failed");
|
|
1353
1235
|
}
|
|
1354
1236
|
}
|
|
1355
1237
|
if (this.contextBuilder && isNonTrivial) {
|
|
@@ -1383,12 +1265,12 @@ ${sanitizedFeed.join("\n")}`
|
|
|
1383
1265
|
}
|
|
1384
1266
|
if (contextParts.length > 0) {
|
|
1385
1267
|
relevantContext = contextParts.join("\n\n");
|
|
1386
|
-
|
|
1268
|
+
log3.debug(
|
|
1387
1269
|
`\u{1F50D} Found ${dbContext.relevantKnowledge.length} knowledge chunks, ${dbContext.relevantFeed.length} feed messages`
|
|
1388
1270
|
);
|
|
1389
1271
|
}
|
|
1390
1272
|
} catch (error) {
|
|
1391
|
-
|
|
1273
|
+
log3.warn({ err: error }, "Context building failed");
|
|
1392
1274
|
}
|
|
1393
1275
|
}
|
|
1394
1276
|
const memoryStats = this.getMemoryStats();
|
|
@@ -1456,7 +1338,7 @@ ${allHookContext}` : "");
|
|
|
1456
1338
|
this.config.agent.utility_model
|
|
1457
1339
|
);
|
|
1458
1340
|
if (preemptiveCompaction) {
|
|
1459
|
-
|
|
1341
|
+
log3.info(`\u{1F5DC}\uFE0F Preemptive compaction triggered, reloading session...`);
|
|
1460
1342
|
session = getSession(chatId);
|
|
1461
1343
|
context = loadContextFromTranscript(session.sessionId);
|
|
1462
1344
|
context.messages.push(userMsg);
|
|
@@ -1478,7 +1360,7 @@ ${allHookContext}` : "");
|
|
|
1478
1360
|
chatId,
|
|
1479
1361
|
isAdmin
|
|
1480
1362
|
);
|
|
1481
|
-
|
|
1363
|
+
log3.info(`\u{1F50D} Tool RAG: ${tools.length}/${this.toolRegistry.count} tools selected`);
|
|
1482
1364
|
} else {
|
|
1483
1365
|
tools = this.toolRegistry?.getForContext(
|
|
1484
1366
|
effectiveIsGroup,
|
|
@@ -1500,7 +1382,7 @@ ${allHookContext}` : "");
|
|
|
1500
1382
|
const seenToolSignatures = /* @__PURE__ */ new Set();
|
|
1501
1383
|
while (iteration < maxIterations) {
|
|
1502
1384
|
iteration++;
|
|
1503
|
-
|
|
1385
|
+
log3.debug(`\u{1F504} Agentic iteration ${iteration}/${maxIterations}`);
|
|
1504
1386
|
const iterationStartIndex = context.messages.length;
|
|
1505
1387
|
const maskedMessages = maskOldToolResults(context.messages, {
|
|
1506
1388
|
toolRegistry: this.toolRegistry ?? void 0,
|
|
@@ -1539,35 +1421,35 @@ ${allHookContext}` : "");
|
|
|
1539
1421
|
"Context overflow persists after session reset. Message may be too large for the model's context window."
|
|
1540
1422
|
);
|
|
1541
1423
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1424
|
+
log3.error(`\u{1F6A8} Context overflow detected: ${errorMsg}`);
|
|
1425
|
+
log3.info(`\u{1F4BE} Saving session memory before reset...`);
|
|
1544
1426
|
const summary = extractContextSummary(context, CONTEXT_OVERFLOW_SUMMARY_MESSAGES);
|
|
1545
1427
|
appendToDailyLog(summary);
|
|
1546
|
-
|
|
1428
|
+
log3.info(`\u2705 Memory saved to daily log`);
|
|
1547
1429
|
const archived = archiveTranscript(session.sessionId);
|
|
1548
1430
|
if (!archived) {
|
|
1549
|
-
|
|
1431
|
+
log3.error(
|
|
1550
1432
|
`\u26A0\uFE0F Failed to archive transcript ${session.sessionId}, proceeding with reset anyway`
|
|
1551
1433
|
);
|
|
1552
1434
|
}
|
|
1553
|
-
|
|
1435
|
+
log3.info(`\u{1F504} Resetting session due to context overflow...`);
|
|
1554
1436
|
session = resetSession(chatId);
|
|
1555
1437
|
context = { messages: [userMsg] };
|
|
1556
1438
|
appendToTranscript(session.sessionId, userMsg);
|
|
1557
|
-
|
|
1439
|
+
log3.info(`\u{1F504} Retrying with fresh context...`);
|
|
1558
1440
|
continue;
|
|
1559
1441
|
} else if (errorMsg.toLowerCase().includes("rate") || errorMsg.includes("429")) {
|
|
1560
1442
|
rateLimitRetries++;
|
|
1561
1443
|
if (rateLimitRetries <= RATE_LIMIT_MAX_RETRIES) {
|
|
1562
1444
|
const delay = 1e3 * Math.pow(2, rateLimitRetries - 1);
|
|
1563
|
-
|
|
1445
|
+
log3.warn(
|
|
1564
1446
|
`\u{1F6AB} Rate limited, retrying in ${delay}ms (attempt ${rateLimitRetries}/${RATE_LIMIT_MAX_RETRIES})...`
|
|
1565
1447
|
);
|
|
1566
1448
|
await new Promise((r3) => setTimeout(r3, delay));
|
|
1567
1449
|
iteration--;
|
|
1568
1450
|
continue;
|
|
1569
1451
|
}
|
|
1570
|
-
|
|
1452
|
+
log3.error(`\u{1F6AB} Rate limited after ${RATE_LIMIT_MAX_RETRIES} retries: ${errorMsg}`);
|
|
1571
1453
|
throw new Error(
|
|
1572
1454
|
`API rate limited after ${RATE_LIMIT_MAX_RETRIES} retries. Please try again later.`
|
|
1573
1455
|
);
|
|
@@ -1575,19 +1457,19 @@ ${allHookContext}` : "");
|
|
|
1575
1457
|
serverErrorRetries++;
|
|
1576
1458
|
if (serverErrorRetries <= SERVER_ERROR_MAX_RETRIES) {
|
|
1577
1459
|
const delay = 2e3 * Math.pow(2, serverErrorRetries - 1);
|
|
1578
|
-
|
|
1460
|
+
log3.warn(
|
|
1579
1461
|
`\u{1F504} Server error, retrying in ${delay}ms (attempt ${serverErrorRetries}/${SERVER_ERROR_MAX_RETRIES})...`
|
|
1580
1462
|
);
|
|
1581
1463
|
await new Promise((r3) => setTimeout(r3, delay));
|
|
1582
1464
|
iteration--;
|
|
1583
1465
|
continue;
|
|
1584
1466
|
}
|
|
1585
|
-
|
|
1467
|
+
log3.error(`\u{1F6A8} Server error after ${SERVER_ERROR_MAX_RETRIES} retries: ${errorMsg}`);
|
|
1586
1468
|
throw new Error(
|
|
1587
1469
|
`API server error after ${SERVER_ERROR_MAX_RETRIES} retries. The provider may be experiencing issues.`
|
|
1588
1470
|
);
|
|
1589
1471
|
} else {
|
|
1590
|
-
|
|
1472
|
+
log3.error(`\u{1F6A8} API error: ${errorMsg}`);
|
|
1591
1473
|
throw new Error(`API error: ${errorMsg || "Unknown error"}`);
|
|
1592
1474
|
}
|
|
1593
1475
|
}
|
|
@@ -1604,15 +1486,15 @@ ${allHookContext}` : "");
|
|
|
1604
1486
|
}
|
|
1605
1487
|
const toolCalls = response2.message.content.filter((block) => block.type === "toolCall");
|
|
1606
1488
|
if (toolCalls.length === 0) {
|
|
1607
|
-
|
|
1489
|
+
log3.info(`\u{1F504} ${iteration}/${maxIterations} \u2192 done`);
|
|
1608
1490
|
finalResponse = response2;
|
|
1609
1491
|
break;
|
|
1610
1492
|
}
|
|
1611
1493
|
if (!this.toolRegistry || !toolContext) {
|
|
1612
|
-
|
|
1494
|
+
log3.error("\u26A0\uFE0F Cannot execute tools: registry or context missing");
|
|
1613
1495
|
break;
|
|
1614
1496
|
}
|
|
1615
|
-
|
|
1497
|
+
log3.debug(`\u{1F527} Executing ${toolCalls.length} tool call(s)`);
|
|
1616
1498
|
context.messages.push(response2.message);
|
|
1617
1499
|
const iterationToolNames = [];
|
|
1618
1500
|
const fullContext = {
|
|
@@ -1712,7 +1594,7 @@ ${allHookContext}` : "");
|
|
|
1712
1594
|
};
|
|
1713
1595
|
await this.hookRunner.runObservingHook("tool:after", afterEvent);
|
|
1714
1596
|
}
|
|
1715
|
-
|
|
1597
|
+
log3.debug(`${block.name}: ${exec.result.success ? "\u2713" : "\u2717"} ${exec.result.error || ""}`);
|
|
1716
1598
|
iterationToolNames.push(`${block.name} ${exec.result.success ? "\u2713" : "\u2717"}`);
|
|
1717
1599
|
totalToolCalls.push({
|
|
1718
1600
|
name: block.name,
|
|
@@ -1720,7 +1602,7 @@ ${allHookContext}` : "");
|
|
|
1720
1602
|
});
|
|
1721
1603
|
let resultText = JSON.stringify(exec.result);
|
|
1722
1604
|
if (resultText.length > MAX_TOOL_RESULT_SIZE) {
|
|
1723
|
-
|
|
1605
|
+
log3.warn(`\u26A0\uFE0F Tool result too large (${resultText.length} chars), truncating...`);
|
|
1724
1606
|
const data = exec.result.data;
|
|
1725
1607
|
if (data?.summary || data?.message) {
|
|
1726
1608
|
resultText = JSON.stringify({
|
|
@@ -1784,26 +1666,26 @@ ${allHookContext}` : "");
|
|
|
1784
1666
|
appendToTranscript(session.sessionId, toolResultMsg);
|
|
1785
1667
|
}
|
|
1786
1668
|
}
|
|
1787
|
-
|
|
1669
|
+
log3.info(`\u{1F504} ${iteration}/${maxIterations} \u2192 ${iterationToolNames.join(", ")}`);
|
|
1788
1670
|
const iterSignatures = toolPlans.map(
|
|
1789
1671
|
(p2) => `${p2.block.name}:${JSON.stringify(p2.params, Object.keys(p2.params).sort())}`
|
|
1790
1672
|
);
|
|
1791
1673
|
const allDuplicates = iterSignatures.length > 0 && iterSignatures.every((sig) => seenToolSignatures.has(sig));
|
|
1792
1674
|
for (const sig of iterSignatures) seenToolSignatures.add(sig);
|
|
1793
1675
|
if (allDuplicates) {
|
|
1794
|
-
|
|
1676
|
+
log3.warn(
|
|
1795
1677
|
`\u{1F501} Loop stall detected: all ${iterSignatures.length} tool call(s) are repeats \u2014 breaking early`
|
|
1796
1678
|
);
|
|
1797
1679
|
finalResponse = response2;
|
|
1798
1680
|
break;
|
|
1799
1681
|
}
|
|
1800
1682
|
if (iteration === maxIterations) {
|
|
1801
|
-
|
|
1683
|
+
log3.info(`\u26A0\uFE0F Max iterations reached (${maxIterations})`);
|
|
1802
1684
|
finalResponse = response2;
|
|
1803
1685
|
}
|
|
1804
1686
|
}
|
|
1805
1687
|
if (!finalResponse) {
|
|
1806
|
-
|
|
1688
|
+
log3.error("\u26A0\uFE0F Agentic loop exited early without final response");
|
|
1807
1689
|
return {
|
|
1808
1690
|
content: "Internal error: Agent loop failed to produce a response.",
|
|
1809
1691
|
toolCalls: []
|
|
@@ -1831,20 +1713,20 @@ ${allHookContext}` : "");
|
|
|
1831
1713
|
if (u.cacheRead) cacheParts.push(`${(u.cacheRead / 1e3).toFixed(1)}K cached`);
|
|
1832
1714
|
if (u.cacheWrite) cacheParts.push(`${(u.cacheWrite / 1e3).toFixed(1)}K new`);
|
|
1833
1715
|
const cacheInfo = cacheParts.length > 0 ? ` (${cacheParts.join(", ")})` : "";
|
|
1834
|
-
|
|
1716
|
+
log3.info(`\u{1F4B0} ${inK}K in${cacheInfo}, ${u.output} out | $${u.totalCost.toFixed(3)}`);
|
|
1835
1717
|
globalTokenUsage.totalTokens += u.input + u.output + u.cacheRead + u.cacheWrite;
|
|
1836
1718
|
globalTokenUsage.totalCost += u.totalCost;
|
|
1837
1719
|
}
|
|
1838
1720
|
let content = accumulatedTexts.join("\n").trim() || response.text;
|
|
1839
1721
|
const usedTelegramSendTool = totalToolCalls.some((tc) => TELEGRAM_SEND_TOOLS.has(tc.name));
|
|
1840
1722
|
if (!content && totalToolCalls.length > 0 && !usedTelegramSendTool) {
|
|
1841
|
-
|
|
1723
|
+
log3.warn("\u26A0\uFE0F Empty response after tool calls - generating fallback");
|
|
1842
1724
|
content = "I executed the requested action but couldn't generate a response. Please try again.";
|
|
1843
1725
|
} else if (!content && usedTelegramSendTool) {
|
|
1844
|
-
|
|
1726
|
+
log3.info("\u2705 Response sent via Telegram tool - no additional text needed");
|
|
1845
1727
|
content = "";
|
|
1846
1728
|
} else if (!content && accumulatedUsage.input === 0 && accumulatedUsage.output === 0) {
|
|
1847
|
-
|
|
1729
|
+
log3.warn("\u26A0\uFE0F Empty response with zero tokens - possible API issue");
|
|
1848
1730
|
content = "I couldn't process your request. Please try again.";
|
|
1849
1731
|
}
|
|
1850
1732
|
let responseMetadata = {};
|
|
@@ -1861,7 +1743,7 @@ ${allHookContext}` : "");
|
|
|
1861
1743
|
};
|
|
1862
1744
|
await this.hookRunner.runModifyingHook("response:before", responseBeforeEvent);
|
|
1863
1745
|
if (responseBeforeEvent.block) {
|
|
1864
|
-
|
|
1746
|
+
log3.info(
|
|
1865
1747
|
`\u{1F6AB} Response blocked by hook: ${responseBeforeEvent.blockReason || "no reason"}`
|
|
1866
1748
|
);
|
|
1867
1749
|
content = "";
|
|
@@ -1888,7 +1770,7 @@ ${allHookContext}` : "");
|
|
|
1888
1770
|
toolCalls: totalToolCalls
|
|
1889
1771
|
};
|
|
1890
1772
|
} catch (error) {
|
|
1891
|
-
|
|
1773
|
+
log3.error({ err: error }, "Agent error");
|
|
1892
1774
|
throw error;
|
|
1893
1775
|
}
|
|
1894
1776
|
}
|
|
@@ -1901,7 +1783,7 @@ ${allHookContext}` : "");
|
|
|
1901
1783
|
).run(chatId);
|
|
1902
1784
|
db.prepare(`DELETE FROM tg_messages WHERE chat_id = ?`).run(chatId);
|
|
1903
1785
|
resetSession(chatId);
|
|
1904
|
-
|
|
1786
|
+
log3.info(`\u{1F5D1}\uFE0F Cleared history for chat ${chatId}`);
|
|
1905
1787
|
}
|
|
1906
1788
|
getConfig() {
|
|
1907
1789
|
return this.config;
|
|
@@ -1922,7 +1804,7 @@ ${allHookContext}` : "");
|
|
|
1922
1804
|
}
|
|
1923
1805
|
configureCompaction(config) {
|
|
1924
1806
|
this.compactionManager.updateConfig(config);
|
|
1925
|
-
|
|
1807
|
+
log3.info({ config: this.compactionManager.getConfig() }, `\u{1F5DC}\uFE0F Compaction config updated`);
|
|
1926
1808
|
}
|
|
1927
1809
|
getCompactionConfig() {
|
|
1928
1810
|
return this.compactionManager.getConfig();
|
|
@@ -2132,7 +2014,7 @@ function unescapeHtml(text) {
|
|
|
2132
2014
|
}
|
|
2133
2015
|
|
|
2134
2016
|
// src/bot/inline-router.ts
|
|
2135
|
-
var
|
|
2017
|
+
var log4 = createLogger("InlineRouter");
|
|
2136
2018
|
var INLINE_TIMEOUT_MS = 5e3;
|
|
2137
2019
|
var CALLBACK_TIMEOUT_MS = 15e3;
|
|
2138
2020
|
function compileGlob(pattern) {
|
|
@@ -2153,11 +2035,11 @@ var InlineRouter = class {
|
|
|
2153
2035
|
}
|
|
2154
2036
|
registerPlugin(name, handlers) {
|
|
2155
2037
|
this.plugins.set(name, handlers);
|
|
2156
|
-
|
|
2038
|
+
log4.info(`Registered plugin "${name}" for inline routing`);
|
|
2157
2039
|
}
|
|
2158
2040
|
unregisterPlugin(name) {
|
|
2159
2041
|
this.plugins.delete(name);
|
|
2160
|
-
|
|
2042
|
+
log4.info(`Unregistered plugin "${name}" from inline routing`);
|
|
2161
2043
|
}
|
|
2162
2044
|
hasPlugin(name) {
|
|
2163
2045
|
return this.plugins.has(name);
|
|
@@ -2229,7 +2111,7 @@ var InlineRouter = class {
|
|
|
2229
2111
|
is_personal: true
|
|
2230
2112
|
});
|
|
2231
2113
|
} catch (error) {
|
|
2232
|
-
|
|
2114
|
+
log4.error({ err: error }, `Plugin "${pluginName}" inline query handler failed`);
|
|
2233
2115
|
try {
|
|
2234
2116
|
await ctx.answerInlineQuery([], { cache_time: 0, is_personal: true });
|
|
2235
2117
|
} catch {
|
|
@@ -2289,7 +2171,7 @@ var InlineRouter = class {
|
|
|
2289
2171
|
} catch (error) {
|
|
2290
2172
|
const errMsg = error?.errorMessage;
|
|
2291
2173
|
if (errMsg === "MESSAGE_NOT_MODIFIED") return;
|
|
2292
|
-
|
|
2174
|
+
log4.debug(`GramJS edit failed, falling back to Grammy: ${errMsg || error}`);
|
|
2293
2175
|
}
|
|
2294
2176
|
}
|
|
2295
2177
|
const replyMarkup = styledButtons ? toGrammyKeyboard(styledButtons) : void 0;
|
|
@@ -2309,7 +2191,7 @@ var InlineRouter = class {
|
|
|
2309
2191
|
await ctx.answerCallbackQuery();
|
|
2310
2192
|
}
|
|
2311
2193
|
} catch (error) {
|
|
2312
|
-
|
|
2194
|
+
log4.error({ err: error }, `Plugin "${pluginName}" callback handler failed`);
|
|
2313
2195
|
if (!answered) {
|
|
2314
2196
|
try {
|
|
2315
2197
|
await ctx.answerCallbackQuery({ text: "Error processing action" });
|
|
@@ -2332,7 +2214,7 @@ var InlineRouter = class {
|
|
|
2332
2214
|
};
|
|
2333
2215
|
await plugin.onChosenResult(crCtx);
|
|
2334
2216
|
} catch (error) {
|
|
2335
|
-
|
|
2217
|
+
log4.error({ err: error }, `Plugin "${pluginName}" chosen result handler failed`);
|
|
2336
2218
|
}
|
|
2337
2219
|
}
|
|
2338
2220
|
/**
|
|
@@ -2410,8 +2292,8 @@ function withTimeout(promise, ms, message) {
|
|
|
2410
2292
|
}
|
|
2411
2293
|
|
|
2412
2294
|
// src/agent/tools/plugin-loader.ts
|
|
2413
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
2414
|
-
import { join as
|
|
2295
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync4, existsSync as existsSync5, statSync } from "fs";
|
|
2296
|
+
import { join as join3 } from "path";
|
|
2415
2297
|
import { pathToFileURL } from "url";
|
|
2416
2298
|
import { execFile } from "child_process";
|
|
2417
2299
|
|
|
@@ -2442,7 +2324,7 @@ import { promisify } from "util";
|
|
|
2442
2324
|
|
|
2443
2325
|
// src/agent/tools/plugin-validator.ts
|
|
2444
2326
|
import { z } from "zod";
|
|
2445
|
-
var
|
|
2327
|
+
var log5 = createLogger("PluginValidator");
|
|
2446
2328
|
var ManifestSchema = z.object({
|
|
2447
2329
|
name: z.string().min(1).max(64).regex(
|
|
2448
2330
|
/^[a-z0-9][a-z0-9-]*$/,
|
|
@@ -2485,20 +2367,20 @@ function validateToolDefs(defs, pluginName) {
|
|
|
2485
2367
|
const valid = [];
|
|
2486
2368
|
for (const def of defs) {
|
|
2487
2369
|
if (!def || typeof def !== "object") {
|
|
2488
|
-
|
|
2370
|
+
log5.warn(`[${pluginName}] tool is not an object, skipping`);
|
|
2489
2371
|
continue;
|
|
2490
2372
|
}
|
|
2491
2373
|
const t = def;
|
|
2492
2374
|
if (!t.name || typeof t.name !== "string") {
|
|
2493
|
-
|
|
2375
|
+
log5.warn(`[${pluginName}] tool missing 'name', skipping`);
|
|
2494
2376
|
continue;
|
|
2495
2377
|
}
|
|
2496
2378
|
if (!t.description || typeof t.description !== "string") {
|
|
2497
|
-
|
|
2379
|
+
log5.warn(`[${pluginName}] tool "${t.name}" missing 'description', skipping`);
|
|
2498
2380
|
continue;
|
|
2499
2381
|
}
|
|
2500
2382
|
if (!t.execute || typeof t.execute !== "function") {
|
|
2501
|
-
|
|
2383
|
+
log5.warn(`[${pluginName}] tool "${t.name}" missing 'execute' function, skipping`);
|
|
2502
2384
|
continue;
|
|
2503
2385
|
}
|
|
2504
2386
|
valid.push(t);
|
|
@@ -2558,25 +2440,25 @@ function withTxLock(fn) {
|
|
|
2558
2440
|
}
|
|
2559
2441
|
|
|
2560
2442
|
// src/ton/transfer.ts
|
|
2561
|
-
var
|
|
2443
|
+
var log6 = createLogger("TON");
|
|
2562
2444
|
async function sendTon(params) {
|
|
2563
2445
|
return withTxLock(async () => {
|
|
2564
2446
|
try {
|
|
2565
2447
|
const { toAddress: toAddress2, amount, comment = "", bounce = false } = params;
|
|
2566
2448
|
if (!Number.isFinite(amount) || amount <= 0) {
|
|
2567
|
-
|
|
2449
|
+
log6.error({ amount }, "Invalid transfer amount");
|
|
2568
2450
|
return null;
|
|
2569
2451
|
}
|
|
2570
2452
|
let recipientAddress;
|
|
2571
2453
|
try {
|
|
2572
2454
|
recipientAddress = Address.parse(toAddress2);
|
|
2573
2455
|
} catch (e) {
|
|
2574
|
-
|
|
2456
|
+
log6.error({ err: e }, `Invalid recipient address: ${toAddress2}`);
|
|
2575
2457
|
return null;
|
|
2576
2458
|
}
|
|
2577
2459
|
const keyPair = await getKeyPair();
|
|
2578
2460
|
if (!keyPair) {
|
|
2579
|
-
|
|
2461
|
+
log6.error("Wallet not initialized");
|
|
2580
2462
|
return null;
|
|
2581
2463
|
}
|
|
2582
2464
|
const wallet = WalletContractV5R1.create({
|
|
@@ -2600,7 +2482,7 @@ async function sendTon(params) {
|
|
|
2600
2482
|
]
|
|
2601
2483
|
});
|
|
2602
2484
|
const pseudoHash = `${seqno}_${Date.now()}_${amount.toFixed(2)}`;
|
|
2603
|
-
|
|
2485
|
+
log6.info(`Sent ${amount} TON to ${toAddress2.slice(0, 8)}... - seqno: ${seqno}`);
|
|
2604
2486
|
return pseudoHash;
|
|
2605
2487
|
} catch (error) {
|
|
2606
2488
|
const err = error;
|
|
@@ -2608,14 +2490,14 @@ async function sendTon(params) {
|
|
|
2608
2490
|
if (status === 429 || status !== void 0 && status >= 500) {
|
|
2609
2491
|
invalidateTonClientCache();
|
|
2610
2492
|
}
|
|
2611
|
-
|
|
2493
|
+
log6.error({ err: error }, "Error sending TON");
|
|
2612
2494
|
throw error;
|
|
2613
2495
|
}
|
|
2614
2496
|
});
|
|
2615
2497
|
}
|
|
2616
2498
|
|
|
2617
2499
|
// src/utils/retry.ts
|
|
2618
|
-
var
|
|
2500
|
+
var log7 = createLogger("Utils");
|
|
2619
2501
|
var DEFAULT_OPTIONS = {
|
|
2620
2502
|
maxAttempts: RETRY_DEFAULT_MAX_ATTEMPTS,
|
|
2621
2503
|
baseDelayMs: RETRY_DEFAULT_BASE_DELAY_MS,
|
|
@@ -2639,7 +2521,7 @@ async function withRetry(fn, options = {}) {
|
|
|
2639
2521
|
return result;
|
|
2640
2522
|
} catch (error) {
|
|
2641
2523
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
2642
|
-
|
|
2524
|
+
log7.warn(`Retry attempt ${attempt}/${opts.maxAttempts} failed: ${lastError.message}`);
|
|
2643
2525
|
if (attempt < opts.maxAttempts) {
|
|
2644
2526
|
const delay = Math.min(opts.baseDelayMs * Math.pow(2, attempt - 1), opts.maxDelayMs);
|
|
2645
2527
|
await sleep(delay);
|
|
@@ -6117,7 +5999,7 @@ var DEDUST_GAS = {
|
|
|
6117
5999
|
var NATIVE_TON_ADDRESS = "EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c";
|
|
6118
6000
|
|
|
6119
6001
|
// src/agent/tools/dedust/asset-cache.ts
|
|
6120
|
-
var
|
|
6002
|
+
var log8 = createLogger("Tools");
|
|
6121
6003
|
var ASSET_LIST_URL = "https://assets.dedust.io/list.json";
|
|
6122
6004
|
var CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
6123
6005
|
var cachedAssets = [];
|
|
@@ -6136,7 +6018,7 @@ async function getAssetList() {
|
|
|
6136
6018
|
return cachedAssets;
|
|
6137
6019
|
} catch (error) {
|
|
6138
6020
|
if (cachedAssets.length > 0) {
|
|
6139
|
-
|
|
6021
|
+
log8.warn({ err: error }, "Asset list fetch failed, using stale cache");
|
|
6140
6022
|
return cachedAssets;
|
|
6141
6023
|
}
|
|
6142
6024
|
throw error;
|
|
@@ -6189,7 +6071,7 @@ var stonApiClient = new StonApiClient();
|
|
|
6189
6071
|
function isTon(asset) {
|
|
6190
6072
|
return asset.toLowerCase() === "ton";
|
|
6191
6073
|
}
|
|
6192
|
-
async function getStonfiQuote(fromAsset, toAsset, amount, slippage,
|
|
6074
|
+
async function getStonfiQuote(fromAsset, toAsset, amount, slippage, log12) {
|
|
6193
6075
|
try {
|
|
6194
6076
|
const isTonInput = isTon(fromAsset);
|
|
6195
6077
|
const isTonOutput = isTon(toAsset);
|
|
@@ -6220,11 +6102,11 @@ async function getStonfiQuote(fromAsset, toAsset, amount, slippage, log13) {
|
|
|
6220
6102
|
fee: feeAmount.toFixed(6)
|
|
6221
6103
|
};
|
|
6222
6104
|
} catch (err) {
|
|
6223
|
-
|
|
6105
|
+
log12.debug("dex.quoteSTONfi() failed:", err);
|
|
6224
6106
|
return null;
|
|
6225
6107
|
}
|
|
6226
6108
|
}
|
|
6227
|
-
async function getDedustQuote(fromAsset, toAsset, amount, slippage,
|
|
6109
|
+
async function getDedustQuote(fromAsset, toAsset, amount, slippage, log12) {
|
|
6228
6110
|
try {
|
|
6229
6111
|
const isTonInput = isTon(fromAsset);
|
|
6230
6112
|
const isTonOutput = isTon(toAsset);
|
|
@@ -6258,7 +6140,7 @@ async function getDedustQuote(fromAsset, toAsset, amount, slippage, log13) {
|
|
|
6258
6140
|
poolType
|
|
6259
6141
|
};
|
|
6260
6142
|
} catch (err) {
|
|
6261
|
-
|
|
6143
|
+
log12.debug("dex.quoteDeDust() failed:", err);
|
|
6262
6144
|
return null;
|
|
6263
6145
|
}
|
|
6264
6146
|
}
|
|
@@ -6430,14 +6312,14 @@ function validateDexParams(amount, slippage) {
|
|
|
6430
6312
|
throw new PluginSDKError("Slippage must be between 0 and 1", "OPERATION_FAILED");
|
|
6431
6313
|
}
|
|
6432
6314
|
}
|
|
6433
|
-
function createDexSDK(
|
|
6315
|
+
function createDexSDK(log12) {
|
|
6434
6316
|
return {
|
|
6435
6317
|
async quote(params) {
|
|
6436
6318
|
validateDexParams(params.amount, params.slippage);
|
|
6437
6319
|
const slippage = params.slippage ?? 0.01;
|
|
6438
6320
|
const [stonfi, dedust] = await Promise.all([
|
|
6439
|
-
getStonfiQuote(params.fromAsset, params.toAsset, params.amount, slippage,
|
|
6440
|
-
getDedustQuote(params.fromAsset, params.toAsset, params.amount, slippage,
|
|
6321
|
+
getStonfiQuote(params.fromAsset, params.toAsset, params.amount, slippage, log12),
|
|
6322
|
+
getDedustQuote(params.fromAsset, params.toAsset, params.amount, slippage, log12)
|
|
6441
6323
|
]);
|
|
6442
6324
|
if (!stonfi && !dedust) {
|
|
6443
6325
|
throw new PluginSDKError("No DEX has liquidity for this pair", "OPERATION_FAILED");
|
|
@@ -6471,7 +6353,7 @@ function createDexSDK(log13) {
|
|
|
6471
6353
|
params.toAsset,
|
|
6472
6354
|
params.amount,
|
|
6473
6355
|
params.slippage ?? 0.01,
|
|
6474
|
-
|
|
6356
|
+
log12
|
|
6475
6357
|
);
|
|
6476
6358
|
},
|
|
6477
6359
|
async quoteDeDust(params) {
|
|
@@ -6480,25 +6362,25 @@ function createDexSDK(log13) {
|
|
|
6480
6362
|
params.toAsset,
|
|
6481
6363
|
params.amount,
|
|
6482
6364
|
params.slippage ?? 0.01,
|
|
6483
|
-
|
|
6365
|
+
log12
|
|
6484
6366
|
);
|
|
6485
6367
|
},
|
|
6486
6368
|
async swap(params) {
|
|
6487
6369
|
validateDexParams(params.amount, params.slippage);
|
|
6488
6370
|
if (params.dex === "stonfi") {
|
|
6489
|
-
return executeSTONfiSwap(params,
|
|
6371
|
+
return executeSTONfiSwap(params, log12);
|
|
6490
6372
|
}
|
|
6491
6373
|
if (params.dex === "dedust") {
|
|
6492
|
-
return executeDedustSwap(params,
|
|
6374
|
+
return executeDedustSwap(params, log12);
|
|
6493
6375
|
}
|
|
6494
6376
|
const quoteResult = await this.quote(params);
|
|
6495
|
-
return quoteResult.recommended === "stonfi" ? executeSTONfiSwap(params,
|
|
6377
|
+
return quoteResult.recommended === "stonfi" ? executeSTONfiSwap(params, log12) : executeDedustSwap(params, log12);
|
|
6496
6378
|
},
|
|
6497
6379
|
async swapSTONfi(params) {
|
|
6498
|
-
return executeSTONfiSwap(params,
|
|
6380
|
+
return executeSTONfiSwap(params, log12);
|
|
6499
6381
|
},
|
|
6500
6382
|
async swapDeDust(params) {
|
|
6501
|
-
return executeDedustSwap(params,
|
|
6383
|
+
return executeDedustSwap(params, log12);
|
|
6502
6384
|
}
|
|
6503
6385
|
};
|
|
6504
6386
|
}
|
|
@@ -6535,7 +6417,7 @@ function normalizeDomain(domain) {
|
|
|
6535
6417
|
if (!d.endsWith(".ton")) d += ".ton";
|
|
6536
6418
|
return d;
|
|
6537
6419
|
}
|
|
6538
|
-
function createDnsSDK(
|
|
6420
|
+
function createDnsSDK(log12) {
|
|
6539
6421
|
return {
|
|
6540
6422
|
async check(domain) {
|
|
6541
6423
|
const normalized = normalizeDomain(domain);
|
|
@@ -6558,7 +6440,7 @@ function createDnsSDK(log13) {
|
|
|
6558
6440
|
};
|
|
6559
6441
|
} catch (err) {
|
|
6560
6442
|
if (err instanceof PluginSDKError) throw err;
|
|
6561
|
-
|
|
6443
|
+
log12.debug("dns.check() failed:", err);
|
|
6562
6444
|
throw new PluginSDKError(
|
|
6563
6445
|
`Failed to check domain: ${err instanceof Error ? err.message : String(err)}`,
|
|
6564
6446
|
"OPERATION_FAILED"
|
|
@@ -6571,7 +6453,7 @@ function createDnsSDK(log13) {
|
|
|
6571
6453
|
const response = await tonapiFetch(`/dns/${encodeURIComponent(normalized)}`);
|
|
6572
6454
|
if (response.status === 404) return null;
|
|
6573
6455
|
if (!response.ok) {
|
|
6574
|
-
|
|
6456
|
+
log12.debug(`dns.resolve() TonAPI error: ${response.status}`);
|
|
6575
6457
|
return null;
|
|
6576
6458
|
}
|
|
6577
6459
|
const data = await response.json();
|
|
@@ -6583,7 +6465,7 @@ function createDnsSDK(log13) {
|
|
|
6583
6465
|
expirationDate: data.expiring_at || void 0
|
|
6584
6466
|
};
|
|
6585
6467
|
} catch (err) {
|
|
6586
|
-
|
|
6468
|
+
log12.debug("dns.resolve() failed:", err);
|
|
6587
6469
|
return null;
|
|
6588
6470
|
}
|
|
6589
6471
|
},
|
|
@@ -6593,7 +6475,7 @@ function createDnsSDK(log13) {
|
|
|
6593
6475
|
`/dns/auctions?tld=ton&limit=${Math.min(limit ?? 20, 100)}`
|
|
6594
6476
|
);
|
|
6595
6477
|
if (!response.ok) {
|
|
6596
|
-
|
|
6478
|
+
log12.debug(`dns.getAuctions() TonAPI error: ${response.status}`);
|
|
6597
6479
|
return [];
|
|
6598
6480
|
}
|
|
6599
6481
|
const data = await response.json();
|
|
@@ -6606,7 +6488,7 @@ function createDnsSDK(log13) {
|
|
|
6606
6488
|
bids: a.bids || 0
|
|
6607
6489
|
}));
|
|
6608
6490
|
} catch (err) {
|
|
6609
|
-
|
|
6491
|
+
log12.debug("dns.getAuctions() failed:", err);
|
|
6610
6492
|
return [];
|
|
6611
6493
|
}
|
|
6612
6494
|
},
|
|
@@ -6920,25 +6802,25 @@ function findJettonBalance(balances, jettonAddress) {
|
|
|
6920
6802
|
}
|
|
6921
6803
|
});
|
|
6922
6804
|
}
|
|
6923
|
-
function cleanupOldTransactions(db, retentionDays,
|
|
6805
|
+
function cleanupOldTransactions(db, retentionDays, log12) {
|
|
6924
6806
|
if (Math.random() > CLEANUP_PROBABILITY) return;
|
|
6925
6807
|
try {
|
|
6926
6808
|
const cutoff = Math.floor(Date.now() / 1e3) - retentionDays * 24 * 60 * 60;
|
|
6927
6809
|
const result = db.prepare("DELETE FROM used_transactions WHERE used_at < ?").run(cutoff);
|
|
6928
6810
|
if (result.changes > 0) {
|
|
6929
|
-
|
|
6811
|
+
log12.debug(`Cleaned up ${result.changes} old transaction records (>${retentionDays}d)`);
|
|
6930
6812
|
}
|
|
6931
6813
|
} catch (err) {
|
|
6932
|
-
|
|
6814
|
+
log12.error("Transaction cleanup failed:", err);
|
|
6933
6815
|
}
|
|
6934
6816
|
}
|
|
6935
|
-
function createTonSDK(
|
|
6817
|
+
function createTonSDK(log12, db) {
|
|
6936
6818
|
return {
|
|
6937
6819
|
getAddress() {
|
|
6938
6820
|
try {
|
|
6939
6821
|
return getWalletAddress();
|
|
6940
6822
|
} catch (err) {
|
|
6941
|
-
|
|
6823
|
+
log12.error("ton.getAddress() failed:", err);
|
|
6942
6824
|
return null;
|
|
6943
6825
|
}
|
|
6944
6826
|
},
|
|
@@ -6948,7 +6830,7 @@ function createTonSDK(log13, db) {
|
|
|
6948
6830
|
if (!addr) return null;
|
|
6949
6831
|
return await getWalletBalance(addr);
|
|
6950
6832
|
} catch (err) {
|
|
6951
|
-
|
|
6833
|
+
log12.error("ton.getBalance() failed:", err);
|
|
6952
6834
|
return null;
|
|
6953
6835
|
}
|
|
6954
6836
|
},
|
|
@@ -6956,7 +6838,7 @@ function createTonSDK(log13, db) {
|
|
|
6956
6838
|
try {
|
|
6957
6839
|
return await getTonPrice();
|
|
6958
6840
|
} catch (err) {
|
|
6959
|
-
|
|
6841
|
+
log12.error("ton.getPrice() failed:", err);
|
|
6960
6842
|
return null;
|
|
6961
6843
|
}
|
|
6962
6844
|
},
|
|
@@ -7007,7 +6889,7 @@ function createTonSDK(log13, db) {
|
|
|
7007
6889
|
);
|
|
7008
6890
|
return formatTransactions(transactions);
|
|
7009
6891
|
} catch (err) {
|
|
7010
|
-
|
|
6892
|
+
log12.error("ton.getTransactions() failed:", err);
|
|
7011
6893
|
return [];
|
|
7012
6894
|
}
|
|
7013
6895
|
},
|
|
@@ -7030,7 +6912,7 @@ function createTonSDK(log13, db) {
|
|
|
7030
6912
|
throw new PluginSDKError("Wallet not initialized", "WALLET_NOT_INITIALIZED");
|
|
7031
6913
|
}
|
|
7032
6914
|
const maxAgeMinutes = params.maxAgeMinutes ?? DEFAULT_MAX_AGE_MINUTES;
|
|
7033
|
-
cleanupOldTransactions(db, DEFAULT_TX_RETENTION_DAYS,
|
|
6915
|
+
cleanupOldTransactions(db, DEFAULT_TX_RETENTION_DAYS, log12);
|
|
7034
6916
|
try {
|
|
7035
6917
|
const txs = await this.getTransactions(address4, 20);
|
|
7036
6918
|
for (const tx of txs) {
|
|
@@ -7064,7 +6946,7 @@ function createTonSDK(log13, db) {
|
|
|
7064
6946
|
};
|
|
7065
6947
|
} catch (err) {
|
|
7066
6948
|
if (err instanceof PluginSDKError) throw err;
|
|
7067
|
-
|
|
6949
|
+
log12.error("ton.verifyPayment() failed:", err);
|
|
7068
6950
|
return {
|
|
7069
6951
|
verified: false,
|
|
7070
6952
|
error: `Verification failed: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -7078,7 +6960,7 @@ function createTonSDK(log13, db) {
|
|
|
7078
6960
|
if (!addr) return [];
|
|
7079
6961
|
const response = await tonapiFetch(`/accounts/${encodeURIComponent(addr)}/jettons`);
|
|
7080
6962
|
if (!response.ok) {
|
|
7081
|
-
|
|
6963
|
+
log12.error(`ton.getJettonBalances() TonAPI error: ${response.status}`);
|
|
7082
6964
|
return [];
|
|
7083
6965
|
}
|
|
7084
6966
|
const data = await response.json();
|
|
@@ -7102,7 +6984,7 @@ function createTonSDK(log13, db) {
|
|
|
7102
6984
|
}
|
|
7103
6985
|
return balances;
|
|
7104
6986
|
} catch (err) {
|
|
7105
|
-
|
|
6987
|
+
log12.error("ton.getJettonBalances() failed:", err);
|
|
7106
6988
|
return [];
|
|
7107
6989
|
}
|
|
7108
6990
|
},
|
|
@@ -7111,7 +6993,7 @@ function createTonSDK(log13, db) {
|
|
|
7111
6993
|
const response = await tonapiFetch(`/jettons/${encodeURIComponent(jettonAddress)}`);
|
|
7112
6994
|
if (response.status === 404) return null;
|
|
7113
6995
|
if (!response.ok) {
|
|
7114
|
-
|
|
6996
|
+
log12.error(`ton.getJettonInfo() TonAPI error: ${response.status}`);
|
|
7115
6997
|
return null;
|
|
7116
6998
|
}
|
|
7117
6999
|
const data = await response.json();
|
|
@@ -7129,7 +7011,7 @@ function createTonSDK(log13, db) {
|
|
|
7129
7011
|
image: data.preview || metadata.image || void 0
|
|
7130
7012
|
};
|
|
7131
7013
|
} catch (err) {
|
|
7132
|
-
|
|
7014
|
+
log12.error("ton.getJettonInfo() failed:", err);
|
|
7133
7015
|
return null;
|
|
7134
7016
|
}
|
|
7135
7017
|
},
|
|
@@ -7222,7 +7104,7 @@ function createTonSDK(log13, db) {
|
|
|
7222
7104
|
if (status === 429 || status && status >= 500) {
|
|
7223
7105
|
invalidateTonClientCache();
|
|
7224
7106
|
if (attempt < MAX_SEND_ATTEMPTS) {
|
|
7225
|
-
|
|
7107
|
+
log12.warn(
|
|
7226
7108
|
`sendJetton attempt ${attempt} failed (${status}): ${JSON.stringify(respData ?? err.message)}, retrying...`
|
|
7227
7109
|
);
|
|
7228
7110
|
await new Promise((r3) => setTimeout(r3, 1e3 * attempt));
|
|
@@ -7252,14 +7134,14 @@ function createTonSDK(log13, db) {
|
|
|
7252
7134
|
try {
|
|
7253
7135
|
const response = await tonapiFetch(`/accounts/${encodeURIComponent(ownerAddress)}/jettons`);
|
|
7254
7136
|
if (!response.ok) {
|
|
7255
|
-
|
|
7137
|
+
log12.error(`ton.getJettonWalletAddress() TonAPI error: ${response.status}`);
|
|
7256
7138
|
return null;
|
|
7257
7139
|
}
|
|
7258
7140
|
const data = await response.json();
|
|
7259
7141
|
const match = findJettonBalance(data.balances ?? [], jettonAddress);
|
|
7260
7142
|
return match ? match.wallet_address.address : null;
|
|
7261
7143
|
} catch (err) {
|
|
7262
|
-
|
|
7144
|
+
log12.error("ton.getJettonWalletAddress() failed:", err);
|
|
7263
7145
|
return null;
|
|
7264
7146
|
}
|
|
7265
7147
|
},
|
|
@@ -7436,7 +7318,7 @@ function createTonSDK(log13, db) {
|
|
|
7436
7318
|
const wallet = loadWallet();
|
|
7437
7319
|
return wallet?.publicKey ?? null;
|
|
7438
7320
|
} catch (err) {
|
|
7439
|
-
|
|
7321
|
+
log12.error("ton.getPublicKey() failed:", err);
|
|
7440
7322
|
return null;
|
|
7441
7323
|
}
|
|
7442
7324
|
},
|
|
@@ -7452,14 +7334,14 @@ function createTonSDK(log13, db) {
|
|
|
7452
7334
|
`/accounts/${encodeURIComponent(addr)}/nfts?limit=100&indirect_ownership=true`
|
|
7453
7335
|
);
|
|
7454
7336
|
if (!response.ok) {
|
|
7455
|
-
|
|
7337
|
+
log12.error(`ton.getNftItems() TonAPI error: ${response.status}`);
|
|
7456
7338
|
return [];
|
|
7457
7339
|
}
|
|
7458
7340
|
const data = await response.json();
|
|
7459
7341
|
if (!Array.isArray(data.nft_items)) return [];
|
|
7460
7342
|
return data.nft_items.filter((item) => item.trust !== "blacklist").map((item) => mapNftItem(item));
|
|
7461
7343
|
} catch (err) {
|
|
7462
|
-
|
|
7344
|
+
log12.error("ton.getNftItems() failed:", err);
|
|
7463
7345
|
return [];
|
|
7464
7346
|
}
|
|
7465
7347
|
},
|
|
@@ -7468,13 +7350,13 @@ function createTonSDK(log13, db) {
|
|
|
7468
7350
|
const response = await tonapiFetch(`/nfts/${encodeURIComponent(nftAddress)}`);
|
|
7469
7351
|
if (response.status === 404) return null;
|
|
7470
7352
|
if (!response.ok) {
|
|
7471
|
-
|
|
7353
|
+
log12.error(`ton.getNftInfo() TonAPI error: ${response.status}`);
|
|
7472
7354
|
return null;
|
|
7473
7355
|
}
|
|
7474
7356
|
const item = await response.json();
|
|
7475
7357
|
return mapNftItem(item);
|
|
7476
7358
|
} catch (err) {
|
|
7477
|
-
|
|
7359
|
+
log12.error("ton.getNftInfo() failed:", err);
|
|
7478
7360
|
return null;
|
|
7479
7361
|
}
|
|
7480
7362
|
},
|
|
@@ -7507,7 +7389,7 @@ function createTonSDK(log13, db) {
|
|
|
7507
7389
|
`/rates?tokens=${encodeURIComponent(jettonAddress)}¤cies=usd,ton`
|
|
7508
7390
|
);
|
|
7509
7391
|
if (!response.ok) {
|
|
7510
|
-
|
|
7392
|
+
log12.debug(`ton.getJettonPrice() TonAPI error: ${response.status}`);
|
|
7511
7393
|
return null;
|
|
7512
7394
|
}
|
|
7513
7395
|
const data = await response.json();
|
|
@@ -7521,7 +7403,7 @@ function createTonSDK(log13, db) {
|
|
|
7521
7403
|
change30d: rateData.diff_30d?.USD ?? null
|
|
7522
7404
|
};
|
|
7523
7405
|
} catch (err) {
|
|
7524
|
-
|
|
7406
|
+
log12.debug("ton.getJettonPrice() failed:", err);
|
|
7525
7407
|
return null;
|
|
7526
7408
|
}
|
|
7527
7409
|
},
|
|
@@ -7535,7 +7417,7 @@ function createTonSDK(log13, db) {
|
|
|
7535
7417
|
tonapiFetch(`/jettons/${encodeURIComponent(jettonAddress)}`)
|
|
7536
7418
|
]);
|
|
7537
7419
|
if (!holdersResponse.ok) {
|
|
7538
|
-
|
|
7420
|
+
log12.debug(`ton.getJettonHolders() TonAPI error: ${holdersResponse.status}`);
|
|
7539
7421
|
return [];
|
|
7540
7422
|
}
|
|
7541
7423
|
const data = await holdersResponse.json();
|
|
@@ -7555,7 +7437,7 @@ function createTonSDK(log13, db) {
|
|
|
7555
7437
|
};
|
|
7556
7438
|
});
|
|
7557
7439
|
} catch (err) {
|
|
7558
|
-
|
|
7440
|
+
log12.debug("ton.getJettonHolders() failed:", err);
|
|
7559
7441
|
return [];
|
|
7560
7442
|
}
|
|
7561
7443
|
},
|
|
@@ -7627,13 +7509,13 @@ function createTonSDK(log13, db) {
|
|
|
7627
7509
|
holders: holdersCount
|
|
7628
7510
|
};
|
|
7629
7511
|
} catch (err) {
|
|
7630
|
-
|
|
7512
|
+
log12.debug("ton.getJettonHistory() failed:", err);
|
|
7631
7513
|
return null;
|
|
7632
7514
|
}
|
|
7633
7515
|
},
|
|
7634
7516
|
// ─── Sub-namespaces ───────────────────────────────────────────
|
|
7635
|
-
dex: Object.freeze(createDexSDK(
|
|
7636
|
-
dns: Object.freeze(createDnsSDK(
|
|
7517
|
+
dex: Object.freeze(createDexSDK(log12)),
|
|
7518
|
+
dns: Object.freeze(createDnsSDK(log12))
|
|
7637
7519
|
};
|
|
7638
7520
|
}
|
|
7639
7521
|
function mapNftItem(item) {
|
|
@@ -7686,7 +7568,7 @@ async function getApi() {
|
|
|
7686
7568
|
}
|
|
7687
7569
|
|
|
7688
7570
|
// src/sdk/telegram-messages.ts
|
|
7689
|
-
function createTelegramMessagesSDK(bridge,
|
|
7571
|
+
function createTelegramMessagesSDK(bridge, log12) {
|
|
7690
7572
|
function requireBridge2() {
|
|
7691
7573
|
requireBridge(bridge);
|
|
7692
7574
|
}
|
|
@@ -7793,7 +7675,7 @@ function createTelegramMessagesSDK(bridge, log13) {
|
|
|
7793
7675
|
return (resultData.messages ?? []).map(toSimpleMessage);
|
|
7794
7676
|
} catch (err) {
|
|
7795
7677
|
if (err instanceof PluginSDKError) throw err;
|
|
7796
|
-
|
|
7678
|
+
log12.error("telegram.searchMessages() failed:", err);
|
|
7797
7679
|
return [];
|
|
7798
7680
|
}
|
|
7799
7681
|
},
|
|
@@ -8036,7 +7918,7 @@ function createTelegramMessagesSDK(bridge, log13) {
|
|
|
8036
7918
|
return messages;
|
|
8037
7919
|
} catch (err) {
|
|
8038
7920
|
if (err instanceof PluginSDKError) throw err;
|
|
8039
|
-
|
|
7921
|
+
log12.error("telegram.getScheduledMessages() failed:", err);
|
|
8040
7922
|
return [];
|
|
8041
7923
|
}
|
|
8042
7924
|
},
|
|
@@ -8097,7 +7979,7 @@ function createTelegramMessagesSDK(bridge, log13) {
|
|
|
8097
7979
|
}
|
|
8098
7980
|
|
|
8099
7981
|
// src/sdk/telegram-social.ts
|
|
8100
|
-
function createTelegramSocialSDK(bridge,
|
|
7982
|
+
function createTelegramSocialSDK(bridge, log12) {
|
|
8101
7983
|
function requireBridge2() {
|
|
8102
7984
|
requireBridge(bridge);
|
|
8103
7985
|
}
|
|
@@ -8172,7 +8054,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8172
8054
|
return null;
|
|
8173
8055
|
} catch (err) {
|
|
8174
8056
|
if (err instanceof PluginSDKError) throw err;
|
|
8175
|
-
|
|
8057
|
+
log12.error("telegram.getChatInfo() failed:", err);
|
|
8176
8058
|
return null;
|
|
8177
8059
|
}
|
|
8178
8060
|
},
|
|
@@ -8286,7 +8168,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8286
8168
|
});
|
|
8287
8169
|
} catch (err) {
|
|
8288
8170
|
if (err instanceof PluginSDKError) throw err;
|
|
8289
|
-
|
|
8171
|
+
log12.error("telegram.getParticipants() failed:", err);
|
|
8290
8172
|
return [];
|
|
8291
8173
|
}
|
|
8292
8174
|
},
|
|
@@ -8648,7 +8530,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8648
8530
|
}));
|
|
8649
8531
|
} catch (err) {
|
|
8650
8532
|
if (err instanceof PluginSDKError) throw err;
|
|
8651
|
-
|
|
8533
|
+
log12.error("telegram.getDialogs() failed:", err);
|
|
8652
8534
|
return [];
|
|
8653
8535
|
}
|
|
8654
8536
|
},
|
|
@@ -8662,7 +8544,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8662
8544
|
return messages.map(toSimpleMessage);
|
|
8663
8545
|
} catch (err) {
|
|
8664
8546
|
if (err instanceof PluginSDKError) throw err;
|
|
8665
|
-
|
|
8547
|
+
log12.error("telegram.getHistory() failed:", err);
|
|
8666
8548
|
return [];
|
|
8667
8549
|
}
|
|
8668
8550
|
},
|
|
@@ -8693,7 +8575,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8693
8575
|
}));
|
|
8694
8576
|
} catch (err) {
|
|
8695
8577
|
if (err instanceof PluginSDKError) throw err;
|
|
8696
|
-
|
|
8578
|
+
log12.error("telegram.getStarsTransactions() failed:", err);
|
|
8697
8579
|
return [];
|
|
8698
8580
|
}
|
|
8699
8581
|
},
|
|
@@ -8798,7 +8680,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8798
8680
|
};
|
|
8799
8681
|
} catch (err) {
|
|
8800
8682
|
if (err instanceof PluginSDKError) throw err;
|
|
8801
|
-
|
|
8683
|
+
log12.error("telegram.getCollectibleInfo() failed:", err);
|
|
8802
8684
|
return null;
|
|
8803
8685
|
}
|
|
8804
8686
|
},
|
|
@@ -8836,7 +8718,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8836
8718
|
} catch (err) {
|
|
8837
8719
|
if (err.errorMessage === "STARGIFT_SLUG_INVALID") return null;
|
|
8838
8720
|
if (err instanceof PluginSDKError) throw err;
|
|
8839
|
-
|
|
8721
|
+
log12.error("telegram.getUniqueGift() failed:", err);
|
|
8840
8722
|
return null;
|
|
8841
8723
|
}
|
|
8842
8724
|
},
|
|
@@ -8862,7 +8744,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8862
8744
|
} catch (err) {
|
|
8863
8745
|
if (err.errorMessage === "STARGIFT_SLUG_INVALID") return null;
|
|
8864
8746
|
if (err instanceof PluginSDKError) throw err;
|
|
8865
|
-
|
|
8747
|
+
log12.error("telegram.getUniqueGiftValue() failed:", err);
|
|
8866
8748
|
return null;
|
|
8867
8749
|
}
|
|
8868
8750
|
},
|
|
@@ -8897,13 +8779,13 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8897
8779
|
const client = getClient2();
|
|
8898
8780
|
const { Api: Api4, helpers } = await import("telegram");
|
|
8899
8781
|
const { CustomFile } = await import("telegram/client/uploads.js");
|
|
8900
|
-
const { readFileSync:
|
|
8782
|
+
const { readFileSync: readFileSync7, statSync: statSync2 } = await import("fs");
|
|
8901
8783
|
const { basename: basename2 } = await import("path");
|
|
8902
8784
|
const { resolve: resolve2, normalize: normalize2 } = await import("path");
|
|
8903
|
-
const { homedir:
|
|
8785
|
+
const { homedir: homedir2 } = await import("os");
|
|
8904
8786
|
const { realpathSync } = await import("fs");
|
|
8905
8787
|
const filePath = realpathSync(resolve2(normalize2(mediaPath)));
|
|
8906
|
-
const home =
|
|
8788
|
+
const home = homedir2();
|
|
8907
8789
|
const teletonWorkspace = `${home}/.teleton/workspace/`;
|
|
8908
8790
|
const allowedPrefixes = [
|
|
8909
8791
|
"/tmp/",
|
|
@@ -8922,7 +8804,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8922
8804
|
}
|
|
8923
8805
|
const fileName = basename2(filePath);
|
|
8924
8806
|
const fileSize = statSync2(filePath).size;
|
|
8925
|
-
const fileBuffer =
|
|
8807
|
+
const fileBuffer = readFileSync7(filePath);
|
|
8926
8808
|
const isVideo = filePath.toLowerCase().match(/\.(mp4|mov|avi|webm|mkv|m4v)$/);
|
|
8927
8809
|
const customFile = new CustomFile(fileName, fileSize, filePath, fileBuffer);
|
|
8928
8810
|
const uploadedFile = await client.uploadFile({
|
|
@@ -8973,7 +8855,7 @@ function createTelegramSocialSDK(bridge, log13) {
|
|
|
8973
8855
|
}
|
|
8974
8856
|
|
|
8975
8857
|
// src/sdk/telegram.ts
|
|
8976
|
-
function createTelegramSDK(bridge,
|
|
8858
|
+
function createTelegramSDK(bridge, log12) {
|
|
8977
8859
|
function requireBridge2() {
|
|
8978
8860
|
requireBridge(bridge);
|
|
8979
8861
|
}
|
|
@@ -9077,7 +8959,7 @@ function createTelegramSDK(bridge, log13) {
|
|
|
9077
8959
|
timestamp: m.timestamp
|
|
9078
8960
|
}));
|
|
9079
8961
|
} catch (err) {
|
|
9080
|
-
|
|
8962
|
+
log12.error("telegram.getMessages() failed:", err);
|
|
9081
8963
|
return [];
|
|
9082
8964
|
}
|
|
9083
8965
|
},
|
|
@@ -9099,7 +8981,7 @@ function createTelegramSDK(bridge, log13) {
|
|
|
9099
8981
|
return bridge.isAvailable();
|
|
9100
8982
|
},
|
|
9101
8983
|
getRawClient() {
|
|
9102
|
-
|
|
8984
|
+
log12.warn("getRawClient() called \u2014 this bypasses SDK sandbox guarantees");
|
|
9103
8985
|
if (!bridge.isAvailable()) return null;
|
|
9104
8986
|
try {
|
|
9105
8987
|
return bridge.getClient().getClient();
|
|
@@ -9108,23 +8990,23 @@ function createTelegramSDK(bridge, log13) {
|
|
|
9108
8990
|
}
|
|
9109
8991
|
},
|
|
9110
8992
|
// Spread extended methods from sub-modules
|
|
9111
|
-
...createTelegramMessagesSDK(bridge,
|
|
9112
|
-
...createTelegramSocialSDK(bridge,
|
|
8993
|
+
...createTelegramMessagesSDK(bridge, log12),
|
|
8994
|
+
...createTelegramSocialSDK(bridge, log12)
|
|
9113
8995
|
};
|
|
9114
8996
|
}
|
|
9115
8997
|
|
|
9116
8998
|
// src/sdk/secrets.ts
|
|
9117
|
-
import { readFileSync as
|
|
9118
|
-
import { join as
|
|
9119
|
-
var SECRETS_DIR =
|
|
8999
|
+
import { readFileSync as readFileSync3, writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
9000
|
+
import { join as join2 } from "path";
|
|
9001
|
+
var SECRETS_DIR = join2(TELETON_ROOT, "plugins", "data");
|
|
9120
9002
|
function getSecretsPath(pluginName) {
|
|
9121
|
-
return
|
|
9003
|
+
return join2(SECRETS_DIR, `${pluginName}.secrets.json`);
|
|
9122
9004
|
}
|
|
9123
9005
|
function readSecretsFile(pluginName) {
|
|
9124
9006
|
const filePath = getSecretsPath(pluginName);
|
|
9125
9007
|
try {
|
|
9126
|
-
if (!
|
|
9127
|
-
const raw =
|
|
9008
|
+
if (!existsSync4(filePath)) return {};
|
|
9009
|
+
const raw = readFileSync3(filePath, "utf-8");
|
|
9128
9010
|
const parsed = JSON.parse(raw);
|
|
9129
9011
|
if (typeof parsed !== "object" || parsed === null) return {};
|
|
9130
9012
|
return parsed;
|
|
@@ -9133,40 +9015,40 @@ function readSecretsFile(pluginName) {
|
|
|
9133
9015
|
}
|
|
9134
9016
|
}
|
|
9135
9017
|
function writePluginSecret(pluginName, key, value) {
|
|
9136
|
-
|
|
9018
|
+
mkdirSync2(SECRETS_DIR, { recursive: true, mode: 448 });
|
|
9137
9019
|
const filePath = getSecretsPath(pluginName);
|
|
9138
9020
|
const existing = readSecretsFile(pluginName);
|
|
9139
9021
|
existing[key] = value;
|
|
9140
|
-
|
|
9022
|
+
writeFileSync(filePath, JSON.stringify(existing, null, 2), { mode: 384 });
|
|
9141
9023
|
}
|
|
9142
9024
|
function deletePluginSecret(pluginName, key) {
|
|
9143
9025
|
const existing = readSecretsFile(pluginName);
|
|
9144
9026
|
if (!(key in existing)) return false;
|
|
9145
9027
|
delete existing[key];
|
|
9146
9028
|
const filePath = getSecretsPath(pluginName);
|
|
9147
|
-
|
|
9029
|
+
writeFileSync(filePath, JSON.stringify(existing, null, 2), { mode: 384 });
|
|
9148
9030
|
return true;
|
|
9149
9031
|
}
|
|
9150
9032
|
function listPluginSecretKeys(pluginName) {
|
|
9151
9033
|
return Object.keys(readSecretsFile(pluginName));
|
|
9152
9034
|
}
|
|
9153
|
-
function createSecretsSDK(pluginName, pluginConfig,
|
|
9035
|
+
function createSecretsSDK(pluginName, pluginConfig, log12) {
|
|
9154
9036
|
const envPrefix = pluginName.replace(/-/g, "_").toUpperCase();
|
|
9155
9037
|
function get(key) {
|
|
9156
9038
|
const envKey = `${envPrefix}_${key.toUpperCase()}`;
|
|
9157
9039
|
const envValue = process.env[envKey];
|
|
9158
9040
|
if (envValue) {
|
|
9159
|
-
|
|
9041
|
+
log12.debug(`Secret "${key}" resolved from env var ${envKey}`);
|
|
9160
9042
|
return envValue;
|
|
9161
9043
|
}
|
|
9162
9044
|
const stored = readSecretsFile(pluginName);
|
|
9163
9045
|
if (key in stored && stored[key]) {
|
|
9164
|
-
|
|
9046
|
+
log12.debug(`Secret "${key}" resolved from secrets store`);
|
|
9165
9047
|
return stored[key];
|
|
9166
9048
|
}
|
|
9167
9049
|
const configValue = pluginConfig[key];
|
|
9168
9050
|
if (configValue !== void 0 && configValue !== null) {
|
|
9169
|
-
|
|
9051
|
+
log12.debug(`Secret "${key}" resolved from pluginConfig`);
|
|
9170
9052
|
return String(configValue);
|
|
9171
9053
|
}
|
|
9172
9054
|
return void 0;
|
|
@@ -9268,7 +9150,7 @@ function createStorageSDK(db) {
|
|
|
9268
9150
|
}
|
|
9269
9151
|
|
|
9270
9152
|
// src/sdk/bot.ts
|
|
9271
|
-
function createBotSDK(router, gramjsBot, grammyBot, pluginName, manifest, rateLimiter,
|
|
9153
|
+
function createBotSDK(router, gramjsBot, grammyBot, pluginName, manifest, rateLimiter, log12) {
|
|
9272
9154
|
if (!router || !manifest || !manifest.inline && !manifest.callbacks) {
|
|
9273
9155
|
return null;
|
|
9274
9156
|
}
|
|
@@ -9291,7 +9173,7 @@ function createBotSDK(router, gramjsBot, grammyBot, pluginName, manifest, rateLi
|
|
|
9291
9173
|
},
|
|
9292
9174
|
onInlineQuery(handler) {
|
|
9293
9175
|
if (handlers.onInlineQuery) {
|
|
9294
|
-
|
|
9176
|
+
log12.warn("onInlineQuery called again \u2014 overwriting previous handler");
|
|
9295
9177
|
}
|
|
9296
9178
|
handlers.onInlineQuery = async (ctx) => {
|
|
9297
9179
|
if (rateLimiter) {
|
|
@@ -9337,7 +9219,7 @@ function createBotSDK(router, gramjsBot, grammyBot, pluginName, manifest, rateLi
|
|
|
9337
9219
|
return;
|
|
9338
9220
|
} catch (error) {
|
|
9339
9221
|
if (error?.errorMessage === "MESSAGE_NOT_MODIFIED") return;
|
|
9340
|
-
|
|
9222
|
+
log12.warn(`GramJS edit failed, falling back to Grammy: ${error?.errorMessage || error}`);
|
|
9341
9223
|
}
|
|
9342
9224
|
}
|
|
9343
9225
|
if (grammyBot) {
|
|
@@ -9350,7 +9232,7 @@ function createBotSDK(router, gramjsBot, grammyBot, pluginName, manifest, rateLi
|
|
|
9350
9232
|
});
|
|
9351
9233
|
} catch (error) {
|
|
9352
9234
|
if (error?.description?.includes("message is not modified")) return;
|
|
9353
|
-
|
|
9235
|
+
log12.error(`Failed to edit inline message: ${error?.description || error}`);
|
|
9354
9236
|
}
|
|
9355
9237
|
}
|
|
9356
9238
|
},
|
|
@@ -9409,13 +9291,13 @@ function createSafeDb(db) {
|
|
|
9409
9291
|
});
|
|
9410
9292
|
}
|
|
9411
9293
|
function createPluginSDK(deps, opts) {
|
|
9412
|
-
const
|
|
9294
|
+
const log12 = createLogger2(opts.pluginName);
|
|
9413
9295
|
const safeDb = opts.db ? createSafeDb(opts.db) : null;
|
|
9414
|
-
const ton = Object.freeze(createTonSDK(
|
|
9415
|
-
const telegram = Object.freeze(createTelegramSDK(deps.bridge,
|
|
9416
|
-
const secrets = Object.freeze(createSecretsSDK(opts.pluginName, opts.pluginConfig,
|
|
9296
|
+
const ton = Object.freeze(createTonSDK(log12, safeDb));
|
|
9297
|
+
const telegram = Object.freeze(createTelegramSDK(deps.bridge, log12));
|
|
9298
|
+
const secrets = Object.freeze(createSecretsSDK(opts.pluginName, opts.pluginConfig, log12));
|
|
9417
9299
|
const storage = safeDb ? Object.freeze(createStorageSDK(safeDb)) : null;
|
|
9418
|
-
const frozenLog = Object.freeze(
|
|
9300
|
+
const frozenLog = Object.freeze(log12);
|
|
9419
9301
|
const frozenConfig = Object.freeze(JSON.parse(JSON.stringify(opts.sanitizedConfig ?? {})));
|
|
9420
9302
|
const frozenPluginConfig = Object.freeze(JSON.parse(JSON.stringify(opts.pluginConfig ?? {})));
|
|
9421
9303
|
let cachedBot;
|
|
@@ -9446,20 +9328,20 @@ function createPluginSDK(deps, opts) {
|
|
|
9446
9328
|
},
|
|
9447
9329
|
on(hookName, handler, onOpts) {
|
|
9448
9330
|
if (!opts.hookRegistry) {
|
|
9449
|
-
|
|
9331
|
+
log12.warn(`Hook registration unavailable \u2014 sdk.on() ignored`);
|
|
9450
9332
|
return;
|
|
9451
9333
|
}
|
|
9452
9334
|
if (opts.declaredHooks) {
|
|
9453
9335
|
const declared = opts.declaredHooks.some((h2) => h2.name === hookName);
|
|
9454
9336
|
if (!declared) {
|
|
9455
|
-
|
|
9337
|
+
log12.warn(`Hook "${hookName}" not declared in manifest \u2014 registration rejected`);
|
|
9456
9338
|
return;
|
|
9457
9339
|
}
|
|
9458
9340
|
}
|
|
9459
9341
|
const rawPriority = Number(onOpts?.priority) || 0;
|
|
9460
9342
|
const clampedPriority = Math.max(-1e3, Math.min(1e3, rawPriority));
|
|
9461
9343
|
if (rawPriority !== clampedPriority) {
|
|
9462
|
-
|
|
9344
|
+
log12.debug(`Hook "${hookName}" priority ${rawPriority} clamped to ${clampedPriority}`);
|
|
9463
9345
|
}
|
|
9464
9346
|
const registered = opts.hookRegistry.register({
|
|
9465
9347
|
pluginId: opts.pluginName,
|
|
@@ -9469,7 +9351,7 @@ function createPluginSDK(deps, opts) {
|
|
|
9469
9351
|
globalPriority: opts.globalPriority ?? 0
|
|
9470
9352
|
});
|
|
9471
9353
|
if (!registered) {
|
|
9472
|
-
|
|
9354
|
+
log12.warn(
|
|
9473
9355
|
`Hook registration limit reached for plugin "${opts.pluginName}" \u2014 "${hookName}" rejected`
|
|
9474
9356
|
);
|
|
9475
9357
|
}
|
|
@@ -9588,24 +9470,24 @@ var HookRegistry = class {
|
|
|
9588
9470
|
|
|
9589
9471
|
// src/agent/tools/plugin-loader.ts
|
|
9590
9472
|
var execFileAsync = promisify(execFile);
|
|
9591
|
-
var
|
|
9592
|
-
var PLUGIN_DATA_DIR =
|
|
9473
|
+
var log9 = createLogger("PluginLoader");
|
|
9474
|
+
var PLUGIN_DATA_DIR = join3(TELETON_ROOT, "plugins", "data");
|
|
9593
9475
|
function adaptPlugin(raw, entryName, config, loadedModuleNames, sdkDeps, hookRegistry, pluginPriorities) {
|
|
9594
9476
|
let manifest = null;
|
|
9595
9477
|
if (raw.manifest) {
|
|
9596
9478
|
try {
|
|
9597
9479
|
manifest = validateManifest(raw.manifest);
|
|
9598
9480
|
} catch (err) {
|
|
9599
|
-
|
|
9481
|
+
log9.warn(
|
|
9600
9482
|
`[${entryName}] invalid manifest, ignoring: ${err instanceof Error ? err.message : err}`
|
|
9601
9483
|
);
|
|
9602
9484
|
}
|
|
9603
9485
|
}
|
|
9604
9486
|
if (!manifest) {
|
|
9605
|
-
const manifestPath =
|
|
9487
|
+
const manifestPath = join3(WORKSPACE_PATHS.PLUGINS_DIR, entryName, "manifest.json");
|
|
9606
9488
|
try {
|
|
9607
|
-
if (
|
|
9608
|
-
const diskManifest = JSON.parse(
|
|
9489
|
+
if (existsSync5(manifestPath)) {
|
|
9490
|
+
const diskManifest = JSON.parse(readFileSync4(manifestPath, "utf-8"));
|
|
9609
9491
|
if (diskManifest && typeof diskManifest.version === "string") {
|
|
9610
9492
|
manifest = {
|
|
9611
9493
|
name: entryName,
|
|
@@ -9680,7 +9562,7 @@ function adaptPlugin(raw, entryName, config, loadedModuleNames, sdkDeps, hookReg
|
|
|
9680
9562
|
},
|
|
9681
9563
|
migrate() {
|
|
9682
9564
|
try {
|
|
9683
|
-
const dbPath =
|
|
9565
|
+
const dbPath = join3(PLUGIN_DATA_DIR, `${pluginName}.db`);
|
|
9684
9566
|
pluginDb = openModuleDb(dbPath);
|
|
9685
9567
|
if (hasMigrate) {
|
|
9686
9568
|
raw.migrate?.(pluginDb);
|
|
@@ -9785,36 +9667,36 @@ function adaptPlugin(raw, entryName, config, loadedModuleNames, sdkDeps, hookReg
|
|
|
9785
9667
|
return module;
|
|
9786
9668
|
}
|
|
9787
9669
|
async function ensurePluginDeps(pluginDir, pluginEntry) {
|
|
9788
|
-
const pkgJson =
|
|
9789
|
-
const lockfile =
|
|
9790
|
-
const nodeModules =
|
|
9791
|
-
if (!
|
|
9792
|
-
if (!
|
|
9793
|
-
|
|
9670
|
+
const pkgJson = join3(pluginDir, "package.json");
|
|
9671
|
+
const lockfile = join3(pluginDir, "package-lock.json");
|
|
9672
|
+
const nodeModules = join3(pluginDir, "node_modules");
|
|
9673
|
+
if (!existsSync5(pkgJson)) return;
|
|
9674
|
+
if (!existsSync5(lockfile)) {
|
|
9675
|
+
log9.warn(
|
|
9794
9676
|
`[${pluginEntry}] package.json without package-lock.json \u2014 skipping (lockfile required)`
|
|
9795
9677
|
);
|
|
9796
9678
|
return;
|
|
9797
9679
|
}
|
|
9798
|
-
if (
|
|
9799
|
-
const marker =
|
|
9800
|
-
if (
|
|
9680
|
+
if (existsSync5(nodeModules)) {
|
|
9681
|
+
const marker = join3(nodeModules, ".package-lock.json");
|
|
9682
|
+
if (existsSync5(marker) && statSync(marker).mtimeMs >= statSync(lockfile).mtimeMs) return;
|
|
9801
9683
|
}
|
|
9802
|
-
|
|
9684
|
+
log9.info(`[${pluginEntry}] Installing dependencies...`);
|
|
9803
9685
|
try {
|
|
9804
9686
|
await execFileAsync("npm", ["ci", "--ignore-scripts", "--no-audit", "--no-fund"], {
|
|
9805
9687
|
cwd: pluginDir,
|
|
9806
9688
|
timeout: 6e4,
|
|
9807
9689
|
env: { ...process.env, NODE_ENV: "production" }
|
|
9808
9690
|
});
|
|
9809
|
-
|
|
9691
|
+
log9.info(`[${pluginEntry}] Dependencies installed`);
|
|
9810
9692
|
} catch (err) {
|
|
9811
|
-
|
|
9693
|
+
log9.error(`[${pluginEntry}] Failed to install deps: ${String(err).slice(0, 300)}`);
|
|
9812
9694
|
}
|
|
9813
9695
|
}
|
|
9814
9696
|
async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
9815
9697
|
const hookRegistry = new HookRegistry();
|
|
9816
9698
|
const pluginsDir = WORKSPACE_PATHS.PLUGINS_DIR;
|
|
9817
|
-
if (!
|
|
9699
|
+
if (!existsSync5(pluginsDir)) {
|
|
9818
9700
|
return { modules: [], hookRegistry };
|
|
9819
9701
|
}
|
|
9820
9702
|
let pluginPriorities = /* @__PURE__ */ new Map();
|
|
@@ -9830,15 +9712,15 @@ async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
|
9830
9712
|
const pluginPaths = [];
|
|
9831
9713
|
for (const entry of entries) {
|
|
9832
9714
|
if (entry === "data") continue;
|
|
9833
|
-
const entryPath =
|
|
9715
|
+
const entryPath = join3(pluginsDir, entry);
|
|
9834
9716
|
let modulePath = null;
|
|
9835
9717
|
try {
|
|
9836
9718
|
const stat = statSync(entryPath);
|
|
9837
9719
|
if (stat.isFile() && entry.endsWith(".js")) {
|
|
9838
9720
|
modulePath = entryPath;
|
|
9839
9721
|
} else if (stat.isDirectory()) {
|
|
9840
|
-
const indexPath =
|
|
9841
|
-
if (
|
|
9722
|
+
const indexPath = join3(entryPath, "index.js");
|
|
9723
|
+
if (existsSync5(indexPath)) {
|
|
9842
9724
|
modulePath = indexPath;
|
|
9843
9725
|
}
|
|
9844
9726
|
}
|
|
@@ -9850,7 +9732,7 @@ async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
|
9850
9732
|
}
|
|
9851
9733
|
}
|
|
9852
9734
|
await Promise.allSettled(
|
|
9853
|
-
pluginPaths.filter(({ path }) => path.endsWith("index.js")).map(({ entry }) => ensurePluginDeps(
|
|
9735
|
+
pluginPaths.filter(({ path }) => path.endsWith("index.js")).map(({ entry }) => ensurePluginDeps(join3(pluginsDir, entry), entry))
|
|
9854
9736
|
);
|
|
9855
9737
|
const loadResults = await Promise.allSettled(
|
|
9856
9738
|
pluginPaths.map(async ({ entry, path }) => {
|
|
@@ -9861,7 +9743,7 @@ async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
|
9861
9743
|
);
|
|
9862
9744
|
for (const result of loadResults) {
|
|
9863
9745
|
if (result.status === "rejected") {
|
|
9864
|
-
|
|
9746
|
+
log9.error(
|
|
9865
9747
|
`Plugin failed to load: ${result.reason instanceof Error ? result.reason.message : result.reason}`
|
|
9866
9748
|
);
|
|
9867
9749
|
continue;
|
|
@@ -9869,7 +9751,7 @@ async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
|
9869
9751
|
const { entry, mod } = result.value;
|
|
9870
9752
|
try {
|
|
9871
9753
|
if (!mod.tools || typeof mod.tools !== "function" && !Array.isArray(mod.tools)) {
|
|
9872
|
-
|
|
9754
|
+
log9.warn(`Plugin "${entry}": no 'tools' array or function exported, skipping`);
|
|
9873
9755
|
continue;
|
|
9874
9756
|
}
|
|
9875
9757
|
const adapted = adaptPlugin(
|
|
@@ -9882,21 +9764,21 @@ async function loadEnhancedPlugins(config, loadedModuleNames, sdkDeps, db) {
|
|
|
9882
9764
|
pluginPriorities
|
|
9883
9765
|
);
|
|
9884
9766
|
if (loadedNames.has(adapted.name)) {
|
|
9885
|
-
|
|
9767
|
+
log9.warn(`Plugin "${adapted.name}" already loaded, skipping duplicate from "${entry}"`);
|
|
9886
9768
|
continue;
|
|
9887
9769
|
}
|
|
9888
9770
|
loadedNames.add(adapted.name);
|
|
9889
9771
|
modules.push(adapted);
|
|
9890
9772
|
} catch (err) {
|
|
9891
|
-
|
|
9773
|
+
log9.error(`Plugin "${entry}" failed to adapt: ${err instanceof Error ? err.message : err}`);
|
|
9892
9774
|
}
|
|
9893
9775
|
}
|
|
9894
9776
|
return { modules, hookRegistry };
|
|
9895
9777
|
}
|
|
9896
9778
|
|
|
9897
9779
|
// src/config/configurable-keys.ts
|
|
9898
|
-
import { readFileSync as
|
|
9899
|
-
import { parse
|
|
9780
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, existsSync as existsSync6 } from "fs";
|
|
9781
|
+
import { parse, stringify } from "yaml";
|
|
9900
9782
|
var noValidation = () => void 0;
|
|
9901
9783
|
var identity = (v) => v;
|
|
9902
9784
|
var nonEmpty = (v) => v.length > 0 ? void 0 : "Must not be empty";
|
|
@@ -10515,11 +10397,11 @@ function deleteNestedValue(obj, path) {
|
|
|
10515
10397
|
}
|
|
10516
10398
|
function readRawConfig(configPath) {
|
|
10517
10399
|
const fullPath = expandPath(configPath);
|
|
10518
|
-
if (!
|
|
10400
|
+
if (!existsSync6(fullPath)) {
|
|
10519
10401
|
throw new Error(`Config file not found: ${fullPath}
|
|
10520
10402
|
Run 'teleton setup' to create one.`);
|
|
10521
10403
|
}
|
|
10522
|
-
const raw =
|
|
10404
|
+
const raw = parse(readFileSync5(fullPath, "utf-8"));
|
|
10523
10405
|
if (!raw || typeof raw !== "object") {
|
|
10524
10406
|
throw new Error(`Invalid config file: ${fullPath}`);
|
|
10525
10407
|
}
|
|
@@ -10535,26 +10417,26 @@ function writeRawConfig(raw, configPath) {
|
|
|
10535
10417
|
raw.meta = raw.meta ?? {};
|
|
10536
10418
|
raw.meta.last_modified_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
10537
10419
|
const fullPath = expandPath(configPath);
|
|
10538
|
-
|
|
10420
|
+
writeFileSync2(fullPath, stringify(raw), { encoding: "utf-8", mode: 384 });
|
|
10539
10421
|
}
|
|
10540
10422
|
|
|
10541
10423
|
// src/ton-proxy/manager.ts
|
|
10542
10424
|
import { spawn, execSync } from "child_process";
|
|
10543
10425
|
import {
|
|
10544
|
-
existsSync as
|
|
10426
|
+
existsSync as existsSync7,
|
|
10545
10427
|
chmodSync,
|
|
10546
10428
|
createWriteStream,
|
|
10547
|
-
readFileSync as
|
|
10548
|
-
writeFileSync as
|
|
10429
|
+
readFileSync as readFileSync6,
|
|
10430
|
+
writeFileSync as writeFileSync3,
|
|
10549
10431
|
unlinkSync
|
|
10550
10432
|
} from "fs";
|
|
10551
10433
|
import { mkdir } from "fs/promises";
|
|
10552
|
-
import { join as
|
|
10434
|
+
import { join as join4 } from "path";
|
|
10553
10435
|
import { pipeline } from "stream/promises";
|
|
10554
|
-
var
|
|
10436
|
+
var log10 = createLogger("TonProxy");
|
|
10555
10437
|
var GITHUB_REPO = "xssnick/Tonutils-Proxy";
|
|
10556
|
-
var BINARY_DIR =
|
|
10557
|
-
var PID_FILE =
|
|
10438
|
+
var BINARY_DIR = join4(TELETON_ROOT, "bin");
|
|
10439
|
+
var PID_FILE = join4(TELETON_ROOT, "ton-proxy.pid");
|
|
10558
10440
|
var HEALTH_CHECK_INTERVAL_MS = 3e4;
|
|
10559
10441
|
var HEALTH_CHECK_TIMEOUT_MS = 5e3;
|
|
10560
10442
|
var KILL_GRACE_MS = 5e3;
|
|
@@ -10570,11 +10452,11 @@ var TonProxyManager = class {
|
|
|
10570
10452
|
/** Resolve the binary path — user-specified or auto-detected */
|
|
10571
10453
|
getBinaryPath() {
|
|
10572
10454
|
if (this.config.binary_path) return this.config.binary_path;
|
|
10573
|
-
return
|
|
10455
|
+
return join4(BINARY_DIR, getBinaryName());
|
|
10574
10456
|
}
|
|
10575
10457
|
/** Check if the binary exists on disk */
|
|
10576
10458
|
isInstalled() {
|
|
10577
|
-
return
|
|
10459
|
+
return existsSync7(this.getBinaryPath());
|
|
10578
10460
|
}
|
|
10579
10461
|
/** Whether the proxy process is currently running */
|
|
10580
10462
|
isRunning() {
|
|
@@ -10586,7 +10468,7 @@ var TonProxyManager = class {
|
|
|
10586
10468
|
*/
|
|
10587
10469
|
async install() {
|
|
10588
10470
|
const binaryName = getBinaryName();
|
|
10589
|
-
|
|
10471
|
+
log10.info(`Downloading TON Proxy binary (${binaryName})...`);
|
|
10590
10472
|
await mkdir(BINARY_DIR, { recursive: true });
|
|
10591
10473
|
const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
|
|
10592
10474
|
const releaseRes = await fetch(releaseUrl, {
|
|
@@ -10598,7 +10480,7 @@ var TonProxyManager = class {
|
|
|
10598
10480
|
const release = await releaseRes.json();
|
|
10599
10481
|
const tag = release.tag_name;
|
|
10600
10482
|
const downloadUrl = `https://github.com/${GITHUB_REPO}/releases/download/${tag}/${binaryName}`;
|
|
10601
|
-
|
|
10483
|
+
log10.info(`Downloading ${downloadUrl}`);
|
|
10602
10484
|
const res = await fetch(downloadUrl);
|
|
10603
10485
|
if (!res.ok || !res.body) {
|
|
10604
10486
|
throw new Error(`Download failed: ${res.status} ${res.statusText}`);
|
|
@@ -10607,17 +10489,17 @@ var TonProxyManager = class {
|
|
|
10607
10489
|
const fileStream = createWriteStream(dest);
|
|
10608
10490
|
await pipeline(res.body, fileStream);
|
|
10609
10491
|
chmodSync(dest, 493);
|
|
10610
|
-
|
|
10492
|
+
log10.info(`TON Proxy installed: ${dest} (${tag})`);
|
|
10611
10493
|
}
|
|
10612
10494
|
/** Kill any orphan proxy process from a previous session */
|
|
10613
10495
|
killOrphan() {
|
|
10614
|
-
if (
|
|
10496
|
+
if (existsSync7(PID_FILE)) {
|
|
10615
10497
|
try {
|
|
10616
|
-
const pid = parseInt(
|
|
10498
|
+
const pid = parseInt(readFileSync6(PID_FILE, "utf-8").trim(), 10);
|
|
10617
10499
|
if (pid && !isNaN(pid)) {
|
|
10618
10500
|
try {
|
|
10619
10501
|
process.kill(pid, 0);
|
|
10620
|
-
|
|
10502
|
+
log10.warn(`Killing orphan TON Proxy (PID ${pid}) from previous session`);
|
|
10621
10503
|
process.kill(pid, "SIGTERM");
|
|
10622
10504
|
} catch {
|
|
10623
10505
|
}
|
|
@@ -10634,7 +10516,7 @@ var TonProxyManager = class {
|
|
|
10634
10516
|
const pidMatch = out.match(/pid=(\d+)/);
|
|
10635
10517
|
if (pidMatch) {
|
|
10636
10518
|
const pid = parseInt(pidMatch[1], 10);
|
|
10637
|
-
|
|
10519
|
+
log10.warn(`Port ${this.config.port} occupied by PID ${pid}, killing it`);
|
|
10638
10520
|
try {
|
|
10639
10521
|
process.kill(pid, "SIGTERM");
|
|
10640
10522
|
} catch {
|
|
@@ -10647,22 +10529,22 @@ var TonProxyManager = class {
|
|
|
10647
10529
|
/** Write PID to file for orphan detection */
|
|
10648
10530
|
writePidFile(pid) {
|
|
10649
10531
|
try {
|
|
10650
|
-
|
|
10532
|
+
writeFileSync3(PID_FILE, String(pid), { mode: 384 });
|
|
10651
10533
|
} catch {
|
|
10652
|
-
|
|
10534
|
+
log10.warn("Failed to write TON Proxy PID file");
|
|
10653
10535
|
}
|
|
10654
10536
|
}
|
|
10655
10537
|
/** Remove PID file */
|
|
10656
10538
|
removePidFile() {
|
|
10657
10539
|
try {
|
|
10658
|
-
if (
|
|
10540
|
+
if (existsSync7(PID_FILE)) unlinkSync(PID_FILE);
|
|
10659
10541
|
} catch {
|
|
10660
10542
|
}
|
|
10661
10543
|
}
|
|
10662
10544
|
/** Start the proxy process */
|
|
10663
10545
|
async start() {
|
|
10664
10546
|
if (this.isRunning()) {
|
|
10665
|
-
|
|
10547
|
+
log10.warn("TON Proxy is already running");
|
|
10666
10548
|
return;
|
|
10667
10549
|
}
|
|
10668
10550
|
this.restartCount = 0;
|
|
@@ -10673,7 +10555,7 @@ var TonProxyManager = class {
|
|
|
10673
10555
|
}
|
|
10674
10556
|
const binaryPath = this.getBinaryPath();
|
|
10675
10557
|
const port = String(this.config.port);
|
|
10676
|
-
|
|
10558
|
+
log10.info(`Starting TON Proxy on 127.0.0.1:${port}`);
|
|
10677
10559
|
this.process = spawn(binaryPath, ["-addr", `127.0.0.1:${port}`], {
|
|
10678
10560
|
cwd: BINARY_DIR,
|
|
10679
10561
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -10681,24 +10563,24 @@ var TonProxyManager = class {
|
|
|
10681
10563
|
});
|
|
10682
10564
|
this.process.stdout?.on("data", (chunk) => {
|
|
10683
10565
|
const line = chunk.toString().trim();
|
|
10684
|
-
if (line)
|
|
10566
|
+
if (line) log10.debug(`[proxy] ${line}`);
|
|
10685
10567
|
});
|
|
10686
10568
|
this.process.stderr?.on("data", (chunk) => {
|
|
10687
10569
|
const line = chunk.toString().trim();
|
|
10688
|
-
if (line)
|
|
10570
|
+
if (line) log10.warn(`[proxy:err] ${line}`);
|
|
10689
10571
|
});
|
|
10690
10572
|
this.process.on("exit", (code, signal) => {
|
|
10691
|
-
|
|
10573
|
+
log10.info(`TON Proxy exited (code=${code}, signal=${signal})`);
|
|
10692
10574
|
this.process = null;
|
|
10693
10575
|
this.removePidFile();
|
|
10694
10576
|
if (code !== 0 && code !== null && this.restartCount < this.maxRestarts) {
|
|
10695
10577
|
this.restartCount++;
|
|
10696
|
-
|
|
10697
|
-
this.start().catch((err) =>
|
|
10578
|
+
log10.warn(`Auto-restarting TON Proxy (attempt ${this.restartCount}/${this.maxRestarts})`);
|
|
10579
|
+
this.start().catch((err) => log10.error({ err }, "Failed to auto-restart TON Proxy"));
|
|
10698
10580
|
}
|
|
10699
10581
|
});
|
|
10700
10582
|
this.process.on("error", (err) => {
|
|
10701
|
-
|
|
10583
|
+
log10.error({ err }, "TON Proxy process error");
|
|
10702
10584
|
this.process = null;
|
|
10703
10585
|
});
|
|
10704
10586
|
this.startHealthCheck();
|
|
@@ -10716,14 +10598,14 @@ var TonProxyManager = class {
|
|
|
10716
10598
|
});
|
|
10717
10599
|
});
|
|
10718
10600
|
if (this.process?.pid) this.writePidFile(this.process.pid);
|
|
10719
|
-
|
|
10601
|
+
log10.info(`TON Proxy running on 127.0.0.1:${port} (PID ${this.process?.pid})`);
|
|
10720
10602
|
}
|
|
10721
10603
|
/** Stop the proxy process gracefully */
|
|
10722
10604
|
async stop() {
|
|
10723
10605
|
this.stopHealthCheck();
|
|
10724
10606
|
if (!this.process) return;
|
|
10725
10607
|
this.maxRestarts = 0;
|
|
10726
|
-
|
|
10608
|
+
log10.info("Stopping TON Proxy...");
|
|
10727
10609
|
return new Promise((resolve2) => {
|
|
10728
10610
|
if (!this.process) {
|
|
10729
10611
|
resolve2();
|
|
@@ -10731,7 +10613,7 @@ var TonProxyManager = class {
|
|
|
10731
10613
|
}
|
|
10732
10614
|
const forceKill = setTimeout(() => {
|
|
10733
10615
|
if (this.process) {
|
|
10734
|
-
|
|
10616
|
+
log10.warn("TON Proxy did not exit gracefully, sending SIGKILL");
|
|
10735
10617
|
this.process.kill("SIGKILL");
|
|
10736
10618
|
}
|
|
10737
10619
|
}, KILL_GRACE_MS);
|
|
@@ -10750,10 +10632,10 @@ var TonProxyManager = class {
|
|
|
10750
10632
|
await this.stop();
|
|
10751
10633
|
}
|
|
10752
10634
|
const binaryPath = this.getBinaryPath();
|
|
10753
|
-
if (
|
|
10635
|
+
if (existsSync7(binaryPath)) {
|
|
10754
10636
|
const { unlink } = await import("fs/promises");
|
|
10755
10637
|
await unlink(binaryPath);
|
|
10756
|
-
|
|
10638
|
+
log10.info(`TON Proxy binary removed: ${binaryPath}`);
|
|
10757
10639
|
}
|
|
10758
10640
|
}
|
|
10759
10641
|
/** Get proxy status for WebUI / tools */
|
|
@@ -10787,7 +10669,7 @@ var TonProxyManager = class {
|
|
|
10787
10669
|
}).catch(() => null);
|
|
10788
10670
|
clearTimeout(timeout);
|
|
10789
10671
|
if (!res) {
|
|
10790
|
-
|
|
10672
|
+
log10.warn("TON Proxy health check failed (no response)");
|
|
10791
10673
|
}
|
|
10792
10674
|
} catch {
|
|
10793
10675
|
}
|
|
@@ -10844,7 +10726,7 @@ var tonProxyStatusExecutor = async () => {
|
|
|
10844
10726
|
};
|
|
10845
10727
|
|
|
10846
10728
|
// src/ton-proxy/module.ts
|
|
10847
|
-
var
|
|
10729
|
+
var log11 = createLogger("TonProxyModule");
|
|
10848
10730
|
var manager = null;
|
|
10849
10731
|
function getTonProxyManager() {
|
|
10850
10732
|
return manager;
|
|
@@ -10871,9 +10753,9 @@ var tonProxyModule = {
|
|
|
10871
10753
|
setProxyManager(manager);
|
|
10872
10754
|
try {
|
|
10873
10755
|
await manager.start();
|
|
10874
|
-
|
|
10756
|
+
log11.info(`TON Proxy started on port ${proxyConfig.port}`);
|
|
10875
10757
|
} catch (err) {
|
|
10876
|
-
|
|
10758
|
+
log11.error({ err }, "Failed to start TON Proxy");
|
|
10877
10759
|
manager = null;
|
|
10878
10760
|
}
|
|
10879
10761
|
},
|
|
@@ -10925,9 +10807,6 @@ function setTriggersConfig(db, triggers) {
|
|
|
10925
10807
|
}
|
|
10926
10808
|
|
|
10927
10809
|
export {
|
|
10928
|
-
loadConfig,
|
|
10929
|
-
configExists,
|
|
10930
|
-
getDefaultConfigPath,
|
|
10931
10810
|
WorkspaceSecurityError,
|
|
10932
10811
|
validatePath,
|
|
10933
10812
|
validateReadPath,
|