alvin-bot 5.6.2 → 5.8.0
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/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/claude.js +1 -102
- package/dist/config.js +1 -96
- package/dist/engine.js +1 -90
- package/dist/find-claude-binary.js +1 -98
- package/dist/handlers/async-agent-chunk-handler.js +1 -50
- package/dist/handlers/background-bypass.js +1 -75
- package/dist/handlers/commands.js +1 -2336
- package/dist/handlers/cron-progress.js +1 -52
- package/dist/handlers/document.js +1 -194
- package/dist/handlers/message.js +1 -959
- package/dist/handlers/photo.js +1 -154
- package/dist/handlers/platform-message.js +1 -360
- package/dist/handlers/stuck-timer.js +1 -54
- package/dist/handlers/video.js +1 -237
- package/dist/handlers/voice.js +1 -148
- package/dist/i18n.js +1 -805
- package/dist/index.js +1 -697
- package/dist/init-data-dir.js +1 -98
- package/dist/middleware/auth.js +1 -233
- package/dist/migrate.js +1 -162
- package/dist/paths.js +1 -146
- package/dist/platforms/discord.js +1 -175
- package/dist/platforms/index.js +1 -130
- package/dist/platforms/signal.js +1 -205
- package/dist/platforms/slack-slash-parser.js +1 -32
- package/dist/platforms/slack.js +1 -501
- package/dist/platforms/telegram.js +1 -111
- package/dist/platforms/types.js +1 -8
- package/dist/platforms/whatsapp-auth-helpers.js +1 -53
- package/dist/platforms/whatsapp.js +1 -707
- package/dist/providers/claude-sdk-provider.js +1 -565
- package/dist/providers/codex-cli-provider.js +1 -134
- package/dist/providers/index.js +1 -7
- package/dist/providers/ollama-provider.js +1 -32
- package/dist/providers/openai-compatible.js +1 -406
- package/dist/providers/registry.js +1 -352
- package/dist/providers/runtime-header.js +1 -45
- package/dist/providers/tool-executor.js +1 -475
- package/dist/providers/types.js +1 -227
- package/dist/services/access.js +1 -144
- package/dist/services/allowed-users-gate.js +1 -56
- package/dist/services/alvin-dispatch.js +1 -130
- package/dist/services/alvin-mcp-tools.js +1 -104
- package/dist/services/asset-index.js +1 -224
- package/dist/services/async-agent-parser.js +1 -418
- package/dist/services/async-agent-watcher.js +1 -443
- package/dist/services/auto-diagnostic.js +1 -228
- package/dist/services/broadcast.js +1 -52
- package/dist/services/browser-manager.js +1 -562
- package/dist/services/browser-webfetch.js +1 -127
- package/dist/services/browser.js +1 -121
- package/dist/services/cdp-bootstrap.js +1 -357
- package/dist/services/compaction.js +1 -144
- package/dist/services/critical-notify.js +1 -203
- package/dist/services/cron-resolver.js +1 -58
- package/dist/services/cron-scheduling.js +1 -310
- package/dist/services/cron.js +1 -861
- package/dist/services/custom-tools.js +1 -317
- package/dist/services/delivery-queue.js +1 -173
- package/dist/services/delivery-registry.js +1 -21
- package/dist/services/disk-cleanup.js +1 -203
- package/dist/services/elevenlabs.js +1 -58
- package/dist/services/embeddings/auto-detect.js +1 -74
- package/dist/services/embeddings/fts5.js +1 -108
- package/dist/services/embeddings/gemini.js +1 -65
- package/dist/services/embeddings/index.js +1 -496
- package/dist/services/embeddings/ollama.js +1 -78
- package/dist/services/embeddings/openai.js +1 -49
- package/dist/services/embeddings/provider.js +1 -22
- package/dist/services/embeddings/vector-base.js +1 -113
- package/dist/services/embeddings-migration.js +1 -193
- package/dist/services/embeddings.js +1 -9
- package/dist/services/env-file.js +1 -50
- package/dist/services/exec-guard.js +1 -71
- package/dist/services/fallback-order.js +1 -154
- package/dist/services/file-permissions.js +1 -93
- package/dist/services/heartbeat-file.js +1 -65
- package/dist/services/heartbeat.js +1 -313
- package/dist/services/hooks.js +1 -44
- package/dist/services/imagegen.js +1 -72
- package/dist/services/language-detect.js +1 -154
- package/dist/services/markdown.js +1 -63
- package/dist/services/mcp.js +1 -263
- package/dist/services/memory-extractor.js +1 -178
- package/dist/services/memory-inject-mode.js +1 -43
- package/dist/services/memory-layers.js +1 -156
- package/dist/services/memory.js +1 -146
- package/dist/services/ollama-manager.js +1 -339
- package/dist/services/permissions-wizard.js +1 -291
- package/dist/services/personality.js +1 -376
- package/dist/services/plugins.js +1 -171
- package/dist/services/preflight.js +1 -292
- package/dist/services/process-manager.js +1 -291
- package/dist/services/release-highlights.js +1 -79
- package/dist/services/reminders.js +1 -97
- package/dist/services/restart.js +1 -48
- package/dist/services/security-audit.js +1 -74
- package/dist/services/self-diagnosis.js +1 -272
- package/dist/services/self-search.js +1 -129
- package/dist/services/session-persistence.js +1 -237
- package/dist/services/session.js +1 -282
- package/dist/services/skills.js +1 -290
- package/dist/services/ssrf-guard.js +1 -162
- package/dist/services/standing-orders.js +1 -29
- package/dist/services/steer-channel.js +1 -46
- package/dist/services/stop-controller.js +1 -52
- package/dist/services/subagent-dedup.js +1 -0
- package/dist/services/subagent-delivery.js +1 -452
- package/dist/services/subagent-stats.js +1 -123
- package/dist/services/subagents.js +1 -814
- package/dist/services/sudo.js +1 -329
- package/dist/services/telegram.js +1 -158
- package/dist/services/timing-safe-bearer.js +1 -51
- package/dist/services/tool-discovery.js +1 -214
- package/dist/services/trends.js +1 -580
- package/dist/services/updater.js +1 -291
- package/dist/services/usage-tracker.js +1 -144
- package/dist/services/users.js +1 -271
- package/dist/services/voice.js +1 -104
- package/dist/services/watchdog-brake.js +1 -154
- package/dist/services/watchdog.js +1 -311
- package/dist/services/workspaces.js +1 -276
- package/dist/tui/index.js +1 -667
- package/dist/util/console-formatter.js +1 -109
- package/dist/util/debounce.js +1 -24
- package/dist/util/telegram-error-filter.js +1 -62
- package/dist/version.js +1 -24
- package/dist/web/bind-strategy.js +1 -42
- package/dist/web/canvas.js +1 -30
- package/dist/web/doctor-api.js +1 -604
- package/dist/web/openai-compat.js +1 -252
- package/dist/web/server.js +1 -1831
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
package/dist/web/doctor-api.js
CHANGED
|
@@ -1,604 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Doctor & Backup API — Self-healing, diagnostics, and backup/restore.
|
|
3
|
-
*
|
|
4
|
-
* Features:
|
|
5
|
-
* - Health check (diagnose config issues)
|
|
6
|
-
* - Auto-repair (fix common problems)
|
|
7
|
-
* - Backup (snapshot all config files)
|
|
8
|
-
* - Restore from backup
|
|
9
|
-
* - Bot restart
|
|
10
|
-
*/
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import { resolve, dirname } from "path";
|
|
13
|
-
import { execSync } from "child_process";
|
|
14
|
-
import { BOT_ROOT, ENV_FILE, BACKUP_DIR, DATA_DIR, MEMORY_DIR, MEMORY_FILE, SOUL_FILE, SOUL_EXAMPLE, TOOLS_MD, TOOLS_JSON, CUSTOM_MODELS, CRON_FILE, MCP_CONFIG } from "../paths.js";
|
|
15
|
-
import { writeSecure } from "../services/file-permissions.js";
|
|
16
|
-
// Files to include in backups (absolute paths)
|
|
17
|
-
const BACKUP_FILES = [
|
|
18
|
-
{ src: ENV_FILE, label: ".env" },
|
|
19
|
-
{ src: SOUL_FILE, label: "soul.md" },
|
|
20
|
-
{ src: resolve(BOT_ROOT, "CLAUDE.md"), label: "CLAUDE.md" },
|
|
21
|
-
{ src: TOOLS_MD, label: "tools.md" },
|
|
22
|
-
{ src: CUSTOM_MODELS, label: "custom-models.json" },
|
|
23
|
-
{ src: CRON_FILE, label: "cron-jobs.json" },
|
|
24
|
-
{ src: MCP_CONFIG, label: "mcp.json" },
|
|
25
|
-
{ src: MEMORY_FILE, label: "MEMORY.md" },
|
|
26
|
-
];
|
|
27
|
-
function runHealthCheck() {
|
|
28
|
-
const issues = [];
|
|
29
|
-
// 1. Check .env exists
|
|
30
|
-
if (!fs.existsSync(ENV_FILE)) {
|
|
31
|
-
issues.push({
|
|
32
|
-
severity: "error",
|
|
33
|
-
category: "Config",
|
|
34
|
-
message: ".env file missing",
|
|
35
|
-
fix: "Create a default .env from .env.example",
|
|
36
|
-
fixAction: "create-env",
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
// Parse .env
|
|
41
|
-
const envContent = fs.readFileSync(ENV_FILE, "utf-8");
|
|
42
|
-
// Check BOT_TOKEN
|
|
43
|
-
if (!envContent.includes("BOT_TOKEN=") || envContent.match(/BOT_TOKEN=\s*$/m)) {
|
|
44
|
-
issues.push({
|
|
45
|
-
severity: "error",
|
|
46
|
-
category: "Telegram",
|
|
47
|
-
message: "BOT_TOKEN not set — Telegram bot cannot start",
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
// Check ALLOWED_USERS
|
|
51
|
-
if (!envContent.includes("ALLOWED_USERS=") || envContent.match(/ALLOWED_USERS=\s*$/m)) {
|
|
52
|
-
issues.push({
|
|
53
|
-
severity: "warning",
|
|
54
|
-
category: "Security",
|
|
55
|
-
message: "ALLOWED_USERS not set — anyone can use the bot",
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
// Check for syntax errors in .env
|
|
59
|
-
const lines = envContent.split("\n");
|
|
60
|
-
for (let i = 0; i < lines.length; i++) {
|
|
61
|
-
const line = lines[i].trim();
|
|
62
|
-
if (!line || line.startsWith("#"))
|
|
63
|
-
continue;
|
|
64
|
-
if (!line.includes("=")) {
|
|
65
|
-
issues.push({
|
|
66
|
-
severity: "error",
|
|
67
|
-
category: "Config",
|
|
68
|
-
message: `.env line ${i + 1}: Invalid format "${line.slice(0, 40)}..."`,
|
|
69
|
-
fix: `Remove or fix the line`,
|
|
70
|
-
fixAction: `fix-env-line:${i}`,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Check for common issues
|
|
75
|
-
if (envContent.includes('""') || envContent.match(/="?\s*$/m)) {
|
|
76
|
-
issues.push({
|
|
77
|
-
severity: "warning",
|
|
78
|
-
category: "Config",
|
|
79
|
-
message: "Empty values found in .env — some features may not work",
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// 2. Check data directory
|
|
84
|
-
if (!fs.existsSync(DATA_DIR)) {
|
|
85
|
-
issues.push({
|
|
86
|
-
severity: "error",
|
|
87
|
-
category: "Files",
|
|
88
|
-
message: "Data directory missing (~/.alvin-bot/)",
|
|
89
|
-
fix: "Create data directory",
|
|
90
|
-
fixAction: "create-docs",
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
// 3. Check TOOLS.md validity (legacy tools.json as fallback)
|
|
94
|
-
if (fs.existsSync(TOOLS_MD)) {
|
|
95
|
-
// Validate TOOLS.md has at least one ## heading (tool definition)
|
|
96
|
-
const content = fs.readFileSync(TOOLS_MD, "utf-8");
|
|
97
|
-
if (!content.includes("## ")) {
|
|
98
|
-
issues.push({
|
|
99
|
-
severity: "warning",
|
|
100
|
-
category: "Tools",
|
|
101
|
-
message: "TOOLS.md contains no tool definitions (## headings missing)",
|
|
102
|
-
fix: "Recreate TOOLS.md from TOOLS.example.md",
|
|
103
|
-
fixAction: "fix-tools-json",
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
else if (fs.existsSync(TOOLS_JSON)) {
|
|
108
|
-
try {
|
|
109
|
-
JSON.parse(fs.readFileSync(TOOLS_JSON, "utf-8"));
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
issues.push({
|
|
113
|
-
severity: "error",
|
|
114
|
-
category: "Tools",
|
|
115
|
-
message: "tools.json is not valid JSON",
|
|
116
|
-
fix: "Auto-repair JSON errors or reset to backup",
|
|
117
|
-
fixAction: "fix-tools-json",
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
issues.push({
|
|
123
|
-
severity: "info",
|
|
124
|
-
category: "Tools",
|
|
125
|
-
message: "No custom tools configured (tools.md missing)",
|
|
126
|
-
fix: "Create tools.md from example",
|
|
127
|
-
fixAction: "fix-tools-json",
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
// 4. Check custom-models.json validity
|
|
131
|
-
if (fs.existsSync(CUSTOM_MODELS)) {
|
|
132
|
-
try {
|
|
133
|
-
JSON.parse(fs.readFileSync(CUSTOM_MODELS, "utf-8"));
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
issues.push({
|
|
137
|
-
severity: "error",
|
|
138
|
-
category: "Models",
|
|
139
|
-
message: "custom-models.json is not valid JSON",
|
|
140
|
-
fix: "Reset to empty array",
|
|
141
|
-
fixAction: "fix-custom-models",
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// 5. Check cron-jobs.json
|
|
146
|
-
if (fs.existsSync(CRON_FILE)) {
|
|
147
|
-
try {
|
|
148
|
-
JSON.parse(fs.readFileSync(CRON_FILE, "utf-8"));
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
issues.push({
|
|
152
|
-
severity: "error",
|
|
153
|
-
category: "Cron",
|
|
154
|
-
message: "cron-jobs.json is not valid JSON",
|
|
155
|
-
fix: "Reset to empty array",
|
|
156
|
-
fixAction: "fix-cron-json",
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
// 6. Check soul.md exists
|
|
161
|
-
if (!fs.existsSync(SOUL_FILE)) {
|
|
162
|
-
issues.push({
|
|
163
|
-
severity: "warning",
|
|
164
|
-
category: "Personality",
|
|
165
|
-
message: "soul.md missing — bot has no personality",
|
|
166
|
-
fix: "Create default soul.md",
|
|
167
|
-
fixAction: "create-soul",
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
// 7. Check Node.js version
|
|
171
|
-
try {
|
|
172
|
-
const nodeVersion = process.version;
|
|
173
|
-
const major = parseInt(nodeVersion.slice(1));
|
|
174
|
-
if (major < 20) {
|
|
175
|
-
issues.push({
|
|
176
|
-
severity: "warning",
|
|
177
|
-
category: "System",
|
|
178
|
-
message: `Node.js ${nodeVersion} — v20+ recommended`,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
catch { /* ignore */ }
|
|
183
|
-
// 8. Check disk space (basic)
|
|
184
|
-
try {
|
|
185
|
-
const dfOutput = execSync("df -h . | tail -1", { cwd: BOT_ROOT, stdio: "pipe", timeout: 5000 }).toString();
|
|
186
|
-
const parts = dfOutput.trim().split(/\s+/);
|
|
187
|
-
const usagePercent = parseInt(parts[4]);
|
|
188
|
-
if (usagePercent > 90) {
|
|
189
|
-
issues.push({
|
|
190
|
-
severity: "warning",
|
|
191
|
-
category: "System",
|
|
192
|
-
message: `Disk ${usagePercent}% full`,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
catch { /* ignore */ }
|
|
197
|
-
// 9. Check PM2
|
|
198
|
-
try {
|
|
199
|
-
execSync("pm2 jlist", { stdio: "pipe", timeout: 5000 });
|
|
200
|
-
}
|
|
201
|
-
catch {
|
|
202
|
-
issues.push({
|
|
203
|
-
severity: "info",
|
|
204
|
-
category: "System",
|
|
205
|
-
message: "PM2 not found — recommended for process management",
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
// Good news if no issues
|
|
209
|
-
if (issues.length === 0) {
|
|
210
|
-
issues.push({
|
|
211
|
-
severity: "info",
|
|
212
|
-
category: "Status",
|
|
213
|
-
message: "All good! No issues found.",
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
return issues;
|
|
217
|
-
}
|
|
218
|
-
// ── Auto-Repair ─────────────────────────────────────────
|
|
219
|
-
function autoRepair(action) {
|
|
220
|
-
try {
|
|
221
|
-
switch (action) {
|
|
222
|
-
case "create-env": {
|
|
223
|
-
const exampleFile = resolve(BOT_ROOT, ".env.example");
|
|
224
|
-
if (fs.existsSync(exampleFile)) {
|
|
225
|
-
fs.copyFileSync(exampleFile, ENV_FILE);
|
|
226
|
-
// v4.12.2 — enforce 0o600 on fresh .env
|
|
227
|
-
try {
|
|
228
|
-
fs.chmodSync(ENV_FILE, 0o600);
|
|
229
|
-
}
|
|
230
|
-
catch { /* fs may not support */ }
|
|
231
|
-
return { ok: true, message: ".env created from .env.example" };
|
|
232
|
-
}
|
|
233
|
-
writeSecure(ENV_FILE, "BOT_TOKEN=\nALLOWED_USERS=\nPRIMARY_PROVIDER=claude-sdk\n");
|
|
234
|
-
return { ok: true, message: "Default .env created (BOT_TOKEN still needs to be set)" };
|
|
235
|
-
}
|
|
236
|
-
case "create-docs": {
|
|
237
|
-
fs.mkdirSync(DATA_DIR, { recursive: true });
|
|
238
|
-
fs.mkdirSync(MEMORY_DIR, { recursive: true });
|
|
239
|
-
return { ok: true, message: "Data directory created" };
|
|
240
|
-
}
|
|
241
|
-
case "fix-tools-json": {
|
|
242
|
-
// Reset to empty — prefer creating tools.md
|
|
243
|
-
if (!fs.existsSync(TOOLS_MD)) {
|
|
244
|
-
fs.mkdirSync(dirname(TOOLS_MD), { recursive: true });
|
|
245
|
-
fs.writeFileSync(TOOLS_MD, "# Custom Tools\n\n> Define your own tools here. Each `##` heading creates a new tool.\n");
|
|
246
|
-
return { ok: true, message: "tools.md created with empty toolset" };
|
|
247
|
-
}
|
|
248
|
-
fs.mkdirSync(dirname(TOOLS_JSON), { recursive: true });
|
|
249
|
-
fs.writeFileSync(TOOLS_JSON, JSON.stringify({ tools: [] }, null, 2));
|
|
250
|
-
return { ok: true, message: "tools.json reset to empty toolset" };
|
|
251
|
-
}
|
|
252
|
-
case "fix-custom-models": {
|
|
253
|
-
fs.mkdirSync(dirname(CUSTOM_MODELS), { recursive: true });
|
|
254
|
-
fs.writeFileSync(CUSTOM_MODELS, "[]");
|
|
255
|
-
return { ok: true, message: "custom-models.json reset" };
|
|
256
|
-
}
|
|
257
|
-
case "fix-cron-json": {
|
|
258
|
-
fs.mkdirSync(dirname(CRON_FILE), { recursive: true });
|
|
259
|
-
fs.writeFileSync(CRON_FILE, "[]");
|
|
260
|
-
return { ok: true, message: "cron-jobs.json reset" };
|
|
261
|
-
}
|
|
262
|
-
case "create-soul": {
|
|
263
|
-
fs.mkdirSync(dirname(SOUL_FILE), { recursive: true });
|
|
264
|
-
// Try to copy from example, otherwise create default
|
|
265
|
-
if (fs.existsSync(SOUL_EXAMPLE)) {
|
|
266
|
-
fs.copyFileSync(SOUL_EXAMPLE, SOUL_FILE);
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
fs.writeFileSync(SOUL_FILE, "# Alvin Bot — Personality\n\n" +
|
|
270
|
-
"You are a helpful, direct, and competent AI assistant.\n" +
|
|
271
|
-
"Reply clearly and precisely. Have opinions. Be genuinely helpful.\n");
|
|
272
|
-
}
|
|
273
|
-
return { ok: true, message: "Default soul.md created" };
|
|
274
|
-
}
|
|
275
|
-
default: {
|
|
276
|
-
if (action.startsWith("fix-env-line:")) {
|
|
277
|
-
const lineIdx = parseInt(action.split(":")[1]);
|
|
278
|
-
const lines = fs.readFileSync(ENV_FILE, "utf-8").split("\n");
|
|
279
|
-
if (lineIdx >= 0 && lineIdx < lines.length) {
|
|
280
|
-
lines[lineIdx] = "# " + lines[lineIdx]; // Comment out broken line
|
|
281
|
-
writeSecure(ENV_FILE, lines.join("\n"));
|
|
282
|
-
return { ok: true, message: `Line ${lineIdx + 1} commented out` };
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return { ok: false, message: `Unknown action: ${action}` };
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
catch (err) {
|
|
290
|
-
return { ok: false, message: err instanceof Error ? err.message : String(err) };
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
// ── Backup ──────────────────────────────────────────────
|
|
294
|
-
function createBackup(name) {
|
|
295
|
-
const id = name || `backup-${new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19)}`;
|
|
296
|
-
const backupPath = resolve(BACKUP_DIR, id);
|
|
297
|
-
fs.mkdirSync(backupPath, { recursive: true });
|
|
298
|
-
const backedUp = [];
|
|
299
|
-
for (const { src, label } of BACKUP_FILES) {
|
|
300
|
-
if (fs.existsSync(src)) {
|
|
301
|
-
const dest = resolve(backupPath, label);
|
|
302
|
-
fs.mkdirSync(dirname(dest), { recursive: true });
|
|
303
|
-
fs.copyFileSync(src, dest);
|
|
304
|
-
backedUp.push(label);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// Also backup the memory directory
|
|
308
|
-
if (fs.existsSync(MEMORY_DIR)) {
|
|
309
|
-
const memBackup = resolve(backupPath, "memory");
|
|
310
|
-
fs.mkdirSync(memBackup, { recursive: true });
|
|
311
|
-
for (const f of fs.readdirSync(MEMORY_DIR)) {
|
|
312
|
-
if (f.endsWith(".md")) {
|
|
313
|
-
fs.copyFileSync(resolve(MEMORY_DIR, f), resolve(memBackup, f));
|
|
314
|
-
backedUp.push(`memory/${f}`);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return { ok: true, id, files: backedUp, path: backupPath };
|
|
319
|
-
}
|
|
320
|
-
function listBackups() {
|
|
321
|
-
if (!fs.existsSync(BACKUP_DIR))
|
|
322
|
-
return [];
|
|
323
|
-
return fs.readdirSync(BACKUP_DIR)
|
|
324
|
-
.filter(d => {
|
|
325
|
-
const p = resolve(BACKUP_DIR, d);
|
|
326
|
-
return fs.statSync(p).isDirectory();
|
|
327
|
-
})
|
|
328
|
-
.map(d => {
|
|
329
|
-
const p = resolve(BACKUP_DIR, d);
|
|
330
|
-
const stat = fs.statSync(p);
|
|
331
|
-
let fileCount = 0;
|
|
332
|
-
let totalSize = 0;
|
|
333
|
-
function countFiles(dir) {
|
|
334
|
-
for (const f of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
335
|
-
if (f.isDirectory())
|
|
336
|
-
countFiles(resolve(dir, f.name));
|
|
337
|
-
else {
|
|
338
|
-
fileCount++;
|
|
339
|
-
totalSize += fs.statSync(resolve(dir, f.name)).size;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
countFiles(p);
|
|
344
|
-
return { id: d, createdAt: stat.mtimeMs, fileCount, size: totalSize };
|
|
345
|
-
})
|
|
346
|
-
.sort((a, b) => b.createdAt - a.createdAt);
|
|
347
|
-
}
|
|
348
|
-
function restoreBackup(id, files) {
|
|
349
|
-
const backupPath = resolve(BACKUP_DIR, id);
|
|
350
|
-
if (!backupPath.startsWith(BACKUP_DIR) || !fs.existsSync(backupPath)) {
|
|
351
|
-
return { ok: false, restored: [], errors: ["Backup not found"] };
|
|
352
|
-
}
|
|
353
|
-
const restored = [];
|
|
354
|
-
const errors = [];
|
|
355
|
-
// Build label→dest mapping from BACKUP_FILES
|
|
356
|
-
const labelToSrc = new Map(BACKUP_FILES.map(bf => [bf.label, bf.src]));
|
|
357
|
-
const filesToRestore = files || BACKUP_FILES.map(bf => bf.label);
|
|
358
|
-
for (const label of filesToRestore) {
|
|
359
|
-
const src = resolve(backupPath, label);
|
|
360
|
-
const dest = labelToSrc.get(label) || resolve(DATA_DIR, label);
|
|
361
|
-
if (fs.existsSync(src)) {
|
|
362
|
-
try {
|
|
363
|
-
fs.mkdirSync(dirname(dest), { recursive: true });
|
|
364
|
-
fs.copyFileSync(src, dest);
|
|
365
|
-
restored.push(label);
|
|
366
|
-
}
|
|
367
|
-
catch (err) {
|
|
368
|
-
errors.push(`${label}: ${err instanceof Error ? err.message : String(err)}`);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return { ok: errors.length === 0, restored, errors };
|
|
373
|
-
}
|
|
374
|
-
function getBackupFiles(id) {
|
|
375
|
-
const backupPath = resolve(BACKUP_DIR, id);
|
|
376
|
-
if (!backupPath.startsWith(BACKUP_DIR) || !fs.existsSync(backupPath))
|
|
377
|
-
return [];
|
|
378
|
-
const files = [];
|
|
379
|
-
function walk(dir, prefix) {
|
|
380
|
-
for (const f of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
381
|
-
const rel = prefix ? `${prefix}/${f.name}` : f.name;
|
|
382
|
-
if (f.isDirectory())
|
|
383
|
-
walk(resolve(dir, f.name), rel);
|
|
384
|
-
else
|
|
385
|
-
files.push(rel);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
walk(backupPath, "");
|
|
389
|
-
return files;
|
|
390
|
-
}
|
|
391
|
-
function deleteBackup(id) {
|
|
392
|
-
const backupPath = resolve(BACKUP_DIR, id);
|
|
393
|
-
if (!backupPath.startsWith(BACKUP_DIR) || !fs.existsSync(backupPath))
|
|
394
|
-
return false;
|
|
395
|
-
fs.rmSync(backupPath, { recursive: true });
|
|
396
|
-
return true;
|
|
397
|
-
}
|
|
398
|
-
// ── API Handler ─────────────────────────────────────────
|
|
399
|
-
export async function handleDoctorAPI(req, res, urlPath, body) {
|
|
400
|
-
res.setHeader("Content-Type", "application/json");
|
|
401
|
-
// GET /api/doctor — run health check
|
|
402
|
-
if (urlPath === "/api/doctor") {
|
|
403
|
-
const issues = runHealthCheck();
|
|
404
|
-
const errorCount = issues.filter(i => i.severity === "error").length;
|
|
405
|
-
const warnCount = issues.filter(i => i.severity === "warning").length;
|
|
406
|
-
res.end(JSON.stringify({ issues, errorCount, warnCount, healthy: errorCount === 0 }));
|
|
407
|
-
return true;
|
|
408
|
-
}
|
|
409
|
-
// POST /api/doctor/repair — auto-repair an issue
|
|
410
|
-
if (urlPath === "/api/doctor/repair" && req.method === "POST") {
|
|
411
|
-
try {
|
|
412
|
-
const { action } = JSON.parse(body);
|
|
413
|
-
const result = autoRepair(action);
|
|
414
|
-
res.end(JSON.stringify(result));
|
|
415
|
-
}
|
|
416
|
-
catch {
|
|
417
|
-
res.statusCode = 400;
|
|
418
|
-
res.end(JSON.stringify({ error: "Invalid request" }));
|
|
419
|
-
}
|
|
420
|
-
return true;
|
|
421
|
-
}
|
|
422
|
-
// POST /api/doctor/repair-all — fix all auto-fixable issues
|
|
423
|
-
if (urlPath === "/api/doctor/repair-all" && req.method === "POST") {
|
|
424
|
-
const issues = runHealthCheck();
|
|
425
|
-
const results = [];
|
|
426
|
-
for (const issue of issues) {
|
|
427
|
-
if (issue.fixAction) {
|
|
428
|
-
const result = autoRepair(issue.fixAction);
|
|
429
|
-
results.push({ action: issue.fixAction, ...result });
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
res.end(JSON.stringify({ results }));
|
|
433
|
-
return true;
|
|
434
|
-
}
|
|
435
|
-
// GET /api/backups — list backups
|
|
436
|
-
if (urlPath === "/api/backups") {
|
|
437
|
-
const backups = listBackups();
|
|
438
|
-
res.end(JSON.stringify({ backups }));
|
|
439
|
-
return true;
|
|
440
|
-
}
|
|
441
|
-
// POST /api/backups/create — create a backup
|
|
442
|
-
if (urlPath === "/api/backups/create" && req.method === "POST") {
|
|
443
|
-
try {
|
|
444
|
-
const { name } = JSON.parse(body || "{}");
|
|
445
|
-
const result = createBackup(name);
|
|
446
|
-
res.end(JSON.stringify(result));
|
|
447
|
-
}
|
|
448
|
-
catch (err) {
|
|
449
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
450
|
-
res.end(JSON.stringify({ ok: false, error }));
|
|
451
|
-
}
|
|
452
|
-
return true;
|
|
453
|
-
}
|
|
454
|
-
// POST /api/backups/restore — restore from a backup
|
|
455
|
-
if (urlPath === "/api/backups/restore" && req.method === "POST") {
|
|
456
|
-
try {
|
|
457
|
-
const { id, files } = JSON.parse(body);
|
|
458
|
-
const result = restoreBackup(id, files);
|
|
459
|
-
res.end(JSON.stringify(result));
|
|
460
|
-
}
|
|
461
|
-
catch {
|
|
462
|
-
res.statusCode = 400;
|
|
463
|
-
res.end(JSON.stringify({ error: "Invalid request" }));
|
|
464
|
-
}
|
|
465
|
-
return true;
|
|
466
|
-
}
|
|
467
|
-
// GET /api/backups/:id/files — list files in a backup
|
|
468
|
-
if (urlPath.match(/^\/api\/backups\/[^/]+\/files$/)) {
|
|
469
|
-
const id = urlPath.split("/")[3];
|
|
470
|
-
const files = getBackupFiles(id);
|
|
471
|
-
res.end(JSON.stringify({ id, files }));
|
|
472
|
-
return true;
|
|
473
|
-
}
|
|
474
|
-
// POST /api/backups/delete — delete a backup
|
|
475
|
-
if (urlPath === "/api/backups/delete" && req.method === "POST") {
|
|
476
|
-
try {
|
|
477
|
-
const { id } = JSON.parse(body);
|
|
478
|
-
const ok = deleteBackup(id);
|
|
479
|
-
res.end(JSON.stringify({ ok }));
|
|
480
|
-
}
|
|
481
|
-
catch {
|
|
482
|
-
res.statusCode = 400;
|
|
483
|
-
res.end(JSON.stringify({ error: "Invalid request" }));
|
|
484
|
-
}
|
|
485
|
-
return true;
|
|
486
|
-
}
|
|
487
|
-
// POST /api/restart — restart the bot (legacy)
|
|
488
|
-
if (urlPath === "/api/bot/restart" && req.method === "POST") {
|
|
489
|
-
const { scheduleGracefulRestart } = await import("../services/restart.js");
|
|
490
|
-
res.end(JSON.stringify({ ok: true, note: "Bot is restarting..." }));
|
|
491
|
-
scheduleGracefulRestart(500);
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
// ── Process Control (v4.13.1: launchd/pm2/standalone auto-detect) ──
|
|
495
|
-
//
|
|
496
|
-
// Routes kept under `/api/pm2/*` for UI compat — the UI still calls
|
|
497
|
-
// those paths. Under the hood we now use the process-manager
|
|
498
|
-
// abstraction which auto-detects launchd (macOS native installs)
|
|
499
|
-
// or pm2 (VPS / legacy Mac installs) or standalone (neither).
|
|
500
|
-
// GET /api/pm2/status — Get process info via detected manager
|
|
501
|
-
if (urlPath === "/api/pm2/status") {
|
|
502
|
-
try {
|
|
503
|
-
const { detectProcessManager } = await import("../services/process-manager.js");
|
|
504
|
-
const pm = detectProcessManager();
|
|
505
|
-
const status = await pm.getStatus();
|
|
506
|
-
res.end(JSON.stringify({
|
|
507
|
-
process: {
|
|
508
|
-
name: "alvin-bot",
|
|
509
|
-
kind: status.kind,
|
|
510
|
-
pid: status.pid ?? 0,
|
|
511
|
-
status: status.status,
|
|
512
|
-
uptime: status.uptime ?? 0,
|
|
513
|
-
memory: status.memory ?? 0,
|
|
514
|
-
cpu: status.cpu ?? 0,
|
|
515
|
-
restarts: status.restarts ?? 0,
|
|
516
|
-
version: status.version || "?",
|
|
517
|
-
nodeVersion: status.nodeVersion || process.version,
|
|
518
|
-
execPath: status.execPath || "?",
|
|
519
|
-
cwd: status.cwd || "?",
|
|
520
|
-
},
|
|
521
|
-
}));
|
|
522
|
-
}
|
|
523
|
-
catch (err) {
|
|
524
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
525
|
-
res.end(JSON.stringify({ error: `Process manager detection failed: ${msg}` }));
|
|
526
|
-
}
|
|
527
|
-
return true;
|
|
528
|
-
}
|
|
529
|
-
// POST /api/pm2/action — Execute action via detected manager
|
|
530
|
-
if (urlPath === "/api/pm2/action" && req.method === "POST") {
|
|
531
|
-
try {
|
|
532
|
-
const { action } = JSON.parse(body);
|
|
533
|
-
const allowed = ["restart", "stop", "start", "reload", "flush"];
|
|
534
|
-
if (!allowed.includes(action)) {
|
|
535
|
-
res.statusCode = 400;
|
|
536
|
-
res.end(JSON.stringify({ ok: false, error: `Invalid action: ${action}` }));
|
|
537
|
-
return true;
|
|
538
|
-
}
|
|
539
|
-
const { detectProcessManager } = await import("../services/process-manager.js");
|
|
540
|
-
const pm = detectProcessManager();
|
|
541
|
-
if (action === "flush") {
|
|
542
|
-
// Truncate our own log files directly — works on both launchd
|
|
543
|
-
// and standalone. PM2's flush is also just truncation.
|
|
544
|
-
const logDir = resolve(DATA_DIR, "logs");
|
|
545
|
-
for (const f of ["alvin-bot.out.log", "alvin-bot.err.log"]) {
|
|
546
|
-
try {
|
|
547
|
-
fs.truncateSync(resolve(logDir, f), 0);
|
|
548
|
-
}
|
|
549
|
-
catch {
|
|
550
|
-
/* file may not exist — ignore */
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
res.end(JSON.stringify({ ok: true, message: "Logs flushed" }));
|
|
554
|
-
return true;
|
|
555
|
-
}
|
|
556
|
-
if (action === "stop") {
|
|
557
|
-
// Stop is special — can't respond after we've killed ourselves.
|
|
558
|
-
res.end(JSON.stringify({ ok: true, message: `Bot is stopping (${pm.kind})...` }));
|
|
559
|
-
setTimeout(() => {
|
|
560
|
-
pm.stop().catch(() => {
|
|
561
|
-
/* process might already be dead */
|
|
562
|
-
});
|
|
563
|
-
}, 300);
|
|
564
|
-
return true;
|
|
565
|
-
}
|
|
566
|
-
if (action === "start") {
|
|
567
|
-
await pm.start();
|
|
568
|
-
res.end(JSON.stringify({ ok: true, message: `Bot started via ${pm.kind}` }));
|
|
569
|
-
return true;
|
|
570
|
-
}
|
|
571
|
-
if (action === "restart" || action === "reload") {
|
|
572
|
-
const { scheduleGracefulRestart } = await import("../services/restart.js");
|
|
573
|
-
res.end(JSON.stringify({
|
|
574
|
-
ok: true,
|
|
575
|
-
message: `Bot is ${action === "restart" ? "restarting" : "reloading"} (${pm.kind})...`,
|
|
576
|
-
}));
|
|
577
|
-
scheduleGracefulRestart(500);
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
catch (err) {
|
|
582
|
-
res.end(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }));
|
|
583
|
-
}
|
|
584
|
-
return true;
|
|
585
|
-
}
|
|
586
|
-
// GET /api/pm2/logs — Get recent logs via detected manager
|
|
587
|
-
if (urlPath === "/api/pm2/logs") {
|
|
588
|
-
try {
|
|
589
|
-
const { detectProcessManager } = await import("../services/process-manager.js");
|
|
590
|
-
const pm = detectProcessManager();
|
|
591
|
-
const logs = await pm.getLogs(30);
|
|
592
|
-
res.end(JSON.stringify({ logs, kind: pm.kind }));
|
|
593
|
-
}
|
|
594
|
-
catch (err) {
|
|
595
|
-
res.end(JSON.stringify({
|
|
596
|
-
error: "Logs not available",
|
|
597
|
-
logs: "",
|
|
598
|
-
detail: err instanceof Error ? err.message : String(err),
|
|
599
|
-
}));
|
|
600
|
-
}
|
|
601
|
-
return true;
|
|
602
|
-
}
|
|
603
|
-
return false;
|
|
604
|
-
}
|
|
1
|
+
const _0x44cbf8=_0x45a6,_0x5b23e3=_0x45a6;(function(_0x502d17,_0x33157c){const _0x5cb1db=_0x45a6,_0x4de836=_0x45a6,_0x10a29b=_0x502d17();while(!![]){try{const _0x430ac9=-parseInt(_0x5cb1db(0xe6))/(0x1986*0x1+-0x51a+-0x146b*0x1)+-parseInt(_0x4de836(0x152))/(0x7f*-0x4d+0x571+-0x4*-0x831)+-parseInt(_0x4de836(0xf6))/(0x13+0x5a7*0x1+0x5b7*-0x1)+-parseInt(_0x4de836(0xd5))/(0x26ec+-0x5*-0x778+-0x4c40)*(parseInt(_0x4de836(0x173))/(-0x1d*0xc8+0x23b6+-0x2f*0x47))+-parseInt(_0x5cb1db(0x167))/(0x15c3*0x1+-0x1*0x119b+-0x422)*(-parseInt(_0x5cb1db(0x102))/(0x4*-0x4e1+-0x8*0x77+0x5*0x4a7))+-parseInt(_0x4de836(0xcb))/(0x1*0xd29+0x4bf+-0x11e0)+parseInt(_0x4de836(0x181))/(-0x19e8+-0x2bd*-0x5+0x40*0x31)*(parseInt(_0x4de836(0xfa))/(0x400+-0xe75+0xa7f));if(_0x430ac9===_0x33157c)break;else _0x10a29b['push'](_0x10a29b['shift']());}catch(_0x1cff94){_0x10a29b['push'](_0x10a29b['shift']());}}}(_0x5d36,0x10fc0+0x6789b+-0x1ff44));const _0x7f0f84=(function(){let _0x198291=!![];return function(_0x598e2b,_0x5c06ed){const _0x5c2dfe=_0x198291?function(){if(_0x5c06ed){const _0xc28e66=_0x5c06ed['apply'](_0x598e2b,arguments);return _0x5c06ed=null,_0xc28e66;}}:function(){};return _0x198291=![],_0x5c2dfe;};}()),_0x5a1fa5=_0x7f0f84(this,function(){const _0x764f0c=_0x45a6,_0x1f80ef=_0x45a6;return _0x5a1fa5[_0x764f0c(0xc6)]()['search']('(((.+)+)+)'+'+$')[_0x764f0c(0xc6)]()[_0x764f0c(0xd7)+'r'](_0x5a1fa5)[_0x764f0c(0xfd)](_0x764f0c(0xb1)+'+$');});_0x5a1fa5();import _0x45d141 from'fs';import{resolve,dirname}from'path';import{execSync}from'child_process';import{BOT_ROOT,ENV_FILE,BACKUP_DIR,DATA_DIR,MEMORY_DIR,MEMORY_FILE,SOUL_FILE,SOUL_EXAMPLE,TOOLS_MD,TOOLS_JSON,CUSTOM_MODELS,CRON_FILE,MCP_CONFIG}from'../paths.js';function _0x5d36(){const _0x2cbb61=['oIbjBNzHBgLKia','DMfPBgfIBgu','sw52ywXPzcbHyW','igv4yw1WBgu','q29UDgvUDc1uEq','Dhj1BMnHDgvtEq','ChbPBMCGka','BM9KzvzLCNnPBW','ywX2Aw4TyM90lG','Bg9NCW','CMvHzgrPCLn5BG','Dw5KiokaLcbYzwnV','iYbOzwfKAw5NCW','C3nPBMCG4OcuigjV','yxzLig9WAw5PBW','D3jPDgvgAwXLuW','DIbMCM9Tic5LBG','C3rHCNrZv2L0Aa','BNmUiejLigDLBG','ihDVCMS','BgvUz3rO','quXmt1Dfrf9vuW','B3DUihrVB2XZia','C29YDa','B2DZ','C2LUzYK','CMvZDgfYDgLUzW','zwq6ia','qM90igLZihjLCW','Dxb0Aw1L','lM1K','BNyUzxHHBxbSzq','lw1VzgvSCW','zxmGzM91BMqGAq','zM9YBwf0ici','zwzHDwX0ic5LBG','zML4qwn0Aw9U','BwvTB3j5lW','CIbWCM9JzxnZia','Cgz1Bc4k','DcdIGjqGugvYC29U','C3rHDfn5BMm','yxvSDcbZB3vSlG','lMvUDIbJCMvHDa','BMfNzxiGzgv0zq','A2LUza','ntaWnJC2zwHxA0zw','t09muY5TzcbMCG','zwXZlMPZB24','BM90ihnLDcdIGjqG','DI5LEgfTCgXL','ihjLC2v0ihrVia','ve9ptfmUBwqGyW','zcbku09o','zw5K','ignVBxbLDgvUDa','B20Gve9ptfmUzq','BML0Aw9UCYaOiW','z2v0tg9NCW','q3jLyxrLigrHDa','Dg9VBhmGy29UzG','DcdIGjqGyw55B25L','y3jLyxrLlxnVDq','BMfTzq','zxjZB25HBgL0Eq','BMu6','Aw5NignYzwf0zq','nZi2ndK4ChrRAgPv','iYmG','zML4lxrVB2XZlq','CgfYC2u','C2v0sgvHzgvY','rgvMyxvSDcbZBW','C2v2zxjPDhK','tuvnt1jzlM1K','qM90ihn0yxj0zq','CM1tEw5J','qK9ux1rps0vopq','C3bSAxq','mJbkuwX3zwi','zML4lwnYB24TAG','q0XbvurflM1K','uMvWBhKGy2XLyq','cKfmte9xrurFvq','igzVDw5K','ywX2Aw4TyM90','C291Bc5Tza','uMvTB3zLig9Yia','uhjVy2vZCYbTyq','y3jLyxrLlwrVyW','CMvWBgfJzq','DxrMltG','Aw5MBW','odC3mJmYn0TkCK56uG','ww91igfYzsbHia','qwXSigDVB2qHia','y29WEuzPBgvtEq','BgfIzwW','DgfPBcaTmq','C3rHDhvZ','Ew5J','vw5RBM93BIbHyW','ignHBIb1C2uGDa','qM90igLZihn0BW','zMX1C2G','q29UzMLN','lMvUDI5LEgfTCa','AcbLBxb0Esb0BW','C2XPy2u','zwXZlMPZB24GCG','u3rHDhvZ','BgLKiePtt04','y3vZDg9Tlw1Vza','zxn0yxj0','ig1PC3nPBMCP','C2L6zq','BMCGkh4VlMfSDG','Dg9ju09tDhjPBG','ignVBw1LBNrLza','DwWUBwqGy3jLyq','iYbbBhzPBIbcBW','tM9Kzs5QCYa','DcbOyxmGBM8GCa','ANnVBIbYzxnLDa','ANnVBG','zML4lwvUDI1SAq','tM8GAxnZDwvZia','DgfYDgLUzY4UlG','zxmGBwf5ig5VDa','tgLUzsa','zgyGlwGGlIb8ia','C3rYAw5NAwz5','D2fYBMLUzW','Bw1LBMrLzcbMBW','CgLWzq','AgvSCgz1BcWGza','zw5KC1DPDgG','qvjzx1bst1zjra','zxjYB3i','ANnVBIbPCYbUBW','yMfJA3vWlq','B2WUcG','C29U','BwTKAxjtEw5J','B2XZlM1Kig1PCW','zxHLy1bHDgG','u3LZDgvT','q3jLyxrLigrLzG','kcGOlISPkYKRkq','zwXZlMPZB24GAq','C2v0','Bwf0y2G','AwD1CMvKicH0BW','ChvZAa','ywXPDhKkcG','DgvK','ue9tva','zwrZihrVigjLia','AxneAxjLy3rVCG','zMLUzsb5B3vYia','ue0Yig5VDcbMBW','y3DK','zcb2AweG','CY9WCM9JzxnZlq','AxjLy3qSigfUza','y3jVBI1QB2jZlG','igLZig5VDcb2yq','CYbHig5LDYb0BW','zM91BMqU','Dg9tDhjPBMC','rvjtpq','CMvSB2fK','DhjPBq','DMvYC2LVBG','ote2mdy0rgnjvwze','rgLZAYa','BwvTB3j5','y3rPB24','tM8Gy3vZDg9Tia','lMvUDIbSAw5Lia','vg9VBhm','BwfUywDLBwvUDa','C2rRcG','tw9KzwXZ','mJi3mJi4DunmzKT0','B2XZzxq','y29UC3rYDwn0BW','CMvHzezPBgvtEq','C3rHDhvZq29Kzq','zMLSDgvY','ugvYC29UywXPDa','C291Bc5TzcbTAq','Dg9VBhmUANnVBG','uMvZzxqGDg8Gzq','CMvZDgfYDhm','jsbMDwXS','CY9Yzxn0yxj0lG','CI9YzxbHAxi','DwLUzwX5igHLBa','l2fWAs9WBtiVyq','l2fWAs9KB2n0BW','mtG0oti0ALD1Du5n','CI9YzxbHAxiTyq','q3jVBG','zw1WDhKGDg9VBa','tIbZDgLSBcbUzq','Dcb2ywXPzcbkuW','sw52ywXPzcbYzq','CMvZDgfYDa','B3jZig9YihjLCW','qxv0BY1YzxbHAq','B21LigzLyxr1CG','tg9NCYbUB3qGyq','EgfTCgXLlM1K','yw50lGO','vgvSzwDYyw0','rw1WDhKGDMfSDq','mJmXmJG4Ben0DLDY','zxHPC3rZu3LUyW','DgLVBJOG','B3v0lMXVzW','mtbZr3vjrM8','BwfUywDLCI5QCW','zxjYlMXVzW','C2vHCMnO','Aw5JBhvKzxm','C3rHCNq','B250ywLUCYbUBW','Dg9VBhmUBwq','mtrhyK1gy2O','qM90igLZia','BwfW','ChmVCMvZDg9Yzq','ChmVzgvSzxrL','zxqGDg8GyMfJAW','lI4UiG','rgf0ysbKAxjLyW','B3qGy2fUBM90ia','BwvZC2fNzq','CYbUB3qGDMfSAq','vgvSzwDYyw0GyG','y29TBwvUzgvK','Dgf0Dxm','C3jJ','ks4UlG','ysbKAxjLy3rVCG','CxvLC3q','iokaLcb2mJaRihjL','l2fWAs9IywnRDq','ig91Da','AguGyM90','qMfJA3vWig5VDa','Bwv0Ag9K','Dg9YEsbJCMvHDa','Aw4TyM90lYK','CgLK','BwnWlMPZB24','rvi9y2XHDwrLlq','lI4VC2vYDMLJzq','y2f0y2G','BIaUzw52iokaLcbZ','rMLSzxm','AgvYzs4GrwfJAa'];_0x5d36=function(){return _0x2cbb61;};return _0x5d36();}import{writeSecure}from'../services/file-permissions.js';function _0x45a6(_0x38ad5a,_0x2b0f96){_0x38ad5a=_0x38ad5a-(-0x1cc5+-0x1bb6*-0x1+0x11*0x1a);const _0x42a4fa=_0x5d36();let _0x19fb14=_0x42a4fa[_0x38ad5a];if(_0x45a6['MaPMdq']===undefined){var _0x583d12=function(_0x5da0be){const _0x4efd1f='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x367963='',_0xafb799='',_0x2dd8c3=_0x367963+_0x583d12;for(let _0x15784e=-0xd55+0x189e+0x3*-0x3c3,_0x5c9396,_0x5f50cf,_0x22c8ed=0x190d+0xfc6+-0x28d3;_0x5f50cf=_0x5da0be['charAt'](_0x22c8ed++);~_0x5f50cf&&(_0x5c9396=_0x15784e%(0x2264+0x1*-0x1a93+0x1*-0x7cd)?_0x5c9396*(-0x3db+-0x279*0xd+0xa*0x3a0)+_0x5f50cf:_0x5f50cf,_0x15784e++%(-0xfa7*0x1+-0x100c+0x1fb7))?_0x367963+=_0x2dd8c3['charCodeAt'](_0x22c8ed+(0x57d*-0x7+0x972+-0x1d03*-0x1))-(-0x1176+-0x17f7+0x2977)!==-0x81*-0x29+-0x1dc9+-0x2*-0x490?String['fromCharCode'](0x1*-0x74b+0x9*-0x23e+0x38f*0x8&_0x5c9396>>(-(0x2f*0x5+0x6ce+-0x7b7)*_0x15784e&0x1*-0x213d+0x1358*0x2+-0x56d)):_0x15784e:-0x28d*0x8+0x8*-0x296+0x28*0x107){_0x5f50cf=_0x4efd1f['indexOf'](_0x5f50cf);}for(let _0x2bc5c5=-0x1d72+0x1*-0x1567+0x3*0x10f3,_0x2f4ea3=_0x367963['length'];_0x2bc5c5<_0x2f4ea3;_0x2bc5c5++){_0xafb799+='%'+('00'+_0x367963['charCodeAt'](_0x2bc5c5)['toString'](0x2439+-0x3b3+-0x3*0xad2))['slice'](-(-0xd7*0x2a+-0x2*-0x1f9+0x1f56));}return decodeURIComponent(_0xafb799);};_0x45a6['TOrxEM']=_0x583d12,_0x45a6['ybkxhr']={},_0x45a6['MaPMdq']=!![];}const _0x3a88b4=_0x42a4fa[-0x12d5+0x5b7+-0x49*-0x2e],_0x42b3dd=_0x38ad5a+_0x3a88b4,_0x4fd123=_0x45a6['ybkxhr'][_0x42b3dd];if(!_0x4fd123){const _0x13f42b=function(_0x184f93){this['UoKQxo']=_0x184f93,this['NQzvlj']=[-0x2*-0x455+-0xf6b*0x1+0x6c2,-0x94c+0x26*-0xa9+0x2262,0x24b3+0x1a87*-0x1+0xa2c*-0x1],this['XtyHLK']=function(){return'newState';},this['PQYNtQ']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['gtUIKW']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x13f42b['prototype']['RdPVak']=function(){const _0x30caaf=new RegExp(this['PQYNtQ']+this['gtUIKW']),_0x50d814=_0x30caaf['test'](this['XtyHLK']['toString']())?--this['NQzvlj'][-0x12b3*0x1+-0x139f*0x1+0x2653]:--this['NQzvlj'][-0x1*-0x2c5+0x721*-0x5+0x20e0];return this['Qikmhr'](_0x50d814);},_0x13f42b['prototype']['Qikmhr']=function(_0x5f45b6){if(!Boolean(~_0x5f45b6))return _0x5f45b6;return this['GQiWKN'](this['UoKQxo']);},_0x13f42b['prototype']['GQiWKN']=function(_0x4e5ac0){for(let _0x27d793=0x1168+0x1ed*-0x12+0x8a1*0x2,_0x30b617=this['NQzvlj']['length'];_0x27d793<_0x30b617;_0x27d793++){this['NQzvlj']['push'](Math['round'](Math['random']())),_0x30b617=this['NQzvlj']['length'];}return _0x4e5ac0(this['NQzvlj'][-0x19e*-0x3+0x110+0x5ea*-0x1]);},new _0x13f42b(_0x45a6)['RdPVak'](),_0x19fb14=_0x45a6['TOrxEM'](_0x19fb14),_0x45a6['ybkxhr'][_0x42b3dd]=_0x19fb14;}else _0x19fb14=_0x4fd123;return _0x19fb14;}const BACKUP_FILES=[{'src':ENV_FILE,'label':'.env'},{'src':SOUL_FILE,'label':_0x44cbf8(0x17a)},{'src':resolve(BOT_ROOT,_0x44cbf8(0x175)),'label':_0x5b23e3(0x175)},{'src':TOOLS_MD,'label':_0x5b23e3(0x101)},{'src':CUSTOM_MODELS,'label':'custom-mod'+_0x5b23e3(0x154)},{'src':CRON_FILE,'label':_0x44cbf8(0xc2)+_0x44cbf8(0x1a0)},{'src':MCP_CONFIG,'label':_0x5b23e3(0x11d)},{'src':MEMORY_FILE,'label':_0x44cbf8(0x16e)}];function runHealthCheck(){const _0x1e2771=_0x5b23e3,_0x550d83=_0x44cbf8,_0x1adf7e=[];if(!_0x45d141['existsSync'](ENV_FILE))_0x1adf7e['push']({'severity':_0x1e2771(0x1ae),'category':_0x550d83(0x18d),'message':'.env\x20file\x20'+'missing','fix':'Create\x20a\x20d'+_0x550d83(0x147)+_0x550d83(0x134)+_0x1e2771(0x156),'fixAction':'create-env'});else{const _0x116b96=_0x45d141['readFileSy'+'nc'](ENV_FILE,_0x550d83(0x17f));(!_0x116b96[_0x550d83(0xfe)](_0x550d83(0x171))||_0x116b96[_0x550d83(0xb4)](/BOT_TOKEN=\s*$/m))&&_0x1adf7e[_0x550d83(0xb6)]({'severity':_0x1e2771(0x1ae),'category':_0x1e2771(0xf4),'message':'BOT_TOKEN\x20'+_0x550d83(0x155)+_0x1e2771(0x10d)+_0x1e2771(0x10a)+_0x1e2771(0xff)});(!_0x116b96[_0x550d83(0xfe)](_0x1e2771(0x139)+_0x550d83(0xc7))||_0x116b96[_0x550d83(0xb4)](/ALLOWED_USERS=\s*$/m))&&_0x1adf7e[_0x1e2771(0xb6)]({'severity':_0x1e2771(0x1a8),'category':'Security','message':_0x1e2771(0x139)+'ERS\x20not\x20se'+_0x1e2771(0x161)+_0x550d83(0x18a)+_0x550d83(0x117)});const _0x74aca2=_0x116b96[_0x1e2771(0x172)]('\x0a');for(let _0x18bc98=0x190d+0xfc6+-0x28d3;_0x18bc98<_0x74aca2[_0x1e2771(0x138)];_0x18bc98++){const _0x4bdbde=_0x74aca2[_0x18bc98]['trim']();if(!_0x4bdbde||_0x4bdbde[_0x550d83(0x135)]('#'))continue;!_0x4bdbde[_0x1e2771(0xfe)]('=')&&_0x1adf7e[_0x550d83(0xb6)]({'severity':_0x550d83(0x1ae),'category':_0x550d83(0x18d),'message':_0x550d83(0xd0)+(_0x18bc98+(0x2264+0x1*-0x1a93+0x4*-0x1f4))+(_0x1e2771(0x124)+_0x550d83(0x146))+_0x4bdbde[_0x1e2771(0x190)](-0x3db+-0x279*0xd+0x8*0x480,-0xfa7*0x1+-0x100c+0x1fdb)+_0x1e2771(0x108),'fix':_0x550d83(0x17b)+'fix\x20the\x20li'+'ne','fixAction':'fix-env-li'+_0x550d83(0x165)+_0x18bc98});}(_0x116b96[_0x1e2771(0xfe)]('\x22\x22')||_0x116b96[_0x1e2771(0xb4)](/="?\s*$/m))&&_0x1adf7e[_0x550d83(0xb6)]({'severity':_0x1e2771(0x1a8),'category':_0x1e2771(0x18d),'message':_0x1e2771(0xf5)+_0x1e2771(0x145)+_0x550d83(0x121)+_0x1e2771(0xf0)+_0x1e2771(0x1a4)+_0x1e2771(0x137)});}!_0x45d141[_0x1e2771(0xf7)](DATA_DIR)&&_0x1adf7e[_0x550d83(0xb6)]({'severity':_0x550d83(0x1ae),'category':_0x1e2771(0x122),'message':_0x1e2771(0x109)+'tory\x20missi'+_0x550d83(0x198)+_0x1e2771(0x11b),'fix':_0x1e2771(0x15f)+_0x1e2771(0x112)+'y','fixAction':_0x550d83(0x17d)+'s'});if(_0x45d141[_0x1e2771(0xf7)](TOOLS_MD)){const _0x39ddd0=_0x45d141[_0x1e2771(0xd8)+'nc'](TOOLS_MD,_0x1e2771(0x17f));!_0x39ddd0[_0x1e2771(0xfe)](_0x1e2771(0x168))&&_0x1adf7e['push']({'severity':'warning','category':'Tools','message':_0x550d83(0x158)+_0x1e2771(0x100)+'\x20tool\x20defi'+_0x550d83(0x15d)+_0x550d83(0x130)+_0x550d83(0x196),'fix':'Recreate\x20T'+_0x550d83(0x153)+_0x550d83(0x15c)+_0x1e2771(0xf2),'fixAction':_0x1e2771(0x169)+_0x550d83(0x1a0)});}else{if(_0x45d141[_0x550d83(0xf7)](TOOLS_JSON))try{JSON['parse'](_0x45d141[_0x550d83(0xd8)+'nc'](TOOLS_JSON,_0x1e2771(0x17f)));}catch{_0x1adf7e[_0x1e2771(0xb6)]({'severity':'error','category':'Tools','message':_0x550d83(0xdd)+_0x1e2771(0xc3)+_0x550d83(0x193),'fix':_0x550d83(0xef)+'r\x20JSON\x20err'+_0x550d83(0xee)+_0x1e2771(0x107)+'up','fixAction':'fix-tools-'+'json'});}else _0x1adf7e['push']({'severity':'info','category':_0x550d83(0xd1),'message':_0x1e2771(0xcf)+_0x550d83(0x160)+_0x550d83(0xb5)+_0x550d83(0xad)+_0x550d83(0x13d),'fix':'Create\x20too'+'ls.md\x20from'+_0x1e2771(0x127),'fixAction':'fix-tools-'+_0x1e2771(0x1a0)});}if(_0x45d141['existsSync'](CUSTOM_MODELS))try{JSON[_0x1e2771(0x16a)](_0x45d141[_0x1e2771(0xd8)+'nc'](CUSTOM_MODELS,_0x1e2771(0x17f)));}catch{_0x1adf7e[_0x1e2771(0xb6)]({'severity':_0x550d83(0x1ae),'category':_0x550d83(0xd4),'message':_0x1e2771(0x194)+_0x1e2771(0xb2)+_0x550d83(0x10c)+_0x550d83(0x159),'fix':_0x550d83(0xde)+'mpty\x20array','fixAction':'fix-custom'+'-models'});}if(_0x45d141[_0x550d83(0xf7)](CRON_FILE))try{JSON['parse'](_0x45d141[_0x1e2771(0xd8)+'nc'](CRON_FILE,_0x1e2771(0x17f)));}catch{_0x1adf7e[_0x1e2771(0xb6)]({'severity':_0x550d83(0x1ae),'category':_0x1e2771(0xe8),'message':_0x1e2771(0xc2)+_0x550d83(0x1af)+_0x550d83(0xeb)+'ON','fix':_0x550d83(0xde)+'mpty\x20array','fixAction':_0x550d83(0x174)+_0x1e2771(0xab)});}!_0x45d141[_0x550d83(0xf7)](SOUL_FILE)&&_0x1adf7e[_0x1e2771(0xb6)]({'severity':_0x550d83(0x1a8),'category':_0x1e2771(0xdb)+'y','message':_0x1e2771(0xdc)+_0x550d83(0x131)+_0x550d83(0x19e)+_0x1e2771(0x164),'fix':_0x1e2771(0xb0)+_0x550d83(0x14e)+'md','fixAction':'create-sou'+'l'});try{const _0x2b2a18=process[_0x550d83(0xca)],_0x26a5c2=parseInt(_0x2b2a18['slice'](0x57d*-0x7+0x972+-0x1cfa*-0x1));_0x26a5c2<-0x1176+-0x17f7+0x2981&&_0x1adf7e['push']({'severity':_0x1e2771(0x1a8),'category':_0x1e2771(0xaf),'message':_0x1e2771(0x19d)+_0x2b2a18+(_0x1e2771(0x114)+_0x1e2771(0x10e))});}catch{}try{const _0x14f50b=execSync(_0x550d83(0x1a6)+_0x1e2771(0x186),{'cwd':BOT_ROOT,'stdio':'pipe','timeout':0x1388})['toString'](),_0x922e9f=_0x14f50b[_0x550d83(0xc9)]()['split'](/\s+/),_0xf3aab2=parseInt(_0x922e9f[-0x81*-0x29+-0x1dc9+-0x5*-0x1d4]);_0xf3aab2>0x1*-0x74b+0x9*-0x23e+0x1a3*0x11&&_0x1adf7e['push']({'severity':'warning','category':_0x1e2771(0xaf),'message':_0x1e2771(0xcc)+_0xf3aab2+_0x1e2771(0xe0)});}catch{}try{execSync('pm2\x20jlist',{'stdio':_0x1e2771(0x1aa),'timeout':0x1388});}catch{_0x1adf7e[_0x1e2771(0xb6)]({'severity':'info','category':_0x550d83(0xaf),'message':_0x1e2771(0xbd)+_0x1e2771(0x12f)+_0x550d83(0x1a9)+_0x1e2771(0x14a)+_0x550d83(0xd2)});}return _0x1adf7e['length']===0x2f*0x5+0x6ce+-0x7b9&&_0x1adf7e[_0x1e2771(0xb6)]({'severity':_0x1e2771(0x180),'category':_0x1e2771(0x192),'message':_0x1e2771(0x183)+_0x1e2771(0x1a2)+_0x550d83(0xc5)}),_0x1adf7e;}function autoRepair(_0x11a00c){const _0xdefc51=_0x5b23e3,_0x33cc3e=_0x5b23e3;try{switch(_0x11a00c){case'create-env':{const _0x56de13=resolve(BOT_ROOT,_0xdefc51(0x18e)+'le');if(_0x45d141[_0x33cc3e(0xf7)](_0x56de13)){_0x45d141[_0x33cc3e(0x184)+'nc'](_0x56de13,ENV_FILE);try{_0x45d141['chmodSync'](ENV_FILE,0x1*-0x213d+0x1358*0x2+-0x3f3);}catch{}return{'ok':!![],'message':_0x33cc3e(0x14f)+'ed\x20from\x20.e'+_0x33cc3e(0x143)};}return writeSecure(ENV_FILE,_0x33cc3e(0x171)+_0x33cc3e(0x177)+'SERS=\x0aPRIM'+_0x33cc3e(0x1ad)+_0xdefc51(0x11e)+_0xdefc51(0xd3)),{'ok':!![],'message':'Default\x20.e'+'nv\x20created'+'\x20(BOT_TOKE'+_0x33cc3e(0xea)+_0x33cc3e(0xba)+'set)'};}case _0x33cc3e(0x17d)+'s':{return _0x45d141[_0x33cc3e(0xac)](DATA_DIR,{'recursive':!![]}),_0x45d141[_0xdefc51(0xac)](MEMORY_DIR,{'recursive':!![]}),{'ok':!![],'message':'Data\x20direc'+_0xdefc51(0x11a)+'ed'};}case _0xdefc51(0x169)+'json':{if(!_0x45d141['existsSync'](TOOLS_MD))return _0x45d141['mkdirSync'](dirname(TOOLS_MD),{'recursive':!![]}),_0x45d141[_0xdefc51(0x133)+_0x33cc3e(0x188)](TOOLS_MD,'#\x20Custom\x20T'+'ools\x0a\x0a>\x20De'+_0xdefc51(0xbc)+_0xdefc51(0x13a)+_0x33cc3e(0x123)+'\x20`##`\x20head'+_0xdefc51(0x166)+_0xdefc51(0xc4)+_0x33cc3e(0x1b1)),{'ok':!![],'message':'tools.md\x20c'+'reated\x20wit'+_0x33cc3e(0x18f)+_0xdefc51(0xd6)};return _0x45d141[_0xdefc51(0xac)](dirname(TOOLS_JSON),{'recursive':!![]}),_0x45d141[_0xdefc51(0x133)+'ync'](TOOLS_JSON,JSON['stringify']({'tools':[]},null,-0x28d*0x8+0x8*-0x296+0x2*0x148d)),{'ok':!![],'message':'tools.json'+_0x33cc3e(0x157)+_0x33cc3e(0xe9)+_0x33cc3e(0xb3)};}case'fix-custom'+_0x33cc3e(0x144):{return _0x45d141[_0xdefc51(0xac)](dirname(CUSTOM_MODELS),{'recursive':!![]}),_0x45d141[_0xdefc51(0x133)+'ync'](CUSTOM_MODELS,'[]'),{'ok':!![],'message':_0x33cc3e(0x194)+_0x33cc3e(0x191)+'eset'};}case _0x33cc3e(0x174)+_0xdefc51(0xab):{return _0x45d141[_0x33cc3e(0xac)](dirname(CRON_FILE),{'recursive':!![]}),_0x45d141[_0x33cc3e(0x133)+'ync'](CRON_FILE,'[]'),{'ok':!![],'message':_0xdefc51(0xc2)+_0xdefc51(0x19f)};}case _0x33cc3e(0x162)+'l':{return _0x45d141[_0x33cc3e(0xac)](dirname(SOUL_FILE),{'recursive':!![]}),_0x45d141['existsSync'](SOUL_EXAMPLE)?_0x45d141[_0x33cc3e(0x184)+'nc'](SOUL_EXAMPLE,SOUL_FILE):_0x45d141[_0x33cc3e(0x133)+_0x33cc3e(0x188)](SOUL_FILE,_0xdefc51(0x19c)+_0x33cc3e(0x14c)+_0xdefc51(0xb7)+(_0xdefc51(0x182)+_0x33cc3e(0x1ab)+_0xdefc51(0xc1)+_0x33cc3e(0x15b)+'\x20AI\x20assist'+_0xdefc51(0xf3))+(_0xdefc51(0x176)+'rly\x20and\x20pr'+'ecisely.\x20H'+_0xdefc51(0x132)+_0xdefc51(0x136)+_0x33cc3e(0xe3)+_0x33cc3e(0x14b))),{'ok':!![],'message':_0xdefc51(0x16c)+_0xdefc51(0x19b)+_0x33cc3e(0xb8)};}default:{if(_0x11a00c[_0xdefc51(0x135)](_0xdefc51(0x1a1)+_0x33cc3e(0x165))){const _0x54c06d=parseInt(_0x11a00c[_0xdefc51(0x172)](':')[-0x1d72+0x1*-0x1567+0x17*0x236]),_0xcb67f6=_0x45d141['readFileSy'+'nc'](ENV_FILE,_0xdefc51(0x17f))['split']('\x0a');if(_0x54c06d>=0x2439+-0x3b3+-0x2*0x1043&&_0x54c06d<_0xcb67f6[_0xdefc51(0x138)])return _0xcb67f6[_0x54c06d]='#\x20'+_0xcb67f6[_0x54c06d],writeSecure(ENV_FILE,_0xcb67f6['join']('\x0a')),{'ok':!![],'message':_0xdefc51(0x1a5)+(_0x54c06d+(-0xd7*0x2a+-0x2*-0x1f9+0x1f55))+(_0xdefc51(0x19a)+_0x33cc3e(0x116))};}return{'ok':![],'message':_0x33cc3e(0x189)+_0x33cc3e(0xf8)+_0x11a00c};}}}catch(_0x228312){return{'ok':![],'message':_0x228312 instanceof Error?_0x228312[_0x33cc3e(0x10b)]:String(_0x228312)};}}function createBackup(_0xb0dafe){const _0x44629c=_0x5b23e3,_0x30d701=_0x44cbf8,_0x1859dc=_0xb0dafe||_0x44629c(0x1b0)+new Date()[_0x44629c(0x199)+'g']()[_0x44629c(0x17e)](/[:.]/g,'-')[_0x44629c(0x190)](-0x12d5+0x5b7+-0x49*-0x2e,-0x2*-0x455+-0xf6b*0x1+0x6d4),_0x58824d=resolve(BACKUP_DIR,_0x1859dc);_0x45d141[_0x44629c(0xac)](_0x58824d,{'recursive':!![]});const _0xc1870=[];for(const {src:_0x4a61d3,label:_0x567725}of BACKUP_FILES){if(_0x45d141['existsSync'](_0x4a61d3)){const _0x6d6975=resolve(_0x58824d,_0x567725);_0x45d141[_0x30d701(0xac)](dirname(_0x6d6975),{'recursive':!![]}),_0x45d141['copyFileSy'+'nc'](_0x4a61d3,_0x6d6975),_0xc1870[_0x30d701(0xb6)](_0x567725);}}if(_0x45d141[_0x30d701(0xf7)](MEMORY_DIR)){const _0x4ab1fc=resolve(_0x58824d,_0x30d701(0xcd));_0x45d141[_0x30d701(0xac)](_0x4ab1fc,{'recursive':!![]});for(const _0x12c393 of _0x45d141[_0x30d701(0x12e)+'c'](MEMORY_DIR)){_0x12c393[_0x44629c(0x1ac)](_0x44629c(0x142))&&(_0x45d141[_0x44629c(0x184)+'nc'](resolve(MEMORY_DIR,_0x12c393),resolve(_0x4ab1fc,_0x12c393)),_0xc1870[_0x44629c(0xb6)](_0x44629c(0x149)+_0x12c393));}}return{'ok':!![],'id':_0x1859dc,'files':_0xc1870,'path':_0x58824d};}function listBackups(){const _0x3eb3ad=_0x5b23e3,_0x1cd339=_0x5b23e3;if(!_0x45d141[_0x3eb3ad(0xf7)](BACKUP_DIR))return[];return _0x45d141[_0x3eb3ad(0x12e)+'c'](BACKUP_DIR)['filter'](_0x495014=>{const _0x1c72d5=_0x3eb3ad,_0x3d2b2c=_0x1cd339,_0x1f747a=resolve(BACKUP_DIR,_0x495014);return _0x45d141[_0x1c72d5(0x14d)](_0x1f747a)[_0x1c72d5(0xbb)+'y']();})[_0x1cd339(0x104)](_0x57cb65=>{const _0xbcca60=resolve(BACKUP_DIR,_0x57cb65),_0x60739d=_0x45d141['statSync'](_0xbcca60);let _0x2f9301=-0x94c+0x26*-0xa9+0x2262,_0x58f980=0x24b3+0x1a87*-0x1+0xa2c*-0x1;function _0x16c90c(_0x2429bc){const _0x25afac=_0x45a6,_0x5178e0=_0x45a6;for(const _0x1a3f09 of _0x45d141[_0x25afac(0x12e)+'c'](_0x2429bc,{'withFileTypes':!![]})){if(_0x1a3f09['isDirector'+'y']())_0x16c90c(resolve(_0x2429bc,_0x1a3f09[_0x25afac(0x163)]));else _0x2f9301++,_0x58f980+=_0x45d141[_0x25afac(0x14d)](resolve(_0x2429bc,_0x1a3f09[_0x5178e0(0x163)]))[_0x5178e0(0x197)];}}return _0x16c90c(_0xbcca60),{'id':_0x57cb65,'createdAt':_0x60739d['mtimeMs'],'fileCount':_0x2f9301,'size':_0x58f980};})[_0x1cd339(0x13b)]((_0x8c16df,_0x3717d3)=>_0x3717d3['createdAt']-_0x8c16df['createdAt']);}function restoreBackup(_0x2fd444,_0x3b8443){const _0x557d23=_0x44cbf8,_0x894c3c=_0x5b23e3,_0x2e83de=resolve(BACKUP_DIR,_0x2fd444);if(!_0x2e83de[_0x557d23(0x135)](BACKUP_DIR)||!_0x45d141[_0x894c3c(0xf7)](_0x2e83de))return{'ok':![],'restored':[],'errors':[_0x557d23(0x118)+_0x894c3c(0x178)]};const _0x2c0e4f=[],_0x259da1=[],_0x215aef=new Map(BACKUP_FILES[_0x557d23(0x104)](_0x463cbc=>[_0x463cbc[_0x557d23(0x185)],_0x463cbc[_0x894c3c(0x110)]])),_0x3635db=_0x3b8443||BACKUP_FILES['map'](_0x535c2a=>_0x535c2a[_0x894c3c(0x185)]);for(const _0x351de5 of _0x3635db){const _0x57aa22=resolve(_0x2e83de,_0x351de5),_0x11b414=_0x215aef['get'](_0x351de5)||resolve(DATA_DIR,_0x351de5);if(_0x45d141[_0x894c3c(0xf7)](_0x57aa22))try{_0x45d141['mkdirSync'](dirname(_0x11b414),{'recursive':!![]}),_0x45d141[_0x557d23(0x184)+'nc'](_0x57aa22,_0x11b414),_0x2c0e4f[_0x557d23(0xb6)](_0x351de5);}catch(_0x4e557d){_0x259da1['push'](_0x351de5+':\x20'+(_0x4e557d instanceof Error?_0x4e557d[_0x894c3c(0x10b)]:String(_0x4e557d)));}}return{'ok':_0x259da1['length']===-0x12b3*0x1+-0x139f*0x1+0x2652,'restored':_0x2c0e4f,'errors':_0x259da1};}function getBackupFiles(_0x25fcbb){const _0x1b1999=_0x5b23e3,_0x230b3d=_0x5b23e3,_0x53cb74=resolve(BACKUP_DIR,_0x25fcbb);if(!_0x53cb74[_0x1b1999(0x135)](BACKUP_DIR)||!_0x45d141[_0x230b3d(0xf7)](_0x53cb74))return[];const _0x477e77=[];function _0x1f21c1(_0x32280c,_0x34c77b){const _0x411e25=_0x1b1999,_0x520154=_0x230b3d;for(const _0x539cf0 of _0x45d141[_0x411e25(0x12e)+'c'](_0x32280c,{'withFileTypes':!![]})){const _0x216085=_0x34c77b?_0x34c77b+'/'+_0x539cf0[_0x411e25(0x163)]:_0x539cf0[_0x520154(0x163)];if(_0x539cf0[_0x520154(0xbb)+'y']())_0x1f21c1(resolve(_0x32280c,_0x539cf0[_0x411e25(0x163)]),_0x216085);else _0x477e77['push'](_0x216085);}}return _0x1f21c1(_0x53cb74,''),_0x477e77;}function deleteBackup(_0x1c4324){const _0x4fdc6c=_0x44cbf8,_0x501d4e=_0x44cbf8,_0x55ae26=resolve(BACKUP_DIR,_0x1c4324);if(!_0x55ae26['startsWith'](BACKUP_DIR)||!_0x45d141[_0x4fdc6c(0xf7)](_0x55ae26))return![];return _0x45d141[_0x501d4e(0x170)](_0x55ae26,{'recursive':!![]}),!![];}export async function handleDoctorAPI(_0x56183f,_0x3d4755,_0x14f4bb,_0x4bc090){const _0x4fc67a=_0x5b23e3,_0x339ad0=_0x44cbf8;_0x3d4755[_0x4fc67a(0x16b)](_0x4fc67a(0x128)+'pe','applicatio'+'n/json');if(_0x14f4bb===_0x4fc67a(0xe5)+'r'){const _0x45b154=runHealthCheck(),_0xeca10d=_0x45b154[_0x4fc67a(0xda)](_0x4e01e6=>_0x4e01e6['severity']===_0x4fc67a(0x1ae))[_0x339ad0(0x138)],_0x43366d=_0x45b154['filter'](_0xc073ae=>_0xc073ae[_0x339ad0(0x16d)]===_0x339ad0(0x1a8))[_0x4fc67a(0x138)];return _0x3d4755[_0x4fc67a(0x15a)](JSON[_0x339ad0(0x1a7)]({'issues':_0x45b154,'errorCount':_0xeca10d,'warnCount':_0x43366d,'healthy':_0xeca10d===-0x1*-0x2c5+0x721*-0x5+0x20e0})),!![];}if(_0x14f4bb==='/api/docto'+_0x339ad0(0xe2)&&_0x56183f['method']==='POST'){try{const {action:_0x5e9890}=JSON['parse'](_0x4bc090),_0x4b1579=autoRepair(_0x5e9890);_0x3d4755[_0x4fc67a(0x15a)](JSON[_0x339ad0(0x1a7)](_0x4b1579));}catch{_0x3d4755[_0x339ad0(0xd9)]=0x1168+0x1ed*-0x12+0x1b6*0xb,_0x3d4755[_0x4fc67a(0x15a)](JSON[_0x4fc67a(0x1a7)]({'error':_0x339ad0(0xec)+'quest'}));}return!![];}if(_0x14f4bb===_0x4fc67a(0xe5)+_0x4fc67a(0xe7)+'ll'&&_0x56183f['method']===_0x339ad0(0xb9)){const _0x2ccd4c=runHealthCheck(),_0x96bc6e=[];for(const _0x137f9c of _0x2ccd4c){if(_0x137f9c['fixAction']){const _0x388169=autoRepair(_0x137f9c[_0x339ad0(0x148)]);_0x96bc6e[_0x4fc67a(0xb6)]({'action':_0x137f9c['fixAction'],..._0x388169});}}return _0x3d4755[_0x4fc67a(0x15a)](JSON['stringify']({'results':_0x96bc6e})),!![];}if(_0x14f4bb===_0x339ad0(0x115)+'ps'){const _0x40b1cd=listBackups();return _0x3d4755['end'](JSON[_0x339ad0(0x1a7)]({'backups':_0x40b1cd})),!![];}if(_0x14f4bb===_0x339ad0(0x115)+'ps/create'&&_0x56183f[_0x339ad0(0x119)]==='POST'){try{const {name:_0x21db6a}=JSON[_0x339ad0(0x16a)](_0x4bc090||'{}'),_0x343abf=createBackup(_0x21db6a);_0x3d4755[_0x4fc67a(0x15a)](JSON['stringify'](_0x343abf));}catch(_0x3abe2b){const _0x370d57=_0x3abe2b instanceof Error?_0x3abe2b[_0x339ad0(0x10b)]:String(_0x3abe2b);_0x3d4755[_0x339ad0(0x15a)](JSON[_0x339ad0(0x1a7)]({'ok':![],'error':_0x370d57}));}return!![];}if(_0x14f4bb===_0x339ad0(0x115)+_0x4fc67a(0x105)&&_0x56183f[_0x339ad0(0x119)]===_0x4fc67a(0xb9)){try{const {id:_0x37dac4,files:_0x304515}=JSON[_0x339ad0(0x16a)](_0x4bc090),_0x1b0f9e=restoreBackup(_0x37dac4,_0x304515);_0x3d4755[_0x4fc67a(0x15a)](JSON['stringify'](_0x1b0f9e));}catch{_0x3d4755[_0x339ad0(0xd9)]=-0x19e*-0x3+0x110+0x45a*-0x1,_0x3d4755[_0x339ad0(0x15a)](JSON[_0x339ad0(0x1a7)]({'error':_0x339ad0(0xec)+_0x4fc67a(0x113)}));}return!![];}if(_0x14f4bb[_0x339ad0(0xb4)](/^\/api\/backups\/[^/]+\/files$/)){const _0x35f01f=_0x14f4bb[_0x339ad0(0x172)]('/')[-0x1d*-0x41+0x1*-0x3cb+0x38f*-0x1],_0x1027a4=getBackupFiles(_0x35f01f);return _0x3d4755['end'](JSON['stringify']({'id':_0x35f01f,'files':_0x1027a4})),!![];}if(_0x14f4bb===_0x339ad0(0x115)+_0x339ad0(0x106)&&_0x56183f[_0x339ad0(0x119)]===_0x4fc67a(0xb9)){try{const {id:_0x515842}=JSON[_0x4fc67a(0x16a)](_0x4bc090),_0x378b95=deleteBackup(_0x515842);_0x3d4755[_0x4fc67a(0x15a)](JSON['stringify']({'ok':_0x378b95}));}catch{_0x3d4755['statusCode']=-0x36c*-0xb+0x19a5+-0x3db9,_0x3d4755[_0x339ad0(0x15a)](JSON[_0x339ad0(0x1a7)]({'error':_0x339ad0(0xec)+_0x339ad0(0x113)}));}return!![];}if(_0x14f4bb==='/api/bot/r'+_0x339ad0(0x195)&&_0x56183f['method']===_0x4fc67a(0xb9)){const {scheduleGracefulRestart:_0xe80f04}=await import(_0x339ad0(0x11f)+'s/restart.'+'js');return _0x3d4755[_0x4fc67a(0x15a)](JSON['stringify']({'ok':!![],'note':_0x339ad0(0x140)+_0x339ad0(0x1a3)})),_0xe80f04(0x24c7+0x2706+-0x49d9),!![];}if(_0x14f4bb==='/api/pm2/s'+_0x339ad0(0x10f)){try{const {detectProcessManager:_0x7e3c1c}=await import(_0x339ad0(0x11f)+_0x339ad0(0xc0)+'manager.js'),_0x4cd83a=_0x7e3c1c(),_0x2794c7=await _0x4cd83a['getStatus']();_0x3d4755[_0x339ad0(0x15a)](JSON[_0x4fc67a(0x1a7)]({'process':{'name':_0x4fc67a(0x179),'kind':_0x2794c7[_0x4fc67a(0x151)],'pid':_0x2794c7[_0x4fc67a(0x11c)]??0x33f*-0x7+0x1327*-0x1+0x29e0,'status':_0x2794c7[_0x339ad0(0x187)],'uptime':_0x2794c7[_0x339ad0(0x141)]??0xd7*0x1+-0x18b*0x13+0x1c7a,'memory':_0x2794c7['memory']??0x25da+0xdf4+-0x26*0x15d,'cpu':_0x2794c7['cpu']??0x7c5+0x1311+-0x1ad6,'restarts':_0x2794c7[_0x339ad0(0xdf)]??0x498+-0x4c+-0x44c,'version':_0x2794c7[_0x339ad0(0xca)]||'?','nodeVersion':_0x2794c7[_0x339ad0(0x12b)+'n']||process['version'],'execPath':_0x2794c7[_0x4fc67a(0xae)]||'?','cwd':_0x2794c7[_0x4fc67a(0xbe)]||'?'}}));}catch(_0x31678c){const _0x3bc830=_0x31678c instanceof Error?_0x31678c['message']:String(_0x31678c);_0x3d4755[_0x339ad0(0x15a)](JSON['stringify']({'error':_0x4fc67a(0x17c)+_0x339ad0(0x150)+'ction\x20fail'+_0x339ad0(0x13f)+_0x3bc830}));}return!![];}if(_0x14f4bb===_0x339ad0(0xe4)+_0x339ad0(0xce)&&_0x56183f[_0x339ad0(0x119)]===_0x4fc67a(0xb9)){try{const {action:_0x322bea}=JSON[_0x339ad0(0x16a)](_0x4bc090),_0x154edd=['restart','stop',_0x339ad0(0xff),_0x339ad0(0xc8),_0x4fc67a(0x18c)];if(!_0x154edd['includes'](_0x322bea))return _0x3d4755[_0x4fc67a(0xd9)]=0x8f9*0x1+-0x1110+0x9a7,_0x3d4755['end'](JSON['stringify']({'ok':![],'error':_0x339ad0(0x126)+_0x339ad0(0xf8)+_0x322bea})),!![];const {detectProcessManager:_0x57ca44}=await import(_0x339ad0(0x11f)+_0x4fc67a(0xc0)+'manager.js'),_0x58f34c=_0x57ca44();if(_0x322bea==='flush'){const _0x448e04=resolve(DATA_DIR,_0x339ad0(0x12d));for(const _0x5cd83f of[_0x339ad0(0x12c)+_0x339ad0(0xf9),_0x4fc67a(0x12c)+_0x339ad0(0xfc)]){try{_0x45d141[_0x339ad0(0x129)+'nc'](resolve(_0x448e04,_0x5cd83f),0xc06+0x1732+-0x2338);}catch{}}return _0x3d4755[_0x339ad0(0x15a)](JSON[_0x4fc67a(0x1a7)]({'ok':!![],'message':'Logs\x20flush'+'ed'})),!![];}if(_0x322bea==='stop')return _0x3d4755[_0x4fc67a(0x15a)](JSON[_0x339ad0(0x1a7)]({'ok':!![],'message':_0x4fc67a(0x18b)+_0x339ad0(0x12a)+_0x58f34c['kind']+_0x339ad0(0x111)})),setTimeout(()=>{const _0x361a7a=_0x339ad0;_0x58f34c['stop']()[_0x361a7a(0x120)](()=>{});},0x1*0x1a6b+0x1ca3+-0x35e2),!![];if(_0x322bea==='start')return await _0x58f34c[_0x339ad0(0xff)](),_0x3d4755[_0x4fc67a(0x15a)](JSON['stringify']({'ok':!![],'message':_0x339ad0(0x16f)+_0x4fc67a(0xbf)+_0x58f34c[_0x339ad0(0x151)]})),!![];if(_0x322bea===_0x339ad0(0xed)||_0x322bea===_0x339ad0(0xc8)){const {scheduleGracefulRestart:_0x26b3ae}=await import(_0x339ad0(0x11f)+_0x4fc67a(0xe1)+'js');return _0x3d4755[_0x4fc67a(0x15a)](JSON[_0x339ad0(0x1a7)]({'ok':!![],'message':_0x339ad0(0x103)+(_0x322bea===_0x4fc67a(0xed)?_0x339ad0(0x13e):'reloading')+'\x20('+_0x58f34c[_0x4fc67a(0x151)]+')...'})),_0x26b3ae(0x9ec+-0x1*-0x2072+0x2*-0x1435),!![];}}catch(_0xb2455b){_0x3d4755[_0x4fc67a(0x15a)](JSON[_0x4fc67a(0x1a7)]({'ok':![],'error':_0xb2455b instanceof Error?_0xb2455b[_0x4fc67a(0x10b)]:String(_0xb2455b)}));}return!![];}if(_0x14f4bb==='/api/pm2/l'+_0x339ad0(0x13c)){try{const {detectProcessManager:_0x359b94}=await import(_0x339ad0(0x11f)+_0x4fc67a(0xc0)+_0x4fc67a(0xfb)),_0xa49dd8=_0x359b94(),_0x1b27dc=await _0xa49dd8[_0x339ad0(0x15e)](0x1*0x1a4d+-0x1a94+0x65);_0x3d4755[_0x4fc67a(0x15a)](JSON[_0x339ad0(0x1a7)]({'logs':_0x1b27dc,'kind':_0xa49dd8[_0x339ad0(0x151)]}));}catch(_0x3175a0){_0x3d4755[_0x4fc67a(0x15a)](JSON[_0x4fc67a(0x1a7)]({'error':_0x4fc67a(0xf1)+_0x4fc67a(0x125),'logs':'','detail':_0x3175a0 instanceof Error?_0x3175a0[_0x339ad0(0x10b)]:String(_0x3175a0)}));}return!![];}return![];}
|