@ebowwa/channel-telegram 1.12.6 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -44
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +3 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/restart.d.ts +7 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +29 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/commands/settings.d.ts +8 -0
- package/dist/commands/settings.d.ts.map +1 -0
- package/dist/commands/settings.js +16 -0
- package/dist/commands/settings.js.map +1 -0
- package/dist/index.d.ts +83 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +352 -712
- package/dist/index.js.map +1 -1
- package/package.json +8 -12
- package/src/commands/index.ts +3 -0
- package/src/commands/restart.ts +41 -0
- package/src/commands/settings.ts +24 -0
- package/src/index.ts +418 -823
- package/dist/mcp/client.d.ts +0 -50
- package/dist/mcp/client.d.ts.map +0 -1
- package/dist/mcp/client.js +0 -150
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -5
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/index.js +0 -5
- package/dist/mcp/index.js.map +0 -1
- package/src/api/fetch-retry.js +0 -96
- package/src/api/keys.js +0 -25
- package/src/commands/cancel.js +0 -120
- package/src/commands/clear.js +0 -59
- package/src/commands/doppler.js +0 -118
- package/src/commands/git.js +0 -126
- package/src/commands/help.js +0 -74
- package/src/commands/index.js +0 -65
- package/src/commands/logs.js +0 -81
- package/src/commands/pause.js +0 -133
- package/src/commands/resources.js +0 -87
- package/src/commands/resume.js +0 -95
- package/src/commands/start.js +0 -68
- package/src/commands/status.js +0 -62
- package/src/commands/tools.js +0 -67
- package/src/commands/toolsoutput.js +0 -85
- package/src/commands/types.js +0 -5
- package/src/conversation-memory.js +0 -216
- package/src/index.js +0 -736
- package/src/mcp/client.ts +0 -188
- package/src/mcp/index.ts +0 -5
- package/src/types.js +0 -5
package/src/index.js
DELETED
|
@@ -1,736 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* GLM Daemon Telegram Bot
|
|
4
|
-
*
|
|
5
|
-
* Full-featured Telegram bot with GLM-4.7 AI, git status, Doppler integration
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - GLM-4.7 AI responses via Z.AI API
|
|
9
|
-
* - 429 rate limit handling with exponential backoff
|
|
10
|
-
* - /git command for git status + GitHub auth
|
|
11
|
-
* - /doppler command for Doppler secrets status
|
|
12
|
-
* - Rolling API key support
|
|
13
|
-
*/
|
|
14
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
15
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
17
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
18
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
19
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
20
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
24
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
25
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
26
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
27
|
-
function step(op) {
|
|
28
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
29
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
30
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
31
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
32
|
-
switch (op[0]) {
|
|
33
|
-
case 0: case 1: t = op; break;
|
|
34
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
35
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
36
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
37
|
-
default:
|
|
38
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
39
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
40
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
41
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
42
|
-
if (t[2]) _.ops.pop();
|
|
43
|
-
_.trys.pop(); continue;
|
|
44
|
-
}
|
|
45
|
-
op = body.call(thisArg, _);
|
|
46
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
47
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
51
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
52
|
-
if (ar || !(i in from)) {
|
|
53
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
54
|
-
ar[i] = from[i];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
58
|
-
};
|
|
59
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
60
|
-
exports.TelegramGLMBot = void 0;
|
|
61
|
-
var node_telegram_bot_api_1 = require("node-telegram-bot-api");
|
|
62
|
-
var child_process_1 = require("child_process");
|
|
63
|
-
var structured_prompts_1 = require("@ebowwa/structured-prompts");
|
|
64
|
-
var fs_1 = require("fs");
|
|
65
|
-
var conversation_memory_1 = require("./conversation-memory");
|
|
66
|
-
var keys_1 = require("./api/keys");
|
|
67
|
-
var fetch_retry_1 = require("./api/fetch-retry");
|
|
68
|
-
var commands_1 = require("./commands");
|
|
69
|
-
var TELEGRAM_BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN || '';
|
|
70
|
-
var TELEGRAM_TEST_CHAT_ID = process.env.TELEGRAM_TEST_CHAT_ID || '';
|
|
71
|
-
var TOOLS = [
|
|
72
|
-
{
|
|
73
|
-
name: 'read_file',
|
|
74
|
-
description: 'Read a file from the filesystem. Use for checking configs, logs, code.',
|
|
75
|
-
parameters: {
|
|
76
|
-
type: 'object',
|
|
77
|
-
properties: {
|
|
78
|
-
path: { type: 'string', description: 'Absolute file path to read' }
|
|
79
|
-
},
|
|
80
|
-
required: ['path']
|
|
81
|
-
},
|
|
82
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
83
|
-
var path, content;
|
|
84
|
-
return __generator(this, function (_a) {
|
|
85
|
-
path = args.path;
|
|
86
|
-
try {
|
|
87
|
-
if (!(0, fs_1.existsSync)(path))
|
|
88
|
-
return [2 /*return*/, "File not found: ".concat(path)];
|
|
89
|
-
content = (0, fs_1.readFileSync)(path, 'utf-8');
|
|
90
|
-
return [2 /*return*/, content.length > 4000 ? content.slice(0, 4000) + '\n...[truncated]' : content];
|
|
91
|
-
}
|
|
92
|
-
catch (e) {
|
|
93
|
-
return [2 /*return*/, "Error reading file: ".concat(e.message)];
|
|
94
|
-
}
|
|
95
|
-
return [2 /*return*/];
|
|
96
|
-
});
|
|
97
|
-
}); }
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
name: 'write_file',
|
|
101
|
-
description: 'Write content to a file. Creates the file if it does not exist, overwrites if it does.',
|
|
102
|
-
parameters: {
|
|
103
|
-
type: 'object',
|
|
104
|
-
properties: {
|
|
105
|
-
path: { type: 'string', description: 'Absolute file path to write' },
|
|
106
|
-
content: { type: 'string', description: 'Content to write to the file' }
|
|
107
|
-
},
|
|
108
|
-
required: ['path', 'content']
|
|
109
|
-
},
|
|
110
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
111
|
-
var path, content;
|
|
112
|
-
return __generator(this, function (_a) {
|
|
113
|
-
path = args.path;
|
|
114
|
-
content = args.content;
|
|
115
|
-
try {
|
|
116
|
-
(0, fs_1.writeFileSync)(path, content, 'utf-8');
|
|
117
|
-
return [2 /*return*/, "Successfully wrote ".concat(content.length, " bytes to ").concat(path)];
|
|
118
|
-
}
|
|
119
|
-
catch (e) {
|
|
120
|
-
return [2 /*return*/, "Error writing file: ".concat(e.message)];
|
|
121
|
-
}
|
|
122
|
-
return [2 /*return*/];
|
|
123
|
-
});
|
|
124
|
-
}); }
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'edit_file',
|
|
128
|
-
description: 'Edit a file by replacing a specific string with new content.',
|
|
129
|
-
parameters: {
|
|
130
|
-
type: 'object',
|
|
131
|
-
properties: {
|
|
132
|
-
path: { type: 'string', description: 'Absolute file path to edit' },
|
|
133
|
-
old_string: { type: 'string', description: 'The exact text to find and replace' },
|
|
134
|
-
new_string: { type: 'string', description: 'The text to replace it with' }
|
|
135
|
-
},
|
|
136
|
-
required: ['path', 'old_string', 'new_string']
|
|
137
|
-
},
|
|
138
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
139
|
-
var path, oldStr, newStr, content, newContent;
|
|
140
|
-
return __generator(this, function (_a) {
|
|
141
|
-
path = args.path;
|
|
142
|
-
oldStr = args.old_string;
|
|
143
|
-
newStr = args.new_string;
|
|
144
|
-
try {
|
|
145
|
-
if (!(0, fs_1.existsSync)(path))
|
|
146
|
-
return [2 /*return*/, "File not found: ".concat(path)];
|
|
147
|
-
content = (0, fs_1.readFileSync)(path, 'utf-8');
|
|
148
|
-
if (!content.includes(oldStr)) {
|
|
149
|
-
return [2 /*return*/, "String not found in file. First 500 chars:\n".concat(content.slice(0, 500))];
|
|
150
|
-
}
|
|
151
|
-
newContent = content.replace(oldStr, newStr);
|
|
152
|
-
(0, fs_1.writeFileSync)(path, newContent, 'utf-8');
|
|
153
|
-
return [2 /*return*/, "Successfully edited ".concat(path)];
|
|
154
|
-
}
|
|
155
|
-
catch (e) {
|
|
156
|
-
return [2 /*return*/, "Error editing file: ".concat(e.message)];
|
|
157
|
-
}
|
|
158
|
-
return [2 /*return*/];
|
|
159
|
-
});
|
|
160
|
-
}); }
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: 'append_file',
|
|
164
|
-
description: 'Append content to the end of a file. Creates the file if it does not exist.',
|
|
165
|
-
parameters: {
|
|
166
|
-
type: 'object',
|
|
167
|
-
properties: {
|
|
168
|
-
path: { type: 'string', description: 'Absolute file path to append to' },
|
|
169
|
-
content: { type: 'string', description: 'Content to append to the file' }
|
|
170
|
-
},
|
|
171
|
-
required: ['path', 'content']
|
|
172
|
-
},
|
|
173
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
174
|
-
var path, content;
|
|
175
|
-
return __generator(this, function (_a) {
|
|
176
|
-
path = args.path;
|
|
177
|
-
content = args.content;
|
|
178
|
-
try {
|
|
179
|
-
(0, fs_1.appendFileSync)(path, content, 'utf-8');
|
|
180
|
-
return [2 /*return*/, "Successfully appended ".concat(content.length, " bytes to ").concat(path)];
|
|
181
|
-
}
|
|
182
|
-
catch (e) {
|
|
183
|
-
return [2 /*return*/, "Error appending to file: ".concat(e.message)];
|
|
184
|
-
}
|
|
185
|
-
return [2 /*return*/];
|
|
186
|
-
});
|
|
187
|
-
}); }
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
name: 'list_dir',
|
|
191
|
-
description: 'List contents of a directory. Shows files and subdirectories.',
|
|
192
|
-
parameters: {
|
|
193
|
-
type: 'object',
|
|
194
|
-
properties: {
|
|
195
|
-
path: { type: 'string', description: 'Directory path to list (default: current working directory)' }
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
199
|
-
var path, items;
|
|
200
|
-
return __generator(this, function (_a) {
|
|
201
|
-
path = args.path || process.cwd();
|
|
202
|
-
try {
|
|
203
|
-
items = (0, child_process_1.execSync)("ls -la \"".concat(path, "\" 2>&1")).toString();
|
|
204
|
-
return [2 /*return*/, items];
|
|
205
|
-
}
|
|
206
|
-
catch (e) {
|
|
207
|
-
return [2 /*return*/, "Error listing directory: ".concat(e.message)];
|
|
208
|
-
}
|
|
209
|
-
return [2 /*return*/];
|
|
210
|
-
});
|
|
211
|
-
}); }
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
name: 'run_command',
|
|
215
|
-
description: 'Execute a shell command. Use for git, system info, etc. BE CAREFUL with destructive commands.',
|
|
216
|
-
parameters: {
|
|
217
|
-
type: 'object',
|
|
218
|
-
properties: {
|
|
219
|
-
command: { type: 'string', description: 'Shell command to execute' },
|
|
220
|
-
cwd: { type: 'string', description: 'Working directory (optional)' }
|
|
221
|
-
},
|
|
222
|
-
required: ['command']
|
|
223
|
-
},
|
|
224
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
225
|
-
var cmd, cwd, blocked, result;
|
|
226
|
-
var _a;
|
|
227
|
-
return __generator(this, function (_b) {
|
|
228
|
-
cmd = args.command;
|
|
229
|
-
cwd = args.cwd || process.cwd();
|
|
230
|
-
blocked = ['rm -rf', 'mkfs', 'dd if=', '> /dev/', 'chmod 777'];
|
|
231
|
-
if (blocked.some(function (b) { return cmd.includes(b); })) {
|
|
232
|
-
return [2 /*return*/, "Blocked: command contains dangerous pattern"];
|
|
233
|
-
}
|
|
234
|
-
try {
|
|
235
|
-
result = (0, child_process_1.execSync)(cmd, { timeout: 10000, cwd: cwd }).toString();
|
|
236
|
-
return [2 /*return*/, result || '(no output)'];
|
|
237
|
-
}
|
|
238
|
-
catch (e) {
|
|
239
|
-
return [2 /*return*/, ((_a = e.stdout) === null || _a === void 0 ? void 0 : _a.toString()) || e.message];
|
|
240
|
-
}
|
|
241
|
-
return [2 /*return*/];
|
|
242
|
-
});
|
|
243
|
-
}); }
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
name: 'git_status',
|
|
247
|
-
description: 'Check git repository status',
|
|
248
|
-
parameters: {
|
|
249
|
-
type: 'object',
|
|
250
|
-
properties: {
|
|
251
|
-
cwd: { type: 'string', description: 'Repository path (optional)' }
|
|
252
|
-
}
|
|
253
|
-
},
|
|
254
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
255
|
-
var cwd, status_1, branch;
|
|
256
|
-
return __generator(this, function (_a) {
|
|
257
|
-
cwd = args.cwd || process.cwd();
|
|
258
|
-
try {
|
|
259
|
-
status_1 = (0, child_process_1.execSync)('git status 2>&1', { cwd: cwd }).toString();
|
|
260
|
-
branch = (0, child_process_1.execSync)('git branch --show-current 2>&1', { cwd: cwd }).toString();
|
|
261
|
-
return [2 /*return*/, "Branch: ".concat(branch, "\n\n").concat(status_1)];
|
|
262
|
-
}
|
|
263
|
-
catch (e) {
|
|
264
|
-
return [2 /*return*/, "Error: ".concat(e.message)];
|
|
265
|
-
}
|
|
266
|
-
return [2 /*return*/];
|
|
267
|
-
});
|
|
268
|
-
}); }
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
name: 'get_prompt',
|
|
272
|
-
description: 'Get a prompt template from the prompt store',
|
|
273
|
-
parameters: {
|
|
274
|
-
type: 'object',
|
|
275
|
-
properties: {
|
|
276
|
-
id: { type: 'string', description: 'Prompt ID to retrieve' }
|
|
277
|
-
},
|
|
278
|
-
required: ['id']
|
|
279
|
-
},
|
|
280
|
-
handler: function (args) { return __awaiter(void 0, void 0, void 0, function () {
|
|
281
|
-
var store, prompt;
|
|
282
|
-
return __generator(this, function (_a) {
|
|
283
|
-
store = (0, structured_prompts_1.getStore)(process.env.PROMPTS_FILE);
|
|
284
|
-
prompt = store.get(args.id);
|
|
285
|
-
return [2 /*return*/, prompt ? JSON.stringify(prompt, null, 2) : "Prompt not found: ".concat(args.id)];
|
|
286
|
-
});
|
|
287
|
-
}); }
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
name: 'list_prompts',
|
|
291
|
-
description: 'List all available prompt templates',
|
|
292
|
-
parameters: { type: 'object', properties: {} },
|
|
293
|
-
handler: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
294
|
-
var store, prompts;
|
|
295
|
-
return __generator(this, function (_a) {
|
|
296
|
-
store = (0, structured_prompts_1.getStore)(process.env.PROMPTS_FILE);
|
|
297
|
-
prompts = store.list();
|
|
298
|
-
return [2 /*return*/, prompts.map(function (p) { return "- ".concat(p.id, ": ").concat(p.name); }).join('\n') || 'No prompts found'];
|
|
299
|
-
});
|
|
300
|
-
}); }
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
name: 'system_info',
|
|
304
|
-
description: 'Get system resource info (CPU, memory, disk, uptime)',
|
|
305
|
-
parameters: { type: 'object', properties: {} },
|
|
306
|
-
handler: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
307
|
-
var cpu, mem, disk, uptime;
|
|
308
|
-
return __generator(this, function (_a) {
|
|
309
|
-
try {
|
|
310
|
-
cpu = (0, child_process_1.execSync)('nproc 2>/dev/null || echo "unknown"').toString().trim();
|
|
311
|
-
mem = (0, child_process_1.execSync)('free -h 2>/dev/null | grep Mem || echo "unknown"').toString().trim();
|
|
312
|
-
disk = (0, child_process_1.execSync)('df -h / 2>/dev/null | tail -1 || echo "unknown"').toString().trim();
|
|
313
|
-
uptime = (0, child_process_1.execSync)('uptime -p 2>/dev/null || uptime 2>/dev/null || echo "unknown"').toString().trim();
|
|
314
|
-
return [2 /*return*/, "CPU cores: ".concat(cpu, "\nMemory: ").concat(mem, "\nDisk: ").concat(disk, "\nUptime: ").concat(uptime)];
|
|
315
|
-
}
|
|
316
|
-
catch (e) {
|
|
317
|
-
return [2 /*return*/, "Error: ".concat(e.message)];
|
|
318
|
-
}
|
|
319
|
-
return [2 /*return*/];
|
|
320
|
-
});
|
|
321
|
-
}); }
|
|
322
|
-
}
|
|
323
|
-
];
|
|
324
|
-
// Convert tools to GLM API format
|
|
325
|
-
var GLM_TOOLS = TOOLS.map(function (t) { return ({
|
|
326
|
-
type: 'function',
|
|
327
|
-
function: {
|
|
328
|
-
name: t.name,
|
|
329
|
-
description: t.description,
|
|
330
|
-
parameters: t.parameters
|
|
331
|
-
}
|
|
332
|
-
}); });
|
|
333
|
-
// Execute a tool by name
|
|
334
|
-
function executeTool(name, args) {
|
|
335
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
336
|
-
var tool;
|
|
337
|
-
return __generator(this, function (_a) {
|
|
338
|
-
tool = TOOLS.find(function (t) { return t.name === name; });
|
|
339
|
-
if (!tool)
|
|
340
|
-
return [2 /*return*/, "Unknown tool: ".concat(name)];
|
|
341
|
-
return [2 /*return*/, tool.handler(args)];
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
var ZAI_API_ENDPOINT = 'https://api.z.ai/api/coding/paas/v4/chat/completions';
|
|
346
|
-
var TelegramGLMBot = /** @class */ (function () {
|
|
347
|
-
function TelegramGLMBot(token) {
|
|
348
|
-
this.bot = new node_telegram_bot_api_1.default(token, { polling: true });
|
|
349
|
-
this.memory = new conversation_memory_1.ConversationMemory(process.env.CONVERSATIONS_FILE);
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Send message, splitting if too long for Telegram (4096 char limit)
|
|
353
|
-
*/
|
|
354
|
-
TelegramGLMBot.prototype.sendLongMessage = function (chatId, text) {
|
|
355
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
356
|
-
var MAX_LENGTH, chunks, remaining, breakPoint, i, prefix;
|
|
357
|
-
return __generator(this, function (_a) {
|
|
358
|
-
switch (_a.label) {
|
|
359
|
-
case 0:
|
|
360
|
-
MAX_LENGTH = 4000;
|
|
361
|
-
if (!(text.length <= MAX_LENGTH)) return [3 /*break*/, 2];
|
|
362
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, text)];
|
|
363
|
-
case 1:
|
|
364
|
-
_a.sent();
|
|
365
|
-
return [2 /*return*/];
|
|
366
|
-
case 2:
|
|
367
|
-
chunks = [];
|
|
368
|
-
remaining = text;
|
|
369
|
-
while (remaining.length > 0) {
|
|
370
|
-
if (remaining.length <= MAX_LENGTH) {
|
|
371
|
-
chunks.push(remaining);
|
|
372
|
-
break;
|
|
373
|
-
}
|
|
374
|
-
breakPoint = remaining.lastIndexOf('\n', MAX_LENGTH);
|
|
375
|
-
if (breakPoint < 1000) {
|
|
376
|
-
breakPoint = remaining.lastIndexOf(' ', MAX_LENGTH);
|
|
377
|
-
}
|
|
378
|
-
if (breakPoint < 1000) {
|
|
379
|
-
breakPoint = MAX_LENGTH;
|
|
380
|
-
}
|
|
381
|
-
chunks.push(remaining.slice(0, breakPoint));
|
|
382
|
-
remaining = remaining.slice(breakPoint).trim();
|
|
383
|
-
}
|
|
384
|
-
i = 0;
|
|
385
|
-
_a.label = 3;
|
|
386
|
-
case 3:
|
|
387
|
-
if (!(i < chunks.length)) return [3 /*break*/, 6];
|
|
388
|
-
prefix = chunks.length > 1 ? "[".concat(i + 1, "/").concat(chunks.length, "] ") : '';
|
|
389
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, prefix + chunks[i])];
|
|
390
|
-
case 4:
|
|
391
|
-
_a.sent();
|
|
392
|
-
_a.label = 5;
|
|
393
|
-
case 5:
|
|
394
|
-
i++;
|
|
395
|
-
return [3 /*break*/, 3];
|
|
396
|
-
case 6: return [2 /*return*/];
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
|
-
};
|
|
401
|
-
TelegramGLMBot.prototype.start = function () {
|
|
402
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
403
|
-
var _this = this;
|
|
404
|
-
return __generator(this, function (_a) {
|
|
405
|
-
switch (_a.label) {
|
|
406
|
-
case 0:
|
|
407
|
-
console.log('🤖 GLM Daemon Telegram Bot starting with GLM-4.7...');
|
|
408
|
-
// Register all commands from commands/ directory
|
|
409
|
-
(0, commands_1.registerAllCommands)(this.bot, this.memory, TOOLS);
|
|
410
|
-
// Handle all text messages with GLM-4.7
|
|
411
|
-
this.bot.on('message', function (msg) { return __awaiter(_this, void 0, void 0, function () {
|
|
412
|
-
var chatId, userName, response;
|
|
413
|
-
var _a, _b;
|
|
414
|
-
return __generator(this, function (_c) {
|
|
415
|
-
switch (_c.label) {
|
|
416
|
-
case 0:
|
|
417
|
-
if (!msg.text)
|
|
418
|
-
return [2 /*return*/];
|
|
419
|
-
if (msg.text.startsWith('/'))
|
|
420
|
-
return [2 /*return*/];
|
|
421
|
-
chatId = msg.chat.id;
|
|
422
|
-
userName = ((_a = msg.from) === null || _a === void 0 ? void 0 : _a.first_name) || ((_b = msg.from) === null || _b === void 0 ? void 0 : _b.username) || 'User';
|
|
423
|
-
console.log("[Telegram] ".concat(userName, ": ").concat(msg.text));
|
|
424
|
-
return [4 /*yield*/, this.bot.sendChatAction(chatId, 'typing')];
|
|
425
|
-
case 1:
|
|
426
|
-
_c.sent();
|
|
427
|
-
return [4 /*yield*/, this.getGLMResponse(chatId, msg.text, userName)];
|
|
428
|
-
case 2:
|
|
429
|
-
response = _c.sent();
|
|
430
|
-
// Save to memory
|
|
431
|
-
this.memory.add(chatId, 'user', msg.text);
|
|
432
|
-
this.memory.add(chatId, 'assistant', response);
|
|
433
|
-
return [4 /*yield*/, this.sendLongMessage(chatId, response)];
|
|
434
|
-
case 3:
|
|
435
|
-
_c.sent();
|
|
436
|
-
return [2 /*return*/];
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
}); });
|
|
440
|
-
// Polling errors
|
|
441
|
-
this.bot.on('polling_error', function (error) {
|
|
442
|
-
console.error('[Telegram] Polling error:', error.message);
|
|
443
|
-
});
|
|
444
|
-
console.log('✅ Telegram bot is running with GLM-4.7!');
|
|
445
|
-
if (!TELEGRAM_TEST_CHAT_ID) return [3 /*break*/, 3];
|
|
446
|
-
return [4 /*yield*/, this.sendTestMessage(Number(TELEGRAM_TEST_CHAT_ID))];
|
|
447
|
-
case 1:
|
|
448
|
-
_a.sent();
|
|
449
|
-
// Check for crash and report
|
|
450
|
-
return [4 /*yield*/, this.checkCrashAndReport(Number(TELEGRAM_TEST_CHAT_ID))];
|
|
451
|
-
case 2:
|
|
452
|
-
// Check for crash and report
|
|
453
|
-
_a.sent();
|
|
454
|
-
return [3 /*break*/, 4];
|
|
455
|
-
case 3:
|
|
456
|
-
console.log('\n💡 Tip: Get your chat ID from @userinfobot and set TELEGRAM_TEST_CHAT_ID');
|
|
457
|
-
_a.label = 4;
|
|
458
|
-
case 4: return [2 /*return*/];
|
|
459
|
-
}
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
};
|
|
463
|
-
TelegramGLMBot.prototype.getGLMResponse = function (chatId, userMessage, userName) {
|
|
464
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
465
|
-
var apiKey, store, systemPrompt, systemContent, temperature, maxTokens, history, messages, iterations, maxIterations, response, data, message, _i, _a, toolCall, toolName, args, sanitizeForTelegram, argsPreview, result, sanitizedResult, resultPreview, error_1;
|
|
466
|
-
var _b, _c, _d, _e, _f, _g, _h;
|
|
467
|
-
return __generator(this, function (_j) {
|
|
468
|
-
switch (_j.label) {
|
|
469
|
-
case 0:
|
|
470
|
-
apiKey = (0, keys_1.getZAIKey)();
|
|
471
|
-
if (!apiKey) {
|
|
472
|
-
return [2 /*return*/, '⚠️ Z_AI_API_KEY not configured in Doppler secrets.\n\nPlease set Z_AI_API_KEY to use GLM-4.7.'];
|
|
473
|
-
}
|
|
474
|
-
store = (0, structured_prompts_1.getStore)(process.env.PROMPTS_FILE);
|
|
475
|
-
systemPrompt = store.get('glm-daemon-system');
|
|
476
|
-
systemContent = (_b = systemPrompt === null || systemPrompt === void 0 ? void 0 : systemPrompt.template) !== null && _b !== void 0 ? _b : 'You are GLM Daemon, a helpful AI assistant.';
|
|
477
|
-
temperature = (_d = (_c = systemPrompt === null || systemPrompt === void 0 ? void 0 : systemPrompt.metadata) === null || _c === void 0 ? void 0 : _c.temperature) !== null && _d !== void 0 ? _d : 0.7;
|
|
478
|
-
maxTokens = (_f = (_e = systemPrompt === null || systemPrompt === void 0 ? void 0 : systemPrompt.metadata) === null || _e === void 0 ? void 0 : _e.maxTokens) !== null && _f !== void 0 ? _f : 2048;
|
|
479
|
-
history = this.memory.get(chatId);
|
|
480
|
-
messages = __spreadArray(__spreadArray([
|
|
481
|
-
{ role: 'system', content: systemContent }
|
|
482
|
-
], history, true), [
|
|
483
|
-
{ role: 'user', content: userMessage }
|
|
484
|
-
], false);
|
|
485
|
-
_j.label = 1;
|
|
486
|
-
case 1:
|
|
487
|
-
_j.trys.push([1, 13, , 14]);
|
|
488
|
-
console.log("\uD83D\uDD04 Calling GLM-4.7 API for: ".concat(userMessage, " (").concat(history.length, " history)"));
|
|
489
|
-
iterations = 0;
|
|
490
|
-
maxIterations = 50;
|
|
491
|
-
_j.label = 2;
|
|
492
|
-
case 2:
|
|
493
|
-
if (!(iterations < maxIterations)) return [3 /*break*/, 12];
|
|
494
|
-
iterations++;
|
|
495
|
-
return [4 /*yield*/, (0, fetch_retry_1.fetchWithRetry)(ZAI_API_ENDPOINT, {
|
|
496
|
-
method: 'POST',
|
|
497
|
-
headers: {
|
|
498
|
-
'Content-Type': 'application/json',
|
|
499
|
-
'Authorization': "Bearer ".concat(apiKey)
|
|
500
|
-
},
|
|
501
|
-
body: JSON.stringify({
|
|
502
|
-
model: 'glm-4.7',
|
|
503
|
-
messages: messages,
|
|
504
|
-
tools: GLM_TOOLS,
|
|
505
|
-
temperature: temperature,
|
|
506
|
-
max_tokens: maxTokens
|
|
507
|
-
})
|
|
508
|
-
}, 3, 1000)];
|
|
509
|
-
case 3:
|
|
510
|
-
response = _j.sent();
|
|
511
|
-
return [4 /*yield*/, response.json()];
|
|
512
|
-
case 4:
|
|
513
|
-
data = _j.sent();
|
|
514
|
-
message = (_h = (_g = data.choices) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.message;
|
|
515
|
-
if (!message) {
|
|
516
|
-
console.error('❌ Unexpected API response format:', data);
|
|
517
|
-
return [2 /*return*/, '❌ Unexpected response from AI API.'];
|
|
518
|
-
}
|
|
519
|
-
if (!(message.tool_calls && message.tool_calls.length > 0)) return [3 /*break*/, 11];
|
|
520
|
-
console.log("\uD83D\uDD27 LLM calling ".concat(message.tool_calls.length, " tool(s)"));
|
|
521
|
-
// Add assistant message with tool calls to history
|
|
522
|
-
messages.push({
|
|
523
|
-
role: 'assistant',
|
|
524
|
-
tool_calls: message.tool_calls
|
|
525
|
-
});
|
|
526
|
-
_i = 0, _a = message.tool_calls;
|
|
527
|
-
_j.label = 5;
|
|
528
|
-
case 5:
|
|
529
|
-
if (!(_i < _a.length)) return [3 /*break*/, 10];
|
|
530
|
-
toolCall = _a[_i];
|
|
531
|
-
toolName = toolCall.function.name;
|
|
532
|
-
args = JSON.parse(toolCall.function.arguments);
|
|
533
|
-
console.log(" \u2192 ".concat(toolName, "(").concat(JSON.stringify(args), ")"));
|
|
534
|
-
sanitizeForTelegram = function (str) {
|
|
535
|
-
return str
|
|
536
|
-
.replace(/[_*[\]()~`>#+=|{}.!-]/g, '') // Remove Markdown special chars
|
|
537
|
-
.replace(/\\/g, '') // Remove backslashes
|
|
538
|
-
.slice(0, 100); // Truncate to prevent long messages
|
|
539
|
-
};
|
|
540
|
-
argsPreview = Object.keys(args).length > 0
|
|
541
|
-
? sanitizeForTelegram(JSON.stringify(args))
|
|
542
|
-
: '';
|
|
543
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, "\uD83D\uDD27 ".concat(toolName).concat(argsPreview ? ' ' + argsPreview : ''))];
|
|
544
|
-
case 6:
|
|
545
|
-
_j.sent();
|
|
546
|
-
return [4 /*yield*/, executeTool(toolName, args)];
|
|
547
|
-
case 7:
|
|
548
|
-
result = _j.sent();
|
|
549
|
-
console.log(" \u2190 ".concat(result.slice(0, 100), "..."));
|
|
550
|
-
sanitizedResult = result
|
|
551
|
-
.replace(/[_*[\]()~`>#+=|{}.!-]/g, '')
|
|
552
|
-
.replace(/\\/g, '');
|
|
553
|
-
resultPreview = sanitizedResult.length > 500 ? sanitizedResult.slice(0, 500) + ' [truncated]' : sanitizedResult;
|
|
554
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, "\uD83D\uDCE5 ".concat(resultPreview))];
|
|
555
|
-
case 8:
|
|
556
|
-
_j.sent();
|
|
557
|
-
// Add tool result to messages
|
|
558
|
-
messages.push({
|
|
559
|
-
role: 'tool',
|
|
560
|
-
name: toolName,
|
|
561
|
-
content: result
|
|
562
|
-
});
|
|
563
|
-
_j.label = 9;
|
|
564
|
-
case 9:
|
|
565
|
-
_i++;
|
|
566
|
-
return [3 /*break*/, 5];
|
|
567
|
-
case 10:
|
|
568
|
-
// Continue loop to get final response
|
|
569
|
-
return [3 /*break*/, 2];
|
|
570
|
-
case 11:
|
|
571
|
-
// No tool calls - we have the final response
|
|
572
|
-
if (message.content) {
|
|
573
|
-
console.log("\u2705 GLM-4.7 response: ".concat(message.content.slice(0, 100), "..."));
|
|
574
|
-
return [2 /*return*/, message.content];
|
|
575
|
-
}
|
|
576
|
-
// No content and no tool calls - something weird
|
|
577
|
-
return [2 /*return*/, '❌ Empty response from AI.'];
|
|
578
|
-
case 12: return [2 /*return*/, '⚠️ Reached tool limit (50). The AI was being very thorough! Try a more specific request.'];
|
|
579
|
-
case 13:
|
|
580
|
-
error_1 = _j.sent();
|
|
581
|
-
console.error('❌ Error calling GLM-4.7:', error_1.message);
|
|
582
|
-
if (error_1.message.includes('429')) {
|
|
583
|
-
return [2 /*return*/, '⚠️ Rate limited by API. Please try again in a moment.'];
|
|
584
|
-
}
|
|
585
|
-
return [2 /*return*/, "\u274C Error: ".concat(error_1.message)];
|
|
586
|
-
case 14: return [2 /*return*/];
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
});
|
|
590
|
-
};
|
|
591
|
-
TelegramGLMBot.prototype.sendTestMessage = function (chatId) {
|
|
592
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
593
|
-
var apiKey;
|
|
594
|
-
return __generator(this, function (_a) {
|
|
595
|
-
switch (_a.label) {
|
|
596
|
-
case 0:
|
|
597
|
-
apiKey = (0, keys_1.getZAIKey)();
|
|
598
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, '✅ GLM Daemon Telegram Bot is NOW ONLINE!\n\n' +
|
|
599
|
-
'🎉 Connected from seed-node-prod!\n\n' +
|
|
600
|
-
"\uD83E\uDDE0 AI: ".concat(apiKey ? 'GLM-4.7 via Z.AI' : 'Not configured', "\n\n") +
|
|
601
|
-
'Commands:\n' +
|
|
602
|
-
'/start - Show welcome message\n' +
|
|
603
|
-
'/status - Check API status\n' +
|
|
604
|
-
'/git - Git & GitHub status\n' +
|
|
605
|
-
'/doppler - Doppler config\n' +
|
|
606
|
-
'/help - Show all commands\n' +
|
|
607
|
-
'Any message - Chat with GLM-4.7 AI')];
|
|
608
|
-
case 1:
|
|
609
|
-
_a.sent();
|
|
610
|
-
console.log("\u2705 Test message sent to chat ".concat(chatId));
|
|
611
|
-
return [2 /*return*/];
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
});
|
|
615
|
-
};
|
|
616
|
-
TelegramGLMBot.prototype.stop = function () {
|
|
617
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
618
|
-
return __generator(this, function (_a) {
|
|
619
|
-
console.log('🛑 Stopping Telegram bot...');
|
|
620
|
-
this.bot.stopPolling();
|
|
621
|
-
return [2 /*return*/];
|
|
622
|
-
});
|
|
623
|
-
});
|
|
624
|
-
};
|
|
625
|
-
/**
|
|
626
|
-
* Check for crash recovery - analyze previous session and report
|
|
627
|
-
* Always sends a startup message (crash or normal)
|
|
628
|
-
*/
|
|
629
|
-
TelegramGLMBot.prototype.checkCrashAndReport = function (chatId) {
|
|
630
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
631
|
-
var crashLog_1, crashIndicators_1, hasCrash, errorLines, diagnosis, e_1;
|
|
632
|
-
return __generator(this, function (_a) {
|
|
633
|
-
switch (_a.label) {
|
|
634
|
-
case 0:
|
|
635
|
-
_a.trys.push([0, 8, , 10]);
|
|
636
|
-
crashLog_1 = (0, child_process_1.execSync)('journalctl -u telegram-bot -b -1 -n 50 --no-pager 2>/dev/null || journalctl -u telegram-bot --since "5 minutes ago" -n 50 --no-pager 2>/dev/null', { encoding: 'utf-8', timeout: 5000 }).trim();
|
|
637
|
-
crashIndicators_1 = ['Error:', 'error', 'crashed', 'killed', 'ETELEGRAM', '400 Bad Request', 'exception'];
|
|
638
|
-
hasCrash = crashLog_1 && crashIndicators_1.some(function (ind) { return crashLog_1.toLowerCase().includes(ind.toLowerCase()); });
|
|
639
|
-
if (!hasCrash) return [3 /*break*/, 5];
|
|
640
|
-
// Crash detected - analyze and report
|
|
641
|
-
console.log('🔍 Crash detected, analyzing...');
|
|
642
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, '🔄 I detected a crash in my previous session. Analyzing...')];
|
|
643
|
-
case 1:
|
|
644
|
-
_a.sent();
|
|
645
|
-
errorLines = crashLog_1.split('\n')
|
|
646
|
-
.filter(function (line) { return crashIndicators_1.some(function (ind) { return line.toLowerCase().includes(ind.toLowerCase()); }); })
|
|
647
|
-
.slice(-10)
|
|
648
|
-
.join('\n');
|
|
649
|
-
if (!errorLines) return [3 /*break*/, 4];
|
|
650
|
-
return [4 /*yield*/, this.getGLMResponse(chatId, "Analyze this crash log and tell me what went wrong in one short paragraph, then suggest a fix:\n\n```\n".concat(errorLines.slice(0, 1000), "\n```\n\nFormat: \"Issue: [what happened]. Fix: [how to fix it]\""), 'CrashAnalyzer')];
|
|
651
|
-
case 2:
|
|
652
|
-
diagnosis = _a.sent();
|
|
653
|
-
return [4 /*yield*/, this.sendLongMessage(chatId, "\uD83C\uDFE5 Crash Diagnosis:\n\n".concat(diagnosis))];
|
|
654
|
-
case 3:
|
|
655
|
-
_a.sent();
|
|
656
|
-
_a.label = 4;
|
|
657
|
-
case 4: return [3 /*break*/, 7];
|
|
658
|
-
case 5:
|
|
659
|
-
// Normal start - no crash detected
|
|
660
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, '✅ Bot started normally.\n\n' +
|
|
661
|
-
'Previous session ended cleanly. Ready to assist!')];
|
|
662
|
-
case 6:
|
|
663
|
-
// Normal start - no crash detected
|
|
664
|
-
_a.sent();
|
|
665
|
-
_a.label = 7;
|
|
666
|
-
case 7: return [3 /*break*/, 10];
|
|
667
|
-
case 8:
|
|
668
|
-
e_1 = _a.sent();
|
|
669
|
-
// If we can't check logs, still notify of normal start
|
|
670
|
-
console.log('Crash check skipped:', e_1.message);
|
|
671
|
-
return [4 /*yield*/, this.bot.sendMessage(chatId, '✅ Bot started fresh.\n\n' +
|
|
672
|
-
'No previous session data available. Ready to assist!')];
|
|
673
|
-
case 9:
|
|
674
|
-
_a.sent();
|
|
675
|
-
return [3 /*break*/, 10];
|
|
676
|
-
case 10: return [2 /*return*/];
|
|
677
|
-
}
|
|
678
|
-
});
|
|
679
|
-
});
|
|
680
|
-
};
|
|
681
|
-
return TelegramGLMBot;
|
|
682
|
-
}());
|
|
683
|
-
exports.TelegramGLMBot = TelegramGLMBot;
|
|
684
|
-
// Main entry point
|
|
685
|
-
function main() {
|
|
686
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
687
|
-
var promptsFile, store, bot;
|
|
688
|
-
var _this = this;
|
|
689
|
-
return __generator(this, function (_a) {
|
|
690
|
-
switch (_a.label) {
|
|
691
|
-
case 0:
|
|
692
|
-
if (!TELEGRAM_BOT_TOKEN) {
|
|
693
|
-
console.error('❌ TELEGRAM_BOT_TOKEN not found in Doppler secrets');
|
|
694
|
-
console.error('Make sure to set in your seed/prd Doppler project');
|
|
695
|
-
process.exit(1);
|
|
696
|
-
}
|
|
697
|
-
promptsFile = process.env.PROMPTS_FILE;
|
|
698
|
-
store = (0, structured_prompts_1.getStore)(promptsFile);
|
|
699
|
-
if (!store.get('glm-daemon-system')) {
|
|
700
|
-
console.log('📝 Seeding prompts...');
|
|
701
|
-
(0, structured_prompts_1.seedPrompts)(promptsFile);
|
|
702
|
-
}
|
|
703
|
-
console.log("\uD83D\uDCF1 Bot token loaded: ".concat(TELEGRAM_BOT_TOKEN.substring(0, 10), "..."));
|
|
704
|
-
console.log("\uD83E\uDD16 Bot name: @SimulationapiBot");
|
|
705
|
-
bot = new TelegramGLMBot(TELEGRAM_BOT_TOKEN);
|
|
706
|
-
return [4 /*yield*/, bot.start()];
|
|
707
|
-
case 1:
|
|
708
|
-
_a.sent();
|
|
709
|
-
process.on('SIGINT', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
710
|
-
return __generator(this, function (_a) {
|
|
711
|
-
switch (_a.label) {
|
|
712
|
-
case 0: return [4 /*yield*/, bot.stop()];
|
|
713
|
-
case 1:
|
|
714
|
-
_a.sent();
|
|
715
|
-
process.exit(0);
|
|
716
|
-
return [2 /*return*/];
|
|
717
|
-
}
|
|
718
|
-
});
|
|
719
|
-
}); });
|
|
720
|
-
process.on('SIGTERM', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
721
|
-
return __generator(this, function (_a) {
|
|
722
|
-
switch (_a.label) {
|
|
723
|
-
case 0: return [4 /*yield*/, bot.stop()];
|
|
724
|
-
case 1:
|
|
725
|
-
_a.sent();
|
|
726
|
-
process.exit(0);
|
|
727
|
-
return [2 /*return*/];
|
|
728
|
-
}
|
|
729
|
-
});
|
|
730
|
-
}); });
|
|
731
|
-
return [2 /*return*/];
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
main().catch(console.error);
|