alvin-bot 5.7.0 → 5.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +25 -31
- 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 -174
- 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 -583
- 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 -86
- 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 -1902
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
|
@@ -1,2336 +1 @@
|
|
|
1
|
-
import { InlineKeyboard, InputFile } from "grammy";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path, { resolve } from "path";
|
|
4
|
-
import os from "os";
|
|
5
|
-
import { getSession, buildSessionKey, resetSession, markSessionDirty, getTelegramWorkspace, setTelegramWorkspace } from "../services/session.js";
|
|
6
|
-
import { listWorkspaces, getWorkspace } from "../services/workspaces.js";
|
|
7
|
-
import { getRegistry } from "../engine.js";
|
|
8
|
-
import { reloadSoul } from "../services/personality.js";
|
|
9
|
-
import { parseDuration, createReminder, listReminders, cancelReminder } from "../services/reminders.js";
|
|
10
|
-
import { writeSessionSummary, getMemoryStats, appendDailyLog } from "../services/memory.js";
|
|
11
|
-
import { approveGroup, blockGroup, listGroups, getSettings, setForwardingAllowed, setAutoApprove, } from "../services/access.js";
|
|
12
|
-
import { generateImage } from "../services/imagegen.js";
|
|
13
|
-
import { searchMemory, reindexMemory, getIndexStats } from "../services/embeddings.js";
|
|
14
|
-
import { listProfiles, addUserNote } from "../services/users.js";
|
|
15
|
-
import { getLoadedPlugins, getPluginsDir } from "../services/plugins.js";
|
|
16
|
-
import { getMCPStatus, getMCPTools, callMCPTool } from "../services/mcp.js";
|
|
17
|
-
import { listCustomTools, executeCustomTool } from "../services/custom-tools.js";
|
|
18
|
-
import { screenshotUrl, extractText, generatePdf, hasPlaywright } from "../services/browser.js";
|
|
19
|
-
import { writeEnvVar } from "../services/env-file.js";
|
|
20
|
-
import { listJobs, createJob, deleteJob, toggleJob, runJobNow, formatNextRun, humanReadableSchedule } from "../services/cron.js";
|
|
21
|
-
import { resolveJobByNameOrId } from "../services/cron-resolver.js";
|
|
22
|
-
import { buildTickerText, buildDoneText, escapeMarkdown } from "./cron-progress.js";
|
|
23
|
-
import { isHarmlessTelegramError } from "../util/telegram-error-filter.js";
|
|
24
|
-
import { storePassword, revokePassword, getSudoStatus, verifyPassword } from "../services/sudo.js";
|
|
25
|
-
import { config } from "../config.js";
|
|
26
|
-
import { BOT_VERSION } from "../version.js";
|
|
27
|
-
import { getWebPort } from "../web/server.js";
|
|
28
|
-
import { getUsageSummary, getAllRateLimits, formatTokens } from "../services/usage-tracker.js";
|
|
29
|
-
import { runUpdate, getAutoUpdate, setAutoUpdate, startAutoUpdateLoop } from "../services/updater.js";
|
|
30
|
-
import { markExpectedRestart } from "../services/watchdog.js";
|
|
31
|
-
import { getReleaseHighlights } from "../services/release-highlights.js";
|
|
32
|
-
import { runCleanup, getCleanupPolicy } from "../services/disk-cleanup.js";
|
|
33
|
-
import { getHealthStatus, isFailedOver } from "../services/heartbeat.js";
|
|
34
|
-
import { t, LOCALE_NAMES, LOCALE_FLAGS } from "../i18n.js";
|
|
35
|
-
import { requestStop, interruptQuery } from "../services/stop-controller.js";
|
|
36
|
-
import { killSessionDetachedAgents, cancelPendingForSession } from "../services/async-agent-watcher.js";
|
|
37
|
-
// Kick off auto-update loop on module load if the persistent flag is set.
|
|
38
|
-
// Doing this as a module side-effect avoids touching the bot entry point.
|
|
39
|
-
if (getAutoUpdate()) {
|
|
40
|
-
// 30s delay so the bot is fully started before the first check
|
|
41
|
-
setTimeout(() => startAutoUpdateLoop(), 30_000);
|
|
42
|
-
}
|
|
43
|
-
/** Bot start time for uptime tracking */
|
|
44
|
-
const botStartTime = Date.now();
|
|
45
|
-
/** Format bytes to human-readable */
|
|
46
|
-
function formatBytes(bytes) {
|
|
47
|
-
if (bytes < 1024)
|
|
48
|
-
return `${bytes} B`;
|
|
49
|
-
if (bytes < 1024 * 1024)
|
|
50
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
51
|
-
if (bytes < 1024 * 1024 * 1024)
|
|
52
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
53
|
-
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
54
|
-
}
|
|
55
|
-
/** Render a working directory path with a meaningful label.
|
|
56
|
-
* Home → 🏠 ~ (Home), anywhere under home → 📁 ~/rel/path, absolute → 📁 /path */
|
|
57
|
-
function formatWorkingDir(workingDir, locale) {
|
|
58
|
-
const home = os.homedir();
|
|
59
|
-
if (workingDir === home) {
|
|
60
|
-
return `🏠 \`~\` _(${t("bot.status.homeLabel", locale)})_`;
|
|
61
|
-
}
|
|
62
|
-
if (workingDir.startsWith(home + "/")) {
|
|
63
|
-
return `📁 \`~${workingDir.slice(home.length)}\``;
|
|
64
|
-
}
|
|
65
|
-
return `📁 \`${workingDir}\``;
|
|
66
|
-
}
|
|
67
|
-
/** Format a raw token count for the context progress line.
|
|
68
|
-
* Keeps precision tight — "450k/1M" not "450.2k/1.0M". */
|
|
69
|
-
function formatContextTokens(n) {
|
|
70
|
-
if (n < 1_000)
|
|
71
|
-
return String(n);
|
|
72
|
-
if (n < 1_000_000)
|
|
73
|
-
return `${Math.round(n / 1_000)}k`;
|
|
74
|
-
const m = n / 1_000_000;
|
|
75
|
-
return m >= 10 ? `${Math.round(m)}M` : `${m.toFixed(1)}M`;
|
|
76
|
-
}
|
|
77
|
-
/** Human relative-time rendered in the user's locale. */
|
|
78
|
-
function formatRelativeTime(ms, locale) {
|
|
79
|
-
const s = Math.floor(ms / 1000);
|
|
80
|
-
if (s < 10)
|
|
81
|
-
return t("bot.time.justNow", locale);
|
|
82
|
-
if (s < 60)
|
|
83
|
-
return t("bot.time.secondsAgo", locale, { n: s });
|
|
84
|
-
const m = Math.floor(s / 60);
|
|
85
|
-
if (m < 60)
|
|
86
|
-
return t("bot.time.minutesAgo", locale, { n: m });
|
|
87
|
-
const h = Math.floor(m / 60);
|
|
88
|
-
if (h < 24)
|
|
89
|
-
return t("bot.time.hoursAgo", locale, { n: h });
|
|
90
|
-
const d = Math.floor(h / 24);
|
|
91
|
-
return t(d === 1 ? "bot.time.dayAgo" : "bot.time.daysAgo", locale, { n: d });
|
|
92
|
-
}
|
|
93
|
-
const EFFORT_LABELS = {
|
|
94
|
-
low: "Low — Quick, concise answers",
|
|
95
|
-
medium: "Medium — Moderate reasoning depth",
|
|
96
|
-
high: "High — Deep reasoning (default)",
|
|
97
|
-
max: "Max — Maximum effort (Opus only)",
|
|
98
|
-
};
|
|
99
|
-
export function registerCommands(bot) {
|
|
100
|
-
bot.command("ping", async (ctx) => {
|
|
101
|
-
const start = Date.now();
|
|
102
|
-
const registry = getRegistry();
|
|
103
|
-
const active = registry.getActive();
|
|
104
|
-
const info = active.getInfo();
|
|
105
|
-
const latency = Date.now() - start;
|
|
106
|
-
await ctx.reply(`🏓 Pong! (${latency}ms)\n${info.name} ${info.status}`);
|
|
107
|
-
});
|
|
108
|
-
bot.command("help", async (ctx) => {
|
|
109
|
-
await ctx.reply(`🤖 *Alvin Bot — Commands*\n\n` +
|
|
110
|
-
`💬 *Chat*\n` +
|
|
111
|
-
`Just write — I'll respond.\n` +
|
|
112
|
-
`I also understand voice messages & photos.\n\n` +
|
|
113
|
-
`⚙️ *Controls*\n` +
|
|
114
|
-
`/model — Switch AI model\n` +
|
|
115
|
-
`/fallback — Provider order\n` +
|
|
116
|
-
`/effort — Set reasoning depth\n` +
|
|
117
|
-
`/voice — Voice replies on/off\n` +
|
|
118
|
-
`/dir <path> — Working directory\n\n` +
|
|
119
|
-
`🧭 *Workspaces*\n` +
|
|
120
|
-
`/workspaces — List all workspaces\n` +
|
|
121
|
-
`/workspace <name> — Switch active workspace\n` +
|
|
122
|
-
`/workspace default — Reset to default\n\n` +
|
|
123
|
-
`🎨 *Extras*\n` +
|
|
124
|
-
`/imagine <prompt> — Generate image\n` +
|
|
125
|
-
`/remind <time> <text> — Set reminder\n` +
|
|
126
|
-
`/export — Export conversation\n\n` +
|
|
127
|
-
`🧠 *Memory*\n` +
|
|
128
|
-
`/recall <query> — Semantic search\n` +
|
|
129
|
-
`/remember <text> — Remember something\n` +
|
|
130
|
-
`/reindex — Re-index memory\n\n` +
|
|
131
|
-
`🌐 *Browser*\n` +
|
|
132
|
-
`/browse <URL> — Screenshot\n` +
|
|
133
|
-
`/browse text <URL> — Extract text\n` +
|
|
134
|
-
`/browse pdf <URL> — Save as PDF\n\n` +
|
|
135
|
-
`🔌 *Extensions*\n` +
|
|
136
|
-
`/plugins — Loaded plugins\n` +
|
|
137
|
-
`/mcp — MCP servers & tools\n` +
|
|
138
|
-
`/users — User profiles\n\n` +
|
|
139
|
-
`🖥️ *Web UI*\n` +
|
|
140
|
-
`/webui — Open Web UI in browser\n\n` +
|
|
141
|
-
`📊 *Session*\n` +
|
|
142
|
-
`/status — Current status\n` +
|
|
143
|
-
`/new — Start new session\n` +
|
|
144
|
-
`/cancel — Cancel running request\n\n` +
|
|
145
|
-
`🔧 *Ops*\n` +
|
|
146
|
-
`/restart — Restart the bot\n` +
|
|
147
|
-
`/update — Pull latest + rebuild + restart\n` +
|
|
148
|
-
`/autoupdate on|off — Auto-update loop (6h)\n\n` +
|
|
149
|
-
`_Tip: Send me documents, photos, or voice messages!_\n` +
|
|
150
|
-
`_In groups: @mention me or reply to my messages._`, { parse_mode: "Markdown" });
|
|
151
|
-
});
|
|
152
|
-
// Register bot commands in Telegram's menu
|
|
153
|
-
bot.api.setMyCommands([
|
|
154
|
-
{ command: "help", description: "Show all commands" },
|
|
155
|
-
{ command: "model", description: "Switch AI model" },
|
|
156
|
-
{ command: "effort", description: "Set reasoning depth" },
|
|
157
|
-
{ command: "voice", description: "Voice replies on/off" },
|
|
158
|
-
{ command: "status", description: "Current status" },
|
|
159
|
-
{ command: "version", description: "Show Alvin Bot version" },
|
|
160
|
-
{ command: "new", description: "Start new session" },
|
|
161
|
-
{ command: "dir", description: "Change working directory" },
|
|
162
|
-
{ command: "workspaces", description: "List all workspaces" },
|
|
163
|
-
{ command: "workspace", description: "Switch active workspace" },
|
|
164
|
-
{ command: "web", description: "Quick web search" },
|
|
165
|
-
{ command: "imagine", description: "Generate image (e.g. /imagine A fox)" },
|
|
166
|
-
{ command: "remind", description: "Set reminder (e.g. /remind 30m Text)" },
|
|
167
|
-
{ command: "export", description: "Export conversation" },
|
|
168
|
-
{ command: "recall", description: "Semantic memory search" },
|
|
169
|
-
{ command: "remember", description: "Remember something" },
|
|
170
|
-
{ command: "cron", description: "Manage scheduled jobs" },
|
|
171
|
-
{ command: "subagents", description: "Manage background sub-agents" },
|
|
172
|
-
{ command: "webui", description: "Open Web UI in browser" },
|
|
173
|
-
{ command: "setup", description: "Configure API keys & platforms" },
|
|
174
|
-
{ command: "cancel", description: "Cancel running request" },
|
|
175
|
-
{ command: "restart", description: "Restart the bot" },
|
|
176
|
-
{ command: "update", description: "Pull latest, build, restart" },
|
|
177
|
-
{ command: "autoupdate", description: "Auto-update on|off|status" },
|
|
178
|
-
]).catch(err => console.error("Failed to set bot commands:", err));
|
|
179
|
-
bot.command("start", async (ctx) => {
|
|
180
|
-
const registry = getRegistry();
|
|
181
|
-
const activeInfo = registry.getActive().getInfo();
|
|
182
|
-
await ctx.reply(`👋 *Hey! I'm Alvin Bot.*\n\n` +
|
|
183
|
-
`Your autonomous AI assistant on Telegram. Just write me — ` +
|
|
184
|
-
`I understand text, voice messages, photos, and documents.\n\n` +
|
|
185
|
-
`🤖 Model: *${activeInfo.name}*\n` +
|
|
186
|
-
`🧠 Reasoning: High\n\n` +
|
|
187
|
-
`Type /help for all commands.`, { parse_mode: "Markdown" });
|
|
188
|
-
});
|
|
189
|
-
bot.command("webui", async (ctx) => {
|
|
190
|
-
const port = getWebPort();
|
|
191
|
-
const url = `http://localhost:${port}`;
|
|
192
|
-
await ctx.reply(`🌐 *Web UI* is running on port ${port}.\n\n` +
|
|
193
|
-
`Open in your browser:\n${url}`, { parse_mode: "Markdown" });
|
|
194
|
-
});
|
|
195
|
-
bot.command("new", async (ctx) => {
|
|
196
|
-
const userId = ctx.from.id;
|
|
197
|
-
const session = getSession(userId);
|
|
198
|
-
const hadSession = !!session.sessionId || session.history.length > 0;
|
|
199
|
-
const msgCount = session.messageCount;
|
|
200
|
-
const cost = session.totalCost;
|
|
201
|
-
// Write session summary to daily log before reset
|
|
202
|
-
if (hadSession && msgCount > 0) {
|
|
203
|
-
const registry = getRegistry();
|
|
204
|
-
writeSessionSummary({
|
|
205
|
-
messageCount: msgCount,
|
|
206
|
-
toolUseCount: session.toolUseCount,
|
|
207
|
-
costUsd: cost,
|
|
208
|
-
provider: registry.getActiveKey(),
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
resetSession(userId);
|
|
212
|
-
if (hadSession) {
|
|
213
|
-
await ctx.reply(`🔄 *New session started.*\n\n` +
|
|
214
|
-
`Previous session: ${msgCount} messages, $${cost.toFixed(4)} cost.\n` +
|
|
215
|
-
`Summary saved to memory.`, { parse_mode: "Markdown" });
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
await ctx.reply("🔄 New session started.");
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
bot.command("dir", async (ctx) => {
|
|
222
|
-
const userId = ctx.from.id;
|
|
223
|
-
const session = getSession(userId);
|
|
224
|
-
const newDir = ctx.match?.trim();
|
|
225
|
-
if (!newDir) {
|
|
226
|
-
await ctx.reply(`Current directory: ${session.workingDir}`);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const resolved = newDir.startsWith("~")
|
|
230
|
-
? path.join(os.homedir(), newDir.slice(1))
|
|
231
|
-
: path.resolve(newDir);
|
|
232
|
-
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
|
233
|
-
// v4.19.1 — Claude Agent SDK's `resume` is bound to the cwd. Changing
|
|
234
|
-
// the working dir without clearing the resume anchor would make the
|
|
235
|
-
// next SDK turn look up the session file in the wrong project folder
|
|
236
|
-
// → silent empty stream. Null out sessionId + history-anchor so the
|
|
237
|
-
// next turn starts a fresh SDK session in the new cwd.
|
|
238
|
-
const cwdChanged = session.workingDir !== resolved;
|
|
239
|
-
session.workingDir = resolved;
|
|
240
|
-
if (cwdChanged) {
|
|
241
|
-
session.sessionId = null;
|
|
242
|
-
// v4.19.2 — Anchor at current last turn so no catch-up bridge is
|
|
243
|
-
// generated for the next turn. /dir semantically means "switch
|
|
244
|
-
// project context" just like /workspace — starting fresh is the
|
|
245
|
-
// sane default.
|
|
246
|
-
session.lastSdkHistoryIndex = session.history.length - 1;
|
|
247
|
-
}
|
|
248
|
-
markSessionDirty(userId);
|
|
249
|
-
await ctx.reply(`Working directory: ${session.workingDir}`);
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
await ctx.reply(`Directory not found: ${resolved}`);
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
bot.command("version", async (ctx) => {
|
|
256
|
-
await ctx.reply(`🤖 *Alvin Bot* \`v${BOT_VERSION}\`\n` +
|
|
257
|
-
`Node ${process.version} · ${process.platform}/${process.arch}`, { parse_mode: "Markdown" });
|
|
258
|
-
});
|
|
259
|
-
bot.command("status", async (ctx) => {
|
|
260
|
-
const userId = ctx.from.id;
|
|
261
|
-
const session = getSession(userId);
|
|
262
|
-
const lang = session.language;
|
|
263
|
-
const registry = getRegistry();
|
|
264
|
-
const active = registry.getActive();
|
|
265
|
-
const info = active.getInfo();
|
|
266
|
-
// Uptime
|
|
267
|
-
const uptimeMs = Date.now() - botStartTime;
|
|
268
|
-
const uptimeH = Math.floor(uptimeMs / 3_600_000);
|
|
269
|
-
const uptimeM = Math.floor((uptimeMs % 3_600_000) / 60_000);
|
|
270
|
-
// Provider type detection
|
|
271
|
-
const isOAuth = active.config.type === "claude-sdk" || active.config.type === "codex-cli";
|
|
272
|
-
const providerTag = isOAuth ? "_Flat-Rate_" : "_API_";
|
|
273
|
-
// ── Session block — intelligent empty/active/idle rendering ─────────
|
|
274
|
-
// The in-memory session is always fresh after a bot restart, so plain
|
|
275
|
-
// "Session (0 min)" with all zeros looks broken. Render an empty state
|
|
276
|
-
// explicitly, plus active/idle badges based on last activity.
|
|
277
|
-
const now = Date.now();
|
|
278
|
-
const idleMs = now - session.lastActivity;
|
|
279
|
-
const sessionAgeMs = now - session.startedAt;
|
|
280
|
-
const sessionAgeMin = Math.floor(sessionAgeMs / 60_000);
|
|
281
|
-
const IDLE_THRESHOLD_MS = 2 * 60 * 1000;
|
|
282
|
-
const isEmpty = session.messageCount === 0
|
|
283
|
-
&& !session.sessionId
|
|
284
|
-
&& session.history.length === 0;
|
|
285
|
-
let sessionBlock;
|
|
286
|
-
const sessionHeader = t("bot.status.sessionHeader", lang);
|
|
287
|
-
if (isEmpty) {
|
|
288
|
-
sessionBlock = `${sessionHeader}\n${t("bot.status.sessionNew", lang)}`;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
const isActiveNow = idleMs < IDLE_THRESHOLD_MS;
|
|
292
|
-
const badge = isActiveNow ? t("bot.status.active", lang) : t("bot.status.idle", lang);
|
|
293
|
-
// Line 1: activity summary
|
|
294
|
-
const msgWord = t(session.messageCount === 1 ? "bot.status.message" : "bot.status.messages", lang);
|
|
295
|
-
const toolWord = t(session.toolUseCount === 1 ? "bot.status.toolCall" : "bot.status.toolCalls", lang);
|
|
296
|
-
const summary = `${badge} — ${session.messageCount} ${msgWord}, ${session.toolUseCount} ${toolWord}`;
|
|
297
|
-
// Line 2: tokens (only if non-zero — zero is noise after restart)
|
|
298
|
-
const totalTok = session.totalInputTokens + session.totalOutputTokens;
|
|
299
|
-
const tokenLine = totalTok > 0
|
|
300
|
-
? `\nTokens: ${formatTokens(session.totalInputTokens)} in / ${formatTokens(session.totalOutputTokens)} out`
|
|
301
|
-
: "";
|
|
302
|
-
// Line 2.5: context window usage progress (X / Y with percentage).
|
|
303
|
-
// Shown only when we have both a last-turn input token count AND the
|
|
304
|
-
// provider declares its context window. Otherwise skipped to avoid
|
|
305
|
-
// showing meaningless zeros.
|
|
306
|
-
const ctxWindow = active.config.contextWindow;
|
|
307
|
-
let contextLine = "";
|
|
308
|
-
if (session.lastTurnInputTokens > 0 && typeof ctxWindow === "number" && ctxWindow > 0) {
|
|
309
|
-
const used = session.lastTurnInputTokens;
|
|
310
|
-
const pct = Math.round((used / ctxWindow) * 100);
|
|
311
|
-
contextLine = `\nContext: ${formatContextTokens(used)}/${formatContextTokens(ctxWindow)} (${pct}%)`;
|
|
312
|
-
}
|
|
313
|
-
// Line 3: timing (age + last turn)
|
|
314
|
-
const ageStr = sessionAgeMin >= 1
|
|
315
|
-
? `${sessionAgeMin} min`
|
|
316
|
-
: t("bot.status.lessThanMin", lang);
|
|
317
|
-
const timingLine = `\n${t("bot.status.duration", lang)}: ${ageStr} | ${t("bot.status.lastTurn", lang)}: ${formatRelativeTime(idleMs, lang)}`;
|
|
318
|
-
// Line 4: cost (only for non-OAuth providers AND only when meaningful)
|
|
319
|
-
const costLine = (!isOAuth && session.totalCost > 0)
|
|
320
|
-
? `\nCost: $${session.totalCost.toFixed(4)}`
|
|
321
|
-
: "";
|
|
322
|
-
// Line 5: telemetry counters — compactions (non-SDK), checkpoint
|
|
323
|
-
// hints (SDK), and SDK-internal sub-tasks (Claude's Task tool).
|
|
324
|
-
// Each only shown when > 0 to keep the status clean.
|
|
325
|
-
const telemetryParts = [];
|
|
326
|
-
if (session.compactionCount > 0) {
|
|
327
|
-
telemetryParts.push(`Compactions: ${session.compactionCount}`);
|
|
328
|
-
}
|
|
329
|
-
if (session.checkpointHintsInjected > 0) {
|
|
330
|
-
telemetryParts.push(`Checkpoint hints: ${session.checkpointHintsInjected}`);
|
|
331
|
-
}
|
|
332
|
-
if (session.sdkSubTaskCount > 0) {
|
|
333
|
-
telemetryParts.push(`SDK sub-tasks: ${session.sdkSubTaskCount}`);
|
|
334
|
-
}
|
|
335
|
-
const telemetryLine = telemetryParts.length > 0
|
|
336
|
-
? `\n${telemetryParts.join(" | ")}`
|
|
337
|
-
: "";
|
|
338
|
-
sessionBlock = `${sessionHeader}\n${summary}${tokenLine}${contextLine}${timingLine}${costLine}${telemetryLine}`;
|
|
339
|
-
}
|
|
340
|
-
// Usage summary (daily/weekly from tracker)
|
|
341
|
-
const usage = getUsageSummary();
|
|
342
|
-
const todayTotalTok = usage.today.inputTokens + usage.today.outputTokens;
|
|
343
|
-
const weekTotalTok = usage.week.inputTokens + usage.week.outputTokens;
|
|
344
|
-
const todayTok = formatTokens(todayTotalTok);
|
|
345
|
-
const weekTok = formatTokens(weekTotalTok);
|
|
346
|
-
// Cost or plan label for usage section
|
|
347
|
-
const todayCostStr = isOAuth ? "" : ` ($${usage.today.costUsd.toFixed(4)})`;
|
|
348
|
-
const weekCostStr = isOAuth ? "" : ` ($${usage.week.costUsd.toFixed(4)})`;
|
|
349
|
-
// Rate limits (from last API response)
|
|
350
|
-
let rlLines = "";
|
|
351
|
-
const allRL = getAllRateLimits();
|
|
352
|
-
if (allRL.size > 0) {
|
|
353
|
-
const parts = [];
|
|
354
|
-
for (const [prov, rl] of allRL) {
|
|
355
|
-
const lines = [];
|
|
356
|
-
if (rl.requestsRemaining != null && rl.requestsLimit) {
|
|
357
|
-
const pct = Math.round((rl.requestsRemaining / rl.requestsLimit) * 100);
|
|
358
|
-
const reset = rl.requestsReset ? ` (reset ${rl.requestsReset.replace(/T.*/, "").slice(5) || rl.requestsReset})` : "";
|
|
359
|
-
lines.push(`Req: ${rl.requestsRemaining}/${rl.requestsLimit} (${pct}%)${reset}`);
|
|
360
|
-
}
|
|
361
|
-
if (rl.tokensRemaining != null && rl.tokensLimit) {
|
|
362
|
-
const pct = Math.round((rl.tokensRemaining / rl.tokensLimit) * 100);
|
|
363
|
-
lines.push(`Tok: ${formatTokens(rl.tokensRemaining)}/${formatTokens(rl.tokensLimit)} (${pct}%)`);
|
|
364
|
-
}
|
|
365
|
-
if (lines.length > 0) {
|
|
366
|
-
parts.push(` ${lines.join(" | ")}`);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (parts.length > 0) {
|
|
370
|
-
rlLines = `\n⚡ *Rate Limits*\n${parts.join("\n")}\n`;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
// Memory stats
|
|
374
|
-
const memStats = getMemoryStats();
|
|
375
|
-
const idxStats = getIndexStats();
|
|
376
|
-
const { getEffectiveInjectMode, getInjectModeRaw } = await import("../services/memory-inject-mode.js");
|
|
377
|
-
const injectMode = getEffectiveInjectMode();
|
|
378
|
-
const injectRaw = getInjectModeRaw();
|
|
379
|
-
const indexLabel = idxStats.tier === "keyword-local" ? "FTS5" : "vec";
|
|
380
|
-
const modeLabel = injectRaw === "auto" ? `${injectMode}(auto)` : injectMode;
|
|
381
|
-
const memLine = `${memStats.dailyLogs} days, ${memStats.todayEntries} entries today, ${formatBytes(memStats.longTermSize)} LTM | 🔍 ${idxStats.entries} ${indexLabel} (${idxStats.provider}) | inject:${modeLabel}`;
|
|
382
|
-
// Provider health + failover state
|
|
383
|
-
const healthRows = getHealthStatus();
|
|
384
|
-
const failedOver = isFailedOver();
|
|
385
|
-
const activeKey = registry.getActiveKey();
|
|
386
|
-
let healthLines = "";
|
|
387
|
-
if (healthRows.length > 0) {
|
|
388
|
-
// Render each row, live-checking lifecycle-managed providers so the
|
|
389
|
-
// status reflects reality (not just heartbeat's always-healthy flag
|
|
390
|
-
// for on-demand runners).
|
|
391
|
-
const rows = await Promise.all(healthRows.map(async (h) => {
|
|
392
|
-
const isActive = h.key === activeKey;
|
|
393
|
-
const arrow = isActive ? "→" : " ";
|
|
394
|
-
const provider = registry.get(h.key);
|
|
395
|
-
// Lifecycle-managed providers (local runners) get on-demand rendering
|
|
396
|
-
if (provider?.lifecycle) {
|
|
397
|
-
const running = await provider.lifecycle.isRunning();
|
|
398
|
-
const botManaged = provider.lifecycle.isBotManaged();
|
|
399
|
-
if (!running) {
|
|
400
|
-
return `${arrow} 💤 ${h.key} ${t("bot.status.ollamaOnDemand", lang)}`;
|
|
401
|
-
}
|
|
402
|
-
if (botManaged) {
|
|
403
|
-
return `${arrow} 🔧 ${h.key} ${t("bot.status.ollamaBotManaged", lang)}`;
|
|
404
|
-
}
|
|
405
|
-
return `${arrow} ✅ ${h.key} ${t("bot.status.ollamaExternal", lang)}`;
|
|
406
|
-
}
|
|
407
|
-
// Default rendering for cloud providers
|
|
408
|
-
const icon = h.healthy ? "✅" : "❌";
|
|
409
|
-
const latency = h.latencyMs > 0 ? ` ${h.latencyMs}ms` : "";
|
|
410
|
-
const fails = h.failCount > 0 ? ` (${h.failCount} fails)` : "";
|
|
411
|
-
return `${arrow} ${icon} ${h.key}${latency}${fails}`;
|
|
412
|
-
}));
|
|
413
|
-
const failoverBadge = failedOver ? ` ${t("bot.status.failedOver", lang)}` : "";
|
|
414
|
-
healthLines = `\n${t("bot.status.providerHealth", lang)}${failoverBadge}\n${rows.join("\n")}\n`;
|
|
415
|
-
}
|
|
416
|
-
await ctx.reply(`🤖 *Alvin Bot* \`v${BOT_VERSION}\`\n\n` +
|
|
417
|
-
`*Model:* ${info.name} ${providerTag}\n` +
|
|
418
|
-
`*Effort:* ${EFFORT_LABELS[session.effort]}\n` +
|
|
419
|
-
`*Voice:* ${session.voiceReply ? "on" : "off"}\n` +
|
|
420
|
-
`*Working Dir:* ${formatWorkingDir(session.workingDir, lang)}\n\n` +
|
|
421
|
-
`${sessionBlock}\n` +
|
|
422
|
-
`\n📈 *Usage*\n` +
|
|
423
|
-
`Today: ${usage.today.queries} req, ${todayTok} tokens${todayCostStr}\n` +
|
|
424
|
-
`Week: ${usage.week.queries} req, ${weekTok} tokens${weekCostStr}\n` +
|
|
425
|
-
(usage.daysTracked > 1 ? `Avg: ${formatTokens(usage.avgDailyTokens)} tok/day _(7d rolling)_\n` : "") +
|
|
426
|
-
rlLines +
|
|
427
|
-
healthLines +
|
|
428
|
-
`\n🧠 *Memory:* ${memLine}\n` +
|
|
429
|
-
`⏱ *Uptime:* ${uptimeH}h ${uptimeM}m`, { parse_mode: "Markdown" });
|
|
430
|
-
});
|
|
431
|
-
bot.command("voice", async (ctx) => {
|
|
432
|
-
const userId = ctx.from.id;
|
|
433
|
-
const session = getSession(userId);
|
|
434
|
-
session.voiceReply = !session.voiceReply;
|
|
435
|
-
markSessionDirty(userId);
|
|
436
|
-
await ctx.reply(session.voiceReply
|
|
437
|
-
? "Voice replies enabled. Responses will also be sent as voice messages."
|
|
438
|
-
: "Voice replies disabled. Text-only responses.");
|
|
439
|
-
});
|
|
440
|
-
bot.command("effort", async (ctx) => {
|
|
441
|
-
const userId = ctx.from.id;
|
|
442
|
-
const session = getSession(userId);
|
|
443
|
-
const level = ctx.match?.trim().toLowerCase();
|
|
444
|
-
if (!level) {
|
|
445
|
-
const keyboard = new InlineKeyboard();
|
|
446
|
-
for (const [key, label] of Object.entries(EFFORT_LABELS)) {
|
|
447
|
-
const marker = key === session.effort ? "✅ " : "";
|
|
448
|
-
keyboard.text(`${marker}${label}`, `effort:${key}`).row();
|
|
449
|
-
}
|
|
450
|
-
await ctx.reply(`🧠 *Choose reasoning depth:*\n\nActive: *${EFFORT_LABELS[session.effort]}*`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
if (!["low", "medium", "high", "max"].includes(level)) {
|
|
454
|
-
await ctx.reply("Invalid. Use: /effort low | medium | high | max");
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
session.effort = level;
|
|
458
|
-
markSessionDirty(userId);
|
|
459
|
-
await ctx.reply(`✅ Effort: ${EFFORT_LABELS[session.effort]}`);
|
|
460
|
-
});
|
|
461
|
-
// v4.12.0 P1 #3 — Multi-workspace support on Telegram
|
|
462
|
-
bot.command("workspaces", async (ctx) => {
|
|
463
|
-
const userId = ctx.from.id;
|
|
464
|
-
const active = getTelegramWorkspace(userId) ?? "default";
|
|
465
|
-
const all = listWorkspaces();
|
|
466
|
-
if (all.length === 0) {
|
|
467
|
-
await ctx.reply("🧭 No workspaces configured.\n\n" +
|
|
468
|
-
"Create one by adding a file at `~/.alvin-bot/workspaces/<name>.md` " +
|
|
469
|
-
"with YAML frontmatter. See docs/install/slack-setup.md for the format.", { parse_mode: "Markdown" });
|
|
470
|
-
return;
|
|
471
|
-
}
|
|
472
|
-
const lines = [`🧭 *Workspaces* (active: \`${active}\`)`, ""];
|
|
473
|
-
for (const ws of all) {
|
|
474
|
-
const marker = ws.name === active ? "✅" : (ws.emoji ?? "▪️");
|
|
475
|
-
const purpose = ws.purpose || "(no purpose)";
|
|
476
|
-
lines.push(`${marker} \`${ws.name}\` — ${purpose}`);
|
|
477
|
-
}
|
|
478
|
-
lines.push("");
|
|
479
|
-
lines.push("Switch with: `/workspace <name>` · Reset: `/workspace default`");
|
|
480
|
-
await ctx.reply(lines.join("\n"), { parse_mode: "Markdown" });
|
|
481
|
-
});
|
|
482
|
-
bot.command("workspace", async (ctx) => {
|
|
483
|
-
const userId = ctx.from.id;
|
|
484
|
-
const arg = ctx.match?.trim();
|
|
485
|
-
if (!arg) {
|
|
486
|
-
const active = getTelegramWorkspace(userId) ?? "default";
|
|
487
|
-
const ws = active === "default" ? null : getWorkspace(active);
|
|
488
|
-
const purpose = ws?.purpose || "global default — no persona, global cwd";
|
|
489
|
-
await ctx.reply(`🧭 Active workspace: *${active}*\n_${purpose}_\n\nUse \`/workspaces\` to see all available.`, { parse_mode: "Markdown" });
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
if (arg === "default" || arg === "reset") {
|
|
493
|
-
setTelegramWorkspace(userId, null);
|
|
494
|
-
await ctx.reply("✅ Switched to the default workspace.");
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
const ws = getWorkspace(arg);
|
|
498
|
-
if (!ws) {
|
|
499
|
-
await ctx.reply(`❌ Workspace \`${arg}\` not found.\nUse \`/workspaces\` to list available ones.`, { parse_mode: "Markdown" });
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
setTelegramWorkspace(userId, arg);
|
|
503
|
-
await ctx.reply(`✅ Switched to workspace *${ws.emoji ?? "🧭"} ${ws.name}*\n_${ws.purpose || "(no purpose set)"}_\n\nNext message will use this workspace's persona and cwd (\`${ws.cwd}\`).`, { parse_mode: "Markdown" });
|
|
504
|
-
});
|
|
505
|
-
// Inline keyboard callback for effort switching
|
|
506
|
-
bot.callbackQuery(/^effort:(.+)$/, async (ctx) => {
|
|
507
|
-
const level = ctx.match[1];
|
|
508
|
-
if (!["low", "medium", "high", "max"].includes(level)) {
|
|
509
|
-
await ctx.answerCallbackQuery("Invalid level");
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
const userId = ctx.from.id;
|
|
513
|
-
const session = getSession(userId);
|
|
514
|
-
session.effort = level;
|
|
515
|
-
markSessionDirty(userId);
|
|
516
|
-
const keyboard = new InlineKeyboard();
|
|
517
|
-
for (const [key, label] of Object.entries(EFFORT_LABELS)) {
|
|
518
|
-
const marker = key === session.effort ? "✅ " : "";
|
|
519
|
-
keyboard.text(`${marker}${label}`, `effort:${key}`).row();
|
|
520
|
-
}
|
|
521
|
-
await ctx.editMessageText(`🧠 *Choose reasoning depth:*\n\nActive: *${EFFORT_LABELS[session.effort]}*`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
522
|
-
await ctx.answerCallbackQuery(`Effort: ${EFFORT_LABELS[session.effort]}`);
|
|
523
|
-
});
|
|
524
|
-
// Helper: switch provider with lifecycle management for local runners.
|
|
525
|
-
// Boots the target's lifecycle daemon (if any) BEFORE the switch, and
|
|
526
|
-
// tears down the previous provider's lifecycle (if any) AFTER the switch.
|
|
527
|
-
// Fully generic — no hardcoded provider keys.
|
|
528
|
-
async function switchProviderWithLifecycle(targetKey, lang) {
|
|
529
|
-
const registry = getRegistry();
|
|
530
|
-
const previousKey = registry.getActiveKey();
|
|
531
|
-
if (previousKey === targetKey)
|
|
532
|
-
return { ok: true };
|
|
533
|
-
const target = registry.get(targetKey);
|
|
534
|
-
if (!target)
|
|
535
|
-
return { ok: false, error: `provider "${targetKey}" not found` };
|
|
536
|
-
const previous = registry.get(previousKey);
|
|
537
|
-
// Boot the target's lifecycle (if any) before the switch
|
|
538
|
-
if (target.lifecycle) {
|
|
539
|
-
const booted = await target.lifecycle.ensureRunning();
|
|
540
|
-
if (!booted) {
|
|
541
|
-
return { ok: false, error: t("bot.model.bootFailed", lang, { key: targetKey }) };
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
if (!registry.switchTo(targetKey)) {
|
|
545
|
-
return { ok: false, error: "switch rejected by registry" };
|
|
546
|
-
}
|
|
547
|
-
// v4.15 — Persist the switch to ~/.alvin-bot/.env so the choice
|
|
548
|
-
// survives bot restarts. In-memory switchTo() alone would revert to
|
|
549
|
-
// PRIMARY_PROVIDER on next boot.
|
|
550
|
-
try {
|
|
551
|
-
writeEnvVar("PRIMARY_PROVIDER", targetKey);
|
|
552
|
-
}
|
|
553
|
-
catch (err) {
|
|
554
|
-
console.warn("⚠️ Failed to persist PRIMARY_PROVIDER:", err);
|
|
555
|
-
}
|
|
556
|
-
// Tear down the previous provider's lifecycle (if any) after the switch.
|
|
557
|
-
// ensureStopped() internally checks isBotManaged — no-op for externally
|
|
558
|
-
// managed daemons.
|
|
559
|
-
if (previous?.lifecycle) {
|
|
560
|
-
await previous.lifecycle.ensureStopped();
|
|
561
|
-
}
|
|
562
|
-
return { ok: true };
|
|
563
|
-
}
|
|
564
|
-
bot.command("model", async (ctx) => {
|
|
565
|
-
const lang = getSession(ctx.from.id).language;
|
|
566
|
-
const arg = ctx.match?.trim().toLowerCase();
|
|
567
|
-
const registry = getRegistry();
|
|
568
|
-
if (!arg) {
|
|
569
|
-
// Show inline keyboard with available models
|
|
570
|
-
const providers = await registry.listAll();
|
|
571
|
-
const keyboard = new InlineKeyboard();
|
|
572
|
-
for (const p of providers) {
|
|
573
|
-
const label = p.active ? `✅ ${p.name}` : p.name;
|
|
574
|
-
keyboard.text(label, `model:${p.key}`).row();
|
|
575
|
-
}
|
|
576
|
-
await ctx.reply(`${t("bot.model.chooseHeader", lang)}\n\n${t("bot.model.active", lang)} *${registry.getActive().getInfo().name}*`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
const result = await switchProviderWithLifecycle(arg, lang);
|
|
580
|
-
if (result.ok) {
|
|
581
|
-
const info = registry.get(arg).getInfo();
|
|
582
|
-
await ctx.reply(`${t("bot.model.switched", lang)} ${info.name} (${info.model})`);
|
|
583
|
-
}
|
|
584
|
-
else {
|
|
585
|
-
await ctx.reply(`${t("bot.model.switchFailed", lang)} ${result.error || `"${arg}"`}\n${t("bot.model.notFoundHint", lang)}`);
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
// Inline keyboard callback for model switching
|
|
589
|
-
bot.callbackQuery(/^model:(.+)$/, async (ctx) => {
|
|
590
|
-
const key = ctx.match[1];
|
|
591
|
-
const registry = getRegistry();
|
|
592
|
-
const lang = getSession(ctx.from.id).language;
|
|
593
|
-
const result = await switchProviderWithLifecycle(key, lang);
|
|
594
|
-
if (result.ok) {
|
|
595
|
-
const provider = registry.get(key);
|
|
596
|
-
const info = provider.getInfo();
|
|
597
|
-
// Update the keyboard to show new selection
|
|
598
|
-
const providers = await registry.listAll();
|
|
599
|
-
const keyboard = new InlineKeyboard();
|
|
600
|
-
for (const p of providers) {
|
|
601
|
-
const label = p.active ? `✅ ${p.name}` : p.name;
|
|
602
|
-
keyboard.text(label, `model:${p.key}`).row();
|
|
603
|
-
}
|
|
604
|
-
await ctx.editMessageText(`🤖 *Choose model:*\n\nActive: *${info.name}*`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
605
|
-
await ctx.answerCallbackQuery(`Switched: ${info.name}`);
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
await ctx.answerCallbackQuery(`Switch failed: ${result.error || "unknown"}`);
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
// ── Fallback Order ────────────────────────────────────────────────────
|
|
612
|
-
bot.command("fallback", async (ctx) => {
|
|
613
|
-
const { getFallbackOrder, setFallbackOrder, formatOrder } = await import("../services/fallback-order.js");
|
|
614
|
-
const { getHealthStatus } = await import("../services/heartbeat.js");
|
|
615
|
-
const registry = getRegistry();
|
|
616
|
-
const arg = ctx.match?.trim();
|
|
617
|
-
if (!arg) {
|
|
618
|
-
// Show current order with inline keyboard
|
|
619
|
-
const order = getFallbackOrder();
|
|
620
|
-
const health = getHealthStatus();
|
|
621
|
-
const healthMap = new Map(health.map(h => [h.key, h]));
|
|
622
|
-
const allKeys = [order.primary, ...order.fallbacks];
|
|
623
|
-
const keyboard = new InlineKeyboard();
|
|
624
|
-
for (let i = 0; i < allKeys.length; i++) {
|
|
625
|
-
const key = allKeys[i];
|
|
626
|
-
const h = healthMap.get(key);
|
|
627
|
-
const status = h ? (h.healthy ? "✅" : "❌") : "❓";
|
|
628
|
-
const label = i === 0 ? `🥇 ${key} ${status}` : `${i + 1}. ${key} ${status}`;
|
|
629
|
-
if (i > 0)
|
|
630
|
-
keyboard.text("⬆️", `fb:up:${key}`);
|
|
631
|
-
keyboard.text(label, `fb:info:${key}`);
|
|
632
|
-
if (i < allKeys.length - 1)
|
|
633
|
-
keyboard.text("⬇️", `fb:down:${key}`);
|
|
634
|
-
keyboard.row();
|
|
635
|
-
}
|
|
636
|
-
const text = `🔄 *Fallback Order*\n\n` +
|
|
637
|
-
`Providers are tried in this order.\n` +
|
|
638
|
-
`Use ⬆️/⬇️ to reorder.\n\n` +
|
|
639
|
-
`_Last changed: ${order.updatedBy} (${new Date(order.updatedAt).toLocaleString("en-US")})_`;
|
|
640
|
-
await ctx.reply(text, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
// Direct text commands: /fallback set groq,openai,nvidia-llama-3.3-70b
|
|
644
|
-
if (arg.startsWith("set ")) {
|
|
645
|
-
const parts = arg.slice(4).split(",").map(s => s.trim()).filter(Boolean);
|
|
646
|
-
if (parts.length < 1) {
|
|
647
|
-
await ctx.reply("Usage: `/fallback set primary,fallback1,fallback2,...`", { parse_mode: "Markdown" });
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
const [primary, ...fallbacks] = parts;
|
|
651
|
-
setFallbackOrder(primary, fallbacks, "telegram");
|
|
652
|
-
await ctx.reply(`✅ New order:\n\n${formatOrder()}`);
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
await ctx.reply(`🔄 *Fallback Order*\n\n` +
|
|
656
|
-
`\`/fallback\` — Show & change order\n` +
|
|
657
|
-
`\`/fallback set groq,openai,...\` — Set directly`, { parse_mode: "Markdown" });
|
|
658
|
-
});
|
|
659
|
-
// Callback queries for fallback ordering
|
|
660
|
-
bot.callbackQuery(/^fb:up:(.+)$/, async (ctx) => {
|
|
661
|
-
const { moveUp, formatOrder, getFallbackOrder } = await import("../services/fallback-order.js");
|
|
662
|
-
const { getHealthStatus } = await import("../services/heartbeat.js");
|
|
663
|
-
const key = ctx.match[1];
|
|
664
|
-
moveUp(key, "telegram");
|
|
665
|
-
const order = getFallbackOrder();
|
|
666
|
-
const health = getHealthStatus();
|
|
667
|
-
const healthMap = new Map(health.map(h => [h.key, h]));
|
|
668
|
-
const allKeys = [order.primary, ...order.fallbacks];
|
|
669
|
-
const keyboard = new InlineKeyboard();
|
|
670
|
-
for (let i = 0; i < allKeys.length; i++) {
|
|
671
|
-
const k = allKeys[i];
|
|
672
|
-
const h = healthMap.get(k);
|
|
673
|
-
const status = h ? (h.healthy ? "✅" : "❌") : "❓";
|
|
674
|
-
const label = i === 0 ? `🥇 ${k} ${status}` : `${i + 1}. ${k} ${status}`;
|
|
675
|
-
if (i > 0)
|
|
676
|
-
keyboard.text("⬆️", `fb:up:${k}`);
|
|
677
|
-
keyboard.text(label, `fb:info:${k}`);
|
|
678
|
-
if (i < allKeys.length - 1)
|
|
679
|
-
keyboard.text("⬇️", `fb:down:${k}`);
|
|
680
|
-
keyboard.row();
|
|
681
|
-
}
|
|
682
|
-
await ctx.editMessageText(`🔄 *Fallback Order*\n\n` +
|
|
683
|
-
`Provider werden in dieser Reihenfolge versucht.\n` +
|
|
684
|
-
`Nutze ⬆️/⬇️ zum Umsortieren.\n\n` +
|
|
685
|
-
`_Last changed: telegram (${new Date().toLocaleString("en-US")})_`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
686
|
-
await ctx.answerCallbackQuery(`${key} moved up`);
|
|
687
|
-
});
|
|
688
|
-
bot.callbackQuery(/^fb:down:(.+)$/, async (ctx) => {
|
|
689
|
-
const { moveDown, getFallbackOrder } = await import("../services/fallback-order.js");
|
|
690
|
-
const { getHealthStatus } = await import("../services/heartbeat.js");
|
|
691
|
-
const key = ctx.match[1];
|
|
692
|
-
moveDown(key, "telegram");
|
|
693
|
-
const order = getFallbackOrder();
|
|
694
|
-
const health = getHealthStatus();
|
|
695
|
-
const healthMap = new Map(health.map(h => [h.key, h]));
|
|
696
|
-
const allKeys = [order.primary, ...order.fallbacks];
|
|
697
|
-
const keyboard = new InlineKeyboard();
|
|
698
|
-
for (let i = 0; i < allKeys.length; i++) {
|
|
699
|
-
const k = allKeys[i];
|
|
700
|
-
const h = healthMap.get(k);
|
|
701
|
-
const status = h ? (h.healthy ? "✅" : "❌") : "❓";
|
|
702
|
-
const label = i === 0 ? `🥇 ${k} ${status}` : `${i + 1}. ${k} ${status}`;
|
|
703
|
-
if (i > 0)
|
|
704
|
-
keyboard.text("⬆️", `fb:up:${k}`);
|
|
705
|
-
keyboard.text(label, `fb:info:${k}`);
|
|
706
|
-
if (i < allKeys.length - 1)
|
|
707
|
-
keyboard.text("⬇️", `fb:down:${k}`);
|
|
708
|
-
keyboard.row();
|
|
709
|
-
}
|
|
710
|
-
await ctx.editMessageText(`🔄 *Fallback Order*\n\n` +
|
|
711
|
-
`Provider werden in dieser Reihenfolge versucht.\n` +
|
|
712
|
-
`Nutze ⬆️/⬇️ zum Umsortieren.\n\n` +
|
|
713
|
-
`_Last changed: telegram (${new Date().toLocaleString("en-US")})_`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
714
|
-
await ctx.answerCallbackQuery(`${key} moved down`);
|
|
715
|
-
});
|
|
716
|
-
bot.callbackQuery(/^fb:info:(.+)$/, async (ctx) => {
|
|
717
|
-
const { getHealthStatus } = await import("../services/heartbeat.js");
|
|
718
|
-
const key = ctx.match[1];
|
|
719
|
-
const health = getHealthStatus();
|
|
720
|
-
const h = health.find(p => p.key === key);
|
|
721
|
-
if (h) {
|
|
722
|
-
await ctx.answerCallbackQuery({
|
|
723
|
-
text: `${key}: ${h.healthy ? "✅ Healthy" : "❌ Unhealthy"} | ${h.latencyMs}ms | Errors: ${h.failCount}`,
|
|
724
|
-
show_alert: true,
|
|
725
|
-
});
|
|
726
|
-
}
|
|
727
|
-
else {
|
|
728
|
-
await ctx.answerCallbackQuery(`${key}: Not checked yet`);
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
bot.command("web", async (ctx) => {
|
|
732
|
-
const query = ctx.match?.trim();
|
|
733
|
-
if (!query) {
|
|
734
|
-
await ctx.reply("Search: `/web your search query`", { parse_mode: "Markdown" });
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
738
|
-
try {
|
|
739
|
-
// Use DuckDuckGo instant answer API (no key needed)
|
|
740
|
-
const encoded = encodeURIComponent(query);
|
|
741
|
-
const res = await fetch(`https://api.duckduckgo.com/?q=${encoded}&format=json&no_html=1&skip_disambig=1`);
|
|
742
|
-
const data = await res.json();
|
|
743
|
-
const lines = [];
|
|
744
|
-
if (data.Answer) {
|
|
745
|
-
lines.push(`💡 *${data.Answer}*\n`);
|
|
746
|
-
}
|
|
747
|
-
if (data.AbstractText) {
|
|
748
|
-
const text = data.AbstractText.length > 500
|
|
749
|
-
? data.AbstractText.slice(0, 500) + "..."
|
|
750
|
-
: data.AbstractText;
|
|
751
|
-
lines.push(text);
|
|
752
|
-
if (data.AbstractSource && data.AbstractURL) {
|
|
753
|
-
lines.push(`\n_Source: [${data.AbstractSource}](${data.AbstractURL})_`);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
if (lines.length === 0 && data.RelatedTopics && data.RelatedTopics.length > 0) {
|
|
757
|
-
lines.push(`🔍 *Results for "${query}":*\n`);
|
|
758
|
-
for (const topic of data.RelatedTopics.slice(0, 5)) {
|
|
759
|
-
if (topic.Text) {
|
|
760
|
-
const short = topic.Text.length > 150 ? topic.Text.slice(0, 150) + "..." : topic.Text;
|
|
761
|
-
lines.push(`• ${short}`);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
if (lines.length === 0) {
|
|
766
|
-
lines.push(`No results for "${query}". Try it as a regular message — I'll search using the AI model.`);
|
|
767
|
-
}
|
|
768
|
-
await ctx.reply(lines.join("\n"), { parse_mode: "Markdown" }).catch(() => ctx.reply(lines.join("\n")));
|
|
769
|
-
}
|
|
770
|
-
catch (err) {
|
|
771
|
-
await ctx.reply(`Search error: ${err instanceof Error ? err.message : String(err)}`);
|
|
772
|
-
}
|
|
773
|
-
});
|
|
774
|
-
bot.command("imagine", async (ctx) => {
|
|
775
|
-
const prompt = ctx.match?.trim();
|
|
776
|
-
if (!prompt) {
|
|
777
|
-
await ctx.reply("Describe what I should generate:\n`/imagine A fox sitting on the moon`", { parse_mode: "Markdown" });
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
if (!config.apiKeys.google) {
|
|
781
|
-
await ctx.reply("⚠️ Image generation unavailable (GOOGLE_API_KEY missing).");
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
784
|
-
await ctx.api.sendChatAction(ctx.chat.id, "upload_photo");
|
|
785
|
-
const result = await generateImage(prompt, config.apiKeys.google);
|
|
786
|
-
if (result.success && result.filePath) {
|
|
787
|
-
try {
|
|
788
|
-
const fileData = fs.readFileSync(result.filePath);
|
|
789
|
-
await ctx.replyWithPhoto(new InputFile(fileData, `generated${result.filePath.endsWith(".png") ? ".png" : ".jpg"}`), {
|
|
790
|
-
caption: `🎨 _${prompt}_`,
|
|
791
|
-
parse_mode: "Markdown",
|
|
792
|
-
});
|
|
793
|
-
fs.unlink(result.filePath, () => { });
|
|
794
|
-
}
|
|
795
|
-
catch (err) {
|
|
796
|
-
await ctx.reply(`Error sending: ${err instanceof Error ? err.message : String(err)}`);
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
else {
|
|
800
|
-
await ctx.reply(`❌ ${result.error || "Image generation failed."}`);
|
|
801
|
-
}
|
|
802
|
-
});
|
|
803
|
-
bot.command("remind", async (ctx) => {
|
|
804
|
-
const userId = ctx.from.id;
|
|
805
|
-
const chatId = ctx.chat.id;
|
|
806
|
-
const input = ctx.match?.trim();
|
|
807
|
-
if (!input) {
|
|
808
|
-
// List reminders
|
|
809
|
-
const pending = listReminders(userId);
|
|
810
|
-
if (pending.length === 0) {
|
|
811
|
-
await ctx.reply("No active reminders.\n\nNew: `/remind 30m Call mom`", { parse_mode: "Markdown" });
|
|
812
|
-
}
|
|
813
|
-
else {
|
|
814
|
-
const lines = pending.map(r => `• *${r.remaining}* — ${r.text} (ID: ${r.id})`);
|
|
815
|
-
await ctx.reply(`⏰ *Active Reminders:*\n\n${lines.join("\n")}\n\nCancel: \`/remind cancel <ID>\``, { parse_mode: "Markdown" });
|
|
816
|
-
}
|
|
817
|
-
return;
|
|
818
|
-
}
|
|
819
|
-
// Cancel a reminder
|
|
820
|
-
if (input.startsWith("cancel ")) {
|
|
821
|
-
const id = parseInt(input.slice(7).trim());
|
|
822
|
-
if (isNaN(id)) {
|
|
823
|
-
await ctx.reply("Invalid ID. Use: `/remind cancel <ID>`", { parse_mode: "Markdown" });
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
if (cancelReminder(id, userId)) {
|
|
827
|
-
await ctx.reply(`✅ Reminder #${id} cancelled.`);
|
|
828
|
-
}
|
|
829
|
-
else {
|
|
830
|
-
await ctx.reply(`❌ Reminder #${id} not found.`);
|
|
831
|
-
}
|
|
832
|
-
return;
|
|
833
|
-
}
|
|
834
|
-
// Parse: /remind <duration> <text>
|
|
835
|
-
const spaceIdx = input.indexOf(" ");
|
|
836
|
-
if (spaceIdx === -1) {
|
|
837
|
-
await ctx.reply("Format: `/remind 30m Reminder text`", { parse_mode: "Markdown" });
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
const durationStr = input.slice(0, spaceIdx);
|
|
841
|
-
const text = input.slice(spaceIdx + 1).trim();
|
|
842
|
-
const delayMs = parseDuration(durationStr);
|
|
843
|
-
if (!delayMs) {
|
|
844
|
-
await ctx.reply("Invalid duration. Examples: `30s`, `5m`, `2h`, `1d`", { parse_mode: "Markdown" });
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
if (!text) {
|
|
848
|
-
await ctx.reply("Please provide text: `/remind 30m Call mom`", { parse_mode: "Markdown" });
|
|
849
|
-
return;
|
|
850
|
-
}
|
|
851
|
-
const reminder = createReminder(chatId, userId, text, delayMs, ctx.api);
|
|
852
|
-
// Format trigger time
|
|
853
|
-
const triggerDate = new Date(reminder.triggerAt);
|
|
854
|
-
const timeStr = triggerDate.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" });
|
|
855
|
-
await ctx.reply(`✅ Reminder set for *${timeStr}*: ${text}`, { parse_mode: "Markdown" });
|
|
856
|
-
});
|
|
857
|
-
bot.command("export", async (ctx) => {
|
|
858
|
-
const userId = ctx.from.id;
|
|
859
|
-
const session = getSession(userId);
|
|
860
|
-
if (session.history.length === 0 && !session.sessionId) {
|
|
861
|
-
await ctx.reply("No conversation data to export.");
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
// Build export text
|
|
865
|
-
const lines = [
|
|
866
|
-
`# Alvin Bot — Conversation Export`,
|
|
867
|
-
`Date: ${new Date().toLocaleString("en-US")}`,
|
|
868
|
-
`Messages: ${session.messageCount}`,
|
|
869
|
-
`Cost: $${session.totalCost.toFixed(4)}`,
|
|
870
|
-
`---\n`,
|
|
871
|
-
];
|
|
872
|
-
for (const msg of session.history) {
|
|
873
|
-
const role = msg.role === "user" ? "👤 User" : "🤖 Alvin Bot";
|
|
874
|
-
lines.push(`### ${role}\n${msg.content}\n`);
|
|
875
|
-
}
|
|
876
|
-
if (session.history.length === 0) {
|
|
877
|
-
lines.push("(SDK session — history managed internally, no export available)\n");
|
|
878
|
-
}
|
|
879
|
-
const exportText = lines.join("\n");
|
|
880
|
-
const buffer = Buffer.from(exportText, "utf-8");
|
|
881
|
-
const filename = `chat-export-${new Date().toISOString().slice(0, 10)}.md`;
|
|
882
|
-
await ctx.replyWithDocument(new InputFile(buffer, filename), {
|
|
883
|
-
caption: `📄 Export: ${session.history.length} messages`,
|
|
884
|
-
});
|
|
885
|
-
});
|
|
886
|
-
// Helper: build the /language inline keyboard for all 4 locales + auto.
|
|
887
|
-
function buildLangKeyboard(current) {
|
|
888
|
-
const kb = new InlineKeyboard();
|
|
889
|
-
const order = ["en", "de", "es", "fr"];
|
|
890
|
-
// First row: 2 buttons
|
|
891
|
-
kb.text(`${current === "en" ? "✅ " : ""}${LOCALE_FLAGS.en} ${LOCALE_NAMES.en}`, "lang:en").text(`${current === "de" ? "✅ " : ""}${LOCALE_FLAGS.de} ${LOCALE_NAMES.de}`, "lang:de").row();
|
|
892
|
-
// Second row: 2 buttons
|
|
893
|
-
kb.text(`${current === "es" ? "✅ " : ""}${LOCALE_FLAGS.es} ${LOCALE_NAMES.es}`, "lang:es").text(`${current === "fr" ? "✅ " : ""}${LOCALE_FLAGS.fr} ${LOCALE_NAMES.fr}`, "lang:fr").row();
|
|
894
|
-
// Third row: auto-detect
|
|
895
|
-
void order; // silence unused warning from the `order` declaration (kept for doc clarity)
|
|
896
|
-
kb.text(t("bot.lang.autoDetect", current), "lang:auto");
|
|
897
|
-
return kb;
|
|
898
|
-
}
|
|
899
|
-
bot.command("lang", async (ctx) => {
|
|
900
|
-
const userId = ctx.from.id;
|
|
901
|
-
const session = getSession(userId);
|
|
902
|
-
const arg = ctx.match?.trim().toLowerCase();
|
|
903
|
-
if (!arg) {
|
|
904
|
-
const header = t("bot.lang.header", session.language);
|
|
905
|
-
const currentName = `${LOCALE_FLAGS[session.language]} ${LOCALE_NAMES[session.language]}`;
|
|
906
|
-
await ctx.reply(`${header} ${currentName}`, {
|
|
907
|
-
parse_mode: "Markdown",
|
|
908
|
-
reply_markup: buildLangKeyboard(session.language),
|
|
909
|
-
});
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
if (arg === "auto") {
|
|
913
|
-
const { resetToAutoLanguage } = await import("../services/language-detect.js");
|
|
914
|
-
resetToAutoLanguage(userId);
|
|
915
|
-
await ctx.reply(t("bot.lang.autoEnabled", session.language));
|
|
916
|
-
}
|
|
917
|
-
else if (arg === "en" || arg === "de" || arg === "es" || arg === "fr") {
|
|
918
|
-
session.language = arg;
|
|
919
|
-
markSessionDirty(userId);
|
|
920
|
-
const { setExplicitLanguage } = await import("../services/language-detect.js");
|
|
921
|
-
setExplicitLanguage(userId, arg);
|
|
922
|
-
await ctx.reply(t("bot.lang.setFixed", arg, { name: LOCALE_NAMES[arg] }));
|
|
923
|
-
}
|
|
924
|
-
else {
|
|
925
|
-
await ctx.reply(t("bot.lang.usage", session.language), { parse_mode: "Markdown" });
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
// /lang callback — accept all 4 locales plus auto
|
|
929
|
-
bot.callbackQuery(/^lang:(en|de|es|fr|auto)$/, async (ctx) => {
|
|
930
|
-
const choice = ctx.match[1];
|
|
931
|
-
const userId = ctx.from.id;
|
|
932
|
-
const session = getSession(userId);
|
|
933
|
-
if (choice === "auto") {
|
|
934
|
-
const { resetToAutoLanguage } = await import("../services/language-detect.js");
|
|
935
|
-
resetToAutoLanguage(userId);
|
|
936
|
-
await ctx.answerCallbackQuery({ text: t("bot.lang.autoEnabled", session.language).slice(0, 60) });
|
|
937
|
-
await ctx.editMessageText(`${t("bot.lang.header", session.language)} ${t("bot.lang.autoDetect", session.language)}`, {
|
|
938
|
-
parse_mode: "Markdown",
|
|
939
|
-
});
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
const newLang = choice;
|
|
943
|
-
session.language = newLang;
|
|
944
|
-
markSessionDirty(userId);
|
|
945
|
-
const { setExplicitLanguage } = await import("../services/language-detect.js");
|
|
946
|
-
setExplicitLanguage(userId, newLang);
|
|
947
|
-
const currentName = `${LOCALE_FLAGS[newLang]} ${LOCALE_NAMES[newLang]}`;
|
|
948
|
-
await ctx.editMessageText(`${t("bot.lang.header", newLang)} ${currentName}`, {
|
|
949
|
-
parse_mode: "Markdown",
|
|
950
|
-
reply_markup: buildLangKeyboard(newLang),
|
|
951
|
-
});
|
|
952
|
-
await ctx.answerCallbackQuery(LOCALE_NAMES[newLang]);
|
|
953
|
-
});
|
|
954
|
-
bot.command("memory", async (ctx) => {
|
|
955
|
-
const stats = getMemoryStats();
|
|
956
|
-
const arg = ctx.match?.trim();
|
|
957
|
-
if (!arg) {
|
|
958
|
-
await ctx.reply(`🧠 *Memory*\n\n` +
|
|
959
|
-
`*Long-term memory:* ${formatBytes(stats.longTermSize)}\n` +
|
|
960
|
-
`*Daily logs:* ${stats.dailyLogs} files\n` +
|
|
961
|
-
`*Today:* ${stats.todayEntries} entries\n\n` +
|
|
962
|
-
`_Memory is automatically written on /new._\n` +
|
|
963
|
-
`_Non-SDK providers load memory as context._`, { parse_mode: "Markdown" });
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
966
|
-
});
|
|
967
|
-
bot.command("system", async (ctx) => {
|
|
968
|
-
const memTotal = os.totalmem();
|
|
969
|
-
const memFree = os.freemem();
|
|
970
|
-
const memUsed = memTotal - memFree;
|
|
971
|
-
const memPercent = Math.round((memUsed / memTotal) * 100);
|
|
972
|
-
const uptime = os.uptime();
|
|
973
|
-
const uptimeH = Math.floor(uptime / 3600);
|
|
974
|
-
const uptimeM = Math.floor((uptime % 3600) / 60);
|
|
975
|
-
const cpus = os.cpus();
|
|
976
|
-
const loadAvg = os.loadavg();
|
|
977
|
-
const procMem = process.memoryUsage();
|
|
978
|
-
await ctx.reply(`🖥 *System Info*\n\n` +
|
|
979
|
-
`*OS:* ${os.platform()} ${os.arch()} (${os.release()})\n` +
|
|
980
|
-
`*Host:* ${os.hostname()}\n` +
|
|
981
|
-
`*CPUs:* ${cpus.length}x ${cpus[0]?.model?.trim() || "unknown"}\n` +
|
|
982
|
-
`*Load:* ${loadAvg.map(l => l.toFixed(2)).join(", ")}\n` +
|
|
983
|
-
`*RAM:* ${formatBytes(memUsed)} / ${formatBytes(memTotal)} (${memPercent}%)\n` +
|
|
984
|
-
`*System Uptime:* ${uptimeH}h ${uptimeM}m\n\n` +
|
|
985
|
-
`🤖 *Bot Process*\n` +
|
|
986
|
-
`*Node:* ${process.version}\n` +
|
|
987
|
-
`*Heap:* ${formatBytes(procMem.heapUsed)} / ${formatBytes(procMem.heapTotal)}\n` +
|
|
988
|
-
`*RSS:* ${formatBytes(procMem.rss)}\n` +
|
|
989
|
-
`*PID:* ${process.pid}`, { parse_mode: "Markdown" });
|
|
990
|
-
});
|
|
991
|
-
bot.command("reload", async (ctx) => {
|
|
992
|
-
const success = reloadSoul();
|
|
993
|
-
await ctx.reply(success ? "✅ SOUL.md reloaded." : "❌ SOUL.md not found.");
|
|
994
|
-
});
|
|
995
|
-
// ── Access Control ────────────────────────────────
|
|
996
|
-
// Callback for group approval/block
|
|
997
|
-
bot.callbackQuery(/^access:(approve|block):(-?\d+)$/, async (ctx) => {
|
|
998
|
-
const action = ctx.match[1];
|
|
999
|
-
const chatId = parseInt(ctx.match[2]);
|
|
1000
|
-
if (action === "approve") {
|
|
1001
|
-
approveGroup(chatId);
|
|
1002
|
-
await ctx.editMessageText(`✅ Group ${chatId} approved. Alvin Bot will now respond there.`);
|
|
1003
|
-
// Notify the group
|
|
1004
|
-
try {
|
|
1005
|
-
await ctx.api.sendMessage(chatId, "👋 Alvin Bot is now active in this group!\n\n@mention me or reply to my messages.");
|
|
1006
|
-
}
|
|
1007
|
-
catch { /* group might not allow bot messages yet */ }
|
|
1008
|
-
}
|
|
1009
|
-
else {
|
|
1010
|
-
blockGroup(chatId);
|
|
1011
|
-
await ctx.editMessageText(`🚫 Group ${chatId} blocked. Alvin Bot will ignore this group.`);
|
|
1012
|
-
}
|
|
1013
|
-
await ctx.answerCallbackQuery();
|
|
1014
|
-
});
|
|
1015
|
-
bot.command("groups", async (ctx) => {
|
|
1016
|
-
const groups = listGroups();
|
|
1017
|
-
if (groups.length === 0) {
|
|
1018
|
-
await ctx.reply("No groups registered.");
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
const lines = groups.map(g => {
|
|
1022
|
-
const status = g.status === "approved" ? "✅" : g.status === "blocked" ? "🚫" : "⏳";
|
|
1023
|
-
return `${status} *${g.title}* (${g.messageCount} msgs)\n ID: \`${g.chatId}\``;
|
|
1024
|
-
});
|
|
1025
|
-
const keyboard = new InlineKeyboard();
|
|
1026
|
-
for (const g of groups) {
|
|
1027
|
-
if (g.status === "approved") {
|
|
1028
|
-
keyboard.text(`🚫 Block: ${g.title.slice(0, 20)}`, `access:block:${g.chatId}`).row();
|
|
1029
|
-
}
|
|
1030
|
-
else if (g.status === "blocked" || g.status === "pending") {
|
|
1031
|
-
keyboard.text(`✅ Approve: ${g.title.slice(0, 20)}`, `access:approve:${g.chatId}`).row();
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
const settings = getSettings();
|
|
1035
|
-
await ctx.reply(`🔐 *Group Management*\n\n` +
|
|
1036
|
-
`${lines.join("\n\n")}\n\n` +
|
|
1037
|
-
`⚙️ *Settings:*\n` +
|
|
1038
|
-
`Forwards: ${settings.allowForwards ? "✅" : "❌"}\n` +
|
|
1039
|
-
`Auto-Approve: ${settings.autoApproveGroups ? "⚠️ ON" : "✅ OFF"}`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
1040
|
-
});
|
|
1041
|
-
bot.command("security", async (ctx) => {
|
|
1042
|
-
const arg = ctx.match?.trim().toLowerCase();
|
|
1043
|
-
const settings = getSettings();
|
|
1044
|
-
if (!arg) {
|
|
1045
|
-
await ctx.reply(`🔐 *Security Settings*\n\n` +
|
|
1046
|
-
`*Forwards:* ${settings.allowForwards ? "✅ allowed" : "❌ blocked"}\n` +
|
|
1047
|
-
`*Auto-Approve Groups:* ${settings.autoApproveGroups ? "⚠️ ON (dangerous!)" : "✅ OFF"}\n` +
|
|
1048
|
-
`*Group Rate Limit:* ${settings.groupRateLimitPerHour}/h\n\n` +
|
|
1049
|
-
`Change:\n` +
|
|
1050
|
-
`\`/security forwards on|off\`\n` +
|
|
1051
|
-
`\`/security autoapprove on|off\``, { parse_mode: "Markdown" });
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
if (arg.startsWith("forwards ")) {
|
|
1055
|
-
const val = arg.slice(9).trim();
|
|
1056
|
-
setForwardingAllowed(val === "on" || val === "true");
|
|
1057
|
-
await ctx.reply(`✅ Forwards: ${val === "on" || val === "true" ? "allowed" : "blocked"}`);
|
|
1058
|
-
}
|
|
1059
|
-
else if (arg.startsWith("autoapprove ")) {
|
|
1060
|
-
const val = arg.slice(12).trim();
|
|
1061
|
-
setAutoApprove(val === "on" || val === "true");
|
|
1062
|
-
await ctx.reply(`${val === "on" || val === "true" ? "⚠️" : "✅"} Auto-Approve: ${val === "on" || val === "true" ? "ON" : "OFF"}`);
|
|
1063
|
-
}
|
|
1064
|
-
else {
|
|
1065
|
-
await ctx.reply("Unknown. Use `/security` for options.", { parse_mode: "Markdown" });
|
|
1066
|
-
}
|
|
1067
|
-
});
|
|
1068
|
-
// ── Browser Automation ─────────────────────────────────
|
|
1069
|
-
bot.command("browse", async (ctx) => {
|
|
1070
|
-
const arg = ctx.match?.toString().trim();
|
|
1071
|
-
if (!arg) {
|
|
1072
|
-
await ctx.reply("🌐 *Browser Commands:*\n\n" +
|
|
1073
|
-
"`/browse <URL>` — Screenshot a webpage\n" +
|
|
1074
|
-
"`/browse text <URL>` — Extract text\n" +
|
|
1075
|
-
"`/browse pdf <URL>` — Save as PDF", { parse_mode: "Markdown" });
|
|
1076
|
-
return;
|
|
1077
|
-
}
|
|
1078
|
-
if (!hasPlaywright()) {
|
|
1079
|
-
await ctx.reply("❌ Playwright not installed.\n`npm install playwright && npx playwright install chromium`", { parse_mode: "Markdown" });
|
|
1080
|
-
return;
|
|
1081
|
-
}
|
|
1082
|
-
try {
|
|
1083
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1084
|
-
// /browse text <url>
|
|
1085
|
-
if (arg.startsWith("text ")) {
|
|
1086
|
-
const url = arg.slice(5).trim();
|
|
1087
|
-
const text = await extractText(url);
|
|
1088
|
-
const truncated = text.length > 3500 ? text.slice(0, 3500) + "\n\n_[...truncated]_" : text;
|
|
1089
|
-
await ctx.reply(`🌐 *Text from ${url}:*\n\n${truncated}`, { parse_mode: "Markdown" });
|
|
1090
|
-
return;
|
|
1091
|
-
}
|
|
1092
|
-
// /browse pdf <url>
|
|
1093
|
-
if (arg.startsWith("pdf ")) {
|
|
1094
|
-
const url = arg.slice(4).trim();
|
|
1095
|
-
await ctx.api.sendChatAction(ctx.chat.id, "upload_document");
|
|
1096
|
-
const pdfPath = await generatePdf(url);
|
|
1097
|
-
await ctx.replyWithDocument(new InputFile(fs.readFileSync(pdfPath), "page.pdf"), {
|
|
1098
|
-
caption: `📄 PDF from ${url}`,
|
|
1099
|
-
});
|
|
1100
|
-
fs.unlink(pdfPath, () => { });
|
|
1101
|
-
return;
|
|
1102
|
-
}
|
|
1103
|
-
// Default: screenshot
|
|
1104
|
-
const url = arg.startsWith("http") ? arg : `https://${arg}`;
|
|
1105
|
-
await ctx.api.sendChatAction(ctx.chat.id, "upload_photo");
|
|
1106
|
-
const screenshotPath = await screenshotUrl(url, { fullPage: false });
|
|
1107
|
-
await ctx.replyWithPhoto(new InputFile(fs.readFileSync(screenshotPath), "screenshot.png"), {
|
|
1108
|
-
caption: `🌐 ${url}`,
|
|
1109
|
-
});
|
|
1110
|
-
fs.unlink(screenshotPath, () => { });
|
|
1111
|
-
}
|
|
1112
|
-
catch (err) {
|
|
1113
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1114
|
-
await ctx.reply(`❌ Browser error: ${msg}`);
|
|
1115
|
-
}
|
|
1116
|
-
});
|
|
1117
|
-
// ── Custom Tools ──────────────────────────────────────
|
|
1118
|
-
bot.command("tools", async (ctx) => {
|
|
1119
|
-
const arg = ctx.match?.toString().trim();
|
|
1120
|
-
// /tools run <name> [params json]
|
|
1121
|
-
if (arg?.startsWith("run ")) {
|
|
1122
|
-
const parts = arg.slice(4).trim().split(/\s+/);
|
|
1123
|
-
const toolName = parts[0];
|
|
1124
|
-
let params = {};
|
|
1125
|
-
if (parts.length > 1) {
|
|
1126
|
-
try {
|
|
1127
|
-
params = JSON.parse(parts.slice(1).join(" "));
|
|
1128
|
-
}
|
|
1129
|
-
catch {
|
|
1130
|
-
await ctx.reply("❌ Invalid JSON for parameters.", { parse_mode: "Markdown" });
|
|
1131
|
-
return;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
try {
|
|
1135
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1136
|
-
const result = await executeCustomTool(toolName, params);
|
|
1137
|
-
const truncated = result.length > 3000 ? result.slice(0, 3000) + "\n..." : result;
|
|
1138
|
-
await ctx.reply(`🔧 *${toolName}:*\n\`\`\`\n${truncated}\n\`\`\``, { parse_mode: "Markdown" });
|
|
1139
|
-
}
|
|
1140
|
-
catch (err) {
|
|
1141
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1142
|
-
await ctx.reply(`❌ Tool error: ${msg}`);
|
|
1143
|
-
}
|
|
1144
|
-
return;
|
|
1145
|
-
}
|
|
1146
|
-
// /tools — list all
|
|
1147
|
-
const tools = listCustomTools();
|
|
1148
|
-
if (tools.length === 0) {
|
|
1149
|
-
await ctx.reply("🔧 *Custom Tools*\n\n" +
|
|
1150
|
-
"No tools configured.\n" +
|
|
1151
|
-
"Create `TOOLS.md` (see `TOOLS.example.md`).", { parse_mode: "Markdown" });
|
|
1152
|
-
return;
|
|
1153
|
-
}
|
|
1154
|
-
const lines = tools.map(t => {
|
|
1155
|
-
const icon = t.type === "http" ? "🌐" : "⚡";
|
|
1156
|
-
return `${icon} \`${t.name}\` — ${t.description}`;
|
|
1157
|
-
});
|
|
1158
|
-
await ctx.reply(`🔧 *Custom Tools (${tools.length}):*\n\n${lines.join("\n")}\n\n` +
|
|
1159
|
-
`_Run: \`/tools run <name> {"param":"value"}\`_`, { parse_mode: "Markdown" });
|
|
1160
|
-
});
|
|
1161
|
-
// ── MCP ────────────────────────────────────────────────
|
|
1162
|
-
bot.command("mcp", async (ctx) => {
|
|
1163
|
-
const arg = ctx.match?.toString().trim();
|
|
1164
|
-
// /mcp call <server> <tool> <json-args>
|
|
1165
|
-
if (arg?.startsWith("call ")) {
|
|
1166
|
-
const parts = arg.slice(5).trim().split(/\s+/);
|
|
1167
|
-
if (parts.length < 2) {
|
|
1168
|
-
await ctx.reply("Format: `/mcp call <server> <tool> {\"arg\":\"value\"}`", { parse_mode: "Markdown" });
|
|
1169
|
-
return;
|
|
1170
|
-
}
|
|
1171
|
-
const [server, tool, ...rest] = parts;
|
|
1172
|
-
let args = {};
|
|
1173
|
-
if (rest.length > 0) {
|
|
1174
|
-
try {
|
|
1175
|
-
args = JSON.parse(rest.join(" "));
|
|
1176
|
-
}
|
|
1177
|
-
catch {
|
|
1178
|
-
await ctx.reply("❌ Invalid JSON for tool arguments.");
|
|
1179
|
-
return;
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
try {
|
|
1183
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1184
|
-
const result = await callMCPTool(server, tool, args);
|
|
1185
|
-
const truncated = result.length > 3000 ? result.slice(0, 3000) + "\n..." : result;
|
|
1186
|
-
await ctx.reply(`🔧 *${server}/${tool}:*\n\`\`\`\n${truncated}\n\`\`\``, { parse_mode: "Markdown" });
|
|
1187
|
-
}
|
|
1188
|
-
catch (err) {
|
|
1189
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1190
|
-
await ctx.reply(`❌ MCP error: ${msg}`);
|
|
1191
|
-
}
|
|
1192
|
-
return;
|
|
1193
|
-
}
|
|
1194
|
-
// Default: show status
|
|
1195
|
-
const mcpServers = getMCPStatus();
|
|
1196
|
-
const tools = getMCPTools();
|
|
1197
|
-
if (mcpServers.length === 0) {
|
|
1198
|
-
await ctx.reply(`🔌 *MCP (Model Context Protocol)*\n\n` +
|
|
1199
|
-
`No servers configured.\n` +
|
|
1200
|
-
`Create \`docs/mcp.json\` (see \`docs/mcp.example.json\`).`, { parse_mode: "Markdown" });
|
|
1201
|
-
return;
|
|
1202
|
-
}
|
|
1203
|
-
const serverLines = mcpServers.map(s => {
|
|
1204
|
-
const status = s.connected ? "🟢" : "🔴";
|
|
1205
|
-
return `${status} *${s.name}* — ${s.tools} Tools`;
|
|
1206
|
-
});
|
|
1207
|
-
const toolLines = tools.length > 0
|
|
1208
|
-
? "\n\n*Available Tools:*\n" + tools.map(t => ` 🔧 \`${t.server}/${t.name}\` — ${t.description}`).join("\n")
|
|
1209
|
-
: "";
|
|
1210
|
-
await ctx.reply(`🔌 *MCP Server (${mcpServers.length}):*\n\n` +
|
|
1211
|
-
serverLines.join("\n") +
|
|
1212
|
-
toolLines +
|
|
1213
|
-
`\n\n_Use \`/mcp call <server> <tool> {args}\` to execute._`, { parse_mode: "Markdown" });
|
|
1214
|
-
});
|
|
1215
|
-
// ── Plugins ───────────────────────────────────────────
|
|
1216
|
-
bot.command("plugins", async (ctx) => {
|
|
1217
|
-
const plugins = getLoadedPlugins();
|
|
1218
|
-
if (plugins.length === 0) {
|
|
1219
|
-
await ctx.reply(`🔌 No plugins loaded.\n\n` +
|
|
1220
|
-
`Place plugins in \`${getPluginsDir()}/\`.\n` +
|
|
1221
|
-
`Each plugin needs a folder with \`index.js\`.`, { parse_mode: "Markdown" });
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
const lines = plugins.map(p => {
|
|
1225
|
-
const cmds = p.commands.length > 0 ? `\n Commands: ${p.commands.join(", ")}` : "";
|
|
1226
|
-
const tools = p.tools.length > 0 ? `\n Tools: ${p.tools.join(", ")}` : "";
|
|
1227
|
-
return `🔌 *${p.name}* v${p.version}\n ${p.description}${cmds}${tools}`;
|
|
1228
|
-
});
|
|
1229
|
-
await ctx.reply(`🔌 *Loaded Plugins (${plugins.length}):*\n\n${lines.join("\n\n")}`, { parse_mode: "Markdown" });
|
|
1230
|
-
});
|
|
1231
|
-
// ── Skills ─────────────────────────────────────────────
|
|
1232
|
-
bot.command("skills", async (ctx) => {
|
|
1233
|
-
const { getSkills } = await import("../services/skills.js");
|
|
1234
|
-
const skills = getSkills();
|
|
1235
|
-
if (skills.length === 0) {
|
|
1236
|
-
await ctx.reply("🎯 No skills installed.\n\nAdd SKILL.md files to the `skills/` directory.", { parse_mode: "HTML" });
|
|
1237
|
-
return;
|
|
1238
|
-
}
|
|
1239
|
-
const lines = skills.map(s => `🎯 <b>${s.name}</b> (${s.category})\n ${s.description || "(no description)"}\n Triggers: ${s.triggers.slice(0, 5).join(", ")}`);
|
|
1240
|
-
await ctx.reply(`🎯 <b>Skills (${skills.length}):</b>\n\n${lines.join("\n\n")}`, { parse_mode: "HTML" });
|
|
1241
|
-
});
|
|
1242
|
-
// ── User Profiles ─────────────────────────────────────
|
|
1243
|
-
bot.command("users", async (ctx) => {
|
|
1244
|
-
const profiles = listProfiles();
|
|
1245
|
-
if (profiles.length === 0) {
|
|
1246
|
-
await ctx.reply("No user profiles saved yet.");
|
|
1247
|
-
return;
|
|
1248
|
-
}
|
|
1249
|
-
const lines = profiles.map(p => {
|
|
1250
|
-
const lastActive = new Date(p.lastActive).toLocaleDateString("en-US");
|
|
1251
|
-
const badge = p.isOwner ? "👑" : "👤";
|
|
1252
|
-
return `${badge} *${p.name}*${p.username ? ` (@${p.username})` : ""}\n ${p.totalMessages} messages, last active: ${lastActive}`;
|
|
1253
|
-
});
|
|
1254
|
-
await ctx.reply(`👥 *User-Profile (${profiles.length}):*\n\n${lines.join("\n\n")}`, { parse_mode: "Markdown" });
|
|
1255
|
-
});
|
|
1256
|
-
bot.command("note", async (ctx) => {
|
|
1257
|
-
const arg = ctx.match?.toString().trim();
|
|
1258
|
-
if (!arg) {
|
|
1259
|
-
await ctx.reply("📝 Use: `/note @username Note text`\nSaves a note about a user.", { parse_mode: "Markdown" });
|
|
1260
|
-
return;
|
|
1261
|
-
}
|
|
1262
|
-
// Parse @username or userId + note text
|
|
1263
|
-
const match = arg.match(/^@?(\S+)\s+(.+)$/s);
|
|
1264
|
-
if (!match) {
|
|
1265
|
-
await ctx.reply("Format: `/note @username Text`", { parse_mode: "Markdown" });
|
|
1266
|
-
return;
|
|
1267
|
-
}
|
|
1268
|
-
const [, target, noteText] = match;
|
|
1269
|
-
const profiles = listProfiles();
|
|
1270
|
-
const profile = profiles.find(p => p.username === target || p.userId.toString() === target || p.name.toLowerCase() === target.toLowerCase());
|
|
1271
|
-
if (!profile) {
|
|
1272
|
-
await ctx.reply(`User "${target}" not found.`);
|
|
1273
|
-
return;
|
|
1274
|
-
}
|
|
1275
|
-
addUserNote(profile.userId, noteText);
|
|
1276
|
-
await ctx.reply(`📝 Note saved for ${profile.name}.`);
|
|
1277
|
-
});
|
|
1278
|
-
// ── Memory Search Commands ───────────────────────────
|
|
1279
|
-
bot.command("recall", async (ctx) => {
|
|
1280
|
-
const query = ctx.match?.toString().trim();
|
|
1281
|
-
if (!query) {
|
|
1282
|
-
await ctx.reply("🔍 Use: `/recall <search term>`\nSemantic search through my memory.", { parse_mode: "Markdown" });
|
|
1283
|
-
return;
|
|
1284
|
-
}
|
|
1285
|
-
try {
|
|
1286
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1287
|
-
const results = await searchMemory(query, 5, 0.25);
|
|
1288
|
-
if (results.length === 0) {
|
|
1289
|
-
await ctx.reply(`🔍 No memories found for "${query}".`);
|
|
1290
|
-
return;
|
|
1291
|
-
}
|
|
1292
|
-
const lines = results.map((r, i) => {
|
|
1293
|
-
const score = Math.round(r.score * 100);
|
|
1294
|
-
const preview = r.text.length > 200 ? r.text.slice(0, 200) + "..." : r.text;
|
|
1295
|
-
return `**${i + 1}.** (${score}%) _${r.source}_\n${preview}`;
|
|
1296
|
-
});
|
|
1297
|
-
await ctx.reply(`🧠 Memories for "${query}":\n\n${lines.join("\n\n")}`, { parse_mode: "Markdown" });
|
|
1298
|
-
}
|
|
1299
|
-
catch (err) {
|
|
1300
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1301
|
-
await ctx.reply(`❌ Recall error: ${msg}`);
|
|
1302
|
-
}
|
|
1303
|
-
});
|
|
1304
|
-
bot.command("remember", async (ctx) => {
|
|
1305
|
-
const text = ctx.match?.toString().trim();
|
|
1306
|
-
if (!text) {
|
|
1307
|
-
await ctx.reply("💾 Use: `/remember <text>`\nSaves something to my memory.", { parse_mode: "Markdown" });
|
|
1308
|
-
return;
|
|
1309
|
-
}
|
|
1310
|
-
try {
|
|
1311
|
-
appendDailyLog(`**Manually remembered:** ${text}`);
|
|
1312
|
-
// Trigger reindex so the new entry is searchable
|
|
1313
|
-
const stats = await reindexMemory();
|
|
1314
|
-
await ctx.reply(`💾 Remembered! (${stats.total} entries in index)`);
|
|
1315
|
-
}
|
|
1316
|
-
catch (err) {
|
|
1317
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1318
|
-
await ctx.reply(`❌ Error saving: ${msg}`);
|
|
1319
|
-
}
|
|
1320
|
-
});
|
|
1321
|
-
bot.command("reindex", async (ctx) => {
|
|
1322
|
-
try {
|
|
1323
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1324
|
-
const stats = await reindexMemory(true);
|
|
1325
|
-
const indexStats = getIndexStats();
|
|
1326
|
-
const sizeKB = (indexStats.sizeBytes / 1024).toFixed(1);
|
|
1327
|
-
await ctx.reply(`🔄 Memory re-indexed!\n\n` +
|
|
1328
|
-
`📊 ${stats.indexed} chunks processed\n` +
|
|
1329
|
-
`📁 ${indexStats.files} files indexed\n` +
|
|
1330
|
-
`🧠 ${stats.total} total entries\n` +
|
|
1331
|
-
`💾 Index size: ${sizeKB} KB`);
|
|
1332
|
-
}
|
|
1333
|
-
catch (err) {
|
|
1334
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1335
|
-
await ctx.reply(`❌ Reindex error: ${msg}`);
|
|
1336
|
-
}
|
|
1337
|
-
});
|
|
1338
|
-
// ── Cron Jobs ──────────────────────────────────────────
|
|
1339
|
-
bot.command("cron", async (ctx) => {
|
|
1340
|
-
const arg = ctx.match?.toString().trim() || "";
|
|
1341
|
-
const userId = ctx.from.id;
|
|
1342
|
-
const chatId = ctx.chat.id;
|
|
1343
|
-
// /cron — list all jobs
|
|
1344
|
-
if (!arg) {
|
|
1345
|
-
const jobs = listJobs();
|
|
1346
|
-
if (jobs.length === 0) {
|
|
1347
|
-
await ctx.reply("⏰ <b>Cron Jobs</b>\n\nNo jobs configured.\n\n" +
|
|
1348
|
-
"Create:\n" +
|
|
1349
|
-
"<code>/cron add 5m reminder Wasser trinken</code>\n" +
|
|
1350
|
-
"<code>/cron add \"0 9 * * 1\" shell pm2 status</code>\n" +
|
|
1351
|
-
"<code>/cron add 1h http https://api.example.com/health</code>\n\n" +
|
|
1352
|
-
"<i>Manage jobs also in the Web UI under ⏰ Cron.</i>", { parse_mode: "HTML" });
|
|
1353
|
-
return;
|
|
1354
|
-
}
|
|
1355
|
-
const lines = jobs.map(j => {
|
|
1356
|
-
const status = j.enabled ? "🟢" : "⏸️";
|
|
1357
|
-
const next = j.enabled ? formatNextRun(j.nextRunAt) : "paused";
|
|
1358
|
-
const lastErr = j.lastError ? " ⚠️" : "";
|
|
1359
|
-
const readable = humanReadableSchedule(j.schedule);
|
|
1360
|
-
const recur = j.oneShot ? "⚡ One-shot" : "🔄 " + readable;
|
|
1361
|
-
return `${status} <b>${j.name}</b>\n 📅 ${recur} | Next: ${next}\n Runs: ${j.runCount}${lastErr} | ID: <code>${j.id}</code>`;
|
|
1362
|
-
});
|
|
1363
|
-
const keyboard = new InlineKeyboard();
|
|
1364
|
-
for (const j of jobs) {
|
|
1365
|
-
const label = j.enabled ? `⏸ ${j.name}` : `▶️ ${j.name}`;
|
|
1366
|
-
keyboard.text(label, `cron:toggle:${j.id}`);
|
|
1367
|
-
keyboard.text(`🗑`, `cron:delete:${j.id}`);
|
|
1368
|
-
keyboard.row();
|
|
1369
|
-
}
|
|
1370
|
-
await ctx.reply(`⏰ <b>Cron Jobs (${jobs.length}):</b>\n\n${lines.join("\n\n")}\n\n` +
|
|
1371
|
-
`Commands: /cron add · delete · toggle · run · info`, { parse_mode: "HTML", reply_markup: keyboard });
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
// /cron add <schedule> <type> <payload> [--timeout <sec|off>]
|
|
1375
|
-
if (arg.startsWith("add ")) {
|
|
1376
|
-
let rest = arg.slice(4).trim();
|
|
1377
|
-
// Extract optional --timeout flag from anywhere in the command.
|
|
1378
|
-
// Accepts seconds, "off", "unlimited", "-1", or "0" — anything ≤ 0
|
|
1379
|
-
// or non-numeric collapses to -1 (unlimited).
|
|
1380
|
-
let timeoutMs;
|
|
1381
|
-
const timeoutMatch = rest.match(/(^|\s)--timeout\s+(\S+)/);
|
|
1382
|
-
if (timeoutMatch) {
|
|
1383
|
-
const val = timeoutMatch[2].toLowerCase();
|
|
1384
|
-
if (["off", "unlimited", "infinite", "-1", "0"].includes(val)) {
|
|
1385
|
-
timeoutMs = -1;
|
|
1386
|
-
}
|
|
1387
|
-
else {
|
|
1388
|
-
const secs = Number(timeoutMatch[2]);
|
|
1389
|
-
if (!Number.isFinite(secs) || secs < 0) {
|
|
1390
|
-
await ctx.reply(`❌ Invalid <code>--timeout</code> value: ${timeoutMatch[2]}`, { parse_mode: "HTML" });
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
|
-
timeoutMs = Math.floor(secs * 1000);
|
|
1394
|
-
}
|
|
1395
|
-
rest = rest.replace(/(^|\s)--timeout\s+\S+/, "").trim();
|
|
1396
|
-
}
|
|
1397
|
-
// Natural language schedule shortcuts (German + English)
|
|
1398
|
-
const naturalSchedules = {
|
|
1399
|
-
"täglich": "0 8 * * *", "daily": "0 8 * * *",
|
|
1400
|
-
"stündlich": "0 * * * *", "hourly": "0 * * * *",
|
|
1401
|
-
"wöchentlich": "0 8 * * 1", "weekly": "0 8 * * 1",
|
|
1402
|
-
"monatlich": "0 8 1 * *", "monthly": "0 8 1 * *",
|
|
1403
|
-
"werktags": "0 8 * * 1-5", "weekdays": "0 8 * * 1-5",
|
|
1404
|
-
"wochenende": "0 10 * * 0,6", "weekend": "0 10 * * 0,6",
|
|
1405
|
-
"montags": "0 8 * * 1", "dienstags": "0 8 * * 2", "mittwochs": "0 8 * * 3",
|
|
1406
|
-
"donnerstags": "0 8 * * 4", "freitags": "0 8 * * 5", "samstags": "0 10 * * 6", "sonntags": "0 10 * * 0",
|
|
1407
|
-
"morgens": "0 8 * * *", "mittags": "0 12 * * *", "abends": "0 18 * * *", "nachts": "0 0 * * *",
|
|
1408
|
-
};
|
|
1409
|
-
// Time-prefixed natural: "8:30 täglich" or "täglich 8:30"
|
|
1410
|
-
function resolveNatural(input) {
|
|
1411
|
-
// Try "HH:MM keyword rest" or "keyword HH:MM rest"
|
|
1412
|
-
const timeKeyword = input.match(/^(\d{1,2}):(\d{2})\s+(\S+)\s*(.*)/);
|
|
1413
|
-
if (timeKeyword) {
|
|
1414
|
-
const key = timeKeyword[3].toLowerCase();
|
|
1415
|
-
if (naturalSchedules[key]) {
|
|
1416
|
-
const base = naturalSchedules[key].split(" ");
|
|
1417
|
-
base[0] = String(parseInt(timeKeyword[2]));
|
|
1418
|
-
base[1] = String(parseInt(timeKeyword[1]));
|
|
1419
|
-
return { schedule: base.join(" "), rest: timeKeyword[4] };
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
const keywordTime = input.match(/^(\S+)\s+(\d{1,2}):(\d{2})\s*(.*)/);
|
|
1423
|
-
if (keywordTime) {
|
|
1424
|
-
const key = keywordTime[1].toLowerCase();
|
|
1425
|
-
if (naturalSchedules[key]) {
|
|
1426
|
-
const base = naturalSchedules[key].split(" ");
|
|
1427
|
-
base[0] = String(parseInt(keywordTime[3]));
|
|
1428
|
-
base[1] = String(parseInt(keywordTime[2]));
|
|
1429
|
-
return { schedule: base.join(" "), rest: keywordTime[4] };
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
// Simple keyword
|
|
1433
|
-
const firstWord = input.split(" ")[0].toLowerCase();
|
|
1434
|
-
if (naturalSchedules[firstWord]) {
|
|
1435
|
-
return { schedule: naturalSchedules[firstWord], rest: input.slice(firstWord.length).trim() };
|
|
1436
|
-
}
|
|
1437
|
-
return null;
|
|
1438
|
-
}
|
|
1439
|
-
// Parse: schedule can be "5m", natural keyword, or "0 9 * * 1" (quoted)
|
|
1440
|
-
let schedule;
|
|
1441
|
-
let remainder;
|
|
1442
|
-
const natural = resolveNatural(rest);
|
|
1443
|
-
if (natural) {
|
|
1444
|
-
schedule = natural.schedule;
|
|
1445
|
-
remainder = natural.rest;
|
|
1446
|
-
}
|
|
1447
|
-
else if (rest.startsWith('"')) {
|
|
1448
|
-
const endQuote = rest.indexOf('"', 1);
|
|
1449
|
-
if (endQuote < 0) {
|
|
1450
|
-
await ctx.reply("❌ Missing closing quote for cron expression.");
|
|
1451
|
-
return;
|
|
1452
|
-
}
|
|
1453
|
-
schedule = rest.slice(1, endQuote);
|
|
1454
|
-
remainder = rest.slice(endQuote + 1).trim();
|
|
1455
|
-
}
|
|
1456
|
-
else {
|
|
1457
|
-
const sp = rest.indexOf(" ");
|
|
1458
|
-
if (sp < 0) {
|
|
1459
|
-
await ctx.reply("Format: <code>/cron add <schedule> <type> <payload> [--timeout <sec|off>]</code>\n\nSchedule options:\n• <b>Intervals:</b> 5m, 1h, 30s, 2d\n• <b>Natural:</b> daily, weekly, monthly, weekdays, hourly\n• <b>With time:</b> 8:30 daily, weekdays 9:00\n• <b>German:</b> täglich, wöchentlich, morgens, abends\n• <b>Cron:</b> \"0 9 * * 1-5\"\n\nOptional <code>--timeout</code> in seconds, or <code>off</code>/<code>-1</code> for unlimited.", { parse_mode: "HTML" });
|
|
1460
|
-
return;
|
|
1461
|
-
}
|
|
1462
|
-
schedule = rest.slice(0, sp);
|
|
1463
|
-
remainder = rest.slice(sp + 1).trim();
|
|
1464
|
-
}
|
|
1465
|
-
// Parse type + payload
|
|
1466
|
-
const typeSp = remainder.indexOf(" ");
|
|
1467
|
-
const typeStr = typeSp >= 0 ? remainder.slice(0, typeSp) : remainder;
|
|
1468
|
-
const payloadStr = typeSp >= 0 ? remainder.slice(typeSp + 1).trim() : "";
|
|
1469
|
-
const validTypes = ["reminder", "shell", "http", "message", "ai-query"];
|
|
1470
|
-
if (!validTypes.includes(typeStr)) {
|
|
1471
|
-
await ctx.reply(`❌ Invalid type "${typeStr}". Allowed: ${validTypes.join(", ")}`);
|
|
1472
|
-
return;
|
|
1473
|
-
}
|
|
1474
|
-
const payload = {};
|
|
1475
|
-
switch (typeStr) {
|
|
1476
|
-
case "reminder":
|
|
1477
|
-
case "message":
|
|
1478
|
-
payload.text = payloadStr;
|
|
1479
|
-
break;
|
|
1480
|
-
case "shell":
|
|
1481
|
-
payload.command = payloadStr;
|
|
1482
|
-
break;
|
|
1483
|
-
case "http":
|
|
1484
|
-
payload.url = payloadStr;
|
|
1485
|
-
break;
|
|
1486
|
-
case "ai-query":
|
|
1487
|
-
payload.prompt = payloadStr;
|
|
1488
|
-
break;
|
|
1489
|
-
}
|
|
1490
|
-
const name = `${typeStr}: ${payloadStr.slice(0, 30)}${payloadStr.length > 30 ? "..." : ""}`;
|
|
1491
|
-
const job = createJob({
|
|
1492
|
-
name,
|
|
1493
|
-
type: typeStr,
|
|
1494
|
-
schedule,
|
|
1495
|
-
payload,
|
|
1496
|
-
target: { platform: "telegram", chatId: String(chatId) },
|
|
1497
|
-
createdBy: `telegram:${userId}`,
|
|
1498
|
-
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
1499
|
-
});
|
|
1500
|
-
const readableSched = humanReadableSchedule(job.schedule);
|
|
1501
|
-
const timeoutLine = typeof job.timeoutMs === "number"
|
|
1502
|
-
? job.timeoutMs <= 0
|
|
1503
|
-
? `<b>Timeout:</b> ∞ (unlimited)\n`
|
|
1504
|
-
: `<b>Timeout:</b> ${Math.round(job.timeoutMs / 1000)}s\n`
|
|
1505
|
-
: "";
|
|
1506
|
-
await ctx.reply(`✅ <b>Cron Job created</b>\n\n` +
|
|
1507
|
-
`<b>Name:</b> ${job.name}\n` +
|
|
1508
|
-
`📅 <b>${readableSched}</b>\n` +
|
|
1509
|
-
`<b>Type:</b> ${job.type}\n` +
|
|
1510
|
-
timeoutLine +
|
|
1511
|
-
`<b>Next run:</b> ${formatNextRun(job.nextRunAt)}\n` +
|
|
1512
|
-
`<b>ID:</b> <code>${job.id}</code>`, { parse_mode: "HTML" });
|
|
1513
|
-
return;
|
|
1514
|
-
}
|
|
1515
|
-
// /cron delete <id>
|
|
1516
|
-
if (arg.startsWith("delete ")) {
|
|
1517
|
-
const id = arg.slice(7).trim();
|
|
1518
|
-
if (deleteJob(id)) {
|
|
1519
|
-
await ctx.reply(`✅ Job \`${id}\` deleted.`, { parse_mode: "Markdown" });
|
|
1520
|
-
}
|
|
1521
|
-
else {
|
|
1522
|
-
await ctx.reply(`❌ Job \`${id}\` not found.`, { parse_mode: "Markdown" });
|
|
1523
|
-
}
|
|
1524
|
-
return;
|
|
1525
|
-
}
|
|
1526
|
-
// /cron toggle <id>
|
|
1527
|
-
if (arg.startsWith("toggle ")) {
|
|
1528
|
-
const id = arg.slice(7).trim();
|
|
1529
|
-
const job = toggleJob(id);
|
|
1530
|
-
if (job) {
|
|
1531
|
-
await ctx.reply(`${job.enabled ? "▶️" : "⏸️"} Job "${job.name}" ${job.enabled ? "enabled" : "paused"}.`);
|
|
1532
|
-
}
|
|
1533
|
-
else {
|
|
1534
|
-
await ctx.reply(`❌ Job not found.`);
|
|
1535
|
-
}
|
|
1536
|
-
return;
|
|
1537
|
-
}
|
|
1538
|
-
// /cron run <name-or-id>
|
|
1539
|
-
//
|
|
1540
|
-
// UX contract:
|
|
1541
|
-
// 1. Instantly post a "🚀 Started …" message so the user knows
|
|
1542
|
-
// the command was received.
|
|
1543
|
-
// 2. Every 60s edit that message with the elapsed-time ticker
|
|
1544
|
-
// so the chat shows proof-of-life during 10+ min sub-agent
|
|
1545
|
-
// runs (the Daily Job Alert takes ~13 min in production).
|
|
1546
|
-
// 3. When runJobNow returns, edit the same message into a
|
|
1547
|
-
// final "✅ Done" / "❌ error" / "⏳ already running" state.
|
|
1548
|
-
// 4. The heavy lifting (banner + full body + chunking) stays in
|
|
1549
|
-
// subagent-delivery.ts — which now has a Markdown→plain-text
|
|
1550
|
-
// fallback so it actually reaches the user.
|
|
1551
|
-
if (arg.startsWith("run ")) {
|
|
1552
|
-
const nameOrId = arg.slice(4).trim();
|
|
1553
|
-
// Resolve up-front so we can show the real job name in the
|
|
1554
|
-
// "Started" ack, and so we handle the not-found case BEFORE
|
|
1555
|
-
// spending a Telegram round-trip on a pointless placeholder.
|
|
1556
|
-
const resolved = resolveJobByNameOrId(listJobs(), nameOrId);
|
|
1557
|
-
if (!resolved) {
|
|
1558
|
-
const jobs = listJobs();
|
|
1559
|
-
const hint = jobs.length > 0
|
|
1560
|
-
? `\n\nAvailable:\n${jobs.slice(0, 10).map(j => `• ${j.name}`).join("\n")}`
|
|
1561
|
-
: "";
|
|
1562
|
-
await ctx.reply(`❌ No job matches <code>${nameOrId}</code>.${hint}`, { parse_mode: "HTML" });
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1565
|
-
const jobName = resolved.name;
|
|
1566
|
-
const startedAt = Date.now();
|
|
1567
|
-
// Post initial ack — we'll edit THIS message for the ticker and
|
|
1568
|
-
// the final state.
|
|
1569
|
-
let ackMessageId = null;
|
|
1570
|
-
try {
|
|
1571
|
-
const ack = await ctx.reply(`🚀 Started *${escapeMarkdown(jobName)}* — working…`, { parse_mode: "Markdown" });
|
|
1572
|
-
ackMessageId = ack.message_id;
|
|
1573
|
-
}
|
|
1574
|
-
catch (err) {
|
|
1575
|
-
// If even the initial ack fails, fall back to plain text so
|
|
1576
|
-
// the user still knows we received the command.
|
|
1577
|
-
try {
|
|
1578
|
-
const ack = await ctx.reply(`🚀 Started ${jobName} — working…`);
|
|
1579
|
-
ackMessageId = ack.message_id;
|
|
1580
|
-
}
|
|
1581
|
-
catch { /* give up on the ack — run still fires below */ }
|
|
1582
|
-
}
|
|
1583
|
-
const chatId = ctx.chat.id;
|
|
1584
|
-
// Progress ticker: edit the ack message with elapsed time every
|
|
1585
|
-
// 60s. Errors from editMessageText (including the harmless
|
|
1586
|
-
// "message is not modified") are swallowed via the central filter.
|
|
1587
|
-
const ticker = setInterval(async () => {
|
|
1588
|
-
if (ackMessageId === null)
|
|
1589
|
-
return;
|
|
1590
|
-
const elapsed = Math.floor((Date.now() - startedAt) / 1000);
|
|
1591
|
-
try {
|
|
1592
|
-
await ctx.api.editMessageText(chatId, ackMessageId, buildTickerText(jobName, elapsed), { parse_mode: "Markdown" });
|
|
1593
|
-
}
|
|
1594
|
-
catch (err) {
|
|
1595
|
-
if (!isHarmlessTelegramError(err)) {
|
|
1596
|
-
console.warn(`[cron:run] ticker edit failed:`, err);
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
}, 60_000);
|
|
1600
|
-
let outcome;
|
|
1601
|
-
try {
|
|
1602
|
-
outcome = await runJobNow(nameOrId);
|
|
1603
|
-
}
|
|
1604
|
-
finally {
|
|
1605
|
-
clearInterval(ticker);
|
|
1606
|
-
}
|
|
1607
|
-
// Final state — edit the ack message one last time.
|
|
1608
|
-
const elapsed = Math.floor((Date.now() - startedAt) / 1000);
|
|
1609
|
-
const finalText = (() => {
|
|
1610
|
-
if (outcome.status === "not-found") {
|
|
1611
|
-
// Shouldn't happen — we already resolved successfully above —
|
|
1612
|
-
// but handle it for completeness.
|
|
1613
|
-
return `❌ ${escapeMarkdown(jobName)} — not found (race?)`;
|
|
1614
|
-
}
|
|
1615
|
-
if (outcome.status === "already-running") {
|
|
1616
|
-
return buildDoneText(outcome.job.name, elapsed, { ok: true, skipped: true });
|
|
1617
|
-
}
|
|
1618
|
-
return buildDoneText(outcome.job.name, elapsed, {
|
|
1619
|
-
ok: !outcome.error,
|
|
1620
|
-
error: outcome.error,
|
|
1621
|
-
});
|
|
1622
|
-
})();
|
|
1623
|
-
if (ackMessageId !== null) {
|
|
1624
|
-
try {
|
|
1625
|
-
await ctx.api.editMessageText(chatId, ackMessageId, finalText, { parse_mode: "Markdown" });
|
|
1626
|
-
}
|
|
1627
|
-
catch (err) {
|
|
1628
|
-
if (!isHarmlessTelegramError(err)) {
|
|
1629
|
-
// Last-ditch fallback: post as a new plain message so the
|
|
1630
|
-
// user sees the result even if the edit failed.
|
|
1631
|
-
await ctx.reply(finalText).catch(() => { });
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
else {
|
|
1636
|
-
// We never got an ack message id — just post fresh
|
|
1637
|
-
await ctx.reply(finalText, { parse_mode: "Markdown" }).catch(() => ctx.reply(finalText));
|
|
1638
|
-
}
|
|
1639
|
-
return;
|
|
1640
|
-
}
|
|
1641
|
-
await ctx.reply("Unknown cron command. Use /cron for help.");
|
|
1642
|
-
});
|
|
1643
|
-
// Inline keyboard callbacks for cron
|
|
1644
|
-
bot.callbackQuery(/^cron:toggle:(.+)$/, async (ctx) => {
|
|
1645
|
-
const id = ctx.match[1];
|
|
1646
|
-
const job = toggleJob(id);
|
|
1647
|
-
if (job) {
|
|
1648
|
-
await ctx.answerCallbackQuery(`${job.enabled ? "Enabled" : "Paused"}: ${job.name}`);
|
|
1649
|
-
// Refresh the cron list
|
|
1650
|
-
ctx.match = "";
|
|
1651
|
-
// Re-render the list message (HTML to avoid Markdown * conflicts with cron expressions)
|
|
1652
|
-
const jobs = listJobs();
|
|
1653
|
-
const lines = jobs.map(j => {
|
|
1654
|
-
const status = j.enabled ? "🟢" : "⏸️";
|
|
1655
|
-
const next = j.enabled ? formatNextRun(j.nextRunAt) : "paused";
|
|
1656
|
-
const readable = humanReadableSchedule(j.schedule);
|
|
1657
|
-
const recur = j.oneShot ? "⚡ One-shot" : "🔄 " + readable;
|
|
1658
|
-
return `${status} <b>${j.name}</b>\n 📅 ${recur} | Next: ${next}\n Runs: ${j.runCount} | ID: <code>${j.id}</code>`;
|
|
1659
|
-
});
|
|
1660
|
-
const keyboard = new InlineKeyboard();
|
|
1661
|
-
for (const j of jobs) {
|
|
1662
|
-
keyboard.text(j.enabled ? `⏸ ${j.name}` : `▶️ ${j.name}`, `cron:toggle:${j.id}`);
|
|
1663
|
-
keyboard.text(`🗑`, `cron:delete:${j.id}`);
|
|
1664
|
-
keyboard.row();
|
|
1665
|
-
}
|
|
1666
|
-
await ctx.editMessageText(`⏰ <b>Cron Jobs (${jobs.length}):</b>\n\n${lines.join("\n\n")}`, { parse_mode: "HTML", reply_markup: keyboard });
|
|
1667
|
-
}
|
|
1668
|
-
});
|
|
1669
|
-
bot.callbackQuery(/^cron:delete:(.+)$/, async (ctx) => {
|
|
1670
|
-
const id = ctx.match[1];
|
|
1671
|
-
deleteJob(id);
|
|
1672
|
-
await ctx.answerCallbackQuery("Deleted");
|
|
1673
|
-
// Refresh (HTML parse mode)
|
|
1674
|
-
const jobs = listJobs();
|
|
1675
|
-
if (jobs.length === 0) {
|
|
1676
|
-
await ctx.editMessageText("⏰ No cron jobs configured.");
|
|
1677
|
-
}
|
|
1678
|
-
else {
|
|
1679
|
-
const lines = jobs.map(j => {
|
|
1680
|
-
const status = j.enabled ? "🟢" : "⏸️";
|
|
1681
|
-
const readable = humanReadableSchedule(j.schedule);
|
|
1682
|
-
return `${status} <b>${j.name}</b>\n 📅 ${readable} | ID: <code>${j.id}</code>`;
|
|
1683
|
-
});
|
|
1684
|
-
const keyboard = new InlineKeyboard();
|
|
1685
|
-
for (const j of jobs) {
|
|
1686
|
-
keyboard.text(j.enabled ? `⏸ ${j.name}` : `▶️ ${j.name}`, `cron:toggle:${j.id}`);
|
|
1687
|
-
keyboard.text(`🗑`, `cron:delete:${j.id}`);
|
|
1688
|
-
keyboard.row();
|
|
1689
|
-
}
|
|
1690
|
-
await ctx.editMessageText(`⏰ <b>Cron Jobs (${jobs.length}):</b>\n\n${lines.join("\n\n")}`, { parse_mode: "HTML", reply_markup: keyboard });
|
|
1691
|
-
}
|
|
1692
|
-
});
|
|
1693
|
-
// ── Setup (API Keys & Platforms via Telegram) ─────────
|
|
1694
|
-
bot.command("setup", async (ctx) => {
|
|
1695
|
-
const arg = ctx.match?.toString().trim() || "";
|
|
1696
|
-
if (!arg) {
|
|
1697
|
-
const registry = getRegistry();
|
|
1698
|
-
const providers = await registry.listAll();
|
|
1699
|
-
const activeInfo = registry.getActive().getInfo();
|
|
1700
|
-
const keyboard = new InlineKeyboard()
|
|
1701
|
-
.text("🔑 Manage API Keys", "setup:keys").row()
|
|
1702
|
-
.text("📱 Platforms", "setup:platforms").row()
|
|
1703
|
-
.text("🔐 Sudo / Admin Access", "setup:sudo").row()
|
|
1704
|
-
.text("🛡️ Permissions Wizard (Mac)", "setup:permissions").row()
|
|
1705
|
-
.text("🔧 Open Web Dashboard", "setup:web").row();
|
|
1706
|
-
await ctx.reply(`⚙️ *Alvin Bot Setup*\n\n` +
|
|
1707
|
-
`*Active Model:* ${activeInfo.name}\n` +
|
|
1708
|
-
`*Providers:* ${providers.length} configured\n` +
|
|
1709
|
-
`*Web UI:* http://localhost:${process.env.WEB_PORT || 3100}\n\n` +
|
|
1710
|
-
`What would you like to configure?`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
// /setup sudo [password] — configure sudo access
|
|
1714
|
-
if (arg.startsWith("sudo")) {
|
|
1715
|
-
const pw = arg.slice(4).trim();
|
|
1716
|
-
if (!pw) {
|
|
1717
|
-
// Show status
|
|
1718
|
-
const status = await getSudoStatus();
|
|
1719
|
-
const statusIcon = status.configured ? (status.verified ? "✅" : "⚠️") : "❌";
|
|
1720
|
-
const keyboard = new InlineKeyboard();
|
|
1721
|
-
if (status.configured) {
|
|
1722
|
-
keyboard.text("🧪 Verify", "sudo:verify").row();
|
|
1723
|
-
keyboard.text("🔴 Revoke Access", "sudo:revoke").row();
|
|
1724
|
-
}
|
|
1725
|
-
await ctx.reply(`🔐 *Sudo / Admin Access*\n\n` +
|
|
1726
|
-
`*Status:* ${statusIcon} ${status.configured ? (status.verified ? "Configured & verified" : "Configured, not verified") : "Not set up"}\n` +
|
|
1727
|
-
`*Storage:* ${status.storageMethod}\n` +
|
|
1728
|
-
`*System:* ${status.platform} (${status.user})\n` +
|
|
1729
|
-
(status.permissions.accessibility !== null ? `*Accessibility:* ${status.permissions.accessibility ? "✅" : "❌"}\n` : "") +
|
|
1730
|
-
(status.permissions.fullDiskAccess !== null ? `*Full Disk Access:* ${status.permissions.fullDiskAccess ? "✅" : "❌"}\n` : "") +
|
|
1731
|
-
`\n*Setup:*\n\`/setup sudo <your-system-password>\`\n\n` +
|
|
1732
|
-
`_The password is securely stored in ${status.storageMethod}. ` +
|
|
1733
|
-
`This allows Alvin Bot to run admin commands (install software, change system settings, etc.)._\n\n` +
|
|
1734
|
-
`⚠️ _Delete this message after setup! The password is visible in chat history._`, { parse_mode: "Markdown", reply_markup: keyboard });
|
|
1735
|
-
return;
|
|
1736
|
-
}
|
|
1737
|
-
// Store the password
|
|
1738
|
-
await ctx.api.sendChatAction(ctx.chat.id, "typing");
|
|
1739
|
-
const result = storePassword(pw);
|
|
1740
|
-
if (!result.ok) {
|
|
1741
|
-
await ctx.reply(`❌ Error saving: ${result.error}`);
|
|
1742
|
-
return;
|
|
1743
|
-
}
|
|
1744
|
-
// Verify
|
|
1745
|
-
const verify = await verifyPassword();
|
|
1746
|
-
if (verify.ok) {
|
|
1747
|
-
await ctx.reply(`✅ *Sudo access configured!*\n\n` +
|
|
1748
|
-
`Password stored in: ${result.method}\n` +
|
|
1749
|
-
`Verification: ✅ successful\n\n` +
|
|
1750
|
-
`Alvin Bot can now run admin commands.\n\n` +
|
|
1751
|
-
`⚠️ _Please delete the message with the password from the chat!_`, { parse_mode: "Markdown" });
|
|
1752
|
-
}
|
|
1753
|
-
else {
|
|
1754
|
-
revokePassword(); // Wrong password — clean up
|
|
1755
|
-
await ctx.reply(`❌ *Wrong password!*\n\n` +
|
|
1756
|
-
`The entered password does not work for sudo.\n` +
|
|
1757
|
-
`Please try again: \`/setup sudo <correct-password>\``, { parse_mode: "Markdown" });
|
|
1758
|
-
}
|
|
1759
|
-
// Try to delete the user's message containing the password
|
|
1760
|
-
try {
|
|
1761
|
-
await ctx.api.deleteMessage(ctx.chat.id, ctx.message.message_id);
|
|
1762
|
-
}
|
|
1763
|
-
catch {
|
|
1764
|
-
// Can't delete in private chats sometimes — that's ok
|
|
1765
|
-
}
|
|
1766
|
-
return;
|
|
1767
|
-
}
|
|
1768
|
-
// /setup key <provider> <key>
|
|
1769
|
-
if (arg.startsWith("key ")) {
|
|
1770
|
-
const parts = arg.slice(4).trim().split(/\s+/);
|
|
1771
|
-
if (parts.length < 2) {
|
|
1772
|
-
await ctx.reply("🔑 *Set API Key:*\n\n" +
|
|
1773
|
-
"`/setup key openai sk-...`\n" +
|
|
1774
|
-
"`/setup key google AIza...`\n" +
|
|
1775
|
-
"`/setup key nvidia nvapi-...`\n" +
|
|
1776
|
-
"`/setup key openrouter sk-or-...`\n\n" +
|
|
1777
|
-
"_The key will be saved to .env. Restart required._", { parse_mode: "Markdown" });
|
|
1778
|
-
return;
|
|
1779
|
-
}
|
|
1780
|
-
const envMap = {
|
|
1781
|
-
openai: "OPENAI_API_KEY",
|
|
1782
|
-
google: "GOOGLE_API_KEY",
|
|
1783
|
-
nvidia: "NVIDIA_API_KEY",
|
|
1784
|
-
openrouter: "OPENROUTER_API_KEY",
|
|
1785
|
-
groq: "GROQ_API_KEY",
|
|
1786
|
-
};
|
|
1787
|
-
const provider = parts[0].toLowerCase();
|
|
1788
|
-
const key = parts.slice(1).join(" ");
|
|
1789
|
-
const envKey = envMap[provider];
|
|
1790
|
-
if (!envKey) {
|
|
1791
|
-
await ctx.reply(`❌ Unknown provider "${provider}". Use: ${Object.keys(envMap).join(", ")}`);
|
|
1792
|
-
return;
|
|
1793
|
-
}
|
|
1794
|
-
// Write to .env
|
|
1795
|
-
const envFile = resolve(process.cwd(), ".env");
|
|
1796
|
-
let content = fs.existsSync(envFile) ? fs.readFileSync(envFile, "utf-8") : "";
|
|
1797
|
-
const regex = new RegExp(`^${envKey}=.*$`, "m");
|
|
1798
|
-
if (regex.test(content))
|
|
1799
|
-
content = content.replace(regex, `${envKey}=${key}`);
|
|
1800
|
-
else
|
|
1801
|
-
content = content.trimEnd() + `\n${envKey}=${key}\n`;
|
|
1802
|
-
fs.writeFileSync(envFile, content);
|
|
1803
|
-
await ctx.reply(`✅ ${envKey} saved! Please restart the bot (/system restart or Web UI).`);
|
|
1804
|
-
return;
|
|
1805
|
-
}
|
|
1806
|
-
});
|
|
1807
|
-
bot.callbackQuery(/^sudo:(.+)$/, async (ctx) => {
|
|
1808
|
-
const action = ctx.match[1];
|
|
1809
|
-
if (action === "verify") {
|
|
1810
|
-
const result = await verifyPassword();
|
|
1811
|
-
await ctx.answerCallbackQuery(result.ok ? "✅ Sudo works!" : `❌ ${result.error}`);
|
|
1812
|
-
}
|
|
1813
|
-
else if (action === "revoke") {
|
|
1814
|
-
revokePassword();
|
|
1815
|
-
await ctx.editMessageText("🔴 Sudo access revoked. Password deleted.");
|
|
1816
|
-
await ctx.answerCallbackQuery("Access revoked");
|
|
1817
|
-
}
|
|
1818
|
-
});
|
|
1819
|
-
bot.callbackQuery(/^setup:(.+)$/, async (ctx) => {
|
|
1820
|
-
const action = ctx.match[1];
|
|
1821
|
-
switch (action) {
|
|
1822
|
-
case "keys": {
|
|
1823
|
-
const envMap = [
|
|
1824
|
-
{ name: "OpenAI", env: "OPENAI_API_KEY", has: !!config.apiKeys.openai },
|
|
1825
|
-
{ name: "Google", env: "GOOGLE_API_KEY", has: !!config.apiKeys.google },
|
|
1826
|
-
{ name: "NVIDIA", env: "NVIDIA_API_KEY", has: !!config.apiKeys.nvidia },
|
|
1827
|
-
{ name: "OpenRouter", env: "OPENROUTER_API_KEY", has: !!config.apiKeys.openrouter },
|
|
1828
|
-
{ name: "Groq", env: "GROQ_API_KEY", has: !!config.apiKeys.groq },
|
|
1829
|
-
];
|
|
1830
|
-
const lines = envMap.map(e => `${e.has ? "✅" : "❌"} *${e.name}* — \`${e.env}\``);
|
|
1831
|
-
await ctx.editMessageText(`🔑 *API Keys*\n\n${lines.join("\n")}\n\n` +
|
|
1832
|
-
`Set key: \`/setup key <provider> <key>\`\n` +
|
|
1833
|
-
`Example: \`/setup key nvidia nvapi-...\`\n\n` +
|
|
1834
|
-
`_Restart required after changes._`, { parse_mode: "Markdown" });
|
|
1835
|
-
break;
|
|
1836
|
-
}
|
|
1837
|
-
case "platforms": {
|
|
1838
|
-
const platforms = [
|
|
1839
|
-
{ name: "Telegram", icon: "📱", env: "BOT_TOKEN", has: !!process.env.BOT_TOKEN },
|
|
1840
|
-
{ name: "Discord", icon: "🎮", env: "DISCORD_TOKEN", has: !!process.env.DISCORD_TOKEN },
|
|
1841
|
-
{ name: "WhatsApp", icon: "💬", env: "WHATSAPP_ENABLED", has: process.env.WHATSAPP_ENABLED === "true" },
|
|
1842
|
-
{ name: "Signal", icon: "🔒", env: "SIGNAL_API_URL", has: !!process.env.SIGNAL_API_URL },
|
|
1843
|
-
];
|
|
1844
|
-
const lines = platforms.map(p => `${p.has ? "✅" : "❌"} ${p.icon} *${p.name}* — \`${p.env}\``);
|
|
1845
|
-
await ctx.editMessageText(`📱 *Platforms*\n\n${lines.join("\n")}\n\n` +
|
|
1846
|
-
`_Set up platforms in Web UI: Models → Platforms_\n` +
|
|
1847
|
-
`_There you can enter tokens and install dependencies._`, { parse_mode: "Markdown" });
|
|
1848
|
-
break;
|
|
1849
|
-
}
|
|
1850
|
-
case "sudo": {
|
|
1851
|
-
const status = await getSudoStatus();
|
|
1852
|
-
const statusIcon = status.configured ? (status.verified ? "✅" : "⚠️") : "❌";
|
|
1853
|
-
await ctx.editMessageText(`🔐 *Sudo / Admin Access*\n\n` +
|
|
1854
|
-
`*Status:* ${statusIcon} ${status.configured ? (status.verified ? "Active & verified" : "Configured") : "Not set up"}\n` +
|
|
1855
|
-
`*Storage:* ${status.storageMethod}\n\n` +
|
|
1856
|
-
`Setup: \`/setup sudo <system-password>\`\n` +
|
|
1857
|
-
`Revoke: \`/setup sudo\` → "Revoke" button\n\n` +
|
|
1858
|
-
`_The password is securely stored in ${status.storageMethod}._`, { parse_mode: "Markdown" });
|
|
1859
|
-
break;
|
|
1860
|
-
}
|
|
1861
|
-
case "permissions": {
|
|
1862
|
-
// 5.1.0 — Permissions Wizard summary. Mobile UX is intentionally
|
|
1863
|
-
// read-only: the wizard itself needs to open System Settings panes
|
|
1864
|
-
// on the host machine, which only the CLI/WebUI can drive. Here
|
|
1865
|
-
// we surface status + tell the user how to run the actual wizard.
|
|
1866
|
-
try {
|
|
1867
|
-
const { readPermissionsSnapshot } = await import("../services/permissions-wizard.js");
|
|
1868
|
-
const snaps = await readPermissionsSnapshot();
|
|
1869
|
-
const icons = { granted: "✅", missing: "❌", "tool-missing": "⚠️", "n/a": "·" };
|
|
1870
|
-
const lines = snaps.map(s => `${icons[s.state]} *${s.permission.name}* — ${s.state}${s.detail ? " _(" + s.detail + ")_" : ""}`);
|
|
1871
|
-
const missing = snaps.filter(s => s.state === "missing" || s.state === "tool-missing").length;
|
|
1872
|
-
const summary = missing === 0
|
|
1873
|
-
? "*All applicable permissions granted.*"
|
|
1874
|
-
: `*${missing} permission${missing === 1 ? "" : "s"} need attention.*`;
|
|
1875
|
-
await ctx.editMessageText(`🛡️ *Permissions Status*\n\n${lines.join("\n")}\n\n${summary}\n\n` +
|
|
1876
|
-
`_macOS doesn't let any app grant TCC permissions on its own — you toggle the switch, the wizard verifies._\n\n` +
|
|
1877
|
-
`*To run the guided wizard:*\n` +
|
|
1878
|
-
`• CLI: \`alvin-bot permissions wizard\` (opens each Settings pane, waits, verifies)\n` +
|
|
1879
|
-
`• WebUI: http://localhost:${process.env.WEB_PORT || 3100} → Settings`, { parse_mode: "Markdown" });
|
|
1880
|
-
}
|
|
1881
|
-
catch (err) {
|
|
1882
|
-
await ctx.editMessageText("🛡️ *Permissions Status*\n\n_Could not load wizard module — try `alvin-bot permissions status` in a terminal._", { parse_mode: "Markdown" });
|
|
1883
|
-
}
|
|
1884
|
-
break;
|
|
1885
|
-
}
|
|
1886
|
-
case "web": {
|
|
1887
|
-
await ctx.editMessageText(`🌐 *Web Dashboard*\n\n` +
|
|
1888
|
-
`URL: \`http://localhost:${process.env.WEB_PORT || 3100}\`\n\n` +
|
|
1889
|
-
`In the dashboard you can:\n` +
|
|
1890
|
-
`• 🤖 Manage models & API keys\n` +
|
|
1891
|
-
`• 📱 Set up platforms\n` +
|
|
1892
|
-
`• ⏰ Manage cron jobs\n` +
|
|
1893
|
-
`• 🧠 Edit memory\n` +
|
|
1894
|
-
`• 💻 Use terminal\n` +
|
|
1895
|
-
`• 🛠️ Run tools`, { parse_mode: "Markdown" });
|
|
1896
|
-
break;
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
await ctx.answerCallbackQuery();
|
|
1900
|
-
});
|
|
1901
|
-
/** Build StopDeps for a session — wires the three stop side-effects. */
|
|
1902
|
-
function buildStopDeps(session) {
|
|
1903
|
-
return {
|
|
1904
|
-
interruptQuery: () => interruptQuery(session),
|
|
1905
|
-
killDetachedAgents: () => killSessionDetachedAgents(session),
|
|
1906
|
-
clearPendingForSession: (k) => cancelPendingForSession(k),
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
bot.command("cancel", async (ctx) => {
|
|
1910
|
-
const userId = ctx.from.id;
|
|
1911
|
-
// Use buildSessionKey so the resolved session is always the SAME object
|
|
1912
|
-
// that message.ts created (and that registered pending agents under this key).
|
|
1913
|
-
// In per-user mode this equals String(userId); in per-channel modes it
|
|
1914
|
-
// incorporates chatId — matching the key used for the ⛔ button payload.
|
|
1915
|
-
const sessionKey = buildSessionKey("telegram", ctx.chat.id, userId);
|
|
1916
|
-
const session = getSession(sessionKey);
|
|
1917
|
-
const lang = session.language;
|
|
1918
|
-
if (session.isProcessing) {
|
|
1919
|
-
requestStop(session, "soft", buildStopDeps(session));
|
|
1920
|
-
await ctx.reply(t("bot.cancel.cancelling", lang));
|
|
1921
|
-
// V56-T2c — a real stop fired: follow the "cancelling…" notice with a
|
|
1922
|
-
// brief confirmation that the work was actually halted (consistent UX
|
|
1923
|
-
// with the ⛔ button). Best-effort — must never throw into the handler.
|
|
1924
|
-
await ctx.reply(t("bot.cancel.confirmed", lang)).catch(() => { });
|
|
1925
|
-
}
|
|
1926
|
-
else {
|
|
1927
|
-
await ctx.reply(t("bot.cancel.noRunning", lang));
|
|
1928
|
-
}
|
|
1929
|
-
});
|
|
1930
|
-
// /stopall — hard stop: interrupt query + kill detached agents + clear queue + cancel pending.
|
|
1931
|
-
bot.command("stopall", async (ctx) => {
|
|
1932
|
-
const userId = ctx.from.id;
|
|
1933
|
-
// Same canonical-key resolution as /cancel above — must match message.ts.
|
|
1934
|
-
const sessionKey = buildSessionKey("telegram", ctx.chat.id, userId);
|
|
1935
|
-
const session = getSession(sessionKey);
|
|
1936
|
-
const lang = session.language;
|
|
1937
|
-
if (session.isProcessing) {
|
|
1938
|
-
requestStop(session, "hard", buildStopDeps(session));
|
|
1939
|
-
await ctx.reply(t("bot.cancel.stoppedAll", lang));
|
|
1940
|
-
}
|
|
1941
|
-
else {
|
|
1942
|
-
await ctx.reply(t("bot.cancel.noRunning", lang));
|
|
1943
|
-
}
|
|
1944
|
-
});
|
|
1945
|
-
// stop: inline keyboard callback — soft stop triggered from the ⛔ button
|
|
1946
|
-
// sent alongside the processing indicator in the message handler.
|
|
1947
|
-
// Payload format: "stop:<sessionKey>" where sessionKey = String(userId) in
|
|
1948
|
-
// default per-user mode (mirrors buildSessionKey used in message.ts).
|
|
1949
|
-
bot.callbackQuery(/^stop:(.+)$/, async (ctx) => {
|
|
1950
|
-
const sessionKey = ctx.match[1];
|
|
1951
|
-
const session = getSession(sessionKey);
|
|
1952
|
-
const lang = session.language;
|
|
1953
|
-
// A1 — Capture isProcessing BEFORE requestStop (which sets it false)
|
|
1954
|
-
// so we can show the right toast: "stopped" vs "already finished".
|
|
1955
|
-
const wasProcessing = session.isProcessing;
|
|
1956
|
-
if (wasProcessing) {
|
|
1957
|
-
requestStop(session, "soft", buildStopDeps(session));
|
|
1958
|
-
}
|
|
1959
|
-
// A1 — Honest toast: if the turn had already finished when the button was
|
|
1960
|
-
// tapped, don't claim "stopped" — tell the user it was already done.
|
|
1961
|
-
const toastKey = wasProcessing
|
|
1962
|
-
? "bot.cancel.stoppedToast"
|
|
1963
|
-
: "bot.cancel.alreadyDone";
|
|
1964
|
-
try {
|
|
1965
|
-
await ctx.answerCallbackQuery({ text: t(toastKey, lang) });
|
|
1966
|
-
}
|
|
1967
|
-
catch { /* harmless grammy race */ }
|
|
1968
|
-
try {
|
|
1969
|
-
await ctx.editMessageReplyMarkup({});
|
|
1970
|
-
}
|
|
1971
|
-
catch { /* harmless grammy race — message may already be gone */ }
|
|
1972
|
-
// V56-T2c — when a real stop genuinely fired (wasProcessing), also send a
|
|
1973
|
-
// short in-chat confirmation in the session language so the user gets a
|
|
1974
|
-
// persistent acknowledgement, not only the ephemeral toast. When nothing
|
|
1975
|
-
// was running we deliberately stay silent here (v5.5.0 honesty: the
|
|
1976
|
-
// alreadyDone toast already told the truth). Best-effort — must never
|
|
1977
|
-
// throw into the handler.
|
|
1978
|
-
if (wasProcessing) {
|
|
1979
|
-
await ctx.reply(t("bot.cancel.confirmed", lang)).catch(() => { });
|
|
1980
|
-
}
|
|
1981
|
-
});
|
|
1982
|
-
// /restart — trigger a PM2-managed restart by exiting the process.
|
|
1983
|
-
// The PM2 supervisor picks up the exit and respawns with --update-env.
|
|
1984
|
-
bot.command("restart", async (ctx) => {
|
|
1985
|
-
const lang = getSession(ctx.from.id).language;
|
|
1986
|
-
await ctx.reply(t("bot.restart.triggered", lang));
|
|
1987
|
-
// Intentional restart — don't let the watchdog score it as a crash.
|
|
1988
|
-
markExpectedRestart();
|
|
1989
|
-
// Small delay so the Telegram message is actually delivered before exit
|
|
1990
|
-
setTimeout(() => process.exit(0), 500);
|
|
1991
|
-
});
|
|
1992
|
-
// /update — git pull + install + build, then PM2-restart if anything changed.
|
|
1993
|
-
bot.command("update", async (ctx) => {
|
|
1994
|
-
const lang = getSession(ctx.from.id).language;
|
|
1995
|
-
await ctx.reply(t("bot.update.checking", lang));
|
|
1996
|
-
try {
|
|
1997
|
-
const result = await runUpdate();
|
|
1998
|
-
if (result.ok) {
|
|
1999
|
-
await ctx.reply(`✅ ${result.message}`);
|
|
2000
|
-
// Extract the installed version from the message (e.g. "Installed v4.16.1 ...")
|
|
2001
|
-
// so we can look up its CHANGELOG block. Falls silently if no match.
|
|
2002
|
-
const versionMatch = result.message.match(/v(\d+\.\d+\.\d+)/);
|
|
2003
|
-
if (versionMatch) {
|
|
2004
|
-
const highlights = getReleaseHighlights(versionMatch[1]);
|
|
2005
|
-
if (highlights) {
|
|
2006
|
-
await ctx.reply(`📝 *What's new in v${versionMatch[1]}*\n\n${highlights}`, {
|
|
2007
|
-
parse_mode: "Markdown",
|
|
2008
|
-
});
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
if (result.requiresRestart) {
|
|
2012
|
-
await ctx.reply(t("bot.update.restarting", lang));
|
|
2013
|
-
// Intentional restart — don't let the watchdog score it as a crash.
|
|
2014
|
-
markExpectedRestart();
|
|
2015
|
-
setTimeout(() => process.exit(0), 500);
|
|
2016
|
-
}
|
|
2017
|
-
}
|
|
2018
|
-
else {
|
|
2019
|
-
await ctx.reply(`${t("bot.update.failed", lang)}\n\`${result.message}\``, { parse_mode: "Markdown" });
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
catch (err) {
|
|
2023
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2024
|
-
await ctx.reply(`${t("bot.update.error", lang)} ${msg}`);
|
|
2025
|
-
}
|
|
2026
|
-
});
|
|
2027
|
-
// /autoupdate on|off|status — toggle the background auto-update loop.
|
|
2028
|
-
// Persisted to ~/.alvin-bot/auto-update.flag so it survives restarts.
|
|
2029
|
-
bot.command("autoupdate", async (ctx) => {
|
|
2030
|
-
const lang = getSession(ctx.from.id).language;
|
|
2031
|
-
const arg = (ctx.match || "").trim().toLowerCase();
|
|
2032
|
-
if (arg === "on") {
|
|
2033
|
-
setAutoUpdate(true);
|
|
2034
|
-
await ctx.reply(t("bot.autoupdate.enabled", lang), { parse_mode: "Markdown" });
|
|
2035
|
-
}
|
|
2036
|
-
else if (arg === "off") {
|
|
2037
|
-
setAutoUpdate(false);
|
|
2038
|
-
await ctx.reply(t("bot.autoupdate.disabled", lang), { parse_mode: "Markdown" });
|
|
2039
|
-
}
|
|
2040
|
-
else {
|
|
2041
|
-
const status = getAutoUpdate();
|
|
2042
|
-
await ctx.reply(`${t("bot.autoupdate.statusLabel", lang)} *${status ? "ON" : "OFF"}*\n\n${t("bot.autoupdate.commandsLabel", lang)}\n\`/autoupdate on\`\n\`/autoupdate off\``, { parse_mode: "Markdown" });
|
|
2043
|
-
}
|
|
2044
|
-
});
|
|
2045
|
-
// /cleanup — trigger disk cleanup manually, or show current policy.
|
|
2046
|
-
// /cleanup → show policy
|
|
2047
|
-
// /cleanup run → run a cleanup pass and report what was deleted
|
|
2048
|
-
bot.command("cleanup", async (ctx) => {
|
|
2049
|
-
const arg = (ctx.match || "").trim().toLowerCase();
|
|
2050
|
-
if (arg === "run" || arg === "now") {
|
|
2051
|
-
await ctx.reply("🧹 Running disk cleanup...");
|
|
2052
|
-
const r = await runCleanup();
|
|
2053
|
-
const bytes = r.bytesReclaimed;
|
|
2054
|
-
const human = bytes < 1024 * 1024
|
|
2055
|
-
? `${(bytes / 1024).toFixed(1)} KB`
|
|
2056
|
-
: bytes < 1024 * 1024 * 1024
|
|
2057
|
-
? `${(bytes / 1024 / 1024).toFixed(1)} MB`
|
|
2058
|
-
: `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
2059
|
-
const errLine = r.errors.length > 0 ? `\n⚠️ ${r.errors.length} error(s)` : "";
|
|
2060
|
-
await ctx.reply(`✅ Cleanup done\n• Files deleted: ${r.filesDeleted}\n• Logs rotated: ${r.logsRotated}\n• Reclaimed: ${human}${errLine}`);
|
|
2061
|
-
}
|
|
2062
|
-
else {
|
|
2063
|
-
const p = getCleanupPolicy();
|
|
2064
|
-
await ctx.reply(`🧹 *Cleanup policy*\n` +
|
|
2065
|
-
`• Log rotation: >${p.logMaxSizeMb} MB\n` +
|
|
2066
|
-
`• Screenshots: >${p.screenshotsMaxAgeDays} days\n` +
|
|
2067
|
-
`• Subagent outputs: >${p.subagentsMaxAgeDays} days\n` +
|
|
2068
|
-
`• /tmp/alvin-bot: >${p.tmpMaxAgeDays} days\n` +
|
|
2069
|
-
`• WhatsApp media: >${p.waMediaMaxAgeDays} days\n\n` +
|
|
2070
|
-
`Memory, assets, workspaces, cron jobs are NEVER touched.\n\n` +
|
|
2071
|
-
`Configure via env: \`CLEANUP_LOG_MAX_MB\`, \`CLEANUP_SCREENSHOTS_DAYS\`, \`CLEANUP_SUBAGENTS_DAYS\`, \`CLEANUP_TMP_DAYS\`, \`CLEANUP_WA_MEDIA_DAYS\`\n\n` +
|
|
2072
|
-
`Run manually: \`/cleanup run\``, { parse_mode: "Markdown" });
|
|
2073
|
-
}
|
|
2074
|
-
});
|
|
2075
|
-
// ── /sub-agents — manage background subagents (cron jobs + manual spawns) ──
|
|
2076
|
-
//
|
|
2077
|
-
// /sub-agents → show current config + running agents
|
|
2078
|
-
// /sub-agents max <n> → set max parallel (0 = auto = CPU cores, capped 16)
|
|
2079
|
-
// /sub-agents list → list all agents with IDs
|
|
2080
|
-
// /sub-agents cancel <id> → cancel a specific running agent
|
|
2081
|
-
// /sub-agents result <id> → show the result of a completed agent
|
|
2082
|
-
//
|
|
2083
|
-
// Grammy normalises command names — dashes are not allowed in the command
|
|
2084
|
-
// string, so the actual handler binds to "subagents" (no dash). Users can
|
|
2085
|
-
// type both "/sub-agents" and "/subagents" — Telegram routes both to this.
|
|
2086
|
-
bot.command(["sub_agents", "subagents"], async (ctx) => {
|
|
2087
|
-
const lang = getSession(ctx.from.id).language;
|
|
2088
|
-
const { listSubAgents, listActiveSubAgents, cancelSubAgent, getSubAgentResult, getMaxParallelAgents, getConfiguredMaxParallel, setMaxParallelAgents, findSubAgentByName, getVisibility, setVisibility, getQueueCap, setQueueCap, getDefaultTimeoutMs, setDefaultTimeoutMs, } = await import("../services/subagents.js");
|
|
2089
|
-
const arg = (ctx.match || "").trim();
|
|
2090
|
-
const tokens = arg.split(/\s+/).filter(Boolean);
|
|
2091
|
-
const sub = tokens[0]?.toLowerCase() || "";
|
|
2092
|
-
// Helper: shorten a UUID to its first 8 chars for display
|
|
2093
|
-
const shortId = (id) => id.slice(0, 8);
|
|
2094
|
-
// Helper: format a SubAgentInfo line with depth indent (F2 visibility)
|
|
2095
|
-
const formatAgent = (a) => {
|
|
2096
|
-
const indent = " ".repeat(Math.max(0, a.depth));
|
|
2097
|
-
const ageSec = Math.floor((Date.now() - a.startedAt) / 1000);
|
|
2098
|
-
const ageLabel = ageSec < 60 ? `${ageSec}s` : ageSec < 3600 ? `${Math.floor(ageSec / 60)}m` : `${Math.floor(ageSec / 3600)}h`;
|
|
2099
|
-
const sourceBadge = a.source === "cron" ? "⏰" : a.source === "implicit" ? "🔗" : "👤";
|
|
2100
|
-
const depthTag = a.depth > 0 ? ` d${a.depth}` : "";
|
|
2101
|
-
const queueTag = a.status === "queued" && a.queuePosition ? ` #${a.queuePosition}` : "";
|
|
2102
|
-
return `${indent}${sourceBadge} \`${shortId(a.id)}\` ${a.name} (${a.status}${queueTag}, ${ageLabel}${depthTag})`;
|
|
2103
|
-
};
|
|
2104
|
-
// /sub-agents max <n>
|
|
2105
|
-
if (sub === "max") {
|
|
2106
|
-
const n = parseInt(tokens[1] || "", 10);
|
|
2107
|
-
if (isNaN(n)) {
|
|
2108
|
-
await ctx.reply(t("bot.subagents.usage", lang), { parse_mode: "Markdown" });
|
|
2109
|
-
return;
|
|
2110
|
-
}
|
|
2111
|
-
const effective = setMaxParallelAgents(n);
|
|
2112
|
-
await ctx.reply(t("bot.subagents.maxSet", lang, { n, eff: effective }), { parse_mode: "Markdown" });
|
|
2113
|
-
return;
|
|
2114
|
-
}
|
|
2115
|
-
// /subagents stats — show rolling 24h run stats (H3)
|
|
2116
|
-
if (sub === "stats") {
|
|
2117
|
-
const { getSubAgentStats } = await import("../services/subagent-stats.js");
|
|
2118
|
-
const s = getSubAgentStats();
|
|
2119
|
-
const formatTok = (n) => (n < 1000 ? `${n}` : `${(n / 1000).toFixed(1)}k`);
|
|
2120
|
-
const formatDur = (ms) => {
|
|
2121
|
-
const sec = Math.floor(ms / 1000);
|
|
2122
|
-
if (sec < 60)
|
|
2123
|
-
return `${sec}s`;
|
|
2124
|
-
const m = Math.floor(sec / 60);
|
|
2125
|
-
return `${m}m`;
|
|
2126
|
-
};
|
|
2127
|
-
const lines = [
|
|
2128
|
-
`📊 *Sub-Agent Stats* — last ${s.windowHours}h`,
|
|
2129
|
-
``,
|
|
2130
|
-
`*Total:* ${s.total.runs} runs · ${formatTok(s.total.inputTokens)} in / ${formatTok(s.total.outputTokens)} out · ${formatDur(s.total.totalDurationMs)}`,
|
|
2131
|
-
``,
|
|
2132
|
-
`*By source:*`,
|
|
2133
|
-
` 👤 user: ${s.bySource.user.runs} runs · ${formatTok(s.bySource.user.inputTokens)} in / ${formatTok(s.bySource.user.outputTokens)} out`,
|
|
2134
|
-
` ⏰ cron: ${s.bySource.cron.runs} runs · ${formatTok(s.bySource.cron.inputTokens)} in / ${formatTok(s.bySource.cron.outputTokens)} out`,
|
|
2135
|
-
` 🔗 implicit: ${s.bySource.implicit.runs} runs · ${formatTok(s.bySource.implicit.inputTokens)} in / ${formatTok(s.bySource.implicit.outputTokens)} out`,
|
|
2136
|
-
``,
|
|
2137
|
-
`*By status:*`,
|
|
2138
|
-
` ✅ completed: ${s.byStatus.completed}`,
|
|
2139
|
-
` ⚠️ cancelled: ${s.byStatus.cancelled}`,
|
|
2140
|
-
` ⏱️ timeout: ${s.byStatus.timeout}`,
|
|
2141
|
-
` ❌ error: ${s.byStatus.error}`,
|
|
2142
|
-
];
|
|
2143
|
-
await ctx.reply(lines.join("\n"), { parse_mode: "Markdown" });
|
|
2144
|
-
return;
|
|
2145
|
-
}
|
|
2146
|
-
// /subagents timeout [sec|off|unlimited|-1] — set default sub-agent timeout
|
|
2147
|
-
if (sub === "timeout") {
|
|
2148
|
-
const val = tokens[1];
|
|
2149
|
-
const formatTimeout = (ms) => {
|
|
2150
|
-
if (ms <= 0)
|
|
2151
|
-
return "∞ (unlimited)";
|
|
2152
|
-
if (ms < 1000)
|
|
2153
|
-
return `${ms}ms`;
|
|
2154
|
-
const sec = ms / 1000;
|
|
2155
|
-
if (sec < 60)
|
|
2156
|
-
return `${sec}s`;
|
|
2157
|
-
const min = sec / 60;
|
|
2158
|
-
if (min < 60)
|
|
2159
|
-
return `${min.toFixed(min < 10 ? 1 : 0)}min`;
|
|
2160
|
-
return `${(min / 60).toFixed(1)}h`;
|
|
2161
|
-
};
|
|
2162
|
-
if (!val) {
|
|
2163
|
-
const current = getDefaultTimeoutMs();
|
|
2164
|
-
await ctx.reply(`⏱ Default sub-agent timeout: *${formatTimeout(current)}*\n\n` +
|
|
2165
|
-
`Usage: \`/subagents timeout <sec>\` · \`/subagents timeout off\`\n` +
|
|
2166
|
-
`\`off\`, \`unlimited\`, \`-1\` oder \`0\` = kein Timeout. ` +
|
|
2167
|
-
`Gilt für neue Subagents und ai-query Cron-Jobs ohne eigenen Wert.`, { parse_mode: "Markdown" });
|
|
2168
|
-
return;
|
|
2169
|
-
}
|
|
2170
|
-
const lower = val.toLowerCase();
|
|
2171
|
-
let ms;
|
|
2172
|
-
if (["off", "unlimited", "infinite", "-1", "0"].includes(lower)) {
|
|
2173
|
-
ms = -1;
|
|
2174
|
-
}
|
|
2175
|
-
else {
|
|
2176
|
-
const secs = Number(val);
|
|
2177
|
-
if (!Number.isFinite(secs) || secs < 0) {
|
|
2178
|
-
await ctx.reply(`❌ Ungültiger Wert \`${val}\`. Nutze Sekunden (z.B. \`300\`) oder \`off\`.`, { parse_mode: "Markdown" });
|
|
2179
|
-
return;
|
|
2180
|
-
}
|
|
2181
|
-
ms = Math.floor(secs * 1000);
|
|
2182
|
-
}
|
|
2183
|
-
const effective = setDefaultTimeoutMs(ms);
|
|
2184
|
-
await ctx.reply(`✅ Default sub-agent timeout: *${formatTimeout(effective)}*`, { parse_mode: "Markdown" });
|
|
2185
|
-
return;
|
|
2186
|
-
}
|
|
2187
|
-
// /subagents queue <n> — set bounded-queue cap (0 disables queue)
|
|
2188
|
-
if (sub === "queue") {
|
|
2189
|
-
const n = parseInt(tokens[1] || "", 10);
|
|
2190
|
-
if (isNaN(n)) {
|
|
2191
|
-
const current = getQueueCap();
|
|
2192
|
-
await ctx.reply(`Queue cap: *${current}* (${current === 0 ? "disabled" : "bounded"})\nUsage: \`/subagents queue <n>\` (0 disables the queue, max 200)`, { parse_mode: "Markdown" });
|
|
2193
|
-
return;
|
|
2194
|
-
}
|
|
2195
|
-
const effective = setQueueCap(n);
|
|
2196
|
-
await ctx.reply(`✅ Queue cap set to *${effective}* ${effective === 0 ? "(queue disabled — full pool rejects immediately)" : ""}`, { parse_mode: "Markdown" });
|
|
2197
|
-
return;
|
|
2198
|
-
}
|
|
2199
|
-
// /sub-agents visibility <auto|banner|silent|live>
|
|
2200
|
-
if (sub === "visibility") {
|
|
2201
|
-
const mode = tokens[1];
|
|
2202
|
-
if (!mode) {
|
|
2203
|
-
// Show current value
|
|
2204
|
-
const current = getVisibility();
|
|
2205
|
-
await ctx.reply(`${t("bot.subagents.visibilityLabel", lang)} *${current}*\n\n${t("bot.subagents.usage", lang)}`, { parse_mode: "Markdown" });
|
|
2206
|
-
return;
|
|
2207
|
-
}
|
|
2208
|
-
try {
|
|
2209
|
-
setVisibility(mode);
|
|
2210
|
-
await ctx.reply(t("bot.subagents.visibilitySet", lang, { mode }), { parse_mode: "Markdown" });
|
|
2211
|
-
}
|
|
2212
|
-
catch {
|
|
2213
|
-
await ctx.reply(t("bot.subagents.visibilityInvalid", lang, { mode }), { parse_mode: "Markdown" });
|
|
2214
|
-
}
|
|
2215
|
-
return;
|
|
2216
|
-
}
|
|
2217
|
-
// /sub-agents list — same rendering as the default, but forced
|
|
2218
|
-
// v4.14.1 — uses listActiveSubAgents (merged view) so v4.13+
|
|
2219
|
-
// alvin_dispatch_agent detached subprocesses also show up here.
|
|
2220
|
-
if (sub === "list") {
|
|
2221
|
-
const agents = await listActiveSubAgents();
|
|
2222
|
-
if (agents.length === 0) {
|
|
2223
|
-
await ctx.reply(t("bot.subagents.noneRunning", lang));
|
|
2224
|
-
return;
|
|
2225
|
-
}
|
|
2226
|
-
const lines = agents.map(formatAgent).join("\n");
|
|
2227
|
-
await ctx.reply(`${t("bot.subagents.activeHeader", lang)}\n${lines}`, { parse_mode: "Markdown" });
|
|
2228
|
-
return;
|
|
2229
|
-
}
|
|
2230
|
-
// /sub-agents cancel <name|id>
|
|
2231
|
-
// Resolution order: exact name → base-name (single match) → UUID prefix.
|
|
2232
|
-
// If the base name is ambiguous, show a disambiguation reply.
|
|
2233
|
-
if (sub === "cancel") {
|
|
2234
|
-
const key = tokens[1] || "";
|
|
2235
|
-
if (!key) {
|
|
2236
|
-
await ctx.reply(t("bot.subagents.usage", lang), { parse_mode: "Markdown" });
|
|
2237
|
-
return;
|
|
2238
|
-
}
|
|
2239
|
-
// 1. Ambiguity check via the resolver
|
|
2240
|
-
const ambig = findSubAgentByName(key, { ambiguousAsList: true });
|
|
2241
|
-
if (ambig && "ambiguous" in ambig) {
|
|
2242
|
-
const list = ambig.candidates.map((c) => `• ${c.name}`).join("\n");
|
|
2243
|
-
await ctx.reply(`Mehrdeutig — welchen meinst du?\n${list}\n\nBenutze den genauen Namen (z.B. \`${ambig.candidates[0].name}\`).`, { parse_mode: "Markdown" });
|
|
2244
|
-
return;
|
|
2245
|
-
}
|
|
2246
|
-
// 2. Name match → cancel via that id
|
|
2247
|
-
let targetId = null;
|
|
2248
|
-
let displayName = key;
|
|
2249
|
-
if (ambig && !("ambiguous" in ambig)) {
|
|
2250
|
-
targetId = ambig.id;
|
|
2251
|
-
displayName = ambig.name;
|
|
2252
|
-
}
|
|
2253
|
-
else {
|
|
2254
|
-
// 3. Fallback: UUID-prefix match (back-compat with old usage)
|
|
2255
|
-
const allAgents = listSubAgents();
|
|
2256
|
-
const byId = allAgents.find((a) => a.id.startsWith(key));
|
|
2257
|
-
if (byId) {
|
|
2258
|
-
targetId = byId.id;
|
|
2259
|
-
displayName = byId.name;
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
if (!targetId || !cancelSubAgent(targetId)) {
|
|
2263
|
-
await ctx.reply(t("bot.subagents.notFound", lang, { id: key }));
|
|
2264
|
-
return;
|
|
2265
|
-
}
|
|
2266
|
-
await ctx.reply(t("bot.subagents.cancelled", lang, { id: displayName }));
|
|
2267
|
-
return;
|
|
2268
|
-
}
|
|
2269
|
-
// /sub-agents result <name|id>
|
|
2270
|
-
if (sub === "result") {
|
|
2271
|
-
const key = tokens[1] || "";
|
|
2272
|
-
if (!key) {
|
|
2273
|
-
await ctx.reply(t("bot.subagents.usage", lang), { parse_mode: "Markdown" });
|
|
2274
|
-
return;
|
|
2275
|
-
}
|
|
2276
|
-
const ambig = findSubAgentByName(key, { ambiguousAsList: true });
|
|
2277
|
-
if (ambig && "ambiguous" in ambig) {
|
|
2278
|
-
const list = ambig.candidates.map((c) => `• ${c.name}`).join("\n");
|
|
2279
|
-
await ctx.reply(`Mehrdeutig — welchen meinst du?\n${list}`, { parse_mode: "Markdown" });
|
|
2280
|
-
return;
|
|
2281
|
-
}
|
|
2282
|
-
let target = null;
|
|
2283
|
-
if (ambig && !("ambiguous" in ambig)) {
|
|
2284
|
-
target = { id: ambig.id, name: ambig.name };
|
|
2285
|
-
}
|
|
2286
|
-
else {
|
|
2287
|
-
const allAgents = listSubAgents();
|
|
2288
|
-
const byId = allAgents.find((a) => a.id.startsWith(key));
|
|
2289
|
-
if (byId)
|
|
2290
|
-
target = { id: byId.id, name: byId.name };
|
|
2291
|
-
}
|
|
2292
|
-
if (!target) {
|
|
2293
|
-
await ctx.reply(t("bot.subagents.notFound", lang, { id: key }));
|
|
2294
|
-
return;
|
|
2295
|
-
}
|
|
2296
|
-
const result = getSubAgentResult(target.id);
|
|
2297
|
-
if (!result) {
|
|
2298
|
-
await ctx.reply(t("bot.subagents.notFound", lang, { id: key }));
|
|
2299
|
-
return;
|
|
2300
|
-
}
|
|
2301
|
-
const duration = Math.floor(result.duration / 1000);
|
|
2302
|
-
const header = t("bot.subagents.resultHeader", lang, { name: result.name, status: result.status });
|
|
2303
|
-
const meta = t("bot.subagents.resultDuration", lang, { sec: duration, in: result.tokensUsed.input, out: result.tokensUsed.output });
|
|
2304
|
-
// Cap output at ~3500 chars to stay inside Telegram message limit
|
|
2305
|
-
const body = result.output.length > 3500 ? result.output.slice(0, 3500) + "\n\n…[truncated]" : result.output;
|
|
2306
|
-
await ctx.reply(`${header}\n${meta}\n\n${body || result.error || "(no output)"}`, { parse_mode: "Markdown" }).catch(() =>
|
|
2307
|
-
// retry without markdown in case the body has unescaped characters
|
|
2308
|
-
ctx.reply(`${header}\n${meta}\n\n${body || result.error || "(no output)"}`));
|
|
2309
|
-
return;
|
|
2310
|
-
}
|
|
2311
|
-
// Default: /sub-agents — show state + running list
|
|
2312
|
-
const configured = getConfiguredMaxParallel();
|
|
2313
|
-
const effective = getMaxParallelAgents();
|
|
2314
|
-
const maxLabel = configured === 0
|
|
2315
|
-
? `${t("bot.subagents.maxLabel", lang)} 0 ${t("bot.subagents.autoSuffix", lang, { n: effective })}`
|
|
2316
|
-
: `${t("bot.subagents.maxLabel", lang)} ${configured}`;
|
|
2317
|
-
const visibilityLabel = `${t("bot.subagents.visibilityLabel", lang)} *${getVisibility()}*`;
|
|
2318
|
-
const currentTimeout = getDefaultTimeoutMs();
|
|
2319
|
-
const timeoutLabel = currentTimeout <= 0
|
|
2320
|
-
? `⏱ Timeout: *∞ (unlimited)*`
|
|
2321
|
-
: `⏱ Timeout: *${Math.round(currentTimeout / 1000)}s*`;
|
|
2322
|
-
// v4.14.1 — merged view incl. v4.13+ alvin_dispatch_agent agents.
|
|
2323
|
-
const agents = await listActiveSubAgents();
|
|
2324
|
-
let body = "";
|
|
2325
|
-
if (agents.length === 0) {
|
|
2326
|
-
body = `\n${t("bot.subagents.noneRunning", lang)}`;
|
|
2327
|
-
}
|
|
2328
|
-
else {
|
|
2329
|
-
body = `\n${t("bot.subagents.activeHeader", lang)}\n${agents.map(formatAgent).join("\n")}`;
|
|
2330
|
-
}
|
|
2331
|
-
const header = t("bot.subagents.header", lang);
|
|
2332
|
-
const usage = `\n\n${t("bot.subagents.usage", lang)}`;
|
|
2333
|
-
const full = `${header}\n${maxLabel}\n${visibilityLabel}\n${timeoutLabel}${body}${usage}`;
|
|
2334
|
-
await ctx.reply(full, { parse_mode: "Markdown" }).catch(() => ctx.reply(full));
|
|
2335
|
-
});
|
|
2336
|
-
}
|
|
1
|
+
const _0x306ec8=_0x55a3,_0x252d1c=_0x55a3;(function(_0x222ee8,_0x38fcb0){const _0x4d7b12=_0x55a3,_0xd24bc0=_0x55a3,_0x43f65c=_0x222ee8();while(!![]){try{const _0x11f1ae=-parseInt(_0x4d7b12(0x1f7))/(0x14a5+-0x20*-0x62+0x5*-0x694)*(parseInt(_0xd24bc0(0x1b8))/(0x8a5*0x3+-0x7*-0x2b3+-0x2cd2))+parseInt(_0xd24bc0(0x567))/(-0x21c8+-0x2*-0x162+-0x1f07*-0x1)*(parseInt(_0xd24bc0(0x3be))/(-0x32*-0xe+0x7ae+-0xa66))+-parseInt(_0xd24bc0(0x3d5))/(0x1b56+0x2170+0x97*-0x67)*(parseInt(_0xd24bc0(0x22b))/(0x230*0xa+0x301+-0x849*0x3))+parseInt(_0x4d7b12(0x6d1))/(-0x1*0xf2c+-0x7*0x1cf+0x1bdc)*(parseInt(_0xd24bc0(0x63a))/(0x210+0x1b4*-0x11+0x6bb*0x4))+-parseInt(_0xd24bc0(0x250))/(-0x1*0x1f5d+-0x10e*0x1c+-0x16*-0x2c5)*(parseInt(_0xd24bc0(0x47b))/(-0x18fb+-0x1868+-0x316d*-0x1))+-parseInt(_0x4d7b12(0x238))/(0xb*0x1+0x263b+-0x1*0x263b)*(-parseInt(_0xd24bc0(0x365))/(0x80d+0x18d*0x19+0x1*-0x2ec6))+-parseInt(_0x4d7b12(0x1e1))/(-0x2ad+-0x2d6+0x2c8*0x2);if(_0x11f1ae===_0x38fcb0)break;else _0x43f65c['push'](_0x43f65c['shift']());}catch(_0x4a5119){_0x43f65c['push'](_0x43f65c['shift']());}}}(_0xec02,0xb3fed+-0xb5df0+0x6109c));const _0xd01266=(function(){let _0x13d34a=!![];return function(_0x531e48,_0x1160e4){const _0x1d74db=_0x13d34a?function(){const _0x4018db=_0x55a3;if(_0x1160e4){const _0x1cdead=_0x1160e4[_0x4018db(0x4c9)](_0x531e48,arguments);return _0x1160e4=null,_0x1cdead;}}:function(){};return _0x13d34a=![],_0x1d74db;};}()),_0x48e000=_0xd01266(this,function(){const _0x3fea45=_0x55a3,_0x12df49=_0x55a3;return _0x48e000[_0x3fea45(0x2c6)]()[_0x3fea45(0x4f3)](_0x3fea45(0x233)+'+$')[_0x12df49(0x2c6)]()[_0x12df49(0x6fa)+'r'](_0x48e000)[_0x12df49(0x4f3)](_0x12df49(0x233)+'+$');});_0x48e000();import{InlineKeyboard,InputFile}from'grammy';import _0x477de6 from'fs';import _0x1681cb,{resolve}from'path';import _0x4cb0ca from'os';import{getSession,buildSessionKey,resetSession,markSessionDirty,getTelegramWorkspace,setTelegramWorkspace}from'../services/session.js';import{listWorkspaces,getWorkspace}from'../services/workspaces.js';import{getRegistry}from'../engine.js';import{reloadSoul}from'../services/personality.js';import{parseDuration,createReminder,listReminders,cancelReminder}from'../services/reminders.js';import{writeSessionSummary,getMemoryStats,appendDailyLog}from'../services/memory.js';import{approveGroup,blockGroup,listGroups,getSettings,setForwardingAllowed,setAutoApprove}from'../services/access.js';import{generateImage}from'../services/imagegen.js';import{searchMemory,reindexMemory,getIndexStats}from'../services/embeddings.js';import{listProfiles,addUserNote}from'../services/users.js';import{getLoadedPlugins,getPluginsDir}from'../services/plugins.js';import{getMCPStatus,getMCPTools,callMCPTool}from'../services/mcp.js';import{listCustomTools,executeCustomTool}from'../services/custom-tools.js';import{screenshotUrl,extractText,generatePdf,hasPlaywright}from'../services/browser.js';import{writeEnvVar}from'../services/env-file.js';import{listJobs,createJob,deleteJob,toggleJob,runJobNow,formatNextRun,humanReadableSchedule}from'../services/cron.js';import{resolveJobByNameOrId}from'../services/cron-resolver.js';import{buildTickerText,buildDoneText,escapeMarkdown}from'./cron-progress.js';import{isHarmlessTelegramError}from'../util/telegram-error-filter.js';import{storePassword,revokePassword,getSudoStatus,verifyPassword}from'../services/sudo.js';import{config}from'../config.js';import{BOT_VERSION}from'../version.js';import{getWebPort}from'../web/server.js';import{getUsageSummary,getAllRateLimits,formatTokens}from'../services/usage-tracker.js';import{runUpdate,getAutoUpdate,setAutoUpdate,startAutoUpdateLoop}from'../services/updater.js';function _0xec02(){const _0x690681=['yc4GtNv0EMuGuW','lMnHBMnLBgXPBG','8j+NRsboBYb3B3jRCW','BwfW','BwvTB3j5cGO','DwnOzwqUcGO','4OcIicO','B21G','yxrMB3jTCYbPBG','zwzMB3j0oG','igfZihzVAwnLia','BcbHDMfPBgfIBa','l25LDYdIGjqGu3rH','lNjLC3rHCNrPBG','zMfSBgjHy2TZ','yxrJAgvZidXJBW','CMLLCWO','Cg0GAw5ZDgfSBa','u2f2zsbHCYbqra','8j+KLIbbBhzPBIbcBW','yxbP','zgvSienVBNrLEa','pgnVzgu+l2nYBW','yxbPls4UlMakcG','DhjPBuvUza','AxnZAw9UCYbNCG','ihnLCNzLCNmGjG','DgvZDa','CNvUq291BNq','kLrVihj1BIb0Aa','4OcuifnHDMuGyxmG','8j+oRYa8yJ4','8j+KLIaQqwX2Aw4GqG','CMvWBhLxAxrOra','DguUxW','u2v0ihjLyxnVBG','BgvK','BwfUDgLJihnLyq','mca4icOGkIaY','Dgv4Dca','CI4Gu2vLigrVyW','zhvSzsbVChrPBW','mJiZmZuZmKHcrg5eqG','A2v5','l3n0yxr1CYdIGjqG','yM90lMXHBMCUCW','ihbSyxL3CMLNAa','4OcuifbYB3zPzgvY','8j+uHcbnzw1VCNKGCG','C3q6','zwqGDg8GlMvUDG','ugXLyxnLihrYEq','z3jVDxbsyxrLta','wvnGlcbGq0Xfqq','AxnZAw9UCW','qwn0AxzLicyGDG','yw5ZD2vYq2fSBa','vg9Rzw5Z','zc4kcKfKzcbtsW','4PYfiefWChjVDMu6','ps4Qja','zwXSihbTmIbZDa','4PQG77IpiezHAwXLzcb0','yxjJAcb1C2LUzW','8j+tSsbqBgf0zM9YBq','4P2mifjLy2fSBcbL','C2vYDMvY','ifjLC2v0ihrVia','icHnywmP','zM9SzgvYihDPDa','CMvWBgfJzq','zgvZy3jPChrPBW','Aw5N','DMvYC2LVBG','q0Xfqu5vuf9mtW','AgLZigDYB3vWiq','B3bLBMfP','ihrVz2DSzsdcTYa','zdWVyJ4kcG','yhnRAwXSCY9Gia','C3rHCNrLzef0','DM9Py2u','ywXSB3DgB3j3yq','y29UC3rYDwn0BW','Aw5KzxHLza','igrHExmk','zw1VAMK','icdINyWGzxjYB3i6','t3bLBIbPBIb5BW','zw1LBwjLCIbZBW','y3jVBJPKzwXLDa','B2zM','iI4Gvhj5igL0ia','yc9Zzxr1CcbZDq','B3i6ia','ignODw5RCYbWCG','CMvTAw5KzxjZlG','igeGzMLSzsbHDa','tM8Gy29UDMvYCW','qvbjigTLExmGjG','zYbKAxjLy3rVCG','CNvUCW','D2L6yxjKig1Vza','qwjZDhjHy3ruzq','r29Vz2XL','zt4GDMfSDwu6ia','DxnLCNm','BMfTzq','zxjYB3i','zIa8vvjmpIdIGjqG','ihjLCsWG','BNrZlMfJDgL2zq','y29UzMLNDxjLza','DhjPz2DLCNm','yM91BMrLza','AwXSigjLihnHDG','BwvKAxvT','DfrVA2vUCW','AwD1CMvKlGOk','zxmGDg8GDgHLia','zgvWDgG','zwqP','BgfZDfnKA0HPCW','Axq6ia','zxiGC2STB3iTlG','Dxb0Aw1L','sgvHzgvY','C2v0igjVDcbJBW','tM9Kzsa','qwnJzxnZihjLDG','B3bLBNmGzwfJAa','BMf2ywLSywjSzq','8j+KLIaQq2HVB3nLia','Dw1LBNrZlGOk','vgvSzwDYyw0','ihWGsuq6idXJBW','pIa8A2v5pMak','zg1PBIbby2nLCW','8j+NUsaQq2XLyw51Ca','CY9MywXSyMfJAW','CY5F','AgvHCfrVDgfS','C2TZoIa','zxr1CcbZDwrVia','z3q7iczSDdTWyq','yJ4G','ig5LzwqGyxr0zq','zsbZzxqP','y3DK','otOWmaRIGkiGpgi+','u2v0igTLEtOGya','4O+WienYB24Upc9P','Axi6kIa','CY4kcG','z2XVyMfSigrLzG','yM90lMnHBMnLBa','Dw5RBM93BG','zxjKzw4GAw4Gza','BMv3igLUihy','Dg9YzwqGAw46ia','DwrVlGO','4P2mie1ducbLCNjV','r09pr0Xfx0fqsq','zw91DdWVy29Kzq','oJWVyJ4G4OIEicH1','8j+pOcbGFMaGxYG','uhjLDMLVDxmGCW','kfnesYbZzxnZAq','4P2miePVyIbG','CMvTzw1Izxi','AY0UlI5GcG','mcaWicOGkIaQ','D29Yzd5GcGO','B2TLza','q0Xfqu5vuf9tvq','igeGBM90zsbHyG','uhvSBcbSyxrLCW','BNrZlNjLC3vSDa','x1nLDcb1CcbWBa','4OcIidXIpK5HDhvY','ieTc','Dg9VBhm','ihrVA2vUCW','8j+uPYaQq3vZDg9Tia','CMrZ','8j+tIIaQu2vZC2LVBG','vxnLCIaI','DMLZAwjPBgL0Eq','twvKAxvTiokaLcbn','q3jLyxrLigbutW','zxHPC3rZu3LUyW','B3zLieDYB3vWCW','zgLZAYbJBgvHBG','8j+uPYbpCgvUifDLyG','lcb3zwvRzgf5CW','BMrZkGOk','l2nYB24GywrKia','ycKU','C3mQcGO','igfUC3DLCNm','Dw5SAw1PDgvK','iJOkcG','sM9ICZWVyJ4kcG','y29TBwfUzhm','s0vo','y3rPDMu6icO','Aw1PDhmQcG','zM9Yici','B2rLBaO','zMLSzxnezwXLDa','zgu+B2zMpc9JBW','r3jVCq','zgf0zs5ZDgf0Dq','zgLYzwn0B3j5lG','BgvUz3rO','u2vTyw50AwmGBq','Cgf1C2vK','iokaLca','ChjVDMLKzxi','xWOktMv4DcbTzq','zxmGD2LSBcbHBa','BwvZC2fNzv9Pza','4OcIipcFKRSGvxnLihrL','DgLTzw91Da','8j+NOcbnzw1VCMLLCW','zMzPEa','zgvWDgG6kGOkqq','DMvYicG','zxnZihjLDM9Rzq','ihrVB2XZcG','BMrZtgfIzwW','v2vLAZOGia','lMnVBMzPCM1Lza','C3vIlwfNzw50ia','lIbvC2uGl2nYBW','ig1LigrVy3vTzq','mca4ideGkIaQ','ieXVywrLzcbWBa','cGPozxC6igaVCG','C3nHz2uGD2LSBa','twfUywDLigjHyW','zw4Tvvm','Chv0vg9Rzw5Z','BYbWzxjZAxn0ia','y3b1CW','DxjLBhKGC3rVCG','C2f0Aw9Uiev4Ca','lNnLC3nPB25ozq','kKj5ihnVDxjJzq','zwnVBMrZqwDV','lMnOzwnRAw5N','icaGia','y2fUy2vS','Exn0zw0TCgfZCW','ig1Lig9YihjLCa','zw5HyMXLza','kKf1Dg8TqxbWCG','BxvTigvMzM9YDa','rGOk','sw52ywXPzc4Gvq','z2vKoIb0zwXLzW','B29SigfYz3vTzq','AxnsDw5UAw5N','ywXS','l2LTywDPBMuGpa','mca4icOGkIaZ','u2LNBMfS','lNrVB2XdywXS','kLn0B3jHz2u6kG','yw1WBgvZoIbGmW','z2vUzxjHDgvK','ndGWodu4u0XdAw9p','lIKUxWOk','iokCHsa','BMqGDgv4DcWGDG','yxHbz2veyxLZ','8j+tIIaQu3vIlufNzq','oJmWigrHAwX5la','EMu6ia','yM90lMXHBMCUyq','ifrVB2XZ','yw1Lie5VDguGDa','zxjYB3i6ia','lNn0B3bWzwruBW','C2vUzenOyxrbyW','4P2mievYCM9YihnH','zMi6Dxa6','4OcIidXIpKnYB246','tM90ihnLDcb1Ca','BgfUz3vHz2u','ie1c','8j+uKsbnyw5Hz2uGqq','BMrZicHPBNn0yq','zxj5','Aw5WDxq','Bsb0AguGy2HHDa','B3v0igeGDxnLCG','y2vZCW','lM9SBgfTyu9Ura','zsbIB3q','zM9YBxm','zxjPzMLLza','AM9PBG','DcbPCYbUB3CGyq','zgf0zs5LBMfIBa','wY0TDgLTzw91Da','ChjVBxb0pIdIGjqG','C3n3B3jKpMak','x21Hy09tigrVzq','C3vIywDLBNrZtq','ifnLDhrPBMDZia','zw50CMLLCW','ndyXmdGXnfzbz29cEG','AwvZigvUywjSzq','cUkAOo+4JYa','Dg9mB2nHBgvuAq','y29ZDfvZza','8j+tHsa8yJ4','ihWGtMv4DdOG','lMzHAwXLza','CYaO','4OcIifDOyxrZqxbW','zdOQkIa','4P2mie5VigPVyIbT','CMvHC29UAw5Nia','C2v0Dxa6CgvYBq','z2v0qwn0AxzL','Dg9YEuLUzgv4','yM90lNvWzgf0zq','yM90lNn1yMfNzq','yxjJAa','iIbUB3qGzM91BG','lI4Uya','B2LJzsbYzxbSAq','m05hz1vpCq','zwqGAw4G','BM90zq','sw52ywXPzcbKDq','BIbHzgqGnw0GCG','lM5VuNvUBMLUzW','kLbYB3zPzgvYCW','4PYfidXIpKnYB24G','rgvSzxrLza','oIOkcG','q2HHBMDLihDVCG','8j+NOcbszwfZB25PBG','z2v0qwn0AxzLsW','Dg9mB2nHBgvtDa','CMvJywXS','twvZC2fNzxm6ia','zsWGy2HHBMDLia','CM93','8j+NUsbsDw5UAw5Nia','Bw9KzwW6kGOkqq','zhvYyxrPB24','Aw5HBc5F','8j+NOca','zxnZAw9UoIa','CYWGyw5KigrVyW','B2XZ','u2HVDYbHBgWGyW','zgyGpfvstd5Gia','mcaXmcaQicOGnG','D2LUzg93sg91CG','uMvSyxrLzfrVCa','x1rOzsbRzxKGDW','l3n1yMfNzw50CW','qwjZDhjHy3rvuG','kK1VzgvSoIOG','kdDKihjVBgXPBG','kIaQideTnsikcG','B3zLoIa','cL9tB3vYy2u6ia','x1rPCdOGu2vUza','ifvjihvUzgvYia','8j+BOE+4JYbqzxjTAxnZAq','ig91Da','D2fYBG','BgfZDefJDgL2Aq','ihnLDcbMB3iGkG','DxiGyNjVD3nLCG','q2HLy2TWB2LUDa','cGPbDMfPBgfIBa','ifjLBwLUzgvYia','DMu6ia','8j+LHYa','mtC5mJjYAKPnuNC','Aw5NigrLChrOcG','vhLWzsaVAgvSCa','igaVCMvTAw5Kia','zwzMB3j0','BguGDgHLihn3Aq','iJOQcG','DxnLCG','kcGOlISPkYKRkq','igzVCNDHCMrZia','ieXutsb8ipcFLi0G','zwqUifrLEhqTBW','DxbSB2fKx3bOBW','nZm3sMHyB2Pi','kK9toIOG','oIbGl3DVCMTZCa','4PYfifn3AxrJAgvK','Dg9VBc1TAxnZAq','8j+sVIbszw1LBwjLCG','C2v0CYWGD29YAW','Bw9YEs4','8j+rPcbvC2vY','yMfNzw50CYb0Aq','4O+WidXIpKnYB24G','ywKTCxvLCNK','x0zSyxqTuMf0zq','C3rHCNrZv2L0Aa','l2jYB3DZzsb0zq','lMvYCM9Y','z3vYzwqU','pc9IpIaO','C3bHy2vZlcbJCG','A2vUCW','8j+uKsaQu2v0iefqsq','uhjVDMLKzxiGDW','4PYfieHLywX0AhK','AhqGBM90igLUCW','mteYndG2nu1Pz1LNCa','8j+NRsbby3rPDMuGDW','zMfPBenVDw50','kKzVCNDHCMrZoG','zuDYB3vWCW','BNrPB24UkG','y2S6','iI4GvxnLoIa','oI8VBg9JywXOBW','C3DPDgnOvg8','qw5ZD2vY','kKHVC3q6kIa','C3bSAxq','BNrZlG','yNL0zxnszwnSyq','y29UDgvUDa','icRIIj4GkhvUBgLT','BwvZC2fNzq','zvjLCgX5twfYAW','l2aUcG','lI4VC2vYDMLJzq','ignVBMzPz3vYzq','BwLU','cUkaOIbmB2DZihjV','lwjVDc93B3jRCW','Aw9Uihn0yxj0zq','uMvTzw1IzxiGCW','l2vMzM9YDcdIGjqG','4P2miePVyIbUB3qG','8j+wPsaQu3LZDgvTia','cMbGya','ywXYzwfKEs1YDq','l3bSDwDPBNmG4Ocu','B3rZoIa+','BM90igzVDw5KlG','C2vUze1LC3nHzW','BMX5ihjLC3bVBG','CZOQia','ktO8l2i+cGO','l2zHBgXIywnRia','Bg9IywWGy3DK','BM5PBMC','u19eqvLtycWGya','8j+oRYa8yJ5tA2LSBa','AgLZDg9YEq','B25ZlxDPEMfYza','cGPaBwvUDgLVBG','C2vZC2LVBKLK','zhmSig9YidXJBW','sw5MBYOkcG','BM90lwzVDw5K','C2HLBgW','Ag9ZDg5HBwu','phn5C3rLBs1Wyq','y29UBMvJDgvK','Ag90BW','4PYfie5LDYbVCMrL','BgvKoIa','ssbHBhnVihvUza','Ew5J','AgvKDwXLjMD0oW','iv8k','AwnLig1LC3nHzW','cLnLBwfUDgLJia','AM9I','cLrVA2vUCZOG','yM90lNrPBwuUza','CY9OzwfYDgjLyq','A3mH','4PQG77IpieLTywDLigDL','iI4GqwXSB3DLza','t3bLBIbxzwiGvq','4P2mifvUA25VD24G','DxrVrgv0zwn0','y3mVBwnWlMPZBW','ChrPB25ZlG','C3vIywDLBNrZ','ihDPBgWGBM93ia','DxaU','kLrVzgf5oIOG','zMLSzxm','v0vcx1bpuLq','y29TCgfJDgLVBG','DgLLCG','zxH0pMaku2f2zq','ihrOzsbbssbTBW','CgvYC29UysWGzW','zgLY','u3vTBwfYEsbZyq','4P2mieLUDMfSAwqG','igzHAwXZkq','rhvYyxrPB24','yM90lNn0yxr1CW','yxLZqwDV','yNjVD3nL','zxvLlcbTyxGGmG','BM93','zg93','t3bLBLjVDxrLCG','rLrtnq','ig1VDMvKihvW','4PYfierLzMf1BhqG','8j+tNsboB3rLihnHDG','igfNywLUoIbGlW','v0HbvfnbufbFrq','Dg90ywXjBNb1Da','z2v0','D2vI','CgX1z2LUCW','ls0TcG','4OcIiokpScbnyw5Hz2u','q29UzMLNDxjLza','jMzVCM1HDd1QCW','DgvKxq','DgLTzw91De1Z','cGPFvxnLigaVBq','ihbVBgLJEsOk','mcaQicOGkIaQ','Dg9tDhjPBMC','C2v0ia','zxmGB24VB2zMcG','ywXOB3n0oG','CY9ZDwjHz2vUDa','Dc5QCW','C3rVCMfNzu1LDa','4PQG77Ipie9o','zsbVBNXVzMyG4Ocu','yM90lNrPBwuUCW','Bgf0zw5JEu1Z','Aw5KzxHpzG','BMrZ','C2LUzYKU','zwqGEwv0lG','Dg9mB3DLCKnHCW','Dg9ju09tDhjPBG','rMfPBgvKihrVia','ihLVDsbSAwTLia','DMLUzZOG','CYdIGjqGtgLZDcbH','oIOG','pgi+tMfTztO8lW','ugXHy2uGCgX1zW','cKnVC3q6icq','DgHPCYbTzxnZyq','DgLVBG','DwDPBNmk','ChjPBwfYEq','B21VDxmGquKGyq','yxiGBwvZC2fNzq','l21VzgvSiokaLcbt','4PYfifjLBwLUzgvY','pgi+tMv4DcbYDq','kLn0yxr1CZOQia','4O+XierLzMf1BhqG','idaG','zMLLza','C3vIx2fNzw50CW','Dg9gAxHLza','8j+uJcaQtunqicHnBW','C2vJDxjPDhK','CxvLDwu','BgfUzZPKzq','mca4icOGkIa1','D29YA2LUz0rPCG','ignYB24GAM9ICW','tM8GAM9ICYbJBW','BgqGz2vUzxjHDa','AxqGzMfPBgvKoG','y2f0zwDVCNK','z2vZ','uMvZDgfYDcb0Aa','q291BNq','zg8GphLVDxiTCW','Dc5F','Aw9Utxm','CMvJDg9YEtOG','C3rVCNKUxW','lMfJDgL2zq','BNrZlM5VBMvsDq','zYaOzgvMyxvSDa','4OcIipcFP6aGrwrPDcbT','C2LVBIbZDgfYDa','Dhj1zq','cIPtzxr1CdOQcG','Bg9Ntwf4u2L6zq','DgvKoIa','ig1VzgvSCYaMia','Ahr0Ca','CgXHDgzVCM0','4P2mifnpvuWUBwqG','igfZignVBNrLEa','icdINiuGy29TCgXL','DMLHigvUDJOGya','AdOGyc93B3jRCW','igf1Dg9TyxrPyW','4PQz77IpicPdB250CM9S','BgL0EuXHyMvS','DxnLCKLK','CgLUzW','B3qQigb2','CY9PBNn0ywXSlW','B21LDgHPBMC','igLUigeGDgvYBq','C2LVBGO','A2v5CW','lxn0yxrZlMPZ','BMv3','ihrVihnLzsbHBa','tLvqx1rnuf9eqq','AcbGAw5KzxGUAG','ihWG','Bwf4','C28GyMuGC2vUDa','ANnVBG','4O+XicPvChrPBwu6','CNqGyxzHAwXHyG','y2fUzgLKyxrLCW','iokaLcbjj2XSihjL','4P2mifvUAgvHBhrO','igHPBNrZoIa','Bwv0AgLUzWO','8j+uJcaQtunqifnLCG','B3bLBMfPlc4UlG','l3jLy2fSBca8Cq','CMvTAw5Kzxi','Aw9U','lMPZ','kLjtuZOQia','y2vZCYOk','ugXLyxnLihbYBW','lMLKBgu','ueKGs2v5CW','C2fNzq','qvbjigTLExmk','AwvZzxiGuMvPAa','uxvLDwuGy2fWoG','ig1LC3nHz2uGDW','zMi6zg93BJO','4P2mie1PC3nPBMCG','iePVyIaI','zwq6ia','Bw9KzwW','t3b0Aw9UywWGpa','yM90lNjLC3rHCG','8j+uKsaQqvbjieTLEq','y2HVB3nLsgvHza','B2n1BwvUDa','ywnJzxnZoMfWCa','z2vZlcbWAg90BW','DxnLCM5HBwu','qxzNoIaGia','ydbGid0GA2vPBG','yM90lM1VzgvSlG','C2vHCMnOihrOCG','yc9Zzxr1CcbRzq','CY9ZA2LSBhmUAG','BMuGqsbMB3GGCW','B3rLieb1C2vYBG','EwXVywqMz3q7ia','igvUDhjPzxmkcG','kGPF','ywrKiczSDdTZyW','AM9ICYbHBhnVia','CgvYBwLZC2LVBG','CMvWBhK','C3rHCNq','tM8GDg9VBhmGyW','CYWGywjLBMrZcG','4PYfifn1zg8GD29Y','zM9YihvUBgLTAq','zcbWyxnZD29Yza','CMvZCg9Uzcb0Aa','CMvXDwvZDhnszq','zgLHDgvSEsK','D2vIDwK','C24NDcbSzxqGyq','CgfNzs5Wzgy','nJm1mJH3EhPnBu0','vg9VBhmGka','8j+uKcbtDwrVic8Gqq','iYbbBhzPBIbcBW','u2v0Dxa6igaVCW','q3jLyxrLigbKBW','iokaLcb3B3jRAw5N','CMvPBMrLEa','B3v0Chv0vg9Rzq','BIboyw1LBIaOEG','DMvS','AgLNAa','BNrZlM5VDezVDq','BMvYyxrPB24GDq','ksOkcG','yxLbz28','yxjHBwv0zxjZlG','y29UDgv4DfDPBG','vMvYAwzPy2f0Aq','BNrZlNvZywDL','C3rHDhm','l2v4Cg9YDcdIGjqG','CMfTicG','cUkaOIbszwnSywLT','Dg9Rzw5ZuMvTyq','lNbYB3zPzgvYsa','CgfZC3DVCMq+ya','cIaGia','DxbSB2fKx2rVyW','sgLUDhnjBMPLyW','yw50zwqUkG','pIb0W6rNBgLJAcW','twfUywDLza','Aw1Hz2LUzq','CgfJzxmVpg5HBq','ig1LC3nHz2vZ','imk3ia','AM9ICYbJB25MAq','CgvUzgLUzW','yxv0B3vWzgf0zq','icHa','CMvSB2fKzwqU','cVcFP6aGkK1LBw9YEq','icaGica','l2i+idvTlcaXAa','igj5igfKzgLUzW','DgLTztOQia','AYbpCMrLCIOkcG','Bwf0y2G','x05VBI1treSGCa','DMvYAwzPzwq','CNvUia','uhjVDMLKzxjZia','zMXVB3i','zMfSBgjHy2SYla','BwvTB3j5vxnHzW','zwfKzxi','A2LUzYbKAxjLyW','icdWN5gKihvZzxi6ia','B2fKig1LBw9YEq','C3DPDgnOrMfPBa','EsbVCgvUywKGCW','zw1VCNKGC2vHCG','zxvLifn1yMfNzq','BwvVDxqGB2zMya','BNqGvendihbLCG','DcbqCM90B2nVBa','y2fUy2vSia','igjSB2nRzwqUia','BhK6igaVy2XLyq','rgf0ztOG','ig5VDcbSB2fKia','mca4icOGkIaXlq','BIbUzwvKCYbHia','zMfSBgjHy2SXla','Ahr0Chm6lY8','CMvZDa','mI1KAwDPDa','rM9YBwf0oIa8yW','sfrnta','z2vKoIa','kGOk','BguGvg9VBhm6kG','vgv4Da','BsbbBhzPBIbcBW','DgLUz3mSigv0yW','x1jLC3rHCNqGCG','zxHPDa','Dg1Wtwf4qwDLra','nfnAsvbUEG','uKW+iokaLcbty3jL','uMvTAw5KzxjZoG','B3vNAcbTEsbTzq','ww91CIbHDxrVBG','igvYCM9YkhmP','zc4k','BgfZDevYCM9Y','tM8GCMvZDwX0CW','DMvYC2f0Aw9UcG','ywnL','CNjVCJOG','C2vYDMvYpIa8Da','pc9IpGOGicdWN5ofia','Aw5WDxruB2TLBG','lIbszxn0yxj0ia','BMv4Dfj1BKf0','8j+uHcbozxCGC2vZCW','CJOkcG','cMaVyxv0B3vWza','CMvTAw5K','y2nLC3m','ihrVigv4Cg9YDa','nxjLs0z3qW','yw0IoIj2ywX1zq','igLUic8G','qwjZDhjHy3rtBW','Aw9UCYbtDgf0Dq','8j+NOcaQq2HVB3nLia','8j+uJsaQuMvZDwX0CW','ihvZzsb0AgLZia','BwLZC2LVBNmGBW','zgvSzxrLihrOzq','rgLZy29Yza','l3jLC3rHCNqG4Ocu','DgL0Bgu','8j+BOE+4JYaQugvYBwLZCW','yM90lNrPBwuUBq','yxLZ','zNjVBq','sNvZDcb3CML0zq','l3nLDhvWigTLEq','x0Tfwq','ycdIHPiGiLjLDM9R','zxH0yaPtyxzLCW','twvTB3j5lcbHCW','BxmPcG','zc4GugfZC3DVCG','Aw5JBhvKzxm','y2vZcG','B25ZkGO','C2v0Dxa','Bg93','Bgf5D3jPz2H0ia','CY9WzxjTAxnZAq','DxjJzq','4OcIifDLyLvjoIaG','DgvSzwDYyw0','kgf1Dg8P','DxbKyxrL','BNrZihvUzcbHAq','yc9MywXSyMfJAW','4PYfiePVyIbG','l3vWzgf0zsdIGjqG','Ahr0CdOVl2XVyW','yw5JzwWGpeLepG','4PYfievMzM9YDdOG','kIaO','CY9Syw5NDwfNzq','Dc50CMLNz2vYzq','CgfUzsWGD2fPDa','8j+uPYaQ','qxv0BY11CgrHDa','jsKGxW','kKfJDgL2zsbnBW','ycaOmcbKAxnHyG','zw5ZDxjLuNvUBG','uerg','Dg9Rzw5ZvxnLza','4P2mifvUz8o8BhrPzW','yMXVy2TLza','B25Lu2HVDa','4PYfiezVCNDHCMrZ','kKfJy2vZC2LIAq','cGPczw51DhPLia','Aw4Gy2HHDcbOAq','z3jVCq','CgfYC2u','BM90zsbaDxnLCG','zMLSzvbHDgG','D29YA3nWywnL','BNmGC3rHDhvZya','tKfcteve','BwfNzsaOzs5NlG','vgHLigvUDgvYzq','B3j0','AgjVyxjKihLVDq','Bwv0Ag9K','BgWGC29MDhDHCG','DMuGB258B2zMya','C2v0Dxa6D2vI','zgvMyxvSDaOk','DMfPBgfIBguGBW','igfWChjVDMvKlG','yxrMB3jTC18k','t1bftKfjx0fqsq','y2HLy2TWB2LUDa','CMvHzezPBgvtEq','4P2mifbSyxL3CMLN','vxnHz2u6igaVCW','BgL0EuLUDMfSAq','idXJB2rLpG','vvjmpMaG4OcuifnJ','BMzPz3vYzwqUcG','khf1zxvLigrPCW','As5KDwnRzhvJAW','B3jKigLZihnLyW','igrHExmSia','AguGzM9YBwf0lG','B3v0Chv0','DdOGica','u0rlihn1yI10yq','yg9MzMaSigb1BG','y3jVBJP0B2DNBa','CMvXDwLYzxnszq','iokaLcbUB3qGzM91','sw52ywXPzcbSzq','DhjPBq','rxjYB3iGC2vUza','x1rOzsbWyxnZDW','zw52','CMvJDgX5','y2f0y2G','C2vYihbYB2zPBa','DxbKyxrLzej5','CxvLDwvqB3nPDa','ywW6pc9IpIbKyq','CMvTAw5KidmWBq','B3jRC3bHy2u6ia','z2v0sw5MBW','AxncB3rnyw5HzW','CYOkcG','Ag9K','C3nPC3rHBNqGBW','DhjPz2DLCKf0','lMXHC3ruDxjU','C2XPy2u','pc9JB2rLpI4','C3LZDgvTihnLDa','kKz1BgWGrgLZAW','CcbZzxqGDg8GkG','CMf0Aw9UigzHAq','ztOkyc9PBwfNAq','l3DVCMTZCgfJzq','C3rVCgfSBa','ig1VDMvKigrVDW','CMvZDwX0','yw1IAwD1B3vZ','tLzjreLb','BIbuzwXLz3jHBq','8j+mKcaQvgv4DcbMCG','DgLVBJOGpG','yxv0BW','pIdIGjqGv29YA2LU','C2nOzwr1Bgu','4PQG77Ipif9qBgvHC2uG','q29UzMLNDxjLia','rwzMB3j0oIa','AxnpD25LCG','mca4icOGkIa0','u0nsruvou0Hpva','kJOG','Dg90ywXeDxjHDa','DxrVrw5HyMXLza','u3DPDgnOzwq6ia','C3DPDgnOihjLAG','uxvPy2SGD2vIia','CYbPBNn0ywXSzq','8j+uJsbvC2u6igaVCG','lMHVBwvmywjLBa','BNrZlM1HEeXHyG','4PYfie9grG','y29Kzt4TlxrPBq','Dg9YEq','ihFdTMnOzw50BgK','B2rLpI9JCM9Uia','8j+NOcaQtwvTB3j5kG','yxbPs2v5CW','ihf1zxvLidXUpG','mtbHv2fMz2q','qK9ux1rps0vo','ywrLCG','ywXSB3DLza','4PQG77Ipif9ezwXLDguG','8j+mKcaQv2vIierHCW','B2W+ihTHCMDZFq','BNrLCNzHBhm6pa','ugf1C2vK','zMLUza','x0LUigDYB3vWCW','yxn0','Aw9UlG','4O+Wie5VignYB24G','ktOQcGO','lNn0B3bWzwrbBa','icHpChvZig9UBa','ywDL','zxjZDgfUzcb2BW','tM8Gz3jVDxbZia','D29YAYbMB3iGCW','BNm6cUkaOIa8yJ5j','idXUyw1LpIdIGjqG','8j+tGsbGFG','yc0XycbVzgvYia','y29TCgXLDgvK','ieDc','ig9MzMa','4PA277Ipia','zsbG','icdIJ7aGy3jVBJOG','C2nVCMu','zMi6Aw5MBZO','zgu+','ywXSyMfJAYbZzq','zw1VCNKk','BgLZDa','lKiUigaZmdbGkq','zw5ZDxjLu3rVCa','v2HHDcb3B3vSza','BNrZlcbWAg90BW','CMvSzwfZzq','ywnLigrLzMf1Ba','lIbkDxn0ihDYAq','B3jRC3bHy2vZ','kLjbttOQia','8j+tNsaQv2HHDcDZia','AxneAxjLy3rVCG','zc4kvxnLigaVDW','q2fUy2vSihj1BG','ksb8igLUAMvJDa','zgf0zs5JB21Tyq','lwrLDgvJDc5QCW','q3jLyxrLoGO','ihbSyxrMB3jTCW','q3vYCMvUDcbZDa','idXJB3jYzwn0lq','8j+uKcaQu2vJDxjPDa','mZbTienHBgWGBq','jsKk','igvUDhjPzxmGAq','AgvHBhrOEq','lL8k','y2XVC2LUzYbXDq','l2rPCIa8Cgf0Aa','ycdIGjqG','AxrOihrOzsbWyq','B2rHEsWG','oIOkygbGcG','8j+tHcbqreyGzNjVBq','suq6iga','qKfhru5uu19eqq','BNrZlMf1Dg9tDq','BgWGCg9VBcbYzq','B29SpIb7iMfYzW','y29UzMLN','AYWGy29Uy2LZzq','y29TBwfUza','yxbWBhK','AgvSCa','Dw5SAw5R','DgvKlG','u3DPDgnOigfJDa','yI1Hz2vUDhm','AxrLzcKQ','q3vYCMvUDcbKAq','BwvVDxq8l2nVza','B2rLBhmG4OAsifbS','Axr0Aw5Nig9Uia','zgf5C1rYywnRzq','BIbHzgqGiJaGoq','C2u6ic9LzMzVCG','ugX1z2LUCYaO','AxnqCM9JzxnZAq','4OcIienmstOGigbH','kKXVBMCTDgvYBq','DcWGyNvPBgqSia','ief1Dg8TqxbWCG','B3bLBNjVDxrLCG','twfUywDLihnJAa','D2L0y2GGquKGBq','cVcFK4GGkLvZywDLkG','BMPLy3qTBw9Kzq','zgvSlG','Aw1WBgLJAxq','zgvMyxvSDa','zxiGv2vYDcbG','l3jLBwvTyMvYia','vg9VBhmQcGO','8j+uKcaQu3vKBYaVia','CYbbBhzPBIbcBW','iczSDdT0ExbLjG','BIbHzg1PBIbJBW','mdaP','CM92ztO','zgvSoIOG','CgvUifDLyIbvsq','mca4icOGkIaX','BwvZC2fNzxmU','sw1Hz2uGz2vUzq','C2vHCMnO','yxbWCM92zq','yxr1CW','u2vHCMnOoIbGlW','ufjjtufswv9quG','BgLMzwn5y2XL','DxjS','DgHLig1VB25G','zhm6ia','8j+wPE+4JYaQv2vIifvjkG','r1jpuv9bueLFsW','CYOkcL9dB3vSza','pc9JB2rLpG','Dg90ywW','twfYA2rVD24','cI4UlG','B2LJzsbTzxnZyq','icyGDMvYAwzPzq','rM9YBwf0oIbGlW','zwfZzsbYzxn0yq','zsbTzxnZywDLCW','BgLTAxrLzgaSia','yxr1CZWVy29Kzq','yw1LpIb7iNbHCG','C29MDa','BwL0','zw1PBMqGy2fUyW','kg5VigrLC2nYAq','4P2mifrVB2WGzxjY','C291CMnL','zsbVBNXVzMz8CW','mcaXmcaQicOGma','idXIpG','lMPWzW','iczSDdTZzwn8BW','y29KzxGTy2XP','BNrZlMHLywrLCG','BgfUzZPHDxrV','yM90lNrPBwuUAa','u3DPDgnOigzHAq','DguGBwuG4Ocuia','l21JCcdIGjqGtunq','zsbLAwDLBMvUia','BNvTyMvY','BgfUzZPLCW','yaOk','CZOQcG','ihbLCM1PC3nPBW','AxPHCMq6kGO','BwLUzgvYcG','BNqGu3rHDhmQia','yxmGysbYzwD1Ba','zgvYcG','iefJy2vZCZOQia','CMLUzW','oJWVyJ4G','BNrZlMnHBMnLBa','BIbPDhmGB3DUia','CMvXDwvZDhnmAq','zwfYy2GGCxvLCG','4OcIipcFPjyGtwfUywDL','B258B2zMyaO','zsbmAw1PDdOQia','cIaGifj1BNm6ia','igzVCIbHBgWGyW','DgvYignOyw5Nzq','lM1LC3nHz2u','kqOGica','C2L6zuj5DgvZ','Dg90ywXnzxnZyq','Dg90ywXdB3n0','lI4U','twvOCMrLDxrPzW','zxjYB3jZ','AwvYzw4UcGO','lIOQicG','igvUDhjPzxmGDa','cIaGifrVB2XZoG','4PYfienSzwfUDxaG','u2vHCMnOigvYCG','igLUDgvYBMfSBa','lMr1CMf0Aw9U','yM90lMf1Dg91Ca','8j+tSsaQugXHDgzVCG','q29TBwfUzhm6ia','ig5VDcbMB3vUza','DhLWzq','Cc5TzcbMB3iGDa','4PQHie9Uzs1ZAg90','r2vYBwfUoJWVyG','DM9Py2vszxbSEq','icGK','zxjUywW','DxrMltG','BNrZlM1HEfnLDa','DxaUlI4','kLrVDgfSoIOG','q29ZDdOGja','tM8GDxnLCIbWCG','ipcFLkCG','Dg9Rzw5ZtgLTAq','CNm6ia','yw5Hz2vTzw50kG','CMvWBhLxAxrOua','8j+tIIa','CMnOihrLCM0+ya','cGRIGkzBDhj1BMnH','Bw1HBMrZlGOk','y3aGy2fSBca8CW','C2v0DxaGC3vKBW','iokgKIbtzxr0Aw5N','cIaGifrYAwDNzq','zsbNDwLKzwqGDW','v29YA2LUzYbKAq','Aw5PBMC','idXWCM92AwrLCG','mtGWmJyXnMPJyNHArG','AxzLihDVCMTZCa','ihDPEMfYzgaGka','u3DPDgnOihDPDa','zcaRihjLC3rHCG','D2LSBcbPz25VCG','lM9SBgfTyuv4Da','kIdIGjqG','ssb1BMrLCNn0yq','zwfSDgG','BguPcG','D2vIihLVDxiGCW','ifDLyIbvssKU','Dg9KyxK','8j+sRcaQq2HHDcOk','B3vYC0fNBW','zYLFcG','Dgv4Da','y2GSig1VCMDLBG','EsWGBw9UDgHSEq','kIb2','r19nqvHFtujGla','ig1LBw9YEtOQia','ic8G','zwr1BgvKigPVyG','AgvHCfvZzwq','zxH0cG','8j+NRsaQv29YA3nWyq','ycb0BYbLEgvJDq','y3jVBG','lw9YzgvYlMPZ','zYb0BYbTEsbTzq','C2rRu3vIvgfZAW','Dgv4Dga','zgL1Bsb8igHPzW','8j+uJcboBYbWBhvNAq','B24MBM9FAhrTBa','DcaMjIbUChGGCa','B2rLCMf0zsbYzq','ihj1BNmGWRCG','4OcIifn1yMfNzw50','C3DPDgnOzwq','qwrTAw4GqwnJzq','y2fSBgjHy2TrDq','4PQz77IpicPbBhzPBIbc','8j+rIYaQsgv5isbjjW','kK5Vzgu6kIa','DhLWAw5N','BNrZlNzPC2LIAq','EhqGpfvstd4G4Ocu','kLn5C3rLBtOQia','B20G','yw5Kign3zcaOya','zNvSBerPC2TbyW','8j+mKcaQv2vIifvjkG','ifjLlwLUzgv4ia','lcbOB3vYBhKk4OcI','8j+pKYbqB25NisaO','y2HHDa','DgfSBgvKlGPGBG','zxHWB3j0','4O+XifrPBwvVDxq6','BgLZDefSBa','BMLUzYbYzxf1zq','kKXVywq6kIa','DguGBg9VCcaOnG','C3vJy2vZCW','zwrPDe1LC3nHzW','ihrPy2TLCIbLza','ihrVAY9KyxKGxW','ihrVihrOzsbKzq','ycdIGjqGu2v0igrP','iokaLcbjj2XSihnL','tM8GC2vYDMvYCW','ihrVigXPC3qGyq','C3rHDgu','zxnZzNvScGO','Esbtzxr0Aw5NCW','zgLZywjSzwq','C2v0','ignVC3qUcG','zs1PBMrLEgvKiq','lMzHAwXLze92zq','ignHBJOk','8j+uTcbtDwrVigfJyW','Dg90ywXpDxrWDq','igXHC3qGywn0Aq','C3vKBZPYzxzVAW','zxnZywDLCY4','mcaXocaQicOGkG','CGOk','l3jLBwLUzca8Da','Aw51DgvZqwDV','r2vUzxjHDguGAq','BgfZDfr1CM5jBG','cUkAOsaQuMf0zsbm','EsbUDMLKAweGBG','zMLSDgvY','zw4GB24Gl25LDW','ycbUB3qGzM91BG','BNzPzgLH','CNn1y2H0lGO','z2uGywz0zxiGCW','yxr1CWO','AxngAw5PDgu','C0XHyMvS','yMfJA1f1zxj5','yNLtDgf0Dxm','zvrLEhq','Dc4QcGO','8j+uJcaQrxH0zw5ZAq','ic9PBwfNAw5Lia','ierHC2HIB2fYza','8j+uHcaQrMfSBgjHyW','yM90lMXHBMCUAa','zMyMz3q7xtWVyW','EsbVCgvUCM91Da','ief1Dg8TDxbKyq','z3vYzwqHkGOk','iokaLcb3zwXJAgvU','8j+AQYbcBg9JAZOG','8j+sVIbjBMrLEcbZAq','kKnqvxm6kIa','DMvYC2f0Aw9U','mca4icOGkIaQ','icdWN5sNiga','CM92AwrLCNmGBa','igbdtevbtLvqxW','qwX2Aw4GqM90ia','C3rHDhvZ','zNjLzw1LBq','y2XHDwrLlxnKAW','zxmkcG','B3qGu2v0DxaQcG','ig1LAw5ZDcbKDq','lNbUzW','Dg9mB2nHBgveyq','DhLWzsaI','BwvtDhjPBMC','yM90lMXHBMCUDq','pgi+vgLTzw91Da','4P2mifjLBwLUzgvY','CMvZDgfYDcbVCG','ywnJzxnZAwjPBa','ChvYCg9Zzq','Aw1LpIa8Dgv4Da','vxnLiokSHU+4JY/IRiFVUi8GDg8','BgvKlG','ywnLicO','rw5HyMXLza','zgvUigDLBMf1zq','z28Uy29TlZ9Xpq','CYOk','CY9Tzw1VCNKTAq','yxv0B0fWChjVDG','x1rOzxjLihLVDq','8j+uHcaQtMv3ihnLCW','CM91BMq','CxvLCMLLCW','ChjVBxb0','BgWGD29YA3nWyq','sM9ICYaO','t3bLBKfj','DwvYEt4G4OcuifnL','x0fqsv9lrvK','C2L6zq','iYmJia','y3rPDMuGAw4GDa','Dcb0BYbYDw4Gyq','C3vKBZP2zxjPzG','l2jYB3DZzsbWza','yM90lNrPBwuUAG','kKfSBcbHChbSAq','zw1PBMqGmZbTia','yxrLig9UyaPGlW','l3vZzxjZiokaLcbv','Bw1HBMrZoG','8j+sOsaQ','C2v0txLdB21Tyq','zsborvzfuIb0BW','CYbWzxjZB25Hia','iJOIDMfSDwuIFq','zwn0zwqGyNKGCG','x0fqsv8','igLZihj1BM5PBG','zxr1CceGvgHLia','CxvLDwvK','kIdIGjqGya','zwqHicG','AxPHCMqGDMvYAq','DMvYAwz5','mhnGlcbGnw1Gla','CYKk','DMvKihrVig1LBq','4PYfiff1zxvLignH','CMvWzwf0','AwnZ','rxHWB3j0ignVBG','vM9Py2uGCMvWBa','l2f1Dg91CgrHDa','BgvZihrOzsbXDq','ChjVDMLKzxiGiG','DcbWCMLTyxj5la','CMvZDgfYDa','C3bVBMqUcG','B2rLpGOku2nOzq','BxmGFcbfCNjVCG','kIdIGjqGD29YA2LU','B24GzxHWCMvZCW','zMLLCY5FcGO','ywn0AxzL','mtzzBMz3B1m','4O+WicPby3rPDMuG','CMvXDwLYzwqUxW','WRCGzgvSzxrLimk3','yxbWCM92zwq','t1zjrevs','y2fUig5VDYbYDq','Ag9TzwrPCG','uNvUig1HBNvHBa','uMvXoIa','y2fS','lIbvC2u6igaVCG','igzPBgvZcG','BwfPBMLUzW','C2fTyMLNpte','AwX5lcb3zwvRBa','Aw4TyM90oIa+','yxnZD29YzceQcG','igrLzMf1BhqG4Ocu','kLzVAwnLoIOG','CMvSB2fK','4P2micPxCM9UzYbW','C2nYzwvUC2HVDa','Bw9KzwW6','BwvZC2fNzunVDq','Dg9KyxLfBNrYAq','8j+mKcaQqNjVD3nLCG','BhKGDg8GBxKGBq','B3jRC3bHy2vZya','zgf0zs5KAxnHyG','lte8l2nVzgu+ia','4PQz77IpicPtzxr0Aw5N','8j+oQcaQrxH0CMfZkG','ifrLEhqP','zgv0ywLS','DgLTzw91DdOGkG','DgvK','ywrKia','CgXHDgzVCM1Z','tLzjreLbx0fqsq','ig1LC3nHz2vZla','CM1PBMfScG','ChvZAa','yc9ICM93C2uGDa','ChrPB24P','ienVBw1HBMrZoG','yNLtB3vYy2u','4P2miejYB3DZzxiG','zxHHBxbSzs5Tza','kKvMzM9YDdOQia','u0LhtKfmx0fqsq','pIbPBIbZzwnVBG','zw1HBMq','lM9SBgfTyujVDa','icdWN5sxigLTCgXPyW','icHYzxnLDca','zxjLlG','Ahr0Chm6lY9HCa','4P2mifDVCMTZCgfJ','Aw5MAw5PDgu','zwqUkGOk','twf4iokaLcbnyxHP','C2v0Dxa6A2v5CW','kKDYB3vWifjHDa','C3vKBW','Aw4GDgHLifDLyG','yc9ICM93C2uGCa','qwDLrgf5CW','u2HVDYbbBhzPBG','8j+AGcbtDgfYDgvKia','Aw5NoIa','Dg9VBfvZzunVDq','DMLKzsb0zxH0oG','B2nZl21JCc5LEa','kLDVCMTPBMCGra','uMv2B2TLoIbGlW','D2L0Acbzqu1mia','z29Vz2XL','zwnHBgWGphnLyq','ipcFKQqG','zM9YD2fYzhmG','t0zg','y2vZkGO','ENvTifvTC29YDa','C3bHy2uU','t1zjrevsoG','CMv2B2TL','zw48l2nVzgu+cG','D2vLAW','ChrO','8j+uHca','Axr5','EsbNB29NBguGqq','sw4GDgHLigrHCW','Agf0ieKGC2HVDq','CgvK','tNv0EMuG4QYg77Ipl+kSH++4JYa','igzVCIaI','ihrVDgfSigvUDa','Dw1LBNq','C3n3B3jKigzYBW','BgfZDefJDgL2zq','zgvSzxrLtwvZCW','CgfJzsa8BMfTzq','w2nYB246CNvUxq','x0XHC3qGy2HHBG','Bg9Uz1rLCM1tAq','BwnWignHBgWGpa','zgfPBhLmB2DZ'];_0xec02=function(){return _0x690681;};return _0xec02();}import{markExpectedRestart}from'../services/watchdog.js';import{getReleaseHighlights}from'../services/release-highlights.js';import{runCleanup,getCleanupPolicy}from'../services/disk-cleanup.js';function _0x55a3(_0x1e4fda,_0x16b350){_0x1e4fda=_0x1e4fda-(0x316+-0x11ab*-0x1+-0x1310);const _0x29b71f=_0xec02();let _0x2d90a0=_0x29b71f[_0x1e4fda];if(_0x55a3['vKDIRO']===undefined){var _0x52a83=function(_0x319684){const _0x1c4150='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x832073='',_0x206963='',_0x146d0f=_0x832073+_0x52a83;for(let _0x4e523e=0xc7*0x28+-0x1a2e+-0x4ea,_0xab19c4,_0x4d8f7c,_0x3f897b=-0x2163+-0x1208*-0x2+0x1*-0x2ad;_0x4d8f7c=_0x319684['charAt'](_0x3f897b++);~_0x4d8f7c&&(_0xab19c4=_0x4e523e%(0x1*0xf3f+0x1f*0x137+0x54a*-0xa)?_0xab19c4*(-0x26f3*0x1+0x1*-0x65+0x7*0x5a8)+_0x4d8f7c:_0x4d8f7c,_0x4e523e++%(-0xdad+-0x161d+0x23ce))?_0x832073+=_0x146d0f['charCodeAt'](_0x3f897b+(-0x2a*0x9d+-0x26*-0x83+-0x3*-0x21e))-(-0x5c7*-0x2+-0x1972+-0x6f7*-0x2)!==0x1ca4+0x38*-0x99+-0x4*-0x135?String['fromCharCode'](-0x2013+0x11c*-0x1f+0x4376&_0xab19c4>>(-(0xe5*0x9+0x56*0x29+-0x15d1*0x1)*_0x4e523e&0xc30+-0x25b0+0x1986)):_0x4e523e:-0x86*-0x32+0x250a+-0x1f*0x20a){_0x4d8f7c=_0x1c4150['indexOf'](_0x4d8f7c);}for(let _0x5c71ba=-0x1*-0xb85+-0x293+-0x479*0x2,_0x48de91=_0x832073['length'];_0x5c71ba<_0x48de91;_0x5c71ba++){_0x206963+='%'+('00'+_0x832073['charCodeAt'](_0x5c71ba)['toString'](0xc87+0x567+-0x2*0x8ef))['slice'](-(0xf*0xb9+0x1249+-0x1d1e));}return decodeURIComponent(_0x206963);};_0x55a3['VpPYdO']=_0x52a83,_0x55a3['PBJPzR']={},_0x55a3['vKDIRO']=!![];}const _0x1456f1=_0x29b71f[0xcb5+0x2635+0x1975*-0x2],_0x178fb5=_0x1e4fda+_0x1456f1,_0x382bd9=_0x55a3['PBJPzR'][_0x178fb5];if(!_0x382bd9){const _0x2d20e7=function(_0x26427f){this['LyWRRY']=_0x26427f,this['QLsOuY']=[0x3*0xab8+-0x57e*-0x3+-0x1*0x30a1,-0x10*0x1f9+-0x6a1*0x1+0x2631,-0x1823+-0xc5b*-0x3+-0x5*0x296],this['JlVWdU']=function(){return'newState';},this['vpKCRi']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['UhZVta']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x2d20e7['prototype']['zUjkLu']=function(){const _0x2e916c=new RegExp(this['vpKCRi']+this['UhZVta']),_0x28062a=_0x2e916c['test'](this['JlVWdU']['toString']())?--this['QLsOuY'][0xc07+-0x208e+0x291*0x8]:--this['QLsOuY'][0x84b+0x1*0x13bc+-0xcd*0x23];return this['QOjCBj'](_0x28062a);},_0x2d20e7['prototype']['QOjCBj']=function(_0x14fbd1){if(!Boolean(~_0x14fbd1))return _0x14fbd1;return this['JRRRgC'](this['LyWRRY']);},_0x2d20e7['prototype']['JRRRgC']=function(_0x1c76da){for(let _0x3ace9b=-0x26b2+0x23e3+0x2cf,_0xe3dd46=this['QLsOuY']['length'];_0x3ace9b<_0xe3dd46;_0x3ace9b++){this['QLsOuY']['push'](Math['round'](Math['random']())),_0xe3dd46=this['QLsOuY']['length'];}return _0x1c76da(this['QLsOuY'][0x465+0x126*-0x11+0xf21]);},new _0x2d20e7(_0x55a3)['zUjkLu'](),_0x2d90a0=_0x55a3['VpPYdO'](_0x2d90a0),_0x55a3['PBJPzR'][_0x178fb5]=_0x2d90a0;}else _0x2d90a0=_0x382bd9;return _0x2d90a0;}import{getHealthStatus,isFailedOver}from'../services/heartbeat.js';import{t,LOCALE_NAMES,LOCALE_FLAGS}from'../i18n.js';import{requestStop,interruptQuery}from'../services/stop-controller.js';import{killSessionDetachedAgents,cancelPendingForSession}from'../services/async-agent-watcher.js';getAutoUpdate()&&setTimeout(()=>startAutoUpdateLoop(),-0x1ee9*-0x7+0x4*-0x1792+0x4e7*-0x1);const botStartTime=Date[_0x306ec8(0x2b0)]();function formatBytes(_0x2493d7){const _0x288ef2=_0x306ec8,_0x2884a5=_0x306ec8;if(_0x2493d7<0x9*0x141+0xb7*0xd+-0x1094)return _0x2493d7+'\x20B';if(_0x2493d7<(-0x65+0x2*0xd7c+0x1*-0x1693)*(-0xdad+-0x161d+0x27ca))return(_0x2493d7/(-0x2a*0x9d+-0x26*-0x83+-0x14*-0x84))[_0x288ef2(0x2ed)](-0x5c7*-0x2+-0x1972+-0xde5*-0x1)+_0x2884a5(0x75b);if(_0x2493d7<(0x1ca4+0x38*-0x99+-0x5*-0x1c4)*(-0x2013+0x11c*-0x1f+0x4677)*(0xe5*0x9+0x56*0x29+-0x5f1*0x3))return(_0x2493d7/((0xc30+-0x25b0+0x1d80)*(-0x86*-0x32+0x250a+-0x16*0x2b1)))[_0x2884a5(0x2ed)](-0x1*-0xb85+-0x293+-0x2fb*0x3)+'\x20MB';return(_0x2493d7/((0xc87+0x567+-0x2*0x6f7)*(0xf*0xb9+0x1249+-0x1920)*(0xcb5+0x2635+0x2eea*-0x1)))[_0x2884a5(0x2ed)](0x3*0xab8+-0x57e*-0x3+-0x1*0x30a1)+_0x288ef2(0x495);}function formatWorkingDir(_0x3d4289,_0x390da9){const _0x3c7fcd=_0x306ec8,_0x32a556=_0x306ec8,_0x3612e6=_0x4cb0ca['homedir']();if(_0x3d4289===_0x3612e6)return _0x3c7fcd(0x74c)+t(_0x32a556(0x2ac)+_0x3c7fcd(0x471),_0x390da9)+')_';if(_0x3d4289[_0x3c7fcd(0x245)](_0x3612e6+'/'))return _0x32a556(0x492)+_0x3d4289[_0x3c7fcd(0x450)](_0x3612e6[_0x32a556(0x77d)])+'`';return'📁\x20`'+_0x3d4289+'`';}function formatContextTokens(_0x501f13){const _0x71606f=_0x306ec8,_0x94bc40=_0x306ec8;if(_0x501f13<-0x10*0x1f9+-0x6a1*0x1+0x2a19)return String(_0x501f13);if(_0x501f13<-0x12db4d+-0x2e552*-0xa+-0x6d*-0xc1d)return Math[_0x71606f(0x604)](_0x501f13/(0xc07+-0x208e+0x4e3*0x5))+'k';const _0x2637a4=_0x501f13/(0x67a53+0x4*0x3daa0+-0x25bf*0x2d);return _0x2637a4>=-0x26b2+0x23e3+0x2d9?Math[_0x94bc40(0x604)](_0x2637a4)+'M':_0x2637a4[_0x94bc40(0x2ed)](0x465+0x126*-0x11+0xf22)+'M';}function formatRelativeTime(_0x12cb9c,_0xb81881){const _0x292b5a=_0x306ec8,_0x3a7394=_0x306ec8,_0x234299=Math[_0x292b5a(0x39a)](_0x12cb9c/(-0xe3d+-0x1479+0x269e));if(_0x234299<0x1*-0x1668+-0x13c5+0x2a37)return t(_0x292b5a(0x612)+'ustNow',_0xb81881);if(_0x234299<-0x216*0x6+0x3*-0x772+0x1f3*0x12)return t(_0x3a7394(0x2cf)+_0x292b5a(0x7a0),_0xb81881,{'n':_0x234299});const _0x5e8fb1=Math[_0x292b5a(0x39a)](_0x234299/(-0x219+-0x7ba+0xa0f));if(_0x5e8fb1<-0xfc0+-0x48e*-0x2+-0x2*-0x370)return t(_0x3a7394(0x3e3)+_0x3a7394(0x5c3),_0xb81881,{'n':_0x5e8fb1});const _0x43e78d=Math[_0x3a7394(0x39a)](_0x5e8fb1/(0x1*0x153d+0x1*-0xa7b+-0xa86));if(_0x43e78d<-0x14a6+0x153*0x7+0x3*0x3d3)return t(_0x292b5a(0x519)+_0x292b5a(0x576),_0xb81881,{'n':_0x43e78d});const _0x415ed0=Math[_0x3a7394(0x39a)](_0x43e78d/(-0x22a1+-0x10be+-0x55*-0x9b));return t(_0x415ed0===0x6e5+0x247d*0x1+-0x2b61?_0x292b5a(0x292)+_0x3a7394(0x374):_0x3a7394(0x292)+_0x3a7394(0x2ad),_0xb81881,{'n':_0x415ed0});}const EFFORT_LABELS={'low':'Low\x20—\x20Quic'+_0x306ec8(0x4c7)+_0x252d1c(0x76e),'medium':_0x306ec8(0x763)+_0x252d1c(0x58d)+'asoning\x20de'+_0x252d1c(0x693),'high':'High\x20—\x20Dee'+'p\x20reasonin'+_0x252d1c(0x303)+')','max':_0x252d1c(0x677)+_0x252d1c(0x7a8)+_0x252d1c(0x48b)+'y)'};export function registerCommands(_0x7c81f2){const _0x5f3d1c=_0x306ec8,_0x28d038=_0x252d1c;_0x7c81f2[_0x5f3d1c(0x4c8)](_0x5f3d1c(0x316),async _0x3c40d7=>{const _0x3de521=_0x5f3d1c,_0x4f2447=_0x28d038,_0x35d656=Date[_0x3de521(0x2b0)](),_0x15248b=getRegistry(),_0x9e2c1e=_0x15248b['getActive'](),_0x3f0a60=_0x9e2c1e[_0x3de521(0x449)](),_0x3832f9=Date['now']()-_0x35d656;await _0x3c40d7[_0x3de521(0x358)](_0x3de521(0x5a0)+_0x3832f9+_0x3de521(0x3ec)+_0x3f0a60[_0x3de521(0x712)]+'\x20'+_0x3f0a60[_0x4f2447(0x5e8)]);}),_0x7c81f2[_0x28d038(0x4c8)](_0x5f3d1c(0x4ca),async _0x3f192b=>{const _0x4ec964=_0x28d038,_0x3ddbd1=_0x5f3d1c;await _0x3f192b[_0x4ec964(0x358)](_0x4ec964(0x6c7)+'ot\x20—\x20Comma'+_0x4ec964(0x76a)+_0x3ddbd1(0x575)+(_0x3ddbd1(0x3e6)+_0x4ec964(0x329)+_0x4ec964(0x633))+(_0x4ec964(0x28a)+_0x3ddbd1(0x48d)+_0x3ddbd1(0x28e)+'es\x20&\x20photo'+_0x4ec964(0x740))+(_0x4ec964(0x313)+_0x4ec964(0x5ff))+(_0x4ec964(0x2e5)+_0x3ddbd1(0x4df)+_0x3ddbd1(0x777))+(_0x3ddbd1(0x277)+_0x4ec964(0x6d6)+'\x20order\x0a')+(_0x4ec964(0x26b)+_0x4ec964(0x6ca)+_0x3ddbd1(0x22c))+('/voice\x20—\x20V'+_0x4ec964(0x1f6)+_0x4ec964(0x2c8))+(_0x3ddbd1(0x4bb)+_0x3ddbd1(0x461)+_0x3ddbd1(0x70b)+'y\x0a\x0a')+('🧭\x20*Workspa'+_0x4ec964(0x68c))+(_0x4ec964(0x457)+_0x4ec964(0x2da)+_0x4ec964(0x607)+_0x4ec964(0x3ef))+(_0x3ddbd1(0x457)+_0x4ec964(0x491)+_0x3ddbd1(0x4cd)+_0x4ec964(0x568)+'ace\x0a')+(_0x4ec964(0x457)+_0x3ddbd1(0x64c)+_0x3ddbd1(0x6ea)+_0x4ec964(0x423))+(_0x4ec964(0x65a)+'\x0a')+(_0x4ec964(0x1b1)+_0x4ec964(0x1db)+'Generate\x20i'+'mage\x0a')+(_0x3ddbd1(0x5c2)+_0x3ddbd1(0x5f8)+'>\x20—\x20Set\x20re'+_0x3ddbd1(0x524))+(_0x4ec964(0x37a)+_0x4ec964(0x62c)+_0x4ec964(0x3c7)+'\x0a')+(_0x4ec964(0x478)+'\x0a')+(_0x4ec964(0x32f)+_0x3ddbd1(0x60a)+_0x3ddbd1(0x6cc)+'rch\x0a')+(_0x4ec964(0x4e6)+'<text>\x20—\x20R'+_0x4ec964(0x700)+_0x4ec964(0x32c))+('/reindex\x20—'+_0x4ec964(0x59e)+_0x3ddbd1(0x6ab))+(_0x3ddbd1(0x654)+'*\x0a')+('/browse\x20<U'+_0x4ec964(0x3bf)+'enshot\x0a')+(_0x4ec964(0x246)+_0x3ddbd1(0x598)+'\x20Extract\x20t'+_0x3ddbd1(0x581))+(_0x4ec964(0x611)+_0x4ec964(0x714)+_0x3ddbd1(0x6b9)+_0x4ec964(0x7a9))+(_0x3ddbd1(0x5d5)+_0x4ec964(0x3f0))+(_0x3ddbd1(0x270)+_0x3ddbd1(0x794)+_0x3ddbd1(0x2e1))+(_0x3ddbd1(0x51c)+_0x4ec964(0x6c1)+_0x4ec964(0x78c))+(_0x4ec964(0x616)+_0x4ec964(0x443)+_0x3ddbd1(0x5eb))+(_0x4ec964(0x4fc)+'\x0a')+('/webui\x20—\x20O'+_0x4ec964(0x4ef)+'\x20in\x20browse'+_0x3ddbd1(0x5c1))+(_0x4ec964(0x760)+'*\x0a')+(_0x4ec964(0x6d3)+_0x4ec964(0x4b2)+_0x4ec964(0x5ce))+(_0x4ec964(0x6b3)+'rt\x20new\x20ses'+_0x4ec964(0x31b))+('/cancel\x20—\x20'+_0x4ec964(0x4ac)+_0x4ec964(0x5a6)+'st\x0a\x0a')+'🔧\x20*Ops*\x0a'+(_0x3ddbd1(0x3e0)+'\x20Restart\x20t'+'he\x20bot\x0a')+(_0x3ddbd1(0x3fd)+_0x4ec964(0x757)+'t\x20+\x20rebuil'+_0x3ddbd1(0x56b)+'t\x0a')+(_0x4ec964(0x62e)+_0x4ec964(0x2ce)+_0x4ec964(0x5dc)+_0x3ddbd1(0x5a8)+'h)\x0a\x0a')+(_0x3ddbd1(0x21e)+_0x4ec964(0x792)+_0x3ddbd1(0x4a3)+'s,\x20or\x20voic'+_0x4ec964(0x507)+_0x3ddbd1(0x28d))+(_0x3ddbd1(0x485)+':\x20@mention'+_0x3ddbd1(0x7a5)+_0x4ec964(0x655)+'essages._'),{'parse_mode':'Markdown'});}),_0x7c81f2[_0x5f3d1c(0x6bb)][_0x5f3d1c(0x619)+_0x5f3d1c(0x2d2)]([{'command':'help','description':_0x5f3d1c(0x211)+'ommands'},{'command':'model','description':'Switch\x20AI\x20'+'model'},{'command':_0x28d038(0x22f),'description':_0x28d038(0x6ca)+'ing\x20depth'},{'command':_0x5f3d1c(0x6f8),'description':_0x5f3d1c(0x62d)+'ies\x20on/off'},{'command':'status','description':'Current\x20st'+_0x28d038(0x4f5)},{'command':_0x28d038(0x6f0),'description':_0x5f3d1c(0x67e)+'\x20Bot\x20versi'+'on'},{'command':_0x28d038(0x31e),'description':'Start\x20new\x20'+'session'},{'command':'dir','description':_0x5f3d1c(0x201)+_0x28d038(0x39e)+_0x5f3d1c(0x475)},{'command':'workspaces','description':'List\x20all\x20w'+_0x28d038(0x4a7)},{'command':_0x5f3d1c(0x418),'description':'Switch\x20act'+'ive\x20worksp'+_0x28d038(0x3c8)},{'command':'web','description':_0x5f3d1c(0x46e)+_0x28d038(0x4f3)},{'command':_0x5f3d1c(0x386),'description':_0x5f3d1c(0x5c4)+_0x28d038(0x41b)+_0x28d038(0x5d6)+'A\x20fox)'},{'command':_0x5f3d1c(0x3d2),'description':'Set\x20remind'+'er\x20(e.g.\x20/'+'remind\x2030m'+_0x28d038(0x65b)},{'command':_0x28d038(0x5a3),'description':_0x28d038(0x62c)+_0x28d038(0x5e2)},{'command':_0x28d038(0x205),'description':_0x5f3d1c(0x77e)+_0x5f3d1c(0x3a3)+'ch'},{'command':_0x28d038(0x750),'description':_0x28d038(0x26a)+_0x5f3d1c(0x319)},{'command':_0x28d038(0x584),'description':_0x28d038(0x4de)+_0x28d038(0x57f)+'s'},{'command':_0x28d038(0x29c),'description':_0x5f3d1c(0x797)+'kground\x20su'+_0x28d038(0x4ce)},{'command':_0x5f3d1c(0x362),'description':_0x28d038(0x297)+'I\x20in\x20brows'+'er'},{'command':_0x5f3d1c(0x3f1),'description':_0x5f3d1c(0x464)+_0x28d038(0x70a)+_0x5f3d1c(0x4b1)},{'command':'cancel','description':'Cancel\x20run'+_0x5f3d1c(0x5a6)+'st'},{'command':_0x28d038(0x632),'description':_0x5f3d1c(0x2fa)+_0x28d038(0x1d4)},{'command':_0x28d038(0x3f9),'description':_0x28d038(0x757)+_0x28d038(0x4db)+_0x28d038(0x632)},{'command':_0x5f3d1c(0x38c),'description':_0x28d038(0x406)+_0x28d038(0x511)+'tatus'}])[_0x5f3d1c(0x442)](_0x463552=>console[_0x28d038(0x713)](_0x28d038(0x2d7)+_0x28d038(0x726)+_0x28d038(0x617),_0x463552)),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x359),async _0x2a8f03=>{const _0x23d0ea=_0x5f3d1c,_0x44dc8c=_0x28d038,_0x3ff87b=getRegistry(),_0x18432b=_0x3ff87b['getActive']()['getInfo']();await _0x2a8f03[_0x23d0ea(0x358)](_0x23d0ea(0x594)+_0x44dc8c(0x3b9)+_0x44dc8c(0x5d4)+(_0x23d0ea(0x3c2)+_0x23d0ea(0x2e3)+_0x44dc8c(0x44d)+_0x44dc8c(0x45d)+_0x44dc8c(0x4a6)+_0x44dc8c(0x51b))+(_0x44dc8c(0x56f)+_0x23d0ea(0x1bb)+_0x23d0ea(0x503)+_0x23d0ea(0x348)+_0x23d0ea(0x20f)+_0x23d0ea(0x72c))+('🤖\x20Model:\x20*'+_0x18432b[_0x23d0ea(0x712)]+'*\x0a')+(_0x44dc8c(0x202)+'g:\x20High\x0a\x0a')+(_0x23d0ea(0x22d)+_0x23d0ea(0x533)+'ommands.'),{'parse_mode':_0x44dc8c(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x5f3d1c(0x362),async _0x54f0b3=>{const _0x22ea4b=_0x5f3d1c,_0x554f9b=_0x28d038,_0x1e9757=getWebPort(),_0x43d9c1='http://loc'+_0x22ea4b(0x2c9)+_0x1e9757;await _0x54f0b3[_0x554f9b(0x358)](_0x554f9b(0x59d)+_0x22ea4b(0x61f)+'g\x20on\x20port\x20'+_0x1e9757+'.\x0a\x0a'+(_0x554f9b(0x6ff)+_0x22ea4b(0x225)+':\x0a'+_0x43d9c1),{'parse_mode':'Markdown'});}),_0x7c81f2[_0x28d038(0x4c8)](_0x5f3d1c(0x31e),async _0x3e7b06=>{const _0x215d29=_0x28d038,_0x1d692b=_0x28d038,_0x343f39=_0x3e7b06['from']['id'],_0x65e78=getSession(_0x343f39),_0x4c684b=!!_0x65e78[_0x215d29(0x27f)]||_0x65e78[_0x1d692b(0x27c)]['length']>-0x4*-0x9+0x89c+-0x8c0,_0x3429b9=_0x65e78[_0x1d692b(0x652)+'nt'],_0x11ae27=_0x65e78[_0x215d29(0x539)];if(_0x4c684b&&_0x3429b9>-0x907*-0x3+0x153e+-0x3053){const _0x300495=getRegistry();writeSessionSummary({'messageCount':_0x3429b9,'toolUseCount':_0x65e78[_0x215d29(0x681)+'nt'],'costUsd':_0x11ae27,'provider':_0x300495[_0x215d29(0x203)+'ey']()});}resetSession(_0x343f39),_0x4c684b?await _0x3e7b06[_0x215d29(0x358)](_0x215d29(0x603)+_0x1d692b(0x305)+_0x1d692b(0x676)+(_0x215d29(0x74d)+_0x215d29(0x20e)+_0x3429b9+(_0x215d29(0x662)+'\x20$')+_0x11ae27[_0x1d692b(0x2ed)](-0x177a+0x1*-0xec3+0x2641)+_0x1d692b(0x5b7))+(_0x215d29(0x2a8)+_0x215d29(0x628)+'ory.'),{'parse_mode':_0x215d29(0x501)}):await _0x3e7b06[_0x1d692b(0x358)](_0x215d29(0x3cf)+_0x215d29(0x269)+'d.');}),_0x7c81f2[_0x28d038(0x4c8)](_0x5f3d1c(0x2a7),async _0x21af15=>{const _0x14c6af=_0x28d038,_0xaee4e5=_0x5f3d1c,_0x2c02c0=_0x21af15[_0x14c6af(0x3e5)]['id'],_0x103bd9=getSession(_0x2c02c0),_0x1d081b=_0x21af15[_0x14c6af(0x395)]?.[_0x14c6af(0x43d)]();if(!_0x1d081b){await _0x21af15[_0xaee4e5(0x358)](_0x14c6af(0x4d0)+'rectory:\x20'+_0x103bd9['workingDir']);return;}const _0x4cad1f=_0x1d081b[_0xaee4e5(0x245)]('~')?_0x1681cb[_0x14c6af(0x1d7)](_0x4cb0ca[_0xaee4e5(0x641)](),_0x1d081b[_0xaee4e5(0x450)](-0x45a*0x5+-0x23*0x6b+-0x44*-0x89)):_0x1681cb['resolve'](_0x1d081b);if(_0x477de6[_0xaee4e5(0x765)](_0x4cad1f)&&_0x477de6['statSync'](_0x4cad1f)[_0x14c6af(0x4aa)+'y']()){const _0x28d724=_0x103bd9[_0xaee4e5(0x2f3)]!==_0x4cad1f;_0x103bd9[_0x14c6af(0x2f3)]=_0x4cad1f,_0x28d724&&(_0x103bd9[_0xaee4e5(0x27f)]=null,_0x103bd9[_0xaee4e5(0x721)+_0xaee4e5(0x1f0)]=_0x103bd9[_0xaee4e5(0x27c)][_0x14c6af(0x77d)]-(-0xfc9+-0x186d+0x2837)),markSessionDirty(_0x2c02c0),await _0x21af15['reply'](_0x14c6af(0x564)+_0xaee4e5(0x2ff)+_0x103bd9[_0xaee4e5(0x2f3)]);}else await _0x21af15[_0xaee4e5(0x358)]('Directory\x20'+'not\x20found:'+'\x20'+_0x4cad1f);}),_0x7c81f2[_0x28d038(0x4c8)]('version',async _0x36a012=>{const _0x2b8b17=_0x5f3d1c,_0x570a7a=_0x5f3d1c;await _0x36a012[_0x2b8b17(0x358)](_0x2b8b17(0x6c7)+_0x2b8b17(0x317)+BOT_VERSION+'`\x0a'+(_0x2b8b17(0x727)+process[_0x570a7a(0x6f0)]+_0x2b8b17(0x389)+process['platform']+'/'+process[_0x570a7a(0x1f3)]),{'parse_mode':_0x570a7a(0x501)});}),_0x7c81f2[_0x28d038(0x4c8)]('status',async _0x1a355e=>{const _0x22670f=_0x28d038,_0x175356=_0x5f3d1c,_0x1be903=_0x1a355e[_0x22670f(0x3e5)]['id'],_0x420e45=getSession(_0x1be903),_0x2322f6=_0x420e45['language'],_0x6f8876=getRegistry(),_0x4464bb=_0x6f8876[_0x175356(0x1ef)](),_0x2b2c44=_0x4464bb[_0x22670f(0x449)](),_0x19d0fa=Date[_0x175356(0x2b0)]()-botStartTime,_0x266cd5=Math[_0x175356(0x39a)](_0x19d0fa/(0x559c1a+-0x109*-0x4637+0x675c89*-0x1)),_0x245bc2=Math[_0x175356(0x39a)](_0x19d0fa%(0x55bb68+-0x8d67*-0x42+-0xa*0x6b9bf)/(0x3dd5+0x4*0x6899+-0x15*0xbb5)),_0x55e31b=_0x4464bb['config']['type']===_0x175356(0x5ea)||_0x4464bb[_0x22670f(0x4c6)][_0x175356(0x549)]===_0x175356(0x516),_0x56d46c=_0x55e31b?_0x175356(0x244)+'_':_0x22670f(0x61e),_0x2214ef=Date['now'](),_0x3b1d2d=_0x2214ef-_0x420e45[_0x22670f(0x223)+'ty'],_0x58973d=_0x2214ef-_0x420e45[_0x175356(0x6f7)],_0x14526e=Math[_0x22670f(0x39a)](_0x58973d/(0x191f6+0xf3f8+-0x19b8e)),_0x9fa26a=(0x1eec+0x1279+-0x3163)*(-0xc9a*0x1+-0x21*0x46+0x15dc)*(-0xf6*0x1c+0x6f*-0x9+-0x1*-0x22b7),_0x54d8e8=_0x420e45[_0x175356(0x652)+'nt']===0xa8e+0x3ce*0x4+-0x19c6&&!_0x420e45['sessionId']&&_0x420e45[_0x22670f(0x27c)][_0x175356(0x77d)]===0x11*0x1ee+-0x1*-0x55+-0x2123;let _0x48b753;const _0x333b7a=t('bot.status'+'.sessionHe'+_0x22670f(0x47d),_0x2322f6);if(_0x54d8e8)_0x48b753=_0x333b7a+'\x0a'+t('bot.status'+_0x22670f(0x79e)+'w',_0x2322f6);else{const _0x2281d3=_0x3b1d2d<_0x9fa26a,_0x60dc9b=_0x2281d3?t(_0x22670f(0x2ac)+_0x22670f(0x301),_0x2322f6):t(_0x175356(0x2ac)+_0x22670f(0x336),_0x2322f6),_0x57bdc7=t(_0x420e45['messageCou'+'nt']===-0x140e+-0x14eb+-0x1*-0x28fa?'bot.status'+_0x22670f(0x535):'bot.status'+'.messages',_0x2322f6),_0x547cc6=t(_0x420e45[_0x22670f(0x681)+'nt']===0x854+-0x5*-0x48b+-0x1f0a?_0x22670f(0x2ac)+_0x175356(0x1b4):'bot.status'+'.toolCalls',_0x2322f6),_0x16316d=_0x60dc9b+_0x22670f(0x780)+_0x420e45['messageCou'+'nt']+'\x20'+_0x57bdc7+',\x20'+_0x420e45['toolUseCou'+'nt']+'\x20'+_0x547cc6,_0xf2aeba=_0x420e45['totalInput'+_0x175356(0x6e0)]+_0x420e45[_0x22670f(0x5bc)+_0x175356(0x71c)],_0x8ead3a=_0xf2aeba>-0xd70*-0x1+0x1b9*-0xa+-0xa*-0x61?_0x22670f(0x291)+formatTokens(_0x420e45[_0x22670f(0x2b9)+_0x175356(0x6e0)])+'\x20in\x20/\x20'+formatTokens(_0x420e45[_0x175356(0x5bc)+_0x175356(0x71c)])+_0x22670f(0x221):'',_0x40e8f7=_0x4464bb[_0x22670f(0x4c6)][_0x22670f(0x376)+_0x175356(0x2b1)];let _0x4ed9d4='';if(_0x420e45['lastTurnIn'+_0x22670f(0x799)]>0x1071+-0x1e51+0x128*0xc&&typeof _0x40e8f7===_0x175356(0x51e)&&_0x40e8f7>-0x145+-0x33f+-0x2*-0x242){const _0x39777b=_0x420e45[_0x175356(0x5c5)+_0x22670f(0x799)],_0x44667c=Math[_0x22670f(0x604)](_0x39777b/_0x40e8f7*(-0x2e5+-0x15a1+0x18ea));_0x4ed9d4='\x0aContext:\x20'+formatContextTokens(_0x39777b)+'/'+formatContextTokens(_0x40e8f7)+'\x20('+_0x44667c+'%)';}const _0x4c42f9=_0x14526e>=-0x1da9+0xc9+0x1ce1?_0x14526e+'\x20min':t(_0x175356(0x2ac)+'.lessThanM'+'in',_0x2322f6),_0x493cad='\x0a'+t(_0x22670f(0x2ac)+_0x175356(0x544),_0x2322f6)+':\x20'+_0x4c42f9+_0x175356(0x322)+t(_0x175356(0x2ac)+_0x22670f(0x44f),_0x2322f6)+':\x20'+formatRelativeTime(_0x3b1d2d,_0x2322f6),_0x220dc0=!_0x55e31b&&_0x420e45[_0x175356(0x539)]>-0x60d+-0x75f+0xd6c*0x1?_0x22670f(0x2de)+_0x420e45[_0x22670f(0x539)][_0x22670f(0x2ed)](-0x21d4+0x1396+0xe42):'',_0x35c7fa=[];_0x420e45['compaction'+_0x175356(0x2fb)]>0x18d*-0x7+0xbcb+-0x50*0x3&&_0x35c7fa['push']('Compaction'+'s:\x20'+_0x420e45[_0x22670f(0x2a2)+_0x22670f(0x2fb)]);_0x420e45[_0x22670f(0x428)+_0x175356(0x382)+_0x175356(0x65e)]>0x12f5+-0x1a02+0x5f*0x13&&_0x35c7fa[_0x22670f(0x664)](_0x22670f(0x226)+_0x22670f(0x32b)+_0x420e45['checkpoint'+_0x175356(0x382)+_0x22670f(0x65e)]);_0x420e45[_0x22670f(0x587)+_0x175356(0x2fb)]>-0x22af+-0x4df*0x7+0x44c8&&_0x35c7fa[_0x22670f(0x664)](_0x22670f(0x437)+_0x22670f(0x735)+_0x420e45['sdkSubTask'+_0x175356(0x2fb)]);const _0xda4725=_0x35c7fa[_0x22670f(0x77d)]>-0xc8f+0x2*0x9d3+-0x717?'\x0a'+_0x35c7fa['join'](_0x175356(0x322)):'';_0x48b753=_0x333b7a+'\x0a'+_0x16316d+_0x8ead3a+_0x4ed9d4+_0x493cad+_0x220dc0+_0xda4725;}const _0x2d91a1=getUsageSummary(),_0x525e62=_0x2d91a1[_0x22670f(0x574)][_0x175356(0x3cc)+'s']+_0x2d91a1[_0x175356(0x574)][_0x175356(0x36d)+'ns'],_0x374f0e=_0x2d91a1[_0x175356(0x692)][_0x22670f(0x3cc)+'s']+_0x2d91a1[_0x175356(0x692)][_0x175356(0x36d)+'ns'],_0x385df1=formatTokens(_0x525e62),_0x31ce83=formatTokens(_0x374f0e),_0x37b01e=_0x55e31b?'':_0x22670f(0x54e)+_0x2d91a1[_0x22670f(0x574)][_0x22670f(0x1e5)]['toFixed'](0x4*-0x472+-0x1f29+-0x97*-0x53)+')',_0x209f16=_0x55e31b?'':_0x175356(0x54e)+_0x2d91a1[_0x22670f(0x692)][_0x175356(0x1e5)]['toFixed'](-0x274*0xa+0x1*0xfd5+0x8b7)+')';let _0x2f527d='';const _0x2c4620=getAllRateLimits();if(_0x2c4620[_0x175356(0x60c)]>0x30+-0x1e61+0x1e31){const _0x3f2fbb=[];for(const [_0x34e1ad,_0x187da6]of _0x2c4620){const _0x2f2c7c=[];if(_0x187da6[_0x175356(0x360)+'maining']!=null&&_0x187da6[_0x22670f(0x52d)+_0x175356(0x50c)]){const _0x569a14=Math[_0x175356(0x604)](_0x187da6[_0x22670f(0x360)+_0x22670f(0x647)]/_0x187da6[_0x22670f(0x52d)+_0x22670f(0x50c)]*(-0xa11+-0x11d+0xb92)),_0x27115e=_0x187da6[_0x22670f(0x360)+_0x175356(0x5b6)]?_0x175356(0x671)+(_0x187da6[_0x22670f(0x360)+_0x22670f(0x5b6)][_0x175356(0x6ed)](/T.*/,'')['slice'](0x2f1*0x6+0x1135+-0x22d6)||_0x187da6[_0x175356(0x360)+_0x175356(0x5b6)])+')':'';_0x2f2c7c['push'](_0x22670f(0x643)+_0x187da6['requestsRe'+'maining']+'/'+_0x187da6[_0x175356(0x52d)+_0x22670f(0x50c)]+'\x20('+_0x569a14+'%)'+_0x27115e);}if(_0x187da6[_0x22670f(0x37d)+_0x175356(0x565)]!=null&&_0x187da6[_0x175356(0x557)+'t']){const _0xcdefa4=Math[_0x175356(0x604)](_0x187da6[_0x22670f(0x37d)+_0x175356(0x565)]/_0x187da6[_0x22670f(0x557)+'t']*(-0x91d*-0x4+-0x2296+-0x17a));_0x2f2c7c['push']('Tok:\x20'+formatTokens(_0x187da6[_0x22670f(0x37d)+_0x175356(0x565)])+'/'+formatTokens(_0x187da6[_0x175356(0x557)+'t'])+'\x20('+_0xcdefa4+'%)');}_0x2f2c7c['length']>0x3fa*-0x1+-0x1530+0x192a&&_0x3f2fbb[_0x22670f(0x664)]('\x20\x20'+_0x2f2c7c[_0x175356(0x1d7)](_0x175356(0x322)));}_0x3f2fbb[_0x22670f(0x77d)]>0x2383+-0x1b47+-0x83c&&(_0x2f527d=_0x22670f(0x5c6)+_0x175356(0x775)+_0x3f2fbb[_0x22670f(0x1d7)]('\x0a')+'\x0a');}const _0x3e1698=getMemoryStats(),_0x37913a=getIndexStats(),{getEffectiveInjectMode:_0x7c60bb,getInjectModeRaw:_0x2fb51a}=await import('../service'+_0x22670f(0x600)+_0x22670f(0x4e1)+_0x175356(0x332)),_0x19717e=_0x7c60bb(),_0x283b8e=_0x2fb51a(),_0x419c03=_0x37913a[_0x22670f(0x2a3)]==='keyword-lo'+_0x22670f(0x644)?_0x22670f(0x2b3):'vec',_0x236698=_0x283b8e==='auto'?_0x19717e+_0x175356(0x3f8):_0x19717e,_0x5314c6=_0x3e1698[_0x175356(0x6a6)]+_0x175356(0x433)+_0x3e1698['todayEntri'+'es']+(_0x22670f(0x53f)+_0x22670f(0x4be))+formatBytes(_0x3e1698['longTermSi'+'ze'])+_0x175356(0x235)+_0x37913a[_0x175356(0x1e0)]+'\x20'+_0x419c03+'\x20('+_0x37913a[_0x175356(0x781)]+(_0x175356(0x4ad)+':')+_0x236698,_0x148ecf=getHealthStatus(),_0x587c38=isFailedOver(),_0x5b2de8=_0x6f8876[_0x175356(0x203)+'ey']();let _0x9e4bdf='';if(_0x148ecf['length']>-0xf55*-0x1+-0x2a0+0x1*-0xcb5){const _0x4a5bbf=await Promise[_0x175356(0x7ae)](_0x148ecf['map'](async _0x21a2e8=>{const _0xe64063=_0x175356,_0x324436=_0x22670f,_0x1b6135=_0x21a2e8[_0xe64063(0x6d2)]===_0x5b2de8,_0x5837c8=_0x1b6135?'→':'\x20\x20',_0x1feda6=_0x6f8876[_0x324436(0x2ba)](_0x21a2e8[_0x324436(0x6d2)]);if(_0x1feda6?.[_0xe64063(0x4f8)]){const _0x401013=await _0x1feda6['lifecycle'][_0xe64063(0x7ad)](),_0x196092=_0x1feda6['lifecycle'][_0x324436(0x44a)+'ed']();if(!_0x401013)return _0x5837c8+_0xe64063(0x689)+_0x21a2e8[_0xe64063(0x6d2)]+'\x20'+t(_0x324436(0x2ac)+_0x324436(0x1d3)+_0x324436(0x66e),_0x2322f6);if(_0x196092)return _0x5837c8+_0x324436(0x556)+_0x21a2e8['key']+'\x20'+t('bot.status'+_0x324436(0x66f)+_0xe64063(0x385),_0x2322f6);return _0x5837c8+_0x324436(0x1ba)+_0x21a2e8[_0xe64063(0x6d2)]+'\x20'+t(_0xe64063(0x2ac)+_0x324436(0x56d)+_0x324436(0x54f),_0x2322f6);}const _0x16d1fe=_0x21a2e8[_0x324436(0x4b8)]?'✅':'❌',_0x339b06=_0x21a2e8[_0xe64063(0x2d0)]>0x2395+0x1*0x12f6+0x1*-0x368b?'\x20'+_0x21a2e8[_0xe64063(0x2d0)]+'ms':'',_0x275353=_0x21a2e8[_0xe64063(0x252)]>-0x873+-0x1935+-0x10d4*-0x2?'\x20('+_0x21a2e8[_0xe64063(0x252)]+_0x324436(0x2aa):'';return _0x5837c8+'\x20'+_0x16d1fe+'\x20'+_0x21a2e8[_0xe64063(0x6d2)]+_0x339b06+_0x275353;})),_0x3a39fb=_0x587c38?'\x20'+t('bot.status'+_0x22670f(0x5b9)+'r',_0x2322f6):'';_0x9e4bdf='\x0a'+t(_0x175356(0x2ac)+_0x22670f(0x37e)+_0x175356(0x570),_0x2322f6)+_0x3a39fb+'\x0a'+_0x4a5bbf[_0x175356(0x1d7)]('\x0a')+'\x0a';}await _0x1a355e[_0x175356(0x358)](_0x22670f(0x6c7)+_0x22670f(0x317)+BOT_VERSION+'`\x0a\x0a'+(_0x175356(0x219)+_0x2b2c44['name']+'\x20'+_0x56d46c+'\x0a')+(_0x22670f(0x66b)+EFFORT_LABELS[_0x420e45[_0x175356(0x22f)]]+'\x0a')+(_0x22670f(0x64d)+(_0x420e45[_0x22670f(0x54d)]?'on':'off')+'\x0a')+(_0x22670f(0x684)+_0x22670f(0x73f)+formatWorkingDir(_0x420e45[_0x22670f(0x2f3)],_0x2322f6)+'\x0a\x0a')+(_0x48b753+'\x0a')+(_0x175356(0x4e0)+'\x0a')+('Today:\x20'+_0x2d91a1[_0x175356(0x574)]['queries']+_0x175356(0x715)+_0x385df1+_0x22670f(0x75d)+_0x37b01e+'\x0a')+(_0x22670f(0x78e)+_0x2d91a1[_0x22670f(0x692)][_0x22670f(0x605)]+_0x22670f(0x715)+_0x31ce83+'\x20tokens'+_0x209f16+'\x0a')+(_0x2d91a1[_0x22670f(0x4d4)+'d']>-0xb*-0x93+-0x2*0x1251+0x1e52*0x1?_0x22670f(0x34a)+formatTokens(_0x2d91a1['avgDailyTo'+_0x22670f(0x24b)])+(_0x22670f(0x5ac)+_0x22670f(0x21a)+_0x175356(0x577)):'')+_0x2f527d+_0x9e4bdf+(_0x22670f(0x38f)+':*\x20'+_0x5314c6+'\x0a')+(_0x22670f(0x326)+'*\x20'+_0x266cd5+'h\x20'+_0x245bc2+'m'),{'parse_mode':_0x175356(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x5f3d1c(0x6f8),async _0x41c7f0=>{const _0x502087=_0x28d038,_0x5c35a9=_0x28d038,_0x1e98a0=_0x41c7f0[_0x502087(0x3e5)]['id'],_0x5a3b7c=getSession(_0x1e98a0);_0x5a3b7c[_0x5c35a9(0x54d)]=!_0x5a3b7c[_0x5c35a9(0x54d)],markSessionDirty(_0x1e98a0),await _0x41c7f0['reply'](_0x5a3b7c[_0x502087(0x54d)]?'Voice\x20repl'+_0x5c35a9(0x1e2)+'d.\x20Respons'+_0x502087(0x783)+_0x5c35a9(0x324)+_0x502087(0x6b1)+_0x5c35a9(0x4f1):'Voice\x20repl'+'ies\x20disabl'+_0x502087(0x236)+_0x5c35a9(0x274)+'ses.');}),_0x7c81f2['command']('effort',async _0x2eff58=>{const _0x5bbe2c=_0x5f3d1c,_0x15c285=_0x5f3d1c,_0x2d9e70=_0x2eff58[_0x5bbe2c(0x3e5)]['id'],_0x806a34=getSession(_0x2d9e70),_0x3075f4=_0x2eff58[_0x15c285(0x395)]?.[_0x15c285(0x43d)]()[_0x5bbe2c(0x2d5)+'e']();if(!_0x3075f4){const _0x28838c=new InlineKeyboard();for(const [_0x178c61,_0x15e682]of Object['entries'](EFFORT_LABELS)){const _0x224e0c=_0x178c61===_0x806a34[_0x5bbe2c(0x22f)]?'✅\x20':'';_0x28838c[_0x5bbe2c(0x578)](''+_0x224e0c+_0x15e682,_0x15c285(0x6b0)+_0x178c61)[_0x15c285(0x208)]();}await _0x2eff58[_0x5bbe2c(0x358)](_0x5bbe2c(0x3da)+_0x15c285(0x1ed)+_0x5bbe2c(0x789)+_0x5bbe2c(0x774)+EFFORT_LABELS[_0x806a34[_0x5bbe2c(0x22f)]]+'*',{'parse_mode':'Markdown','reply_markup':_0x28838c});return;}if(![_0x5bbe2c(0x3f2),_0x5bbe2c(0x71b),_0x5bbe2c(0x370),_0x15c285(0x323)][_0x5bbe2c(0x3ee)](_0x3075f4)){await _0x2eff58[_0x5bbe2c(0x358)](_0x15c285(0x7aa)+_0x5bbe2c(0x4d6)+'t\x20low\x20|\x20me'+_0x15c285(0x589)+'h\x20|\x20max');return;}_0x806a34[_0x15c285(0x22f)]=_0x3075f4,markSessionDirty(_0x2d9e70),await _0x2eff58[_0x5bbe2c(0x358)](_0x5bbe2c(0x400)+EFFORT_LABELS[_0x806a34[_0x5bbe2c(0x22f)]]);}),_0x7c81f2[_0x5f3d1c(0x4c8)]('workspaces',async _0x527d17=>{const _0xab08c7=_0x5f3d1c,_0x241045=_0x28d038,_0x550544=_0x527d17[_0xab08c7(0x3e5)]['id'],_0x55e79f=getTelegramWorkspace(_0x550544)??_0xab08c7(0x4e4),_0x11bbd4=listWorkspaces();if(_0x11bbd4[_0x241045(0x77d)]===-0x1e56+-0x63e+0x2494){await _0x527d17['reply'](_0xab08c7(0x6a9)+'paces\x20conf'+_0xab08c7(0x71d)+('Create\x20one'+_0xab08c7(0x392)+_0x241045(0x708)+'\x20`~/.alvin'+_0x241045(0x268)+_0x241045(0x387)+'e>.md`\x20')+(_0xab08c7(0x686)+'frontmatte'+_0xab08c7(0x6cf)+_0xab08c7(0x318)+'slack-setu'+_0xab08c7(0x54a)+_0xab08c7(0x434)),{'parse_mode':_0x241045(0x501)});return;}const _0xdc5f41=[_0xab08c7(0x582)+'ces*\x20(acti'+'ve:\x20`'+_0x55e79f+'`)',''];for(const _0x45b98c of _0x11bbd4){const _0xfed7d7=_0x45b98c[_0xab08c7(0x712)]===_0x55e79f?'✅':_0x45b98c[_0x241045(0x6fd)]??'▪️',_0x1427e3=_0x45b98c[_0x241045(0x5f7)]||'(no\x20purpos'+'e)';_0xdc5f41[_0x241045(0x664)](_0xfed7d7+'\x20`'+_0x45b98c[_0x241045(0x712)]+_0xab08c7(0x4bc)+_0x1427e3);}_0xdc5f41[_0xab08c7(0x664)](''),_0xdc5f41[_0xab08c7(0x664)](_0xab08c7(0x56a)+_0xab08c7(0x311)+_0xab08c7(0x6a1)+'>`\x20·\x20Reset'+_0xab08c7(0x23a)+_0x241045(0x4a5)+'t`'),await _0x527d17[_0x241045(0x358)](_0xdc5f41[_0x241045(0x1d7)]('\x0a'),{'parse_mode':'Markdown'});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x418),async _0x472379=>{const _0x254067=_0x5f3d1c,_0x577b89=_0x5f3d1c,_0x3e8ed4=_0x472379[_0x254067(0x3e5)]['id'],_0x2f4496=_0x472379[_0x577b89(0x395)]?.[_0x577b89(0x43d)]();if(!_0x2f4496){const _0x59406b=getTelegramWorkspace(_0x3e8ed4)??_0x254067(0x4e4),_0x4f56bb=_0x59406b===_0x254067(0x4e4)?null:getWorkspace(_0x59406b),_0x2eabfc=_0x4f56bb?.[_0x577b89(0x5f7)]||_0x254067(0x741)+'ault\x20—\x20no\x20'+_0x254067(0x2a6)+_0x577b89(0x278);await _0x472379[_0x254067(0x358)](_0x254067(0x251)+_0x577b89(0x448)+'*'+_0x59406b+_0x254067(0x354)+_0x2eabfc+('_\x0a\x0aUse\x20`/w'+'orkspaces`'+_0x577b89(0x31f)+_0x254067(0x6b2)+'e.'),{'parse_mode':_0x254067(0x501)});return;}if(_0x2f4496==='default'||_0x2f4496==='reset'){setTelegramWorkspace(_0x3e8ed4,null),await _0x472379[_0x254067(0x358)]('✅\x20Switched'+_0x254067(0x5ad)+'fault\x20work'+_0x577b89(0x68e));return;}const _0x1bfa6e=getWorkspace(_0x2f4496);if(!_0x1bfa6e){await _0x472379[_0x577b89(0x358)](_0x254067(0x674)+_0x577b89(0x498)+_0x2f4496+(_0x254067(0x5ca)+_0x577b89(0x4ab)+_0x254067(0x656)+_0x254067(0x5b1)+_0x254067(0x424)+'nes.'),{'parse_mode':'Markdown'});return;}setTelegramWorkspace(_0x3e8ed4,_0x2f4496),await _0x472379['reply'](_0x254067(0x23b)+'\x20to\x20worksp'+_0x577b89(0x5fb)+(_0x1bfa6e[_0x254067(0x6fd)]??'🧭')+'\x20'+_0x1bfa6e[_0x254067(0x712)]+_0x254067(0x354)+(_0x1bfa6e['purpose']||'(no\x20purpos'+_0x577b89(0x73a))+(_0x254067(0x782)+_0x577b89(0x796)+_0x577b89(0x3dc)+'workspace\x27'+_0x577b89(0x61b)+_0x254067(0x59b))+_0x1bfa6e[_0x254067(0x73b)]+'`).',{'parse_mode':_0x254067(0x501)});}),_0x7c81f2[_0x5f3d1c(0x592)+_0x28d038(0x1ce)](/^effort:(.+)$/,async _0x37e37b=>{const _0x4b6f22=_0x5f3d1c,_0x2c7c0b=_0x5f3d1c,_0x5c6dd4=_0x37e37b[_0x4b6f22(0x395)][-0x1955+-0x3*-0x6cf+0x4e9];if(!['low',_0x4b6f22(0x71b),'high',_0x2c7c0b(0x323)][_0x2c7c0b(0x3ee)](_0x5c6dd4)){await _0x37e37b[_0x4b6f22(0x6df)+'backQuery'](_0x2c7c0b(0x43c)+_0x2c7c0b(0x36f));return;}const _0x3cff98=_0x37e37b[_0x2c7c0b(0x3e5)]['id'],_0x4fa693=getSession(_0x3cff98);_0x4fa693[_0x4b6f22(0x22f)]=_0x5c6dd4,markSessionDirty(_0x3cff98);const _0xc0e660=new InlineKeyboard();for(const [_0x23f5cb,_0x3af34b]of Object['entries'](EFFORT_LABELS)){const _0x9b7138=_0x23f5cb===_0x4fa693[_0x4b6f22(0x22f)]?'✅\x20':'';_0xc0e660[_0x2c7c0b(0x578)](''+_0x9b7138+_0x3af34b,'effort:'+_0x23f5cb)['row']();}await _0x37e37b['editMessag'+_0x4b6f22(0x5d3)](_0x2c7c0b(0x3da)+_0x2c7c0b(0x1ed)+_0x4b6f22(0x789)+_0x2c7c0b(0x774)+EFFORT_LABELS[_0x4fa693[_0x4b6f22(0x22f)]]+'*',{'parse_mode':'Markdown','reply_markup':_0xc0e660}),await _0x37e37b['answerCall'+_0x2c7c0b(0x5d1)](_0x4b6f22(0x465)+EFFORT_LABELS[_0x4fa693[_0x2c7c0b(0x22f)]]);});async function _0xcfd159(_0x3d7898,_0x32fca9){const _0x2f3176=_0x5f3d1c,_0x54cb5d=_0x28d038,_0x3bdcd5=getRegistry(),_0x4a47db=_0x3bdcd5[_0x2f3176(0x203)+'ey']();if(_0x4a47db===_0x3d7898)return{'ok':!![]};const _0x260b41=_0x3bdcd5['get'](_0x3d7898);if(!_0x260b41)return{'ok':![],'error':_0x2f3176(0x630)+_0x3d7898+(_0x2f3176(0x1f4)+'d')};const _0x344527=_0x3bdcd5['get'](_0x4a47db);if(_0x260b41['lifecycle']){const _0x525ff5=await _0x260b41[_0x2f3176(0x4f8)][_0x2f3176(0x40a)+_0x2f3176(0x6ef)]();if(!_0x525ff5)return{'ok':![],'error':t(_0x54cb5d(0x34c)+'bootFailed',_0x32fca9,{'key':_0x3d7898})};}if(!_0x3bdcd5[_0x2f3176(0x259)](_0x3d7898))return{'ok':![],'error':_0x2f3176(0x46d)+_0x54cb5d(0x61d)+'egistry'};try{writeEnvVar(_0x54cb5d(0x4f7)+_0x54cb5d(0x63f),_0x3d7898);}catch(_0x59cf05){console[_0x54cb5d(0x222)](_0x2f3176(0x6e5)+_0x54cb5d(0x79a)+_0x54cb5d(0x4f7)+_0x54cb5d(0x68f),_0x59cf05);}return _0x344527?.['lifecycle']&&await _0x344527[_0x2f3176(0x4f8)][_0x54cb5d(0x4a1)+_0x54cb5d(0x699)](),{'ok':!![]};}_0x7c81f2[_0x5f3d1c(0x4c8)]('model',async _0x3018a2=>{const _0xf0dbd0=_0x5f3d1c,_0x286108=_0x28d038,_0xbe5eba=getSession(_0x3018a2[_0xf0dbd0(0x3e5)]['id'])['language'],_0x1e73c1=_0x3018a2[_0x286108(0x395)]?.[_0x286108(0x43d)]()[_0xf0dbd0(0x2d5)+'e'](),_0x440670=getRegistry();if(!_0x1e73c1){const _0x4a1e7b=await _0x440670[_0xf0dbd0(0x5a5)](),_0x581b3b=new InlineKeyboard();for(const _0x4cf521 of _0x4a1e7b){const _0x2a5018=_0x4cf521[_0xf0dbd0(0x639)]?'✅\x20'+_0x4cf521[_0x286108(0x712)]:_0x4cf521['name'];_0x581b3b[_0x286108(0x578)](_0x2a5018,_0xf0dbd0(0x651)+_0x4cf521[_0xf0dbd0(0x6d2)])['row']();}await _0x3018a2[_0xf0dbd0(0x358)](t(_0xf0dbd0(0x34c)+_0xf0dbd0(0x345)+'er',_0xbe5eba)+'\x0a\x0a'+t(_0xf0dbd0(0x34c)+_0x286108(0x639),_0xbe5eba)+'\x20*'+_0x440670[_0x286108(0x1ef)]()[_0x286108(0x449)]()[_0xf0dbd0(0x712)]+'*',{'parse_mode':_0x286108(0x501),'reply_markup':_0x581b3b});return;}const _0x1362d5=await _0xcfd159(_0x1e73c1,_0xbe5eba);if(_0x1362d5['ok']){const _0x6514c6=_0x440670[_0x286108(0x2ba)](_0x1e73c1)[_0x286108(0x449)]();await _0x3018a2[_0x286108(0x358)](t(_0xf0dbd0(0x34c)+_0x286108(0x590),_0xbe5eba)+'\x20'+_0x6514c6['name']+'\x20('+_0x6514c6[_0x286108(0x341)]+')');}else await _0x3018a2[_0xf0dbd0(0x358)](t(_0x286108(0x34c)+_0x286108(0x3a1)+'ed',_0xbe5eba)+'\x20'+(_0x1362d5[_0x286108(0x713)]||'\x22'+_0x1e73c1+'\x22')+'\x0a'+t('bot.model.'+'notFoundHi'+'nt',_0xbe5eba));}),_0x7c81f2['callbackQu'+_0x5f3d1c(0x1ce)](/^model:(.+)$/,async _0x37ee13=>{const _0x264897=_0x28d038,_0x4ee3d8=_0x5f3d1c,_0x4aec20=_0x37ee13[_0x264897(0x395)][-0x1*0x1101+0xab+-0x1057*-0x1],_0xbe1800=getRegistry(),_0x2a0fad=getSession(_0x37ee13[_0x264897(0x3e5)]['id'])['language'],_0x146f48=await _0xcfd159(_0x4aec20,_0x2a0fad);if(_0x146f48['ok']){const _0x2a3a97=_0xbe1800[_0x4ee3d8(0x2ba)](_0x4aec20),_0x143e45=_0x2a3a97[_0x4ee3d8(0x449)](),_0x40e95a=await _0xbe1800[_0x4ee3d8(0x5a5)](),_0x30ba50=new InlineKeyboard();for(const _0xfb8c3e of _0x40e95a){const _0x3eb58f=_0xfb8c3e[_0x264897(0x639)]?'✅\x20'+_0xfb8c3e['name']:_0xfb8c3e[_0x4ee3d8(0x712)];_0x30ba50[_0x4ee3d8(0x578)](_0x3eb58f,_0x264897(0x651)+_0xfb8c3e['key'])[_0x264897(0x208)]();}await _0x37ee13[_0x4ee3d8(0x5aa)+_0x264897(0x5d3)](_0x4ee3d8(0x72b)+_0x264897(0x20a)+_0x4ee3d8(0x774)+_0x143e45[_0x264897(0x712)]+'*',{'parse_mode':_0x4ee3d8(0x501),'reply_markup':_0x30ba50}),await _0x37ee13[_0x4ee3d8(0x6df)+_0x4ee3d8(0x5d1)](_0x264897(0x46c)+_0x143e45[_0x264897(0x712)]);}else await _0x37ee13['answerCall'+_0x264897(0x5d1)](_0x4ee3d8(0x51a)+_0x4ee3d8(0x289)+(_0x146f48[_0x4ee3d8(0x713)]||_0x264897(0x743)));}),_0x7c81f2[_0x28d038(0x4c8)]('fallback',async _0xce9dd=>{const _0x2d269e=_0x5f3d1c,_0x3a909a=_0x28d038,{getFallbackOrder:_0x4b7e6a,setFallbackOrder:_0x57ff84,formatOrder:_0x44eb0d}=await import('../service'+_0x2d269e(0x732)+_0x2d269e(0x585)),{getHealthStatus:_0x26f45a}=await import('../service'+_0x2d269e(0x293)+_0x2d269e(0x2cb)),_0x7bc878=getRegistry(),_0x18ac44=_0xce9dd[_0x3a909a(0x395)]?.[_0x3a909a(0x43d)]();if(!_0x18ac44){const _0x46cceb=_0x4b7e6a(),_0x2ca883=_0x26f45a(),_0x1cba8c=new Map(_0x2ca883[_0x2d269e(0x6aa)](_0x1a5d87=>[_0x1a5d87[_0x3a909a(0x6d2)],_0x1a5d87])),_0x24a2e0=[_0x46cceb['primary'],..._0x46cceb[_0x3a909a(0x6b5)]],_0x59dc70=new InlineKeyboard();for(let _0x2c84c3=-0x4*-0x1df+0x2e9+0x377*-0x3;_0x2c84c3<_0x24a2e0['length'];_0x2c84c3++){const _0x373fea=_0x24a2e0[_0x2c84c3],_0x42c7d3=_0x1cba8c[_0x3a909a(0x2ba)](_0x373fea),_0x4f9b44=_0x42c7d3?_0x42c7d3[_0x2d269e(0x4b8)]?'✅':'❌':'❓',_0x47047d=_0x2c84c3===0x2*0x64d+0x313+-0xfad?_0x3a909a(0x22a)+_0x373fea+'\x20'+_0x4f9b44:_0x2c84c3+(-0x150a+-0x10a6+0x25b1)+'.\x20'+_0x373fea+'\x20'+_0x4f9b44;if(_0x2c84c3>0x1127*-0x1+0x187d*0x1+-0x756)_0x59dc70[_0x2d269e(0x578)]('⬆️',_0x2d269e(0x1c7)+_0x373fea);_0x59dc70['text'](_0x47047d,_0x2d269e(0x49b)+_0x373fea);if(_0x2c84c3<_0x24a2e0[_0x2d269e(0x77d)]-(-0x26e3+-0x2*0x2a+-0x7d8*-0x5))_0x59dc70[_0x3a909a(0x578)]('⬇️','fb:down:'+_0x373fea);_0x59dc70[_0x3a909a(0x208)]();}const _0x151832=_0x3a909a(0x5d8)+_0x2d269e(0x394)+(_0x3a909a(0x399)+'are\x20tried\x20'+'in\x20this\x20or'+'der.\x0a')+(_0x2d269e(0x5f9)+'\x20reorder.\x0a'+'\x0a')+(_0x3a909a(0x6a3)+_0x3a909a(0x3b5)+_0x46cceb[_0x3a909a(0x444)]+'\x20('+new Date(_0x46cceb['updatedAt'])[_0x3a909a(0x204)+_0x3a909a(0x529)](_0x2d269e(0x798))+')_');await _0xce9dd[_0x2d269e(0x358)](_0x151832,{'parse_mode':_0x2d269e(0x501),'reply_markup':_0x59dc70});return;}if(_0x18ac44[_0x2d269e(0x245)](_0x2d269e(0x2c7))){const _0x54b369=_0x18ac44[_0x2d269e(0x450)](-0x83a+0x91*-0x1d+0x1*0x18ab)[_0x3a909a(0x25c)](',')[_0x2d269e(0x6aa)](_0x104f8d=>_0x104f8d[_0x3a909a(0x43d)]())[_0x2d269e(0x5c8)](Boolean);if(_0x54b369['length']<-0x1d*-0xf1+-0x1181*0x1+-0x1*0x9cb){await _0xce9dd['reply']('Usage:\x20`/f'+_0x3a909a(0x49d)+_0x2d269e(0x631)+_0x3a909a(0x3af)+_0x3a909a(0x39b)+_0x2d269e(0x1f5),{'parse_mode':_0x2d269e(0x501)});return;}const [_0x202a3a,..._0x9b105a]=_0x54b369;_0x57ff84(_0x202a3a,_0x9b105a,'telegram'),await _0xce9dd[_0x3a909a(0x358)](_0x3a909a(0x288)+_0x3a909a(0x3d0)+_0x44eb0d());return;}await _0xce9dd[_0x2d269e(0x358)](_0x2d269e(0x5d8)+_0x3a909a(0x394)+('`/fallback'+'`\x20—\x20Show\x20&'+'\x20change\x20or'+_0x3a909a(0x527))+(_0x2d269e(0x3fb)+'\x20set\x20groq,'+_0x2d269e(0x32e)+_0x3a909a(0x5ae)+_0x3a909a(0x441)),{'parse_mode':_0x2d269e(0x501)});}),_0x7c81f2[_0x5f3d1c(0x592)+_0x5f3d1c(0x1ce)](/^fb:up:(.+)$/,async _0x2e95a7=>{const _0x2c9a66=_0x28d038,_0x48439b=_0x28d038,{moveUp:_0x52049c,formatOrder:_0x1060ba,getFallbackOrder:_0x2709e6}=await import(_0x2c9a66(0x264)+_0x2c9a66(0x732)+_0x2c9a66(0x585)),{getHealthStatus:_0x49a57a}=await import(_0x48439b(0x264)+_0x2c9a66(0x293)+_0x48439b(0x2cb)),_0x5e62b7=_0x2e95a7['match'][-0x2459+0x4*-0x835+0x452e];_0x52049c(_0x5e62b7,'telegram');const _0x20b38e=_0x2709e6(),_0x21df39=_0x49a57a(),_0x18f9db=new Map(_0x21df39[_0x2c9a66(0x6aa)](_0x1ca590=>[_0x1ca590['key'],_0x1ca590])),_0x3584cc=[_0x20b38e['primary'],..._0x20b38e[_0x2c9a66(0x6b5)]],_0x4def7f=new InlineKeyboard();for(let _0x3f8eb2=0x1*0x10ed+-0x54d*-0x5+0x3*-0xe7a;_0x3f8eb2<_0x3584cc[_0x2c9a66(0x77d)];_0x3f8eb2++){const _0x13c6fa=_0x3584cc[_0x3f8eb2],_0x3229c3=_0x18f9db[_0x2c9a66(0x2ba)](_0x13c6fa),_0x25e3e1=_0x3229c3?_0x3229c3[_0x48439b(0x4b8)]?'✅':'❌':'❓',_0x1310f0=_0x3f8eb2===-0xd4*0xd+-0xe31+0x1*0x18f5?_0x2c9a66(0x22a)+_0x13c6fa+'\x20'+_0x25e3e1:_0x3f8eb2+(0xec6+-0x1*0xedb+-0x1*-0x16)+'.\x20'+_0x13c6fa+'\x20'+_0x25e3e1;if(_0x3f8eb2>-0x5d*0x11+-0x1*-0x23ba+0x1d8d*-0x1)_0x4def7f[_0x2c9a66(0x578)]('⬆️',_0x2c9a66(0x1c7)+_0x13c6fa);_0x4def7f[_0x2c9a66(0x578)](_0x1310f0,_0x48439b(0x49b)+_0x13c6fa);if(_0x3f8eb2<_0x3584cc[_0x2c9a66(0x77d)]-(-0x159c+0x1e*0xb5+0x1*0x67))_0x4def7f[_0x2c9a66(0x578)]('⬇️','fb:down:'+_0x13c6fa);_0x4def7f['row']();}await _0x2e95a7['editMessag'+'eText'](_0x48439b(0x5d8)+_0x2c9a66(0x394)+(_0x48439b(0x24d)+_0x48439b(0x744)+_0x48439b(0x33a)+'enfolge\x20ve'+_0x2c9a66(0x5cc))+(_0x48439b(0x69a)+_0x48439b(0x68d)+'ieren.\x0a\x0a')+(_0x48439b(0x6a3)+_0x2c9a66(0x7ab)+_0x2c9a66(0x37b)+new Date()[_0x2c9a66(0x204)+_0x48439b(0x529)]('en-US')+')_'),{'parse_mode':_0x2c9a66(0x501),'reply_markup':_0x4def7f}),await _0x2e95a7[_0x48439b(0x6df)+_0x2c9a66(0x5d1)](_0x5e62b7+_0x48439b(0x2b4));}),_0x7c81f2[_0x5f3d1c(0x592)+'ery'](/^fb:down:(.+)$/,async _0x2047f9=>{const _0x28b5fd=_0x5f3d1c,_0x111001=_0x5f3d1c,{moveDown:_0x1cb27c,getFallbackOrder:_0x5f654b}=await import('../service'+_0x28b5fd(0x732)+_0x28b5fd(0x585)),{getHealthStatus:_0x49c07b}=await import(_0x28b5fd(0x264)+_0x111001(0x293)+'t.js'),_0x59608d=_0x2047f9[_0x28b5fd(0x395)][-0x13f1+0x604+-0xdee*-0x1];_0x1cb27c(_0x59608d,_0x28b5fd(0x3f7));const _0x227c6d=_0x5f654b(),_0x1fd356=_0x49c07b(),_0x16dc7b=new Map(_0x1fd356[_0x28b5fd(0x6aa)](_0x3325d5=>[_0x3325d5[_0x111001(0x6d2)],_0x3325d5])),_0x5bf664=[_0x227c6d[_0x28b5fd(0x2e2)],..._0x227c6d[_0x111001(0x6b5)]],_0x2f99e8=new InlineKeyboard();for(let _0x24a3fc=0xb15*-0x3+0xba4+0x159b*0x1;_0x24a3fc<_0x5bf664[_0x28b5fd(0x77d)];_0x24a3fc++){const _0x5d8c43=_0x5bf664[_0x24a3fc],_0x2632a0=_0x16dc7b[_0x111001(0x2ba)](_0x5d8c43),_0x3862d7=_0x2632a0?_0x2632a0['healthy']?'✅':'❌':'❓',_0x51c87c=_0x24a3fc===-0x3*0x655+0x13cb*0x1+0x33*-0x4?'🥇\x20'+_0x5d8c43+'\x20'+_0x3862d7:_0x24a3fc+(-0x231a*-0x1+0x1f3*0x3+0x6*-0x6d3)+'.\x20'+_0x5d8c43+'\x20'+_0x3862d7;if(_0x24a3fc>-0xa39*0x3+0x82*-0x4a+-0x1*-0x443f)_0x2f99e8[_0x28b5fd(0x578)]('⬆️',_0x111001(0x1c7)+_0x5d8c43);_0x2f99e8[_0x28b5fd(0x578)](_0x51c87c,_0x111001(0x49b)+_0x5d8c43);if(_0x24a3fc<_0x5bf664[_0x111001(0x77d)]-(-0x1*0x1e8e+-0x1d6a+0x3bf9))_0x2f99e8[_0x28b5fd(0x578)]('⬇️',_0x111001(0x33d)+_0x5d8c43);_0x2f99e8['row']();}await _0x2047f9['editMessag'+'eText'](_0x28b5fd(0x5d8)+_0x111001(0x394)+(_0x111001(0x24d)+'erden\x20in\x20d'+_0x111001(0x33a)+'enfolge\x20ve'+_0x111001(0x5cc))+(_0x111001(0x69a)+_0x28b5fd(0x68d)+_0x28b5fd(0x53d))+(_0x111001(0x6a3)+_0x28b5fd(0x7ab)+_0x28b5fd(0x37b)+new Date()[_0x28b5fd(0x204)+_0x28b5fd(0x529)]('en-US')+')_'),{'parse_mode':_0x28b5fd(0x501),'reply_markup':_0x2f99e8}),await _0x2047f9['answerCall'+_0x111001(0x5d1)](_0x59608d+(_0x28b5fd(0x459)+'n'));}),_0x7c81f2[_0x28d038(0x592)+_0x28d038(0x1ce)](/^fb:info:(.+)$/,async _0x10cf9b=>{const _0x49d440=_0x5f3d1c,_0x23dab0=_0x5f3d1c,{getHealthStatus:_0x5a8b2a}=await import(_0x49d440(0x264)+_0x23dab0(0x293)+_0x49d440(0x2cb)),_0x529799=_0x10cf9b[_0x23dab0(0x395)][0x1*-0x259+-0x21a1*-0x1+-0x1f47],_0x4b1833=_0x5a8b2a(),_0xfc247d=_0x4b1833[_0x49d440(0x484)](_0x2bf2e3=>_0x2bf2e3[_0x23dab0(0x6d2)]===_0x529799);_0xfc247d?await _0x10cf9b['answerCall'+_0x49d440(0x5d1)]({'text':_0x529799+':\x20'+(_0xfc247d[_0x49d440(0x4b8)]?_0x23dab0(0x24e):_0x23dab0(0x32a)+'y')+_0x23dab0(0x322)+_0xfc247d[_0x49d440(0x2d0)]+(_0x49d440(0x635)+'s:\x20')+_0xfc247d['failCount'],'show_alert':!![]}):await _0x10cf9b[_0x49d440(0x6df)+_0x49d440(0x5d1)](_0x529799+(':\x20Not\x20chec'+'ked\x20yet'));}),_0x7c81f2['command'](_0x28d038(0x2bb),async _0x4c05bc=>{const _0x5c3e2b=_0x28d038,_0x3d8fc2=_0x5f3d1c,_0x5309f5=_0x4c05bc[_0x5c3e2b(0x395)]?.[_0x3d8fc2(0x43d)]();if(!_0x5309f5){await _0x4c05bc[_0x5c3e2b(0x358)](_0x3d8fc2(0x4f6)+_0x3d8fc2(0x572)+_0x3d8fc2(0x52e)+'y`',{'parse_mode':_0x5c3e2b(0x501)});return;}await _0x4c05bc[_0x3d8fc2(0x6bb)]['sendChatAc'+_0x3d8fc2(0x2e0)](_0x4c05bc[_0x3d8fc2(0x5a1)]['id'],_0x3d8fc2(0x596));try{const _0x4ad731=encodeURIComponent(_0x5309f5),_0x12e1c0=await fetch(_0x5c3e2b(0x673)+_0x5c3e2b(0x431)+_0x3d8fc2(0x5fe)+_0x4ad731+(_0x3d8fc2(0x2c0)+_0x3d8fc2(0x58b)+'=1&skip_di'+_0x3d8fc2(0x648))),_0x1c9897=await _0x12e1c0[_0x3d8fc2(0x325)](),_0x4df914=[];_0x1c9897[_0x5c3e2b(0x25a)]&&_0x4df914[_0x5c3e2b(0x664)](_0x3d8fc2(0x618)+_0x1c9897['Answer']+'*\x0a');if(_0x1c9897['AbstractTe'+'xt']){const _0x5311e9=_0x1c9897['AbstractTe'+'xt'][_0x3d8fc2(0x77d)]>0x1*-0x234a+0x1*-0x9eb+0x2f29?_0x1c9897[_0x3d8fc2(0x70e)+'xt'][_0x3d8fc2(0x450)](0xca*-0x21+0x17f*0x12+-0xe4,0x73e+0x1160+0x78e*-0x3)+_0x5c3e2b(0x53a):_0x1c9897[_0x3d8fc2(0x70e)+'xt'];_0x4df914['push'](_0x5311e9),_0x1c9897[_0x5c3e2b(0x3d8)+_0x5c3e2b(0x3f5)]&&_0x1c9897[_0x3d8fc2(0x218)+'L']&&_0x4df914[_0x3d8fc2(0x664)](_0x5c3e2b(0x21d)+'['+_0x1c9897['AbstractSo'+_0x3d8fc2(0x3f5)]+']('+_0x1c9897[_0x5c3e2b(0x218)+'L']+')_');}if(_0x4df914['length']===-0x1220+0x172f*0x1+-0x50f&&_0x1c9897[_0x5c3e2b(0x215)+_0x3d8fc2(0x62b)]&&_0x1c9897['RelatedTop'+'ics'][_0x3d8fc2(0x77d)]>-0x3*0x75c+0x4c7+-0x67*-0x2b){_0x4df914[_0x5c3e2b(0x664)](_0x5c3e2b(0x3db)+_0x3d8fc2(0x69b)+_0x5309f5+_0x5c3e2b(0x231));for(const _0x4ce1a5 of _0x1c9897[_0x3d8fc2(0x215)+_0x3d8fc2(0x62b)][_0x3d8fc2(0x450)](0x40f*-0x2+0x6*-0x553+0x2810,0x1388*0x1+-0x6f3*-0x1+-0x1a76)){if(_0x4ce1a5['Text']){const _0x312c42=_0x4ce1a5[_0x5c3e2b(0x3b8)]['length']>0x1704+-0x222+-0x6c4*0x3?_0x4ce1a5['Text']['slice'](0x2562+-0x1*0x106a+-0x7a*0x2c,-0xc*0x19a+0x1939+-0x56b)+_0x3d8fc2(0x53a):_0x4ce1a5['Text'];_0x4df914[_0x3d8fc2(0x664)]('•\x20'+_0x312c42);}}}_0x4df914[_0x3d8fc2(0x77d)]===-0x3*0x5c6+-0x14c5+0x2617&&_0x4df914['push'](_0x3d8fc2(0x3c6)+_0x3d8fc2(0x69b)+_0x5309f5+(_0x5c3e2b(0x703)+_0x3d8fc2(0x526)+_0x5c3e2b(0x2e4)+_0x5c3e2b(0x5af)+_0x3d8fc2(0x6e6)+_0x3d8fc2(0x2a5)+_0x3d8fc2(0x4e2))),await _0x4c05bc[_0x5c3e2b(0x358)](_0x4df914['join']('\x0a'),{'parse_mode':_0x5c3e2b(0x501)})[_0x5c3e2b(0x442)](()=>_0x4c05bc[_0x3d8fc2(0x358)](_0x4df914[_0x3d8fc2(0x1d7)]('\x0a')));}catch(_0x4c71ed){await _0x4c05bc[_0x5c3e2b(0x358)](_0x5c3e2b(0x542)+_0x5c3e2b(0x705)+(_0x4c71ed instanceof Error?_0x4c71ed[_0x3d8fc2(0x261)]:String(_0x4c71ed)));}}),_0x7c81f2['command'](_0x5f3d1c(0x386),async _0x2ada46=>{const _0x7dabc0=_0x5f3d1c,_0x13127a=_0x5f3d1c,_0x5216e1=_0x2ada46[_0x7dabc0(0x395)]?.['trim']();if(!_0x5216e1){await _0x2ada46[_0x7dabc0(0x358)]('Describe\x20w'+_0x13127a(0x698)+_0x13127a(0x2f6)+_0x7dabc0(0x456)+_0x7dabc0(0x350)+_0x13127a(0x4d3)+_0x13127a(0x4fa),{'parse_mode':'Markdown'});return;}if(!config[_0x13127a(0x479)][_0x7dabc0(0x687)]){await _0x2ada46['reply'](_0x7dabc0(0x295)+_0x7dabc0(0x372)+_0x7dabc0(0x72a)+'\x20(GOOGLE_A'+'PI_KEY\x20mis'+_0x7dabc0(0x2d3));return;}await _0x2ada46[_0x7dabc0(0x6bb)][_0x13127a(0x1c5)+_0x13127a(0x2e0)](_0x2ada46[_0x13127a(0x5a1)]['id'],_0x13127a(0x237)+'to');const _0x41cbc3=await generateImage(_0x5216e1,config[_0x7dabc0(0x479)][_0x13127a(0x687)]);if(_0x41cbc3[_0x13127a(0x5a9)]&&_0x41cbc3[_0x7dabc0(0x417)])try{const _0x203b86=_0x477de6[_0x13127a(0x429)+'nc'](_0x41cbc3[_0x13127a(0x417)]);await _0x2ada46[_0x7dabc0(0x55a)+'hoto'](new InputFile(_0x203b86,_0x7dabc0(0x1b7)+(_0x41cbc3[_0x7dabc0(0x417)]['endsWith'](_0x7dabc0(0x5ee))?_0x13127a(0x5ee):_0x13127a(0x514))),{'caption':'🎨\x20_'+_0x5216e1+'_','parse_mode':'Markdown'}),_0x477de6[_0x7dabc0(0x4cb)](_0x41cbc3[_0x7dabc0(0x417)],()=>{});}catch(_0x96318c){await _0x2ada46[_0x7dabc0(0x358)](_0x7dabc0(0x43e)+_0x13127a(0x680)+(_0x96318c instanceof Error?_0x96318c['message']:String(_0x96318c)));}else await _0x2ada46[_0x13127a(0x358)]('❌\x20'+(_0x41cbc3[_0x13127a(0x713)]||_0x7dabc0(0x4f2)+_0x13127a(0x455)+_0x13127a(0x5fa)));}),_0x7c81f2[_0x5f3d1c(0x4c8)]('remind',async _0x5a2c45=>{const _0x58ae16=_0x5f3d1c,_0x12d3a6=_0x5f3d1c,_0x358d08=_0x5a2c45['from']['id'],_0x546316=_0x5a2c45[_0x58ae16(0x5a1)]['id'],_0x1bdbef=_0x5a2c45[_0x58ae16(0x395)]?.[_0x12d3a6(0x43d)]();if(!_0x1bdbef){const _0x275c9a=listReminders(_0x358d08);if(_0x275c9a['length']===-0x34b+-0x74b+0xa96)await _0x5a2c45[_0x58ae16(0x358)]('No\x20active\x20'+_0x12d3a6(0x707)+_0x58ae16(0x795)+_0x12d3a6(0x614)+'Call\x20mom`',{'parse_mode':_0x12d3a6(0x501)});else{const _0x2ac3cc=_0x275c9a['map'](_0x8e0d43=>_0x58ae16(0x6ad)+_0x8e0d43['remaining']+_0x12d3a6(0x56e)+_0x8e0d43[_0x12d3a6(0x578)]+'\x20(ID:\x20'+_0x8e0d43['id']+')');await _0x5a2c45[_0x12d3a6(0x358)](_0x12d3a6(0x63b)+_0x58ae16(0x3c0)+_0x12d3a6(0x3b6)+_0x2ac3cc[_0x58ae16(0x1d7)]('\x0a')+('\x0a\x0aCancel:\x20'+'`/remind\x20c'+_0x58ae16(0x3ff)+'`'),{'parse_mode':'Markdown'});}return;}if(_0x1bdbef[_0x58ae16(0x245)](_0x58ae16(0x3a8))){const _0x1ffa16=parseInt(_0x1bdbef[_0x58ae16(0x450)](-0x11b3+-0x1c0d+0x2dc7)['trim']());if(isNaN(_0x1ffa16)){await _0x5a2c45['reply']('Invalid\x20ID'+_0x12d3a6(0x645)+_0x12d3a6(0x50d)+'el\x20<ID>`',{'parse_mode':_0x12d3a6(0x501)});return;}cancelReminder(_0x1ffa16,_0x358d08)?await _0x5a2c45[_0x58ae16(0x358)](_0x12d3a6(0x2e6)+'\x20#'+_0x1ffa16+('\x20cancelled'+'.')):await _0x5a2c45[_0x12d3a6(0x358)](_0x58ae16(0x5f4)+'\x20#'+_0x1ffa16+(_0x12d3a6(0x548)+'.'));return;}const _0x3b3bd6=_0x1bdbef[_0x58ae16(0x2d1)]('\x20');if(_0x3b3bd6===-(0x7*0x1ce+-0x1037*-0x1+-0x1cd8)){await _0x5a2c45[_0x12d3a6(0x358)](_0x58ae16(0x505)+_0x58ae16(0x447)+_0x58ae16(0x228)+_0x58ae16(0x588),{'parse_mode':_0x58ae16(0x501)});return;}const _0x19b5a3=_0x1bdbef[_0x12d3a6(0x450)](-0x1*0x1b1+0x1196+-0x1*0xfe5,_0x3b3bd6),_0x28a7a0=_0x1bdbef[_0x12d3a6(0x450)](_0x3b3bd6+(0x796+-0x1933+0x119e))[_0x12d3a6(0x43d)](),_0x31d953=parseDuration(_0x19b5a3);if(!_0x31d953){await _0x5a2c45[_0x58ae16(0x358)](_0x12d3a6(0x1fa)+'ration.\x20Ex'+_0x12d3a6(0x1b6)+_0x12d3a6(0x626)+'\x20`2h`,\x20`1d'+'`',{'parse_mode':_0x12d3a6(0x501)});return;}if(!_0x28a7a0){await _0x5a2c45[_0x12d3a6(0x358)](_0x12d3a6(0x335)+_0x58ae16(0x682)+_0x58ae16(0x22e)+_0x58ae16(0x4b5)+_0x12d3a6(0x6ae),{'parse_mode':_0x12d3a6(0x501)});return;}const _0x10ae39=createReminder(_0x546316,_0x358d08,_0x28a7a0,_0x31d953,_0x5a2c45[_0x58ae16(0x6bb)]),_0x9f72da=new Date(_0x10ae39[_0x58ae16(0x44e)]),_0x231576=_0x9f72da[_0x12d3a6(0x1e4)+_0x58ae16(0x5f1)](_0x12d3a6(0x798),{'hour':'2-digit','minute':_0x12d3a6(0x3b2)});await _0x5a2c45['reply'](_0x12d3a6(0x2e6)+_0x12d3a6(0x224)+_0x231576+_0x12d3a6(0x469)+_0x28a7a0,{'parse_mode':_0x12d3a6(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x5a3),async _0x2639b4=>{const _0xa6215b=_0x5f3d1c,_0x246476=_0x5f3d1c,_0x4af47f=_0x2639b4[_0xa6215b(0x3e5)]['id'],_0x59b9f2=getSession(_0x4af47f);if(_0x59b9f2[_0x246476(0x27c)][_0xa6215b(0x77d)]===0xb*-0x70+0xde1+-0xb*0xd3&&!_0x59b9f2[_0xa6215b(0x27f)]){await _0x2639b4['reply'](_0xa6215b(0x709)+'ation\x20data'+_0xa6215b(0x3d4)+'.');return;}const _0x131206=[_0xa6215b(0x368)+'t\x20—\x20Conver'+_0xa6215b(0x79d)+_0xa6215b(0x41d),_0x246476(0x3ab)+new Date()[_0xa6215b(0x204)+_0xa6215b(0x529)](_0x246476(0x798)),_0x246476(0x206)+_0x59b9f2[_0xa6215b(0x652)+'nt'],_0xa6215b(0x554)+_0x59b9f2[_0x246476(0x539)]['toFixed'](-0x1*0x21fb+-0x2469+0x4668),_0xa6215b(0x2bd)];for(const _0x49f884 of _0x59b9f2[_0x246476(0x27c)]){const _0x507090=_0x49f884['role']==='user'?_0xa6215b(0x240):_0x246476(0x6ba)+'t';_0x131206['push'](_0xa6215b(0x60d)+_0x507090+'\x0a'+_0x49f884[_0xa6215b(0x25f)]+'\x0a');}_0x59b9f2[_0x246476(0x27c)]['length']===-0x6f1+-0xb*0x2ab+0x244a&&_0x131206['push'](_0x246476(0x74e)+'on\x20—\x20histo'+'ry\x20managed'+_0xa6215b(0x543)+'y,\x20no\x20expo'+_0xa6215b(0x327)+_0xa6215b(0x571));const _0x2dc30b=_0x131206[_0x246476(0x1d7)]('\x0a'),_0x3aeac5=Buffer[_0xa6215b(0x3e5)](_0x2dc30b,_0x246476(0x550)),_0x1e9fdf='chat-expor'+'t-'+new Date()[_0x246476(0x2d6)+'g']()[_0xa6215b(0x450)](0x249f*0x1+0xf76+-0x3415,0xdfb+0x1c5d+0x2a4e*-0x1)+'.md';await _0x2639b4['replyWithD'+_0xa6215b(0x346)](new InputFile(_0x3aeac5,_0x1e9fdf),{'caption':'📄\x20Export:\x20'+_0x59b9f2[_0xa6215b(0x27c)][_0x246476(0x77d)]+_0xa6215b(0x388)});});function _0x230974(_0x204a27){const _0xa0ac6=_0x28d038,_0x5cf756=_0x28d038,_0xba06d8=new InlineKeyboard(),_0x5cee42=['en','de','es','fr'];return _0xba06d8[_0xa0ac6(0x578)](''+(_0x204a27==='en'?'✅\x20':'')+LOCALE_FLAGS['en']+'\x20'+LOCALE_NAMES['en'],'lang:en')[_0xa0ac6(0x578)](''+(_0x204a27==='de'?'✅\x20':'')+LOCALE_FLAGS['de']+'\x20'+LOCALE_NAMES['de'],_0x5cf756(0x2f1))[_0xa0ac6(0x208)](),_0xba06d8[_0xa0ac6(0x578)](''+(_0x204a27==='es'?'✅\x20':'')+LOCALE_FLAGS['es']+'\x20'+LOCALE_NAMES['es'],_0x5cf756(0x51f))[_0x5cf756(0x578)](''+(_0x204a27==='fr'?'✅\x20':'')+LOCALE_FLAGS['fr']+'\x20'+LOCALE_NAMES['fr'],'lang:fr')[_0xa0ac6(0x208)](),void _0x5cee42,_0xba06d8[_0x5cf756(0x578)](t('bot.lang.a'+_0xa0ac6(0x299),_0x204a27),_0xa0ac6(0x518)),_0xba06d8;}_0x7c81f2[_0x5f3d1c(0x4c8)]('lang',async _0x5adb1f=>{const _0x2eb24b=_0x5f3d1c,_0x43932f=_0x28d038,_0xb18233=_0x5adb1f[_0x2eb24b(0x3e5)]['id'],_0x48de40=getSession(_0xb18233),_0x33a072=_0x5adb1f[_0x2eb24b(0x395)]?.[_0x43932f(0x43d)]()['toLowerCas'+'e']();if(!_0x33a072){const _0x15ac64=t(_0x43932f(0x5d9)+_0x43932f(0x39d),_0x48de40[_0x2eb24b(0x1ca)]),_0x562e1d=LOCALE_FLAGS[_0x48de40[_0x2eb24b(0x1ca)]]+'\x20'+LOCALE_NAMES[_0x48de40[_0x43932f(0x1ca)]];await _0x5adb1f[_0x2eb24b(0x358)](_0x15ac64+'\x20'+_0x562e1d,{'parse_mode':'Markdown','reply_markup':_0x230974(_0x48de40[_0x43932f(0x1ca)])});return;}if(_0x33a072==='auto'){const {resetToAutoLanguage:_0x347126}=await import(_0x2eb24b(0x264)+_0x43932f(0x402)+_0x43932f(0x4af));_0x347126(_0xb18233),await _0x5adb1f[_0x43932f(0x358)](t(_0x43932f(0x1c0)+_0x43932f(0x46b),_0x48de40[_0x2eb24b(0x1ca)]));}else{if(_0x33a072==='en'||_0x33a072==='de'||_0x33a072==='es'||_0x33a072==='fr'){_0x48de40[_0x43932f(0x1ca)]=_0x33a072,markSessionDirty(_0xb18233);const {setExplicitLanguage:_0x46bb68}=await import(_0x43932f(0x264)+_0x2eb24b(0x402)+_0x2eb24b(0x4af));_0x46bb68(_0xb18233,_0x33a072),await _0x5adb1f['reply'](t(_0x43932f(0x6d4)+'etFixed',_0x33a072,{'name':LOCALE_NAMES[_0x33a072]}));}else await _0x5adb1f[_0x43932f(0x358)](t(_0x2eb24b(0x5f2)+_0x43932f(0x338),_0x48de40['language']),{'parse_mode':_0x43932f(0x501)});}}),_0x7c81f2[_0x5f3d1c(0x592)+_0x28d038(0x1ce)](/^lang:(en|de|es|fr|auto)$/,async _0x6d8594=>{const _0x3af422=_0x5f3d1c,_0xf3df92=_0x5f3d1c,_0x4b7cf4=_0x6d8594['match'][0x9*-0x1b+0x18cc+-0x17d8],_0x25beed=_0x6d8594[_0x3af422(0x3e5)]['id'],_0x1d6d9f=getSession(_0x25beed);if(_0x4b7cf4===_0x3af422(0x460)){const {resetToAutoLanguage:_0x99544}=await import(_0xf3df92(0x264)+_0x3af422(0x402)+'-detect.js');_0x99544(_0x25beed),await _0x6d8594[_0x3af422(0x6df)+_0x3af422(0x5d1)]({'text':t(_0xf3df92(0x1c0)+_0x3af422(0x46b),_0x1d6d9f[_0xf3df92(0x1ca)])[_0x3af422(0x450)](-0x1*0x91+-0x1*0x1979+-0x2*-0xd05,-0x2140+0x1410+0xd6c)}),await _0x6d8594[_0xf3df92(0x5aa)+_0xf3df92(0x5d3)](t(_0xf3df92(0x5d9)+_0x3af422(0x39d),_0x1d6d9f[_0xf3df92(0x1ca)])+'\x20'+t(_0x3af422(0x1c0)+_0xf3df92(0x299),_0x1d6d9f['language']),{'parse_mode':_0x3af422(0x501)});return;}const _0x36cb97=_0x4b7cf4;_0x1d6d9f['language']=_0x36cb97,markSessionDirty(_0x25beed);const {setExplicitLanguage:_0x13749b}=await import(_0xf3df92(0x264)+_0xf3df92(0x402)+_0x3af422(0x4af));_0x13749b(_0x25beed,_0x36cb97);const _0x1b5137=LOCALE_FLAGS[_0x36cb97]+'\x20'+LOCALE_NAMES[_0x36cb97];await _0x6d8594[_0x3af422(0x5aa)+'eText'](t(_0xf3df92(0x5d9)+'eader',_0x36cb97)+'\x20'+_0x1b5137,{'parse_mode':_0xf3df92(0x501),'reply_markup':_0x230974(_0x36cb97)}),await _0x6d8594[_0xf3df92(0x6df)+_0xf3df92(0x5d1)](LOCALE_NAMES[_0x36cb97]);}),_0x7c81f2['command']('memory',async _0x11ed3e=>{const _0x22fa25=_0x28d038,_0x2fe7dd=_0x28d038,_0x58830a=getMemoryStats(),_0xf877fa=_0x11ed3e[_0x22fa25(0x395)]?.['trim']();if(!_0xf877fa){await _0x11ed3e[_0x22fa25(0x358)](_0x22fa25(0x478)+'\x0a\x0a'+(_0x2fe7dd(0x4da)+_0x22fa25(0x57d)+formatBytes(_0x58830a[_0x22fa25(0x6a4)+'ze'])+'\x0a')+('*Daily\x20log'+_0x22fa25(0x275)+_0x58830a[_0x22fa25(0x6a6)]+_0x2fe7dd(0x646))+(_0x2fe7dd(0x29f)+_0x58830a[_0x22fa25(0x653)+'es']+_0x22fa25(0x353))+('_Memory\x20is'+_0x22fa25(0x312)+'ally\x20writt'+_0x2fe7dd(0x5c9)+_0x22fa25(0x4b9))+(_0x2fe7dd(0x396)+_0x22fa25(0x5e5)+_0x22fa25(0x3a0)+_0x2fe7dd(0x30e)+_0x2fe7dd(0x2fd)),{'parse_mode':_0x2fe7dd(0x501)});return;}}),_0x7c81f2['command']('system',async _0xa0ad68=>{const _0x3f3872=_0x28d038,_0x34bd6d=_0x28d038,_0x1eac58=_0x4cb0ca['totalmem'](),_0x13b458=_0x4cb0ca[_0x3f3872(0x5e9)](),_0x26ebbb=_0x1eac58-_0x13b458,_0x3ef052=Math[_0x34bd6d(0x604)](_0x26ebbb/_0x1eac58*(0xfa9+-0x1*-0xa83+0x14a*-0x14)),_0x184762=_0x4cb0ca[_0x3f3872(0x724)](),_0x3b3c66=Math[_0x3f3872(0x39a)](_0x184762/(0x3*0x8fe+0x9d6+0x7*-0x340)),_0x443376=Math[_0x3f3872(0x39a)](_0x184762%(-0x1d*0xd1+-0x1*0x221a+0x15b*0x35)/(0x20dd+-0x14b+-0x7*0x47a)),_0x409000=_0x4cb0ca[_0x3f3872(0x79b)](),_0x5e4b17=_0x4cb0ca['loadavg'](),_0x5832a1=process[_0x34bd6d(0x39c)+'e']();await _0xa0ad68['reply'](_0x34bd6d(0x26d)+_0x34bd6d(0x281)+(_0x34bd6d(0x239)+_0x4cb0ca[_0x3f3872(0x30c)]()+'\x20'+_0x4cb0ca[_0x34bd6d(0x1f3)]()+'\x20('+_0x4cb0ca[_0x34bd6d(0x4a4)]()+')\x0a')+(_0x3f3872(0x25b)+_0x4cb0ca[_0x34bd6d(0x284)]()+'\x0a')+(_0x34bd6d(0x5e1)+_0x409000[_0x3f3872(0x77d)]+'x\x20'+(_0x409000[-0x5b0+0x1*-0x210a+0x26ba]?.['model']?.[_0x3f3872(0x43d)]()||'unknown')+'\x0a')+(_0x34bd6d(0x5a7)+_0x5e4b17[_0x3f3872(0x6aa)](_0x834137=>_0x834137[_0x3f3872(0x2ed)](-0x1412+-0x254d+0x25*0x18d))[_0x3f3872(0x1d7)](',\x20')+'\x0a')+(_0x34bd6d(0x4a8)+formatBytes(_0x26ebbb)+_0x34bd6d(0x57e)+formatBytes(_0x1eac58)+'\x20('+_0x3ef052+_0x34bd6d(0x4b6))+('*System\x20Up'+_0x3f3872(0x393)+_0x3b3c66+'h\x20'+_0x443376+'m\x0a\x0a')+('🤖\x20*Bot\x20Pro'+_0x3f3872(0x334))+(_0x34bd6d(0x595)+process['version']+'\x0a')+('*Heap:*\x20'+formatBytes(_0x5832a1[_0x3f3872(0x580)])+'\x20/\x20'+formatBytes(_0x5832a1[_0x34bd6d(0x734)])+'\x0a')+(_0x34bd6d(0x333)+formatBytes(_0x5832a1['rss'])+'\x0a')+('*PID:*\x20'+process['pid']),{'parse_mode':_0x3f3872(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x64e),async _0x203858=>{const _0x1358d8=_0x28d038,_0x130b36=_0x28d038,_0x62740e=reloadSoul();await _0x203858[_0x1358d8(0x358)](_0x62740e?'✅\x20SOUL.md\x20'+_0x1358d8(0x38e):_0x1358d8(0x30d)+_0x130b36(0x272));}),_0x7c81f2[_0x28d038(0x592)+'ery'](/^access:(approve|block):(-?\d+)$/,async _0x3b1741=>{const _0x57dc47=_0x28d038,_0x561827=_0x5f3d1c,_0xeb2ff3=_0x3b1741['match'][0x1d29+-0x1f3*0x4+0x557*-0x4],_0x615c2a=parseInt(_0x3b1741[_0x57dc47(0x395)][0x2b4*-0x2+0x20b*-0x5+0xfa1*0x1]);if(_0xeb2ff3===_0x561827(0x4f4)){approveGroup(_0x615c2a),await _0x3b1741[_0x57dc47(0x5aa)+_0x57dc47(0x5d3)]('✅\x20Group\x20'+_0x615c2a+(_0x561827(0x425)+'\x20Alvin\x20Bot'+_0x561827(0x29d)+_0x57dc47(0x35f)+_0x561827(0x672)));try{await _0x3b1741[_0x57dc47(0x6bb)][_0x561827(0x273)+'e'](_0x615c2a,'👋\x20Alvin\x20Bo'+_0x561827(0x1d8)+_0x57dc47(0x60e)+_0x561827(0x6f2)+_0x561827(0x27e)+_0x561827(0x7a5)+_0x57dc47(0x655)+_0x57dc47(0x5bf));}catch{}}else blockGroup(_0x615c2a),await _0x3b1741[_0x561827(0x5aa)+_0x561827(0x5d3)]('🚫\x20Group\x20'+_0x615c2a+(_0x561827(0x3a9)+_0x57dc47(0x5e7)+_0x57dc47(0x56c)+'e\x20this\x20gro'+_0x57dc47(0x29e)));await _0x3b1741[_0x561827(0x6df)+_0x561827(0x5d1)]();}),_0x7c81f2[_0x5f3d1c(0x4c8)]('groups',async _0x384355=>{const _0x52cc08=_0x5f3d1c,_0x1903fe=_0x5f3d1c,_0x8c86ed=listGroups();if(_0x8c86ed[_0x52cc08(0x77d)]===0x779+-0x76a+-0xf){await _0x384355[_0x52cc08(0x358)](_0x52cc08(0x48e)+'registered'+'.');return;}const _0x232a6c=_0x8c86ed[_0x52cc08(0x6aa)](_0x1f45c0=>{const _0x30ef34=_0x52cc08,_0x2ab018=_0x1903fe,_0x522574=_0x1f45c0['status']===_0x30ef34(0x63e)?'✅':_0x1f45c0[_0x30ef34(0x5e8)]===_0x2ab018(0x40e)?'🚫':'⏳';return _0x522574+'\x20*'+_0x1f45c0[_0x30ef34(0x3e1)]+_0x30ef34(0x401)+_0x1f45c0[_0x2ab018(0x652)+'nt']+('\x20msgs)\x0a\x20\x20\x20'+_0x30ef34(0x4c1))+_0x1f45c0['chatId']+'`';}),_0x5ece82=new InlineKeyboard();for(const _0x501efd of _0x8c86ed){if(_0x501efd[_0x1903fe(0x5e8)]===_0x52cc08(0x63e))_0x5ece82[_0x1903fe(0x578)](_0x52cc08(0x5df)+_0x501efd[_0x52cc08(0x3e1)][_0x52cc08(0x450)](0x1162+0x1dbb+0x7*-0x6bb,0x1*-0x18c6+0xe4a+0xd*0xd0),'access:blo'+_0x1903fe(0x256)+_0x501efd['chatId'])['row']();else(_0x501efd[_0x1903fe(0x5e8)]==='blocked'||_0x501efd[_0x1903fe(0x5e8)]===_0x1903fe(0x38b))&&_0x5ece82['text'](_0x52cc08(0x6e2)+'\x20'+_0x501efd['title']['slice'](-0x3c2+0xd33*-0x1+0x10f5,-0x86+0xb*0x24+-0xf2),_0x1903fe(0x347)+_0x1903fe(0x4ed)+_0x501efd['chatId'])[_0x1903fe(0x208)]();}const _0x38f2d1=getSettings();await _0x384355[_0x52cc08(0x358)]('🔐\x20*Group\x20M'+_0x1903fe(0x559)+'\x0a\x0a'+(_0x232a6c['join']('\x0a\x0a')+'\x0a\x0a')+(_0x1903fe(0x659)+_0x1903fe(0x521))+('Forwards:\x20'+(_0x38f2d1[_0x1903fe(0x6f9)+_0x52cc08(0x75f)]?'✅':'❌')+'\x0a')+('Auto-Appro'+'ve:\x20'+(_0x38f2d1[_0x1903fe(0x601)+_0x52cc08(0x254)]?_0x52cc08(0x2cd):_0x52cc08(0x473))),{'parse_mode':_0x1903fe(0x501),'reply_markup':_0x5ece82});}),_0x7c81f2['command'](_0x28d038(0x2ef),async _0x57b649=>{const _0x42d475=_0x5f3d1c,_0x4b7557=_0x5f3d1c,_0x5c9cc1=_0x57b649['match']?.[_0x42d475(0x43d)]()[_0x4b7557(0x2d5)+'e'](),_0x57dc86=getSettings();if(!_0x5c9cc1){await _0x57b649[_0x4b7557(0x358)](_0x4b7557(0x4b4)+_0x42d475(0x5b4)+'*\x0a\x0a'+(_0x4b7557(0x253)+'*\x20'+(_0x57dc86[_0x42d475(0x6f9)+_0x42d475(0x75f)]?'✅\x20allowed':'❌\x20blocked')+'\x0a')+(_0x4b7557(0x7a7)+_0x42d475(0x766)+_0x4b7557(0x2db)+(_0x57dc86['autoApprov'+_0x4b7557(0x254)]?'⚠️\x20ON\x20(dang'+'erous!)':_0x42d475(0x473))+'\x0a')+(_0x4b7557(0x679)+_0x42d475(0x531)+_0x57dc86[_0x4b7557(0x6db)+'imitPerHou'+'r']+'/h\x0a\x0a')+'Change:\x0a'+('`/security'+_0x4b7557(0x234)+_0x4b7557(0x530))+('`/security'+'\x20autoappro'+_0x4b7557(0x421)),{'parse_mode':_0x4b7557(0x501)});return;}if(_0x5c9cc1[_0x42d475(0x245)](_0x42d475(0x68a))){const _0x297850=_0x5c9cc1[_0x42d475(0x450)](-0x129e+-0x2*0x6b7+0x2b*0xbf)[_0x42d475(0x43d)]();setForwardingAllowed(_0x297850==='on'||_0x297850===_0x42d475(0x306)),await _0x57b649[_0x4b7557(0x358)](_0x42d475(0x410)+':\x20'+(_0x297850==='on'||_0x297850==='true'?_0x42d475(0x47e):'blocked'));}else{if(_0x5c9cc1[_0x4b7557(0x245)]('autoapprov'+'e\x20')){const _0x41afbe=_0x5c9cc1[_0x42d475(0x450)](0x61*-0x47+0x1*-0x1e15+0x3908)['trim']();setAutoApprove(_0x41afbe==='on'||_0x41afbe===_0x4b7557(0x306)),await _0x57b649[_0x42d475(0x358)]((_0x41afbe==='on'||_0x41afbe===_0x4b7557(0x306)?'⚠️':'✅')+(_0x4b7557(0x4dc)+_0x4b7557(0x21c))+(_0x41afbe==='on'||_0x41afbe===_0x42d475(0x306)?'ON':'OFF'));}else await _0x57b649[_0x4b7557(0x358)]('Unknown.\x20U'+'se\x20`/secur'+'ity`\x20for\x20o'+_0x4b7557(0x29b),{'parse_mode':_0x4b7557(0x501)});}}),_0x7c81f2[_0x28d038(0x4c8)](_0x28d038(0x2ae),async _0x1e3f4f=>{const _0x521110=_0x5f3d1c,_0x274cbf=_0x5f3d1c,_0x275487=_0x1e3f4f[_0x521110(0x395)]?.['toString']()['trim']();if(!_0x275487){await _0x1e3f4f[_0x274cbf(0x358)]('🌐\x20*Browser'+_0x521110(0x667)+_0x274cbf(0x3b6)+('`/browse\x20<'+_0x274cbf(0x42e)+'reenshot\x20a'+'\x20webpage\x0a')+(_0x521110(0x665)+'ext\x20<URL>`'+'\x20—\x20Extract'+'\x20text\x0a')+(_0x521110(0x67c)+_0x274cbf(0x212)+_0x274cbf(0x6c5)+_0x521110(0x40b)),{'parse_mode':_0x274cbf(0x501)});return;}if(!hasPlaywright()){await _0x1e3f4f[_0x274cbf(0x358)](_0x274cbf(0x42a)+_0x274cbf(0x24f)+_0x274cbf(0x5a2)+_0x274cbf(0x6b8)+_0x274cbf(0x6d5)+_0x521110(0x58c)+_0x521110(0x3f3)+'install\x20ch'+'romium`',{'parse_mode':_0x521110(0x501)});return;}try{await _0x1e3f4f[_0x521110(0x6bb)][_0x274cbf(0x1c5)+_0x521110(0x2e0)](_0x1e3f4f['chat']['id'],_0x521110(0x596));if(_0x275487['startsWith'](_0x521110(0x6ce))){const _0x23b559=_0x275487[_0x521110(0x450)](0x9ca*0x2+0xafa+-0x1*0x1e89)[_0x521110(0x43d)](),_0x2353f9=await extractText(_0x23b559),_0x48645f=_0x2353f9['length']>-0x21e4+-0xab5+0x3a45?_0x2353f9[_0x521110(0x450)](-0x2*0x21f+-0x1a3f+0x1e7d,-0x1*0x8e8+0x8*-0x487+0x3acc)+('\x0a\x0a_[...tru'+'ncated]_'):_0x2353f9;await _0x1e3f4f[_0x521110(0x358)](_0x274cbf(0x45e)+_0x521110(0x59a)+_0x23b559+_0x274cbf(0x200)+_0x48645f,{'parse_mode':_0x274cbf(0x501)});return;}if(_0x275487[_0x274cbf(0x245)]('pdf\x20')){const _0x25f53f=_0x275487['slice'](0x232f+-0x160a+0xd21*-0x1)['trim']();await _0x1e3f4f['api'][_0x521110(0x1c5)+'tion'](_0x1e3f4f[_0x521110(0x5a1)]['id'],_0x521110(0x381)+_0x274cbf(0x69d));const _0x429543=await generatePdf(_0x25f53f);await _0x1e3f4f[_0x274cbf(0x6c8)+'ocument'](new InputFile(_0x477de6[_0x521110(0x429)+'nc'](_0x429543),_0x521110(0x364)),{'caption':_0x274cbf(0x4c0)+'\x20'+_0x25f53f}),_0x477de6[_0x274cbf(0x4cb)](_0x429543,()=>{});return;}const _0x37407d=_0x275487[_0x521110(0x245)](_0x274cbf(0x30b))?_0x275487:_0x274cbf(0x3b0)+_0x275487;await _0x1e3f4f['api'][_0x274cbf(0x1c5)+'tion'](_0x1e3f4f[_0x274cbf(0x5a1)]['id'],_0x521110(0x237)+'to');const _0x41555d=await screenshotUrl(_0x37407d,{'fullPage':![]});await _0x1e3f4f[_0x521110(0x55a)+_0x521110(0x287)](new InputFile(_0x477de6[_0x521110(0x429)+'nc'](_0x41555d),_0x521110(0x650)+_0x521110(0x5ee)),{'caption':'🌐\x20'+_0x37407d}),_0x477de6[_0x274cbf(0x4cb)](_0x41555d,()=>{});}catch(_0x47ae09){const _0xcb8321=_0x47ae09 instanceof Error?_0x47ae09[_0x521110(0x261)]:String(_0x47ae09);await _0x1e3f4f[_0x521110(0x358)](_0x274cbf(0x669)+_0x274cbf(0x1c3)+_0xcb8321);}}),_0x7c81f2[_0x28d038(0x4c8)](_0x5f3d1c(0x75c),async _0xcf8c96=>{const _0x382db9=_0x28d038,_0x18cec4=_0x28d038,_0x2caef2=_0xcf8c96[_0x382db9(0x395)]?.['toString']()[_0x18cec4(0x43d)]();if(_0x2caef2?.['startsWith'](_0x382db9(0x398))){const _0x430540=_0x2caef2[_0x18cec4(0x450)](0x160*0x1+0x1d7f+-0x1edb)['trim']()['split'](/\s+/),_0x3df277=_0x430540[0x1f1f+-0x21c8+0x2a9];let _0x40ae5d={};if(_0x430540[_0x382db9(0x77d)]>0x2d1+-0x1648+0x1378*0x1)try{_0x40ae5d=JSON[_0x18cec4(0x415)](_0x430540[_0x18cec4(0x450)](0xa34+-0x251+-0x7e2)[_0x382db9(0x1d7)]('\x20'));}catch{await _0xcf8c96[_0x382db9(0x358)]('❌\x20Invalid\x20'+'JSON\x20for\x20p'+_0x382db9(0x375),{'parse_mode':'Markdown'});return;}try{await _0xcf8c96[_0x18cec4(0x6bb)][_0x382db9(0x1c5)+'tion'](_0xcf8c96[_0x18cec4(0x5a1)]['id'],'typing');const _0x4f77d5=await executeCustomTool(_0x3df277,_0x40ae5d),_0x24d8b4=_0x4f77d5['length']>-0x24aa+-0xce*-0xc+0x26ba?_0x4f77d5[_0x18cec4(0x450)](-0x5*0xd7+0x539*0x1+-0x1*0x106,0x2*-0xa63+-0x1c93*0x1+0x145b*0x3)+_0x18cec4(0x502):_0x4f77d5;await _0xcf8c96[_0x382db9(0x358)](_0x382db9(0x405)+_0x3df277+_0x382db9(0x4bf)+_0x24d8b4+'\x0a```',{'parse_mode':'Markdown'});}catch(_0x1bf78c){const _0x2608a8=_0x1bf78c instanceof Error?_0x1bf78c[_0x382db9(0x261)]:String(_0x1bf78c);await _0xcf8c96[_0x382db9(0x358)](_0x382db9(0x50f)+_0x18cec4(0x705)+_0x2608a8);}return;}const _0x51a604=listCustomTools();if(_0x51a604[_0x18cec4(0x77d)]===-0x20d7+-0x1*0x1e7e+0x20b*0x1f){await _0xcf8c96[_0x382db9(0x358)](_0x382db9(0x75e)+_0x382db9(0x4e7)+(_0x382db9(0x35a)+'onfigured.'+'\x0a')+(_0x382db9(0x764)+'OLS.md`\x20(s'+'ee\x20`TOOLS.'+_0x18cec4(0x66a)+_0x382db9(0x76c)),{'parse_mode':_0x382db9(0x501)});return;}const _0x338fcc=_0x51a604[_0x18cec4(0x6aa)](_0x23ea24=>{const _0x4e2e76=_0x382db9,_0x33843b=_0x18cec4,_0x536419=_0x23ea24[_0x4e2e76(0x549)]===_0x33843b(0x30b)?'🌐':'⚡';return _0x536419+'\x20`'+_0x23ea24[_0x33843b(0x712)]+_0x4e2e76(0x4bc)+_0x23ea24[_0x4e2e76(0x6ee)+'n'];});await _0xcf8c96[_0x18cec4(0x358)](_0x382db9(0x75e)+_0x382db9(0x366)+_0x51a604[_0x18cec4(0x77d)]+_0x382db9(0x489)+_0x338fcc[_0x382db9(0x1d7)]('\x0a')+'\x0a\x0a'+('_Run:\x20`/to'+'ols\x20run\x20<n'+_0x382db9(0x50a)+_0x18cec4(0x3d6)+'\x22}`_'),{'parse_mode':_0x382db9(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)]('mcp',async _0x38f9cf=>{const _0x33ff90=_0x5f3d1c,_0x33d46e=_0x5f3d1c,_0x3020f3=_0x38f9cf[_0x33ff90(0x395)]?.[_0x33d46e(0x2c6)]()['trim']();if(_0x3020f3?.[_0x33ff90(0x245)]('call\x20')){const _0x4fcfe7=_0x3020f3[_0x33ff90(0x450)](-0xa93*-0x1+-0x737*-0x5+-0xad*0x45)[_0x33ff90(0x43d)]()['split'](/\s+/);if(_0x4fcfe7['length']<-0x1*-0x2390+0x1*0xf16+-0x32a4){await _0x38f9cf[_0x33ff90(0x358)]('Format:\x20`/'+_0x33d46e(0x6a5)+_0x33ff90(0x3ca)+_0x33ff90(0x4c5)+_0x33ff90(0x61c)+'`',{'parse_mode':'Markdown'});return;}const [_0x36c745,_0x2fc606,..._0x258524]=_0x4fcfe7;let _0x22f3e8={};if(_0x258524[_0x33d46e(0x77d)]>0x73c*-0x1+0x1*0x109f+0x1*-0x963)try{_0x22f3e8=JSON['parse'](_0x258524[_0x33d46e(0x1d7)]('\x20'));}catch{await _0x38f9cf[_0x33d46e(0x358)](_0x33ff90(0x2a9)+'JSON\x20for\x20t'+_0x33ff90(0x7ac)+_0x33d46e(0x25d));return;}try{await _0x38f9cf['api']['sendChatAc'+_0x33ff90(0x2e0)](_0x38f9cf[_0x33ff90(0x5a1)]['id'],_0x33d46e(0x596));const _0x29e08c=await callMCPTool(_0x36c745,_0x2fc606,_0x22f3e8),_0x399a84=_0x29e08c['length']>-0x1fef+-0x1fac*-0x1+0xbfb?_0x29e08c['slice'](0x20d8+-0x2127+0x4f,0x1*0x1a4b+-0x13c3*-0x1+-0x6de*0x5)+'\x0a...':_0x29e08c;await _0x38f9cf[_0x33ff90(0x358)](_0x33ff90(0x405)+_0x36c745+'/'+_0x2fc606+_0x33ff90(0x4bf)+_0x399a84+_0x33d46e(0x26e),{'parse_mode':_0x33ff90(0x501)});}catch(_0x5be101){const _0x55b05a=_0x5be101 instanceof Error?_0x5be101['message']:String(_0x5be101);await _0x38f9cf[_0x33ff90(0x358)](_0x33ff90(0x748)+'r:\x20'+_0x55b05a);}return;}const _0x2f9753=getMCPStatus(),_0x3c7c88=getMCPTools();if(_0x2f9753['length']===0x100c+-0x23b+0x9*-0x189){await _0x38f9cf[_0x33d46e(0x358)](_0x33ff90(0x2ee)+_0x33d46e(0x6bc)+_0x33d46e(0x3a7)+_0x33d46e(0x373)+(_0x33ff90(0x5b0)+_0x33d46e(0x265)+_0x33d46e(0x3c4))+(_0x33d46e(0x36a)+_0x33d46e(0x29a)+'n`\x20(see\x20`d'+_0x33ff90(0x683)+'ample.json'+_0x33d46e(0x76c)),{'parse_mode':_0x33d46e(0x501)});return;}const _0x562270=_0x2f9753['map'](_0xb4e9bd=>{const _0x467d22=_0x33d46e,_0x2ff84c=_0x33ff90,_0x4e5b1e=_0xb4e9bd[_0x467d22(0x286)]?'🟢':'🔴';return _0x4e5b1e+'\x20*'+_0xb4e9bd['name']+'*\x20—\x20'+_0xb4e9bd[_0x2ff84c(0x75c)]+_0x2ff84c(0x1c1);}),_0x2df2a5=_0x3c7c88[_0x33ff90(0x77d)]>0x16*0xc5+-0x1*-0x1535+0xd*-0x2ef?'\x0a\x0a*Availab'+_0x33d46e(0x3b7)+'\x0a'+_0x3c7c88[_0x33d46e(0x6aa)](_0x3ea5c1=>_0x33ff90(0x5e4)+_0x3ea5c1[_0x33ff90(0x6e9)]+'/'+_0x3ea5c1[_0x33ff90(0x712)]+'`\x20—\x20'+_0x3ea5c1[_0x33ff90(0x6ee)+'n'])[_0x33ff90(0x1d7)]('\x0a'):'';await _0x38f9cf[_0x33d46e(0x358)](_0x33d46e(0x32d)+_0x33d46e(0x78a)+_0x2f9753[_0x33ff90(0x77d)]+_0x33ff90(0x489)+_0x562270[_0x33d46e(0x1d7)]('\x0a')+_0x2df2a5+(_0x33ff90(0x2c3)+_0x33ff90(0x55f)+'erver>\x20<to'+_0x33ff90(0x481)+_0x33d46e(0x583)+_0x33d46e(0x6c9)),{'parse_mode':_0x33d46e(0x501)});}),_0x7c81f2['command'](_0x5f3d1c(0x2bc),async _0x39d5d6=>{const _0x307cfb=_0x5f3d1c,_0x4e59db=_0x28d038,_0x56a756=getLoadedPlugins();if(_0x56a756[_0x307cfb(0x77d)]===0x1*-0xa88+-0x6c4+-0x5c4*-0x3){await _0x39d5d6['reply'](_0x307cfb(0x58a)+'ns\x20loaded.'+'\x0a\x0a'+(_0x4e59db(0x2dd)+'ins\x20in\x20`'+getPluginsDir()+_0x307cfb(0x263))+('Each\x20plugi'+_0x307cfb(0x3ae)+_0x4e59db(0x6ec)+_0x4e59db(0x321)+'s`.'),{'parse_mode':'Markdown'});return;}const _0x3a57d7=_0x56a756[_0x4e59db(0x6aa)](_0x2864fc=>{const _0x4837a5=_0x307cfb,_0x1e1c9f=_0x307cfb,_0x57ac2a=_0x2864fc[_0x4837a5(0x772)]['length']>0x107b*0x2+-0x1371+-0xd85?'\x0a\x20\x20\x20Comman'+_0x4837a5(0x4fb)+_0x2864fc['commands']['join'](',\x20'):'',_0x212af6=_0x2864fc[_0x4837a5(0x75c)][_0x1e1c9f(0x77d)]>-0x1c5d+0xbfd+0x1060?_0x1e1c9f(0x540)+'\x20'+_0x2864fc[_0x4837a5(0x75c)][_0x4837a5(0x1d7)](',\x20'):'';return'🔌\x20*'+_0x2864fc[_0x4837a5(0x712)]+_0x1e1c9f(0x57b)+_0x2864fc['version']+_0x1e1c9f(0x380)+_0x2864fc[_0x4837a5(0x6ee)+'n']+_0x57ac2a+_0x212af6;});await _0x39d5d6[_0x4e59db(0x358)]('🔌\x20*Loaded\x20'+_0x4e59db(0x4d7)+_0x56a756[_0x307cfb(0x77d)]+_0x307cfb(0x489)+_0x3a57d7['join']('\x0a\x0a'),{'parse_mode':_0x307cfb(0x501)});}),_0x7c81f2[_0x5f3d1c(0x4c8)]('skills',async _0x15bded=>{const _0x58bdc4=_0x28d038,_0x3ced65=_0x5f3d1c,{getSkills:_0x276212}=await import(_0x58bdc4(0x264)+_0x3ced65(0x34f)+'s'),_0x5a28e7=_0x276212();if(_0x5a28e7['length']===-0x2d3*0x9+0x34b+-0x3*-0x760){await _0x15bded[_0x3ced65(0x358)]('🎯\x20No\x20skill'+_0x3ced65(0x46f)+_0x58bdc4(0x6e1)+'ILL.md\x20fil'+_0x58bdc4(0x71e)+_0x3ced65(0x6f6)+_0x58bdc4(0x77c),{'parse_mode':'HTML'});return;}const _0x588c89=_0x5a28e7[_0x58bdc4(0x6aa)](_0x3b9131=>_0x58bdc4(0x6c6)+_0x3b9131['name']+_0x3ced65(0x249)+_0x3b9131[_0x58bdc4(0x2f8)]+_0x3ced65(0x536)+(_0x3b9131['descriptio'+'n']||_0x58bdc4(0x50e)+_0x3ced65(0x666))+(_0x58bdc4(0x562)+_0x58bdc4(0x558))+_0x3b9131[_0x58bdc4(0x718)][_0x3ced65(0x450)](-0x57*-0x67+0x143c*-0x1+0xec5*-0x1,0xd*-0x2f+-0x1*0x1f1a+0x2182)[_0x3ced65(0x1d7)](',\x20'));await _0x15bded['reply'](_0x3ced65(0x27b)+_0x3ced65(0x1e9)+_0x5a28e7[_0x58bdc4(0x77d)]+_0x3ced65(0x276)+_0x588c89[_0x58bdc4(0x1d7)]('\x0a\x0a'),{'parse_mode':_0x3ced65(0x3b4)});}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x711),async _0x262dd=>{const _0x1aa984=_0x5f3d1c,_0x17d5c5=_0x5f3d1c,_0x562d0e=listProfiles();if(_0x562d0e['length']===-0x2602+-0x3*-0xac6+0x5b0){await _0x262dd[_0x1aa984(0x358)](_0x1aa984(0x555)+'ofiles\x20sav'+_0x17d5c5(0x2d4));return;}const _0x4e916c=_0x562d0e[_0x1aa984(0x6aa)](_0x42f55e=>{const _0x134d34=_0x1aa984,_0x3193ea=_0x1aa984,_0x5793f9=new Date(_0x42f55e[_0x134d34(0x69f)])[_0x3193ea(0x5ef)+'teString']('en-US'),_0x58a28c=_0x42f55e[_0x3193ea(0x466)]?'👑':'👤';return _0x58a28c+'\x20*'+_0x42f55e[_0x134d34(0x712)]+'*'+(_0x42f55e[_0x134d34(0x349)]?_0x3193ea(0x38d)+_0x42f55e[_0x134d34(0x349)]+')':'')+_0x3193ea(0x380)+_0x42f55e[_0x134d34(0x538)+_0x3193ea(0x2f9)]+('\x20messages,'+_0x134d34(0x5bd)+_0x3193ea(0x229))+_0x5793f9;});await _0x262dd['reply']('👥\x20*User-Pr'+'ofile\x20('+_0x562d0e[_0x17d5c5(0x77d)]+'):*\x0a\x0a'+_0x4e916c['join']('\x0a\x0a'),{'parse_mode':_0x17d5c5(0x501)});}),_0x7c81f2['command'](_0x5f3d1c(0x1f9),async _0x2709ad=>{const _0x270da3=_0x28d038,_0x2a9f7f=_0x5f3d1c,_0xed9f30=_0x2709ad[_0x270da3(0x395)]?.[_0x270da3(0x2c6)]()[_0x2a9f7f(0x43d)]();if(!_0xed9f30){await _0x2709ad[_0x270da3(0x358)]('📝\x20Use:\x20`/n'+_0x2a9f7f(0x351)+_0x2a9f7f(0x1c2)+_0x2a9f7f(0x3ea)+_0x270da3(0x756)+_0x270da3(0x1d1)+'.',{'parse_mode':'Markdown'});return;}const _0x31f396=_0xed9f30[_0x2a9f7f(0x395)](/^@?(\S+)\s+(.+)$/s);if(!_0x31f396){await _0x2709ad[_0x2a9f7f(0x358)](_0x2a9f7f(0x505)+_0x2a9f7f(0x416)+'name\x20Text`',{'parse_mode':_0x270da3(0x501)});return;}const [,_0x23ef3a,_0x88b8d1]=_0x31f396,_0x181063=listProfiles(),_0xad3fbe=_0x181063['find'](_0x27ce14=>_0x27ce14[_0x270da3(0x349)]===_0x23ef3a||_0x27ce14[_0x270da3(0x315)][_0x270da3(0x2c6)]()===_0x23ef3a||_0x27ce14[_0x2a9f7f(0x712)][_0x270da3(0x2d5)+'e']()===_0x23ef3a[_0x270da3(0x2d5)+'e']());if(!_0xad3fbe){await _0x2709ad[_0x2a9f7f(0x358)](_0x270da3(0x761)+_0x23ef3a+('\x22\x20not\x20foun'+'d.'));return;}addUserNote(_0xad3fbe['userId'],_0x88b8d1),await _0x2709ad[_0x2a9f7f(0x358)](_0x270da3(0x2b6)+'ed\x20for\x20'+_0xad3fbe[_0x270da3(0x712)]+'.');}),_0x7c81f2['command']('recall',async _0x5eb363=>{const _0x631c3b=_0x5f3d1c,_0x55fa8b=_0x5f3d1c,_0x608734=_0x5eb363[_0x631c3b(0x395)]?.[_0x55fa8b(0x2c6)]()[_0x55fa8b(0x43d)]();if(!_0x608734){await _0x5eb363['reply'](_0x55fa8b(0x470)+_0x631c3b(0x688)+_0x55fa8b(0x55c)+_0x631c3b(0x28f)+_0x55fa8b(0x34d)+_0x55fa8b(0x3c1)+_0x55fa8b(0x23f),{'parse_mode':'Markdown'});return;}try{await _0x5eb363[_0x631c3b(0x6bb)]['sendChatAc'+'tion'](_0x5eb363[_0x55fa8b(0x5a1)]['id'],_0x631c3b(0x596));const _0x3e63e3=await searchMemory(_0x608734,0x2394+-0x2623+0x294,0x11da+0x71+-0x124b+0.25);if(_0x3e63e3[_0x55fa8b(0x77d)]===-0xe2*0x5+0xcf1*0x3+-0x17*0x17f){await _0x5eb363['reply']('🔍\x20No\x20memor'+'ies\x20found\x20'+_0x55fa8b(0x776)+_0x608734+'\x22.');return;}const _0x47b9a1=_0x3e63e3[_0x55fa8b(0x6aa)]((_0x212827,_0x3b4047)=>{const _0x109cdd=_0x55fa8b,_0x4e412f=_0x631c3b,_0xeb87f=Math[_0x109cdd(0x604)](_0x212827[_0x109cdd(0x49a)]*(-0x2656+0x2342+0x378)),_0x5e85ef=_0x212827['text']['length']>-0xe57+-0x1*-0xd51+0x1ce?_0x212827['text'][_0x109cdd(0x450)](0x5*-0xbf+0x2563+-0x10d4*0x2,-0x2*-0x819+-0x5f5*-0x1+-0x155f)+_0x4e412f(0x53a):_0x212827[_0x4e412f(0x578)];return'**'+(_0x3b4047+(0x5*-0x469+-0x107+0x1*0x1715))+_0x4e412f(0x53e)+_0xeb87f+_0x109cdd(0x407)+_0x212827[_0x4e412f(0x510)]+'_\x0a'+_0x5e85ef;});await _0x5eb363[_0x631c3b(0x358)](_0x631c3b(0x787)+_0x55fa8b(0x69b)+_0x608734+_0x631c3b(0x770)+_0x47b9a1[_0x55fa8b(0x1d7)]('\x0a\x0a'),{'parse_mode':'Markdown'});}catch(_0x426000){const _0x23df65=_0x426000 instanceof Error?_0x426000[_0x631c3b(0x261)]:String(_0x426000);await _0x5eb363['reply'](_0x55fa8b(0x6e8)+_0x55fa8b(0x3c9)+_0x23df65);}}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x5f3d1c(0x750),async _0x1df0f9=>{const _0x3afa0d=_0x5f3d1c,_0x4fbc0f=_0x28d038,_0x5c3fe6=_0x1df0f9[_0x3afa0d(0x395)]?.[_0x3afa0d(0x2c6)]()['trim']();if(!_0x5c3fe6){await _0x1df0f9[_0x4fbc0f(0x358)]('💾\x20Use:\x20`/r'+'emember\x20<t'+_0x3afa0d(0x2a4)+'s\x20somethin'+_0x3afa0d(0x586)+_0x4fbc0f(0x23f),{'parse_mode':'Markdown'});return;}try{appendDailyLog('**Manually'+'\x20remembere'+_0x4fbc0f(0x1eb)+_0x5c3fe6);const _0x3cbebf=await reindexMemory();await _0x1df0f9[_0x3afa0d(0x358)](_0x4fbc0f(0x23d)+_0x3afa0d(0x623)+_0x3cbebf['total']+(_0x4fbc0f(0x4b7)+'n\x20index)'));}catch(_0x314adf){const _0x5e25fa=_0x314adf instanceof Error?_0x314adf[_0x3afa0d(0x261)]:String(_0x314adf);await _0x1df0f9[_0x4fbc0f(0x358)](_0x3afa0d(0x1c6)+_0x4fbc0f(0x2d9)+_0x5e25fa);}}),_0x7c81f2[_0x28d038(0x4c8)](_0x28d038(0x36c),async _0x3062a9=>{const _0x57806d=_0x28d038,_0x42cf1e=_0x28d038;try{await _0x3062a9[_0x57806d(0x6bb)][_0x57806d(0x1c5)+'tion'](_0x3062a9[_0x42cf1e(0x5a1)]['id'],_0x42cf1e(0x596));const _0x3bfb45=await reindexMemory(!![]),_0x520272=getIndexStats(),_0x17249a=(_0x520272[_0x42cf1e(0x537)]/(-0x383*-0x3+-0x18ae+0x1225))[_0x57806d(0x2ed)](0x3*-0xbcf+-0x15fb+0x3969);await _0x3062a9[_0x42cf1e(0x358)](_0x57806d(0x6d7)+_0x57806d(0x5b8)+'\x0a\x0a'+(_0x57806d(0x55b)+_0x3bfb45[_0x57806d(0x6fb)]+(_0x42cf1e(0x706)+'ocessed\x0a'))+('📁\x20'+_0x520272[_0x42cf1e(0x2a0)]+('\x20files\x20ind'+'exed\x0a'))+(_0x57806d(0x20d)+_0x3bfb45['total']+(_0x42cf1e(0x69c)+_0x42cf1e(0x6b7)))+(_0x57806d(0x5e0)+_0x57806d(0x1bf)+_0x17249a+_0x42cf1e(0x75b)));}catch(_0x1eece2){const _0x53a42e=_0x1eece2 instanceof Error?_0x1eece2[_0x57806d(0x261)]:String(_0x1eece2);await _0x3062a9[_0x42cf1e(0x358)]('❌\x20Reindex\x20'+_0x57806d(0x1c3)+_0x53a42e);}}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x28d038(0x584),async _0x475435=>{const _0x1cb4c9=_0x5f3d1c,_0x2739fb=_0x5f3d1c,_0x40b22c=_0x475435[_0x1cb4c9(0x395)]?.[_0x1cb4c9(0x2c6)]()[_0x2739fb(0x43d)]()||'',_0x1d4df6=_0x475435['from']['id'],_0x51b4d3=_0x475435[_0x1cb4c9(0x5a1)]['id'];if(!_0x40b22c){const _0x475279=listJobs();if(_0x475279[_0x2739fb(0x77d)]===-0xa*0x38a+0x1*0x160f+-0x1*-0xd55){await _0x475435[_0x1cb4c9(0x358)]('⏰\x20<b>Cron\x20'+_0x2739fb(0x771)+_0x2739fb(0x2f5)+_0x2739fb(0x42f)+'\x0a'+_0x2739fb(0x4b0)+(_0x1cb4c9(0x6bd)+_0x2739fb(0x1fb)+'eminder\x20Wa'+'sser\x20trink'+_0x2739fb(0x691))+('<code>/cro'+_0x2739fb(0x4d5)+'\x20*\x20*\x201\x22\x20sh'+_0x1cb4c9(0x6e4)+_0x2739fb(0x509)+'>\x0a')+(_0x2739fb(0x6bd)+'n\x20add\x201h\x20h'+'ttp\x20https:'+'//api.exam'+'ple.com/he'+'alth</code'+'>\x0a\x0a')+('<i>Manage\x20'+_0x1cb4c9(0x356)+_0x2739fb(0x67b)+_0x1cb4c9(0x21f)+_0x1cb4c9(0x73e)+'>'),{'parse_mode':_0x1cb4c9(0x3b4)});return;}const _0x363456=_0x475279[_0x2739fb(0x6aa)](_0x30c1df=>{const _0x17d5a4=_0x2739fb,_0x24952e=_0x2739fb,_0x85dd7d=_0x30c1df[_0x17d5a4(0x7a6)]?'🟢':'⏸️',_0x5a832e=_0x30c1df[_0x17d5a4(0x7a6)]?formatNextRun(_0x30c1df[_0x17d5a4(0x3ce)]):_0x24952e(0x77f),_0x3b8725=_0x30c1df[_0x24952e(0x3c5)]?'\x20⚠️':'',_0x5d8410=humanReadableSchedule(_0x30c1df[_0x24952e(0x462)]),_0x5db660=_0x30c1df[_0x24952e(0x40f)]?_0x24952e(0x54b):_0x17d5a4(0x694)+_0x5d8410;return _0x85dd7d+_0x17d5a4(0x513)+_0x30c1df[_0x17d5a4(0x712)]+_0x24952e(0x3cb)+_0x5db660+_0x24952e(0x1e7)+_0x5a832e+_0x24952e(0x532)+_0x30c1df[_0x24952e(0x6c3)]+_0x3b8725+(_0x24952e(0x72e)+_0x17d5a4(0x49c))+_0x30c1df['id']+_0x17d5a4(0x4ff);}),_0x34b033=new InlineKeyboard();for(const _0x438b35 of _0x475279){const _0x1df820=_0x438b35[_0x1cb4c9(0x7a6)]?'⏸\x20'+_0x438b35[_0x2739fb(0x712)]:_0x1cb4c9(0x497)+_0x438b35['name'];_0x34b033[_0x2739fb(0x578)](_0x1df820,'cron:toggl'+'e:'+_0x438b35['id']),_0x34b033[_0x1cb4c9(0x578)]('🗑',_0x1cb4c9(0x701)+'e:'+_0x438b35['id']),_0x34b033['row']();}await _0x475435[_0x1cb4c9(0x358)](_0x1cb4c9(0x242)+_0x2739fb(0x608)+_0x475279['length']+_0x1cb4c9(0x276)+_0x363456[_0x1cb4c9(0x1d7)]('\x0a\x0a')+'\x0a\x0a'+(_0x2739fb(0x547)+_0x2739fb(0x76b)+_0x1cb4c9(0x63d)+_0x2739fb(0x6f4)+'run\x20·\x20info'),{'parse_mode':'HTML','reply_markup':_0x34b033});return;}if(_0x40b22c[_0x2739fb(0x245)](_0x2739fb(0x65f))){let _0x5bcbea=_0x40b22c[_0x1cb4c9(0x450)](-0x1d*0x1b+-0x743*0x4+-0x1*-0x201f)[_0x2739fb(0x43d)](),_0x2e3632;const _0x4f2e66=_0x5bcbea['match'](/(^|\s)--timeout\s+(\S+)/);if(_0x4f2e66){const _0x376bcc=_0x4f2e66[0x6d7+-0x2*-0x109c+-0x280d][_0x2739fb(0x2d5)+'e']();if([_0x1cb4c9(0x702),_0x1cb4c9(0x76f),'infinite','-1','0']['includes'](_0x376bcc))_0x2e3632=-(-0x349*0x9+0xe9a+-0xef8*-0x1);else{const _0x227f55=Number(_0x4f2e66[0x11*-0x68+-0x19c4+0x20ae]);if(!Number[_0x2739fb(0x5cf)](_0x227f55)||_0x227f55<0x1*0x1bf7+0x552*0x1+-0x2149){await _0x475435[_0x2739fb(0x358)]('❌\x20Invalid\x20'+'<code>--ti'+_0x2739fb(0x4d1)+_0x2739fb(0x710)+_0x4f2e66[0x1676+-0x12b6+0x2*-0x1df],{'parse_mode':'HTML'});return;}_0x2e3632=Math['floor'](_0x227f55*(-0xc7*-0x6+-0x25a3+0x24e1));}_0x5bcbea=_0x5bcbea['replace'](/(^|\s)--timeout\s+\S+/,'')['trim']();}const _0x5e1997={'täglich':_0x1cb4c9(0x5e3),'daily':'0\x208\x20*\x20*\x20*','stündlich':_0x2739fb(0x2c5),'hourly':_0x2739fb(0x2c5),'wöchentlich':_0x1cb4c9(0x4f0),'weekly':_0x1cb4c9(0x4f0),'monatlich':_0x2739fb(0x793),'monthly':'0\x208\x201\x20*\x20*','werktags':_0x1cb4c9(0x3ad)+'5','weekdays':_0x1cb4c9(0x3ad)+'5','wochenende':_0x1cb4c9(0x512)+',6','weekend':_0x1cb4c9(0x512)+',6','montags':_0x2739fb(0x4f0),'dienstags':_0x1cb4c9(0x6cd),'mittwochs':_0x1cb4c9(0x1b2),'donnerstags':_0x1cb4c9(0x467),'freitags':_0x1cb4c9(0x2f2),'samstags':_0x1cb4c9(0x213),'sonntags':_0x1cb4c9(0x512),'morgens':_0x1cb4c9(0x5e3),'mittags':'0\x2012\x20*\x20*\x20*','abends':_0x2739fb(0x5c0),'nachts':_0x2739fb(0x752)};function _0x340da2(_0x46ada7){const _0xb320cc=_0x1cb4c9,_0x46285b=_0x1cb4c9,_0x4c1924=_0x46ada7[_0xb320cc(0x395)](/^(\d{1,2}):(\d{2})\s+(\S+)\s*(.*)/);if(_0x4c1924){const _0x331d70=_0x4c1924[0xe*0x22c+0x353+-0x68*0x53]['toLowerCas'+'e']();if(_0x5e1997[_0x331d70]){const _0x28a94a=_0x5e1997[_0x331d70][_0x46285b(0x25c)]('\x20');return _0x28a94a[-0x1d26+-0x1afc+-0xb3a*-0x5]=String(parseInt(_0x4c1924[0x1*-0x183b+-0x213a*-0x1+-0x8fd])),_0x28a94a[0xb2d+-0x151*-0x13+-0x242f]=String(parseInt(_0x4c1924[0xfe*-0x11+-0x2605+0x36e4])),{'schedule':_0x28a94a['join']('\x20'),'rest':_0x4c1924[-0x7c*0xc+0x1b91+0x9f*-0x23]};}}const _0x466251=_0x46ada7[_0x46285b(0x395)](/^(\S+)\s+(\d{1,2}):(\d{2})\s*(.*)/);if(_0x466251){const _0xa547b7=_0x466251[0x1*-0x1a26+0xfc7+0xa60][_0xb320cc(0x2d5)+'e']();if(_0x5e1997[_0xa547b7]){const _0x193e78=_0x5e1997[_0xa547b7]['split']('\x20');return _0x193e78[0x1*-0x167e+0x478+0x1206]=String(parseInt(_0x466251[0x86e*-0x4+0x7*-0x261+0x3262])),_0x193e78[-0x1*0x1d79+-0x491*-0x2+0x1458]=String(parseInt(_0x466251[-0x4*-0x38c+-0x12e7*0x1+0x4b9])),{'schedule':_0x193e78[_0xb320cc(0x1d7)]('\x20'),'rest':_0x466251[0x31*0x90+0x7*-0xd9+-0x159d]};}}const _0x5a39ae=_0x46ada7[_0x46285b(0x25c)]('\x20')[0x47*0x1+0x4be*0x4+-0x133f]['toLowerCas'+'e']();if(_0x5e1997[_0x5a39ae])return{'schedule':_0x5e1997[_0x5a39ae],'rest':_0x46ada7[_0x46285b(0x450)](_0x5a39ae['length'])[_0x46285b(0x43d)]()};return null;}let _0x11495f,_0x206735;const _0x5d6ffb=_0x340da2(_0x5bcbea);if(_0x5d6ffb)_0x11495f=_0x5d6ffb['schedule'],_0x206735=_0x5d6ffb[_0x2739fb(0x3b1)];else{if(_0x5bcbea[_0x2739fb(0x245)]('\x22')){const _0x13319e=_0x5bcbea['indexOf']('\x22',0xa5e*-0x1+-0x3*-0xadb+-0x1632);if(_0x13319e<0x7*0x383+-0x187+-0x170e){await _0x475435['reply'](_0x1cb4c9(0x33e)+_0x1cb4c9(0x4ba)+'ote\x20for\x20cr'+_0x1cb4c9(0x637)+_0x1cb4c9(0x487));return;}_0x11495f=_0x5bcbea[_0x1cb4c9(0x450)](0x2*-0x12aa+-0x159d+0x3ee*0xf,_0x13319e),_0x206735=_0x5bcbea[_0x1cb4c9(0x450)](_0x13319e+(0x8e*0xe+-0xa29+-0x266*-0x1))['trim']();}else{const _0x17fc26=_0x5bcbea[_0x2739fb(0x2d1)]('\x20');if(_0x17fc26<-0x52d+0x771*0x2+-0x9b5){await _0x475435[_0x2739fb(0x358)](_0x2739fb(0x3b3)+_0x1cb4c9(0x477)+_0x2739fb(0x355)+_0x1cb4c9(0x28c)+_0x1cb4c9(0x4ea)+_0x1cb4c9(0x737)+_0x2739fb(0x352)+_0x1cb4c9(0x1da)+_0x2739fb(0x515)+_0x1cb4c9(0x5da)+_0x2739fb(0x634)+_0x2739fb(0x6d0)+_0x1cb4c9(0x490)+_0x1cb4c9(0x482)+_0x2739fb(0x391)+',\x2030s,\x202d\x0a'+_0x1cb4c9(0x75a)+_0x1cb4c9(0x446)+_0x2739fb(0x649)+_0x1cb4c9(0x57a)+_0x1cb4c9(0x769)+_0x2739fb(0x59f)+'\x20<b>With\x20t'+'ime:</b>\x208'+_0x2739fb(0x1be)+'\x20weekdays\x20'+_0x2739fb(0x73c)+_0x1cb4c9(0x54c)+_0x1cb4c9(0x384)+_0x2739fb(0x476)+_0x2739fb(0x579)+_0x1cb4c9(0x35b)+_0x1cb4c9(0x1c8)+'</b>\x20\x220\x209\x20'+_0x2739fb(0x21b)+_0x2739fb(0x342)+_0x1cb4c9(0x474)+_0x1cb4c9(0x74a)+_0x1cb4c9(0x66d)+_0x1cb4c9(0x280)+_0x1cb4c9(0x779)+'de>/<code>'+_0x1cb4c9(0x658)+_0x2739fb(0x35d)+_0x1cb4c9(0x4cc),{'parse_mode':_0x1cb4c9(0x3b4)});return;}_0x11495f=_0x5bcbea[_0x2739fb(0x450)](-0x196*0x2+0x1fca+-0x1c9e,_0x17fc26),_0x206735=_0x5bcbea['slice'](_0x17fc26+(0x3a6*-0x2+-0x8*0x214+-0x5*-0x4c9))['trim']();}}const _0x6f199e=_0x206735['indexOf']('\x20'),_0x364eb8=_0x6f199e>=0x2dd*-0x8+0x1082+-0x333*-0x2?_0x206735[_0x1cb4c9(0x450)](-0x1981+0x13a+0x1847,_0x6f199e):_0x206735,_0x1f15f0=_0x6f199e>=0xb23+-0xd46+0x1*0x223?_0x206735[_0x2739fb(0x450)](_0x6f199e+(0x1cf+0x1*-0x757+0x1*0x589))[_0x2739fb(0x43d)]():'',_0x2e1203=[_0x1cb4c9(0x330),_0x1cb4c9(0x283),'http',_0x1cb4c9(0x261),'ai-query'];if(!_0x2e1203[_0x2739fb(0x3ee)](_0x364eb8)){await _0x475435['reply']('❌\x20Invalid\x20'+_0x1cb4c9(0x5f0)+_0x364eb8+(_0x2739fb(0x296)+':\x20')+_0x2e1203[_0x1cb4c9(0x1d7)](',\x20'));return;}const _0x26d95b={};switch(_0x364eb8){case _0x2739fb(0x330):case'message':_0x26d95b['text']=_0x1f15f0;break;case _0x2739fb(0x283):_0x26d95b[_0x1cb4c9(0x4c8)]=_0x1f15f0;break;case _0x2739fb(0x30b):_0x26d95b[_0x2739fb(0x4f9)]=_0x1f15f0;break;case _0x1cb4c9(0x243):_0x26d95b[_0x1cb4c9(0x606)]=_0x1f15f0;break;}const _0x221a2a=_0x364eb8+':\x20'+_0x1f15f0[_0x2739fb(0x450)](0xf06+-0x16fa+0x7f4,-0x586+0x6*-0x619+-0x1*-0x2a3a)+(_0x1f15f0[_0x1cb4c9(0x77d)]>-0x2*0x1076+-0x1*0x2d2+0x23dc?_0x1cb4c9(0x53a):''),_0x5602db=createJob({'name':_0x221a2a,'type':_0x364eb8,'schedule':_0x11495f,'payload':_0x26d95b,'target':{'platform':_0x2739fb(0x3f7),'chatId':String(_0x51b4d3)},'createdBy':'telegram:'+_0x1d4df6,..._0x2e3632!==undefined?{'timeoutMs':_0x2e3632}:{}}),_0x3bdeef=humanReadableSchedule(_0x5602db[_0x2739fb(0x462)]),_0x19b308=typeof _0x5602db[_0x2739fb(0x2c2)]==='number'?_0x5602db['timeoutMs']<=0x1d87+-0x841*0x1+-0x30a*0x7?_0x1cb4c9(0x5f3)+_0x1cb4c9(0x74b)+'nlimited)\x0a':_0x2739fb(0x5f3)+_0x2739fb(0x52a)+Math[_0x1cb4c9(0x604)](_0x5602db[_0x1cb4c9(0x2c2)]/(0x1*0x1aa+0x36d+-0x12f))+'s\x0a':'';await _0x475435['reply'](_0x1cb4c9(0x1fe)+'Job\x20create'+_0x1cb4c9(0x6f5)+(_0x1cb4c9(0x2dc)+_0x2739fb(0x738)+_0x5602db[_0x1cb4c9(0x712)]+'\x0a')+(_0x2739fb(0x1e6)+_0x3bdeef+'</b>\x0a')+('<b>Type:</'+_0x2739fb(0x738)+_0x5602db[_0x2739fb(0x549)]+'\x0a')+_0x19b308+(_0x1cb4c9(0x2e7)+'n:</b>\x20'+formatNextRun(_0x5602db[_0x2739fb(0x3ce)])+'\x0a')+('<b>ID:</b>'+_0x2739fb(0x42d)+_0x5602db['id']+_0x2739fb(0x4ff)),{'parse_mode':_0x1cb4c9(0x3b4)});return;}if(_0x40b22c[_0x1cb4c9(0x245)]('delete\x20')){const _0x25677=_0x40b22c[_0x1cb4c9(0x450)](0x9*0x169+0x1507*-0x1+0x85d)[_0x2739fb(0x43d)]();deleteJob(_0x25677)?await _0x475435[_0x1cb4c9(0x358)](_0x1cb4c9(0x3fc)+_0x25677+'`\x20deleted.',{'parse_mode':'Markdown'}):await _0x475435[_0x1cb4c9(0x358)](_0x1cb4c9(0x74f)+_0x25677+(_0x1cb4c9(0x5ca)+'d.'),{'parse_mode':'Markdown'});return;}if(_0x40b22c[_0x2739fb(0x245)]('toggle\x20')){const _0x1a12a0=_0x40b22c[_0x1cb4c9(0x450)](0x1*0x1c22+-0x18ba+-0x361)[_0x1cb4c9(0x43d)](),_0x37ffd9=toggleJob(_0x1a12a0);_0x37ffd9?await _0x475435[_0x2739fb(0x358)]((_0x37ffd9[_0x1cb4c9(0x7a6)]?'▶️':'⏸️')+_0x1cb4c9(0x33f)+_0x37ffd9[_0x2739fb(0x712)]+'\x22\x20'+(_0x37ffd9[_0x2739fb(0x7a6)]?_0x1cb4c9(0x7a6):_0x2739fb(0x77f))+'.'):await _0x475435[_0x2739fb(0x358)](_0x2739fb(0x26c)+'found.');return;}if(_0x40b22c[_0x1cb4c9(0x245)](_0x1cb4c9(0x398))){const _0x420669=_0x40b22c[_0x1cb4c9(0x450)](0x1715+-0x238f*0x1+0x3*0x42a)[_0x1cb4c9(0x43d)](),_0xd83592=resolveJobByNameOrId(listJobs(),_0x420669);if(!_0xd83592){const _0x535ee3=listJobs(),_0x1aacae=_0x535ee3[_0x2739fb(0x77d)]>0x49*0x74+-0x33*0x49+-0x1289?_0x2739fb(0x227)+'e:\x0a'+_0x535ee3[_0x1cb4c9(0x450)](0x21d*-0x1+-0x1c68+0x1e85*0x1,-0x407*0x1+-0x13*-0x1a8+-0x1b67)['map'](_0x4bb715=>'•\x20'+_0x4bb715[_0x2739fb(0x712)])[_0x1cb4c9(0x1d7)]('\x0a'):'';await _0x475435['reply'](_0x1cb4c9(0x1ec)+_0x2739fb(0x6b6)+_0x2739fb(0x49c)+_0x420669+_0x2739fb(0x451)+_0x1aacae,{'parse_mode':_0x2739fb(0x3b4)});return;}const _0x475fc2=_0xd83592[_0x1cb4c9(0x712)],_0x3eb3bb=Date[_0x2739fb(0x2b0)]();let _0x58b996=null;try{const _0x578dd6=await _0x475435[_0x1cb4c9(0x358)](_0x1cb4c9(0x67f)+'*'+escapeMarkdown(_0x475fc2)+(_0x2739fb(0x636)+'g…'),{'parse_mode':_0x1cb4c9(0x501)});_0x58b996=_0x578dd6[_0x1cb4c9(0x784)];}catch(_0x148293){try{const _0x40e1d4=await _0x475435[_0x2739fb(0x358)]('🚀\x20Started\x20'+_0x475fc2+(_0x1cb4c9(0x36b)+'…'));_0x58b996=_0x40e1d4[_0x2739fb(0x784)];}catch{}}const _0x3a6763=_0x475435['chat']['id'],_0x1a21c3=setInterval(async()=>{const _0xb8dc3c=_0x2739fb,_0x253465=_0x2739fb;if(_0x58b996===null)return;const _0x372edb=Math[_0xb8dc3c(0x39a)]((Date['now']()-_0x3eb3bb)/(0x7*0x277+-0xdc5+-0x36*-0x2));try{await _0x475435[_0xb8dc3c(0x6bb)][_0x253465(0x5aa)+_0x253465(0x5d3)](_0x3a6763,_0x58b996,buildTickerText(_0x475fc2,_0x372edb),{'parse_mode':'Markdown'});}catch(_0x12937a){!isHarmlessTelegramError(_0x12937a)&&console[_0x253465(0x222)](_0x253465(0x6a2)+_0xb8dc3c(0x5ab)+_0x253465(0x2f7),_0x12937a);}},0x1a0d9+-0x2765+-0x8f14);let _0x5cae60;try{_0x5cae60=await runJobNow(_0x420669);}finally{clearInterval(_0x1a21c3);}const _0xc86502=Math[_0x1cb4c9(0x39a)]((Date[_0x2739fb(0x2b0)]()-_0x3eb3bb)/(0x10*-0x100+-0x1a*-0xec+-0x28*0x1a)),_0x51b85a=((()=>{const _0x3700b0=_0x2739fb,_0x4bc784=_0x1cb4c9;if(_0x5cae60[_0x3700b0(0x5e8)]===_0x3700b0(0x282))return'❌\x20'+escapeMarkdown(_0x475fc2)+(_0x3700b0(0x43b)+'nd\x20(race?)');if(_0x5cae60[_0x4bc784(0x5e8)]===_0x3700b0(0x26f)+'nning')return buildDoneText(_0x5cae60[_0x4bc784(0x290)][_0x3700b0(0x712)],_0xc86502,{'ok':!![],'skipped':!![]});return buildDoneText(_0x5cae60['job'][_0x4bc784(0x712)],_0xc86502,{'ok':!_0x5cae60[_0x4bc784(0x713)],'error':_0x5cae60[_0x4bc784(0x713)]});})());if(_0x58b996!==null)try{await _0x475435['api']['editMessag'+_0x2739fb(0x5d3)](_0x3a6763,_0x58b996,_0x51b85a,{'parse_mode':_0x2739fb(0x501)});}catch(_0x18d628){!isHarmlessTelegramError(_0x18d628)&&await _0x475435[_0x2739fb(0x358)](_0x51b85a)[_0x2739fb(0x442)](()=>{});}else await _0x475435[_0x1cb4c9(0x358)](_0x51b85a,{'parse_mode':'Markdown'})[_0x2739fb(0x442)](()=>_0x475435['reply'](_0x51b85a));return;}await _0x475435[_0x1cb4c9(0x358)]('Unknown\x20cr'+'on\x20command'+_0x2739fb(0x791)+'n\x20for\x20help'+'.');}),_0x7c81f2[_0x5f3d1c(0x592)+_0x5f3d1c(0x1ce)](/^cron:toggle:(.+)$/,async _0x11a3c3=>{const _0x588648=_0x5f3d1c,_0x1bff8e=_0x28d038,_0x3a6102=_0x11a3c3[_0x588648(0x395)][-0x325+-0x236+0x55c],_0x303743=toggleJob(_0x3a6102);if(_0x303743){await _0x11a3c3[_0x1bff8e(0x6df)+'backQuery']((_0x303743['enabled']?_0x1bff8e(0x5fc):_0x588648(0x483))+':\x20'+_0x303743[_0x1bff8e(0x712)]),_0x11a3c3['match']='';const _0x49fc63=listJobs(),_0xc8e2d6=_0x49fc63[_0x1bff8e(0x6aa)](_0x1d0b8f=>{const _0xfd8a4=_0x588648,_0x5d87be=_0x588648,_0x55a1b4=_0x1d0b8f[_0xfd8a4(0x7a6)]?'🟢':'⏸️',_0x5c7179=_0x1d0b8f[_0x5d87be(0x7a6)]?formatNextRun(_0x1d0b8f[_0xfd8a4(0x3ce)]):'paused',_0xf17de0=humanReadableSchedule(_0x1d0b8f[_0x5d87be(0x462)]),_0x2479b6=_0x1d0b8f['oneShot']?_0x5d87be(0x54b):_0x5d87be(0x694)+_0xf17de0;return _0x55a1b4+_0x5d87be(0x513)+_0x1d0b8f[_0xfd8a4(0x712)]+_0x5d87be(0x3cb)+_0x2479b6+_0x5d87be(0x1e7)+_0x5c7179+_0x5d87be(0x532)+_0x1d0b8f['runCount']+('\x20|\x20ID:\x20<co'+_0x5d87be(0x49c))+_0x1d0b8f['id']+_0xfd8a4(0x4ff);}),_0x13e30a=new InlineKeyboard();for(const _0x1c0860 of _0x49fc63){_0x13e30a['text'](_0x1c0860[_0x1bff8e(0x7a6)]?'⏸\x20'+_0x1c0860[_0x1bff8e(0x712)]:'▶️\x20'+_0x1c0860['name'],'cron:toggl'+'e:'+_0x1c0860['id']),_0x13e30a['text']('🗑',_0x1bff8e(0x701)+'e:'+_0x1c0860['id']),_0x13e30a[_0x588648(0x208)]();}await _0x11a3c3[_0x1bff8e(0x5aa)+_0x588648(0x5d3)]('⏰\x20<b>Cron\x20'+'Jobs\x20('+_0x49fc63['length']+_0x588648(0x276)+_0xc8e2d6[_0x588648(0x1d7)]('\x0a\x0a'),{'parse_mode':_0x588648(0x3b4),'reply_markup':_0x13e30a});}}),_0x7c81f2['callbackQu'+_0x5f3d1c(0x1ce)](/^cron:delete:(.+)$/,async _0x31ca27=>{const _0x549f26=_0x28d038,_0x35ed3d=_0x28d038,_0x206d0e=_0x31ca27[_0x549f26(0x395)][-0x1102*-0x2+-0x8b*-0x3+-0x2*0x11d2];deleteJob(_0x206d0e),await _0x31ca27[_0x35ed3d(0x6df)+_0x35ed3d(0x5d1)](_0x35ed3d(0x1ff));const _0x4f2685=listJobs();if(_0x4f2685[_0x549f26(0x77d)]===-0x12d0+0x9f*0x8+-0x1bb*-0x8)await _0x31ca27['editMessag'+'eText'](_0x549f26(0x488)+_0x35ed3d(0x38a)+_0x35ed3d(0x248));else{const _0x3095fe=_0x4f2685[_0x549f26(0x6aa)](_0x3c006d=>{const _0x4fdcbb=_0x549f26,_0x9d7db7=_0x549f26,_0x3d827f=_0x3c006d[_0x4fdcbb(0x7a6)]?'🟢':'⏸️',_0x4baad4=humanReadableSchedule(_0x3c006d[_0x4fdcbb(0x462)]);return _0x3d827f+_0x4fdcbb(0x513)+_0x3c006d[_0x9d7db7(0x712)]+_0x9d7db7(0x3cb)+_0x4baad4+(_0x9d7db7(0x72e)+_0x9d7db7(0x49c))+_0x3c006d['id']+_0x9d7db7(0x4ff);}),_0x324d13=new InlineKeyboard();for(const _0x703c3b of _0x4f2685){_0x324d13[_0x35ed3d(0x578)](_0x703c3b['enabled']?'⏸\x20'+_0x703c3b[_0x35ed3d(0x712)]:_0x549f26(0x497)+_0x703c3b[_0x35ed3d(0x712)],_0x549f26(0x439)+'e:'+_0x703c3b['id']),_0x324d13[_0x35ed3d(0x578)]('🗑','cron:delet'+'e:'+_0x703c3b['id']),_0x324d13[_0x549f26(0x208)]();}await _0x31ca27['editMessag'+_0x549f26(0x5d3)](_0x549f26(0x242)+_0x549f26(0x608)+_0x4f2685[_0x35ed3d(0x77d)]+_0x35ed3d(0x276)+_0x3095fe[_0x549f26(0x1d7)]('\x0a\x0a'),{'parse_mode':_0x35ed3d(0x3b4),'reply_markup':_0x324d13});}}),_0x7c81f2['command'](_0x28d038(0x3f1),async _0x30690c=>{const _0x239df6=_0x5f3d1c,_0x581b3e=_0x28d038,_0x37a3b3=_0x30690c[_0x239df6(0x395)]?.['toString']()[_0x581b3e(0x43d)]()||'';if(!_0x37a3b3){const _0x3797fc=getRegistry(),_0x4f7c13=await _0x3797fc[_0x239df6(0x5a5)](),_0x10f856=_0x3797fc['getActive']()[_0x581b3e(0x449)](),_0x58c0c5=new InlineKeyboard()['text'](_0x239df6(0x1cc)+_0x581b3e(0x337),_0x239df6(0x678))[_0x239df6(0x208)]()['text'](_0x239df6(0x6e7)+'s','setup:plat'+_0x239df6(0x1d5))[_0x581b3e(0x208)]()['text'](_0x581b3e(0x367)+_0x239df6(0x730)+'s','setup:sudo')['row']()[_0x581b3e(0x578)](_0x581b3e(0x220)+'ons\x20Wizard'+_0x239df6(0x6eb),_0x581b3e(0x1ee)+_0x239df6(0x6dd))['row']()[_0x581b3e(0x578)](_0x581b3e(0x768)+_0x581b3e(0x5d7),_0x239df6(0x422))[_0x581b3e(0x208)]();await _0x30690c[_0x239df6(0x358)](_0x239df6(0x593)+_0x581b3e(0x5ec)+'\x0a'+(_0x239df6(0x408)+_0x239df6(0x4ee)+_0x10f856[_0x239df6(0x712)]+'\x0a')+(_0x581b3e(0x1fd)+_0x581b3e(0x2db)+_0x4f7c13['length']+(_0x581b3e(0x265)+'d\x0a'))+('*Web\x20UI:*\x20'+'http://loc'+_0x581b3e(0x2c9)+(process[_0x581b3e(0x440)][_0x239df6(0x2a1)]||0x1*-0x202a+-0x85*-0x2+0x2b3c)+'\x0a\x0a')+(_0x581b3e(0x4a2)+_0x581b3e(0x2d8)+'to\x20configu'+'re?'),{'parse_mode':'Markdown','reply_markup':_0x58c0c5});return;}if(_0x37a3b3[_0x581b3e(0x245)](_0x239df6(0x67a))){const _0x164cf1=_0x37a3b3[_0x581b3e(0x450)](0x9*-0x179+0x2*-0x2bc+-0x27*-0x7b)['trim']();if(!_0x164cf1){const _0x57fffd=await getSudoStatus(),_0x24ecc2=_0x57fffd[_0x581b3e(0x717)]?_0x57fffd[_0x239df6(0x397)]?'✅':'⚠️':'❌',_0x3507f3=new InlineKeyboard();_0x57fffd[_0x581b3e(0x717)]&&(_0x3507f3[_0x581b3e(0x578)]('🧪\x20Verify',_0x581b3e(0x610)+'y')[_0x239df6(0x208)](),_0x3507f3['text']('🔴\x20Revoke\x20A'+_0x239df6(0x3d3),_0x239df6(0x5be)+'e')['row']());await _0x30690c[_0x581b3e(0x358)]('🔐\x20*Sudo\x20/\x20'+_0x239df6(0x591)+'ss*\x0a\x0a'+(_0x239df6(0x2e8)+_0x24ecc2+'\x20'+(_0x57fffd[_0x581b3e(0x717)]?_0x57fffd[_0x581b3e(0x397)]?_0x239df6(0x2bf)+_0x581b3e(0x504)+'d':_0x239df6(0x2bf)+',\x20not\x20veri'+_0x239df6(0x2eb):'Not\x20set\x20up')+'\x0a')+('*Storage:*'+'\x20'+_0x57fffd[_0x581b3e(0x2cc)+_0x581b3e(0x44c)]+'\x0a')+(_0x239df6(0x599)+_0x57fffd[_0x581b3e(0x30c)]+'\x20('+_0x57fffd[_0x239df6(0x232)]+')\x0a')+(_0x57fffd['permission'+'s']['accessibil'+_0x239df6(0x695)]!==null?_0x581b3e(0x411)+'lity:*\x20'+(_0x57fffd['permission'+'s'][_0x239df6(0x5f6)+_0x239df6(0x695)]?'✅':'❌')+'\x0a':'')+(_0x57fffd[_0x581b3e(0x357)+'s']['fullDiskAc'+_0x239df6(0x1d2)]!==null?_0x239df6(0x453)+_0x581b3e(0x528)+(_0x57fffd[_0x581b3e(0x357)+'s'][_0x239df6(0x59c)+'cess']?'✅':'❌')+'\x0a':'')+(_0x239df6(0x307)+_0x239df6(0x704)+_0x239df6(0x2fc)+_0x239df6(0x7a4)+_0x581b3e(0x753))+(_0x239df6(0x43f)+_0x239df6(0x432)+'urely\x20stor'+_0x581b3e(0x1f8)+_0x57fffd['storageMet'+_0x239df6(0x44c)]+'.\x20')+('This\x20allow'+_0x581b3e(0x4e9)+_0x581b3e(0x60f)+'dmin\x20comma'+_0x581b3e(0x1cd)+_0x239df6(0x420)+_0x239df6(0x207)+_0x239df6(0x452)+_0x239df6(0x3ba)+_0x581b3e(0x1b9))+(_0x239df6(0x47f)+_0x581b3e(0x2df)+_0x239df6(0x5cd)+_0x581b3e(0x620)+'password\x20i'+'s\x20visible\x20'+_0x581b3e(0x413)+_0x239df6(0x300)),{'parse_mode':_0x239df6(0x501),'reply_markup':_0x3507f3});return;}await _0x30690c[_0x239df6(0x6bb)][_0x581b3e(0x1c5)+_0x581b3e(0x2e0)](_0x30690c[_0x239df6(0x5a1)]['id'],_0x239df6(0x596));const _0x381261=storePassword(_0x164cf1);if(!_0x381261['ok']){await _0x30690c['reply'](_0x239df6(0x1c6)+_0x239df6(0x2d9)+_0x381261[_0x581b3e(0x713)]);return;}const _0x1e3e8f=await verifyPassword();_0x1e3e8f['ok']?await _0x30690c[_0x239df6(0x358)]('✅\x20*Sudo\x20ac'+'cess\x20confi'+_0x581b3e(0x5dd)+('Password\x20s'+_0x239df6(0x746)+_0x381261[_0x581b3e(0x41f)]+'\x0a')+(_0x581b3e(0x377)+'on:\x20✅\x20succ'+_0x581b3e(0x5b3))+(_0x239df6(0x5e7)+_0x239df6(0x640)+_0x239df6(0x4eb)+_0x239df6(0x55e))+(_0x239df6(0x463)+_0x239df6(0x3de)+_0x239df6(0x33c)+_0x239df6(0x4bd)+_0x239df6(0x69e)+_0x239df6(0x1d0)+'!_'),{'parse_mode':_0x239df6(0x501)}):(revokePassword(),await _0x30690c[_0x581b3e(0x358)](_0x581b3e(0x64f)+_0x239df6(0x64b)+'\x0a'+(_0x239df6(0x41c)+_0x239df6(0x35e)+'\x20does\x20not\x20'+_0x239df6(0x48f)+_0x239df6(0x747))+(_0x239df6(0x6da)+_0x581b3e(0x2b7)+'setup\x20sudo'+_0x239df6(0x4b3)+_0x239df6(0x37f)),{'parse_mode':_0x239df6(0x501)}));try{await _0x30690c[_0x239df6(0x6bb)][_0x239df6(0x6a0)+_0x581b3e(0x48c)](_0x30690c['chat']['id'],_0x30690c[_0x239df6(0x261)][_0x239df6(0x784)]);}catch{}return;}if(_0x37a3b3['startsWith']('key\x20')){const _0x2be345=_0x37a3b3['slice'](0x7*0x8d+0x166d+-0x1a44)[_0x581b3e(0x43d)]()[_0x239df6(0x25c)](/\s+/);if(_0x2be345[_0x239df6(0x77d)]<-0x22*-0x4+0x1a20+-0x1aa6){await _0x30690c[_0x581b3e(0x358)](_0x581b3e(0x24c)+'\x20Key:*\x0a\x0a'+(_0x581b3e(0x34e)+_0x581b3e(0x3a2)+_0x239df6(0x751))+('`/setup\x20ke'+_0x239df6(0x696)+'Iza...`\x0a')+(_0x581b3e(0x34e)+_0x581b3e(0x5c7)+'vapi-...`\x0a')+(_0x239df6(0x34e)+_0x239df6(0x5db)+_0x581b3e(0x723)+'..`\x0a\x0a')+(_0x581b3e(0x216)+_0x239df6(0x71a)+_0x581b3e(0x6d9)+_0x581b3e(0x3cd)+_0x239df6(0x63c)),{'parse_mode':'Markdown'});return;}const _0x5b7917={'openai':_0x239df6(0x427)+_0x239df6(0x3e8),'google':_0x581b3e(0x749)+'_KEY','nvidia':_0x239df6(0x661)+_0x239df6(0x3e8),'openrouter':'OPENROUTER'+_0x581b3e(0x60b),'groq':'GROQ_API_K'+'EY'},_0x342d60=_0x2be345[-0x23bb*0x1+-0x11b9*0x2+0x472d][_0x239df6(0x2d5)+'e'](),_0x24b374=_0x2be345[_0x581b3e(0x450)](-0x1304+0x2*0x5bc+0x78d)['join']('\x20'),_0x50ac66=_0x5b7917[_0x342d60];if(!_0x50ac66){await _0x30690c[_0x581b3e(0x358)](_0x581b3e(0x298)+_0x581b3e(0x630)+_0x342d60+_0x581b3e(0x257)+Object[_0x581b3e(0x31c)](_0x5b7917)[_0x581b3e(0x1d7)](',\x20'));return;}const _0x2b905d=resolve(process[_0x239df6(0x73b)](),'.env');let _0x9d4192=_0x477de6[_0x581b3e(0x765)](_0x2b905d)?_0x477de6[_0x581b3e(0x429)+'nc'](_0x2b905d,'utf-8'):'';const _0xcbf120=new RegExp('^'+_0x50ac66+_0x581b3e(0x6e3),'m');if(_0xcbf120[_0x239df6(0x6c2)](_0x9d4192))_0x9d4192=_0x9d4192[_0x239df6(0x6ed)](_0xcbf120,_0x50ac66+'='+_0x24b374);else _0x9d4192=_0x9d4192[_0x239df6(0x6bf)]()+('\x0a'+_0x50ac66+'='+_0x24b374+'\x0a');_0x477de6['writeFileS'+_0x239df6(0x28b)](_0x2b905d,_0x9d4192),await _0x30690c[_0x239df6(0x358)]('✅\x20'+_0x50ac66+('\x20saved!\x20Pl'+_0x581b3e(0x506)+'rt\x20the\x20bot'+'\x20(/system\x20'+_0x581b3e(0x5f5)+_0x581b3e(0x573)));return;}}),_0x7c81f2[_0x28d038(0x592)+'ery'](/^sudo:(.+)$/,async _0x487b10=>{const _0x41f750=_0x5f3d1c,_0x935b52=_0x28d038,_0x8b77f1=_0x487b10[_0x41f750(0x395)][0x327+-0x1271+0x1d*0x87];if(_0x8b77f1===_0x41f750(0x625)){const _0x4d3876=await verifyPassword();await _0x487b10[_0x41f750(0x6df)+_0x41f750(0x5d1)](_0x4d3876['ok']?_0x935b52(0x35c)+_0x935b52(0x294):'❌\x20'+_0x4d3876['error']);}else _0x8b77f1===_0x935b52(0x690)&&(revokePassword(),await _0x487b10['editMessag'+_0x935b52(0x5d3)](_0x935b52(0x5bb)+_0x935b52(0x78b)+_0x935b52(0x3ed)+'d\x20deleted.'),await _0x487b10[_0x935b52(0x6df)+_0x935b52(0x5d1)](_0x935b52(0x728)+_0x41f750(0x754)));}),_0x7c81f2['callbackQu'+_0x28d038(0x1ce)](/^setup:(.+)$/,async _0x4d8886=>{const _0x553100=_0x5f3d1c,_0x3d406b=_0x5f3d1c,_0x3e288b=_0x4d8886[_0x553100(0x395)][0x2431+-0x2091+-0x39f*0x1];switch(_0x3e288b){case'keys':{const _0x412cf2=[{'name':_0x553100(0x609),'env':_0x3d406b(0x427)+_0x553100(0x3e8),'has':!!config[_0x3d406b(0x479)][_0x553100(0x6f3)]},{'name':_0x553100(0x70f),'env':'GOOGLE_API'+_0x553100(0x3e8),'has':!!config[_0x3d406b(0x479)][_0x553100(0x687)]},{'name':_0x3d406b(0x45c),'env':'NVIDIA_API'+_0x3d406b(0x3e8),'has':!!config[_0x553100(0x479)][_0x3d406b(0x5cb)]},{'name':_0x3d406b(0x2b2),'env':'OPENROUTER'+_0x3d406b(0x60b),'has':!!config['apiKeys'][_0x553100(0x4dd)]},{'name':_0x553100(0x77a),'env':_0x3d406b(0x4fd)+'EY','has':!!config[_0x553100(0x479)][_0x553100(0x414)]}],_0x1c4ee2=_0x412cf2['map'](_0x3612d6=>(_0x3612d6['has']?'✅':'❌')+'\x20*'+_0x3612d6[_0x553100(0x712)]+_0x553100(0x622)+_0x3612d6[_0x553100(0x440)]+'`');await _0x4d8886['editMessag'+_0x3d406b(0x5d3)](_0x3d406b(0x344)+_0x553100(0x44b)+_0x1c4ee2['join']('\x0a')+'\x0a\x0a'+(_0x553100(0x73d)+_0x553100(0x3e7)+_0x553100(0x566)+_0x553100(0x72f))+('Example:\x20`'+_0x3d406b(0x3e7)+'\x20nvidia\x20nv'+_0x3d406b(0x6be))+(_0x553100(0x3bb)+'equired\x20af'+_0x553100(0x534)+_0x553100(0x733)),{'parse_mode':_0x553100(0x501)});break;}case _0x3d406b(0x660):{const _0x335c50=[{'name':_0x3d406b(0x72d),'icon':'📱','env':_0x553100(0x47c),'has':!!process['env'][_0x553100(0x47c)]},{'name':_0x553100(0x3df),'icon':'🎮','env':'DISCORD_TO'+_0x553100(0x773),'has':!!process[_0x553100(0x440)]['DISCORD_TO'+_0x3d406b(0x773)]},{'name':'WhatsApp','icon':'💬','env':'WHATSAPP_E'+_0x553100(0x41a),'has':process[_0x553100(0x440)][_0x553100(0x2b8)+'NABLED']===_0x553100(0x306)},{'name':_0x3d406b(0x1b3),'icon':'🔒','env':_0x3d406b(0x66c)+'_URL','has':!!process[_0x553100(0x440)][_0x553100(0x66c)+'_URL']}],_0x36ff06=_0x335c50[_0x553100(0x6aa)](_0x17a8a3=>(_0x17a8a3['has']?'✅':'❌')+'\x20'+_0x17a8a3['icon']+'\x20*'+_0x17a8a3[_0x553100(0x712)]+_0x3d406b(0x622)+_0x17a8a3['env']+'`');await _0x4d8886['editMessag'+_0x3d406b(0x5d3)](_0x553100(0x546)+'ms*\x0a\x0a'+_0x36ff06['join']('\x0a')+'\x0a\x0a'+(_0x553100(0x759)+_0x3d406b(0x6af)+'\x20Web\x20UI:\x20M'+_0x553100(0x4d2)+_0x3d406b(0x426))+(_0x553100(0x602)+'\x20can\x20enter'+'\x20tokens\x20an'+'d\x20install\x20'+'dependenci'+'es._'),{'parse_mode':_0x3d406b(0x501)});break;}case _0x553100(0x67a):{const _0x77433a=await getSudoStatus(),_0x560d98=_0x77433a['configured']?_0x77433a[_0x553100(0x397)]?'✅':'⚠️':'❌';await _0x4d8886[_0x3d406b(0x5aa)+_0x553100(0x5d3)](_0x3d406b(0x4e8)+_0x553100(0x591)+_0x553100(0x76d)+(_0x3d406b(0x2e8)+_0x560d98+'\x20'+(_0x77433a[_0x3d406b(0x717)]?_0x77433a[_0x3d406b(0x397)]?_0x3d406b(0x6de)+_0x3d406b(0x1d6):_0x3d406b(0x2bf):_0x3d406b(0x1c9))+'\x0a')+(_0x3d406b(0x1b5)+'\x20'+_0x77433a['storageMet'+_0x553100(0x44c)]+'\x0a\x0a')+(_0x553100(0x369)+_0x553100(0x736)+_0x3d406b(0x285)+_0x3d406b(0x1dc))+(_0x553100(0x685)+_0x3d406b(0x560)+_0x553100(0x3e9)+'e\x22\x20button\x0a'+'\x0a')+(_0x553100(0x43f)+_0x553100(0x432)+_0x3d406b(0x79c)+_0x553100(0x1f8)+_0x77433a[_0x553100(0x2cc)+'hod']+'._'),{'parse_mode':_0x3d406b(0x501)});break;}case _0x553100(0x357)+'s':{try{const {readPermissionsSnapshot:_0x4f41f5}=await import(_0x553100(0x264)+_0x3d406b(0x3f4)+_0x3d406b(0x27d)+'.js'),_0x509126=await _0x4f41f5(),_0xf02aa9={'granted':'✅','missing':'❌','tool-missing':'⚠️','n/a':'·'},_0x176673=_0x509126[_0x553100(0x6aa)](_0xfef16b=>_0xf02aa9[_0xfef16b[_0x553100(0x5b2)]]+'\x20*'+_0xfef16b['permission'][_0x3d406b(0x712)]+_0x3d406b(0x56e)+_0xfef16b['state']+(_0xfef16b[_0x553100(0x65c)]?'\x20\x20_('+_0xfef16b['detail']+')_':'')),_0x5bcb1e=_0x509126[_0x3d406b(0x5c8)](_0xf00605=>_0xf00605[_0x553100(0x5b2)]==='missing'||_0xf00605[_0x553100(0x5b2)]===_0x3d406b(0x23c)+'ng')[_0x553100(0x77d)],_0x53e39d=_0x5bcb1e===-0x63a*-0x1+0x1d1c+-0x2356?_0x3d406b(0x613)+'cable\x20perm'+_0x553100(0x6c0)+_0x3d406b(0x383):'*'+_0x5bcb1e+('\x20permissio'+'n')+(_0x5bcb1e===-0x1adc+0x17*0x6f+0x2*0x872?'':'s')+(_0x3d406b(0x739)+_0x3d406b(0x255));await _0x4d8886['editMessag'+_0x3d406b(0x5d3)]('🛡️\x20*Permiss'+'ions\x20Statu'+'s*\x0a\x0a'+_0x176673[_0x553100(0x1d7)]('\x0a')+'\x0a\x0a'+_0x53e39d+'\x0a\x0a'+(_0x553100(0x1dd)+_0x3d406b(0x363)+'ny\x20app\x20gra'+_0x553100(0x3a6)+_0x3d406b(0x3dd)+_0x3d406b(0x52c)+'—\x20you\x20togg'+_0x553100(0x230)+'tch,\x20the\x20w'+_0x3d406b(0x624)+_0x3d406b(0x638))+(_0x3d406b(0x6c4)+_0x553100(0x563)+_0x3d406b(0x523))+(_0x553100(0x4d9)+'lvin-bot\x20p'+'ermissions'+_0x3d406b(0x569)+_0x553100(0x729)+_0x553100(0x1df)+_0x553100(0x404)+'s,\x20verifie'+_0x3d406b(0x627))+(_0x3d406b(0x3f6)+_0x553100(0x3fe)+_0x553100(0x2c9)+(process[_0x553100(0x440)]['WEB_PORT']||-0xb08+-0x17dd+0x2f01)+(_0x3d406b(0x561)+'s')),{'parse_mode':_0x3d406b(0x501)});}catch(_0x26ff8d){await _0x4d8886[_0x3d406b(0x5aa)+_0x3d406b(0x5d3)](_0x3d406b(0x3e2)+_0x553100(0x3d9)+_0x553100(0x4fe)+_0x553100(0x3ac)+_0x553100(0x70d)+'ule\x20—\x20try\x20'+'`alvin-bot'+_0x553100(0x522)+_0x553100(0x419)+_0x553100(0x31a)+_0x553100(0x20c),{'parse_mode':'Markdown'});}break;}case _0x3d406b(0x2bb):{await _0x4d8886['editMessag'+'eText'](_0x553100(0x480)+'hboard*\x0a\x0a'+('URL:\x20`http'+_0x553100(0x258)+_0x3d406b(0x6d8)+(process['env'][_0x553100(0x2a1)]||0x1fd+0x9c1+-0x5e*-0x1)+_0x553100(0x520))+(_0x553100(0x697)+_0x553100(0x41e)+_0x553100(0x5ba))+(_0x553100(0x52f)+_0x553100(0x30a)+_0x553100(0x339))+('•\x20📱\x20Set\x20up'+_0x3d406b(0x4b1)+'\x0a')+(_0x3d406b(0x2be)+_0x3d406b(0x2f4)+'\x0a')+(_0x3d406b(0x304)+_0x3d406b(0x49e))+(_0x553100(0x785)+_0x3d406b(0x663))+('•\x20🛠️\x20Run\x20to'+_0x3d406b(0x210)),{'parse_mode':_0x553100(0x501)});break;}}await _0x4d8886[_0x3d406b(0x6df)+'backQuery']();});function _0x192874(_0x44912c){return{'interruptQuery':()=>interruptQuery(_0x44912c),'killDetachedAgents':()=>killSessionDetachedAgents(_0x44912c),'clearPendingForSession':_0x1f2262=>cancelPendingForSession(_0x1f2262)};}_0x7c81f2[_0x28d038(0x4c8)](_0x5f3d1c(0x7a3),async _0x1a1c4c=>{const _0x248254=_0x5f3d1c,_0x27f7f4=_0x5f3d1c,_0x4a7c30=_0x1a1c4c[_0x248254(0x3e5)]['id'],_0x46d599=buildSessionKey(_0x27f7f4(0x3f7),_0x1a1c4c[_0x27f7f4(0x5a1)]['id'],_0x4a7c30),_0xa1c148=getSession(_0x46d599),_0x342caa=_0xa1c148[_0x27f7f4(0x1ca)];_0xa1c148[_0x248254(0x4d8)+'ng']?(requestStop(_0xa1c148,_0x248254(0x50b),_0x192874(_0xa1c148)),await _0x1a1c4c[_0x248254(0x358)](t(_0x248254(0x742)+_0x248254(0x6a8)+'g',_0x342caa)),await _0x1a1c4c[_0x27f7f4(0x358)](t(_0x27f7f4(0x742)+_0x27f7f4(0x78f),_0x342caa))[_0x248254(0x442)](()=>{})):await _0x1a1c4c[_0x248254(0x358)](t(_0x248254(0x742)+'.noRunning',_0x342caa));}),_0x7c81f2['command'](_0x5f3d1c(0x458),async _0xb2f509=>{const _0x598741=_0x28d038,_0x4cf3df=_0x5f3d1c,_0x2b893b=_0xb2f509[_0x598741(0x3e5)]['id'],_0x20be39=buildSessionKey(_0x598741(0x3f7),_0xb2f509[_0x598741(0x5a1)]['id'],_0x2b893b),_0x468130=getSession(_0x20be39),_0x35b885=_0x468130[_0x4cf3df(0x1ca)];_0x468130[_0x4cf3df(0x4d8)+'ng']?(requestStop(_0x468130,'hard',_0x192874(_0x468130)),await _0xb2f509[_0x4cf3df(0x358)](t(_0x598741(0x742)+_0x4cf3df(0x48a)+'l',_0x35b885))):await _0xb2f509[_0x598741(0x358)](t('bot.cancel'+_0x4cf3df(0x1fc),_0x35b885));}),_0x7c81f2[_0x5f3d1c(0x592)+_0x5f3d1c(0x1ce)](/^stop:(.+)$/,async _0x4f4bda=>{const _0x24aadb=_0x28d038,_0x5e1983=_0x5f3d1c,_0x251377=_0x4f4bda[_0x24aadb(0x395)][0xbf2+0x3*0x46f+0x9*-0x2ce],_0x163ad0=getSession(_0x251377),_0x76d542=_0x163ad0[_0x5e1983(0x1ca)],_0x486a05=_0x163ad0['isProcessi'+'ng'];_0x486a05&&requestStop(_0x163ad0,_0x24aadb(0x50b),_0x192874(_0x163ad0));const _0x562806=_0x486a05?_0x5e1983(0x742)+_0x5e1983(0x1c4)+_0x5e1983(0x486):_0x24aadb(0x742)+'.alreadyDo'+'ne';try{await _0x4f4bda['answerCall'+_0x5e1983(0x5d1)]({'text':t(_0x562806,_0x76d542)});}catch{}try{await _0x4f4bda[_0x5e1983(0x5aa)+_0x24aadb(0x262)+'up']({});}catch{}_0x486a05&&await _0x4f4bda[_0x24aadb(0x358)](t(_0x24aadb(0x742)+'.confirmed',_0x76d542))['catch'](()=>{});}),_0x7c81f2[_0x5f3d1c(0x4c8)]('restart',async _0x33c5b9=>{const _0x2ef9d1=_0x5f3d1c,_0x53657e=_0x28d038,_0x32952b=getSession(_0x33c5b9[_0x2ef9d1(0x3e5)]['id'])['language'];await _0x33c5b9[_0x2ef9d1(0x358)](t(_0x2ef9d1(0x343)+_0x53657e(0x403)+'d',_0x32952b)),markExpectedRestart(),setTimeout(()=>process[_0x53657e(0x3bc)](-0x4*-0x301+-0x4*-0x5cb+-0x2330),-0x16cb+-0x2af+0x1b6e);}),_0x7c81f2[_0x5f3d1c(0x4c8)](_0x5f3d1c(0x3f9),async _0x21a83a=>{const _0x51052f=_0x28d038,_0x4be909=_0x28d038,_0x58fab6=getSession(_0x21a83a[_0x51052f(0x3e5)]['id'])[_0x51052f(0x1ca)];await _0x21a83a['reply'](t(_0x4be909(0x1f1)+_0x51052f(0x7a1),_0x58fab6));try{const _0x3ab705=await runUpdate();if(_0x3ab705['ok']){await _0x21a83a[_0x4be909(0x358)]('✅\x20'+_0x3ab705[_0x4be909(0x261)]);const _0x350acc=_0x3ab705[_0x51052f(0x261)][_0x4be909(0x395)](/v(\d+\.\d+\.\d+)/);if(_0x350acc){const _0x16ece2=getReleaseHighlights(_0x350acc[-0x7c8*0x4+-0xbc*-0x3+0x1ced]);_0x16ece2&&await _0x21a83a[_0x51052f(0x358)](_0x4be909(0x4a9)+_0x51052f(0x745)+_0x350acc[0x1*0x1903+0x269e+0x4*-0xfe8]+_0x51052f(0x3b6)+_0x16ece2,{'parse_mode':_0x51052f(0x501)});}_0x3ab705[_0x51052f(0x43a)+_0x4be909(0x359)]&&(await _0x21a83a[_0x51052f(0x358)](t('bot.update'+_0x4be909(0x6b4)+'g',_0x58fab6)),markExpectedRestart(),setTimeout(()=>process[_0x4be909(0x3bc)](0x1bce+0xca2+-0x50e*0x8),-0xc9c+-0x941*-0x1+0x54f));}else await _0x21a83a[_0x4be909(0x358)](t(_0x4be909(0x1f1)+_0x51052f(0x1e8),_0x58fab6)+'\x0a`'+_0x3ab705['message']+'`',{'parse_mode':_0x4be909(0x501)});}catch(_0x17c2fb){const _0x5cd437=_0x17c2fb instanceof Error?_0x17c2fb[_0x4be909(0x261)]:String(_0x17c2fb);await _0x21a83a[_0x51052f(0x358)](t(_0x4be909(0x1f1)+_0x51052f(0x247),_0x58fab6)+'\x20'+_0x5cd437);}}),_0x7c81f2[_0x28d038(0x4c8)](_0x28d038(0x38c),async _0x4c5d93=>{const _0x2d4858=_0x28d038,_0x220eb5=_0x5f3d1c,_0x3d2e6d=getSession(_0x4c5d93[_0x2d4858(0x3e5)]['id'])[_0x220eb5(0x1ca)],_0x3c46e7=(_0x4c5d93[_0x2d4858(0x395)]||'')[_0x2d4858(0x43d)]()['toLowerCas'+'e']();if(_0x3c46e7==='on')setAutoUpdate(!![]),await _0x4c5d93[_0x2d4858(0x358)](t(_0x2d4858(0x545)+_0x220eb5(0x1d9)+'ed',_0x3d2e6d),{'parse_mode':_0x2d4858(0x501)});else{if(_0x3c46e7===_0x2d4858(0x702))setAutoUpdate(![]),await _0x4c5d93[_0x2d4858(0x358)](t(_0x2d4858(0x545)+_0x2d4858(0x657)+_0x220eb5(0x6cb),_0x3d2e6d),{'parse_mode':_0x2d4858(0x501)});else{const _0x339acc=getAutoUpdate();await _0x4c5d93[_0x220eb5(0x358)](t(_0x2d4858(0x545)+_0x220eb5(0x77b)+_0x2d4858(0x5d0),_0x3d2e6d)+'\x20*'+(_0x339acc?'ON':_0x2d4858(0x68b))+_0x2d4858(0x3b6)+t(_0x220eb5(0x545)+_0x220eb5(0x4ae)+_0x220eb5(0x78d),_0x3d2e6d)+(_0x2d4858(0x3d1)+_0x2d4858(0x615)+_0x2d4858(0x38c)+_0x2d4858(0x496)),{'parse_mode':'Markdown'});}}}),_0x7c81f2[_0x5f3d1c(0x4c8)]('cleanup',async _0x5d7a1c=>{const _0x508796=_0x28d038,_0x2d119c=_0x5f3d1c,_0x4994b8=(_0x5d7a1c[_0x508796(0x395)]||'')[_0x508796(0x43d)]()[_0x2d119c(0x2d5)+'e']();if(_0x4994b8==='run'||_0x4994b8==='now'){await _0x5d7a1c[_0x508796(0x358)](_0x508796(0x209)+_0x2d119c(0x767)+_0x508796(0x552));const _0x5af686=await runCleanup(),_0x30978e=_0x5af686[_0x2d119c(0x25e)+'imed'],_0x18382a=_0x30978e<(-0x1ba9*0x1+-0x13a3+0x334c)*(-0x35*-0x5+-0x1753+-0x2*-0xd25)?(_0x30978e/(0x20b2+0x25aa+0x7c*-0x89))[_0x2d119c(0x2ed)](-0x1*-0x1919+-0x4*-0x5e1+-0x309c)+_0x2d119c(0x75b):_0x30978e<(0x1c5c+0x1194+-0x4*0xa7c)*(0x1d*0x151+0x4f*-0x2a+-0x1537)*(0x883*0x1+0x67*-0x17+-0x2*-0x25f)?(_0x30978e/(0xf0d+-0x1f45+0x1438)/(-0x11c*0x1+0x2462+-0x1f46*0x1))[_0x508796(0x2ed)](0x7e3+-0x20bd*0x1+0x18db)+_0x508796(0x1cb):(_0x30978e/(0x155b+-0x964+0x7f7*-0x1)/(-0x1950+0x1*-0x9df+0x1*0x272f)/(0x19c4*-0x1+0xfc9+0x1*0xdfb))['toFixed'](0x1394+0x227*-0x11+0x1105)+_0x2d119c(0x495),_0x1d911e=_0x5af686[_0x2d119c(0x53c)][_0x2d119c(0x77d)]>0x1f7*-0xc+-0x37e*-0x3+-0x56*-0x27?_0x508796(0x1e3)+_0x5af686['errors'][_0x2d119c(0x77d)]+_0x508796(0x3c3):'';await _0x5d7a1c['reply'](_0x508796(0x541)+'done\x0a•\x20Fil'+'es\x20deleted'+':\x20'+_0x5af686[_0x508796(0x778)+'ed']+(_0x2d119c(0x267)+'tated:\x20')+_0x5af686['logsRotate'+'d']+(_0x508796(0x37c)+_0x2d119c(0x340))+_0x18382a+_0x1d911e);}else{const _0x383cc3=getCleanupPolicy();await _0x5d7a1c[_0x2d119c(0x358)](_0x508796(0x731)+_0x2d119c(0x2c4)+('•\x20Log\x20rota'+_0x508796(0x45f)+_0x383cc3[_0x508796(0x308)+'Mb']+'\x20MB\x0a')+('•\x20Screensh'+_0x2d119c(0x271)+_0x383cc3['screenshot'+'sMaxAgeDay'+'s']+_0x508796(0x6fc))+(_0x508796(0x58f)+'\x20outputs:\x20'+'>'+_0x383cc3[_0x2d119c(0x1de)+_0x2d119c(0x1bc)]+_0x508796(0x6fc))+('•\x20/tmp/alv'+_0x508796(0x64a)+_0x383cc3[_0x508796(0x3bd)+_0x508796(0x3e4)]+_0x508796(0x6fc))+(_0x2d119c(0x1ea)+'\x20media:\x20>'+_0x383cc3['waMediaMax'+_0x2d119c(0x67d)]+'\x20days\x0a\x0a')+(_0x2d119c(0x3eb)+_0x508796(0x23e)+_0x508796(0x24a)+'on\x20jobs\x20ar'+_0x508796(0x61a)+_0x508796(0x6ac))+('Configure\x20'+_0x508796(0x310)+_0x508796(0x6f1)+_0x2d119c(0x57c)+_0x508796(0x5e6)+_0x2d119c(0x468)+_0x2d119c(0x27a)+_0x2d119c(0x755)+_0x508796(0x4c2)+'YS`,\x20`CLEA'+_0x508796(0x320)+_0x2d119c(0x6dc)+'NUP_WA_MED'+'IA_DAYS`\x0a\x0a')+(_0x2d119c(0x642)+_0x2d119c(0x3aa)+'nup\x20run`'),{'parse_mode':_0x508796(0x501)});}}),_0x7c81f2[_0x28d038(0x4c8)]([_0x5f3d1c(0x2ec),_0x5f3d1c(0x29c)],async _0x36a60a=>{const _0x2a93e3=_0x5f3d1c,_0x42a41f=_0x5f3d1c,_0x383818=getSession(_0x36a60a[_0x2a93e3(0x3e5)]['id'])['language'],{listSubAgents:_0x2027fd,listActiveSubAgents:_0x5406b0,cancelSubAgent:_0x442ce9,getSubAgentResult:_0x4a9559,getMaxParallelAgents:_0x369f1e,getConfiguredMaxParallel:_0x2bca62,setMaxParallelAgents:_0x5b09fe,findSubAgentByName:_0x33dce3,getVisibility:_0x13fa77,setVisibility:_0x3cdc37,getQueueCap:_0x3eb0f2,setQueueCap:_0x506dd0,getDefaultTimeoutMs:_0x4646cd,setDefaultTimeoutMs:_0x322c97}=await import('../service'+_0x2a93e3(0x2ca)+'s.js'),_0x1141ad=(_0x36a60a[_0x2a93e3(0x395)]||'')[_0x42a41f(0x43d)](),_0xc6b91=_0x1141ad[_0x42a41f(0x25c)](/\s+/)[_0x42a41f(0x5c8)](Boolean),_0x53e110=_0xc6b91[0x189a+0x5b3*0x3+-0x1ab*0x19]?.['toLowerCas'+'e']()||'',_0x2a289b=_0x2a6d53=>_0x2a6d53['slice'](0x1f36+-0x12f7+0xa5*-0x13,-0x226b+-0xd5*0x7+0x2846),_0x4c224e=_0x2c8895=>{const _0x48615d=_0x2a93e3,_0x4a0920=_0x2a93e3,_0x179de1='\x20\x20'[_0x48615d(0x62a)](Math[_0x4a0920(0x323)](-0x2f*0x23+0x64a+0x23,_0x2c8895['depth'])),_0x2d0f73=Math[_0x4a0920(0x39a)]((Date[_0x48615d(0x2b0)]()-_0x2c8895[_0x4a0920(0x6f7)])/(-0x2164+-0x2*0xac2+0x1*0x3ad0)),_0x52644b=_0x2d0f73<-0x1*-0x5c+0x14df+-0x14ff?_0x2d0f73+'s':_0x2d0f73<-0x1ad6+-0xff1+0x38d7?Math[_0x48615d(0x39a)](_0x2d0f73/(0x8e*-0x19+0xd3d*0x1+0xdd))+'m':Math[_0x4a0920(0x39a)](_0x2d0f73/(-0x5d6+0x1370+0x76))+'h',_0x3c9444=_0x2c8895['source']===_0x48615d(0x584)?'⏰':_0x2c8895['source']==='implicit'?'🔗':'👤',_0x2b739a=_0x2c8895[_0x48615d(0x71f)]>-0x8d4*-0x2+-0xd2b*-0x1+-0x1ed3?'\x20d'+_0x2c8895[_0x4a0920(0x71f)]:'',_0x17c23a=_0x2c8895[_0x48615d(0x5e8)]===_0x4a0920(0x621)&&_0x2c8895[_0x48615d(0x445)+_0x48615d(0x331)]?'\x20#'+_0x2c8895['queuePosit'+_0x48615d(0x331)]:'';return''+_0x179de1+_0x3c9444+'\x20`'+_0x2a289b(_0x2c8895['id'])+'`\x20'+_0x2c8895[_0x48615d(0x712)]+'\x20('+_0x2c8895['status']+_0x17c23a+',\x20'+_0x52644b+_0x2b739a+')';};if(_0x53e110===_0x2a93e3(0x323)){const _0x3daa08=parseInt(_0xc6b91[-0xdb4*0x2+0x2085+-0x51c]||'',-0x2309*0x1+-0x662+0x2975);if(isNaN(_0x3daa08)){await _0x36a60a['reply'](t('bot.subage'+_0x2a93e3(0x378),_0x383818),{'parse_mode':_0x42a41f(0x501)});return;}const _0x3401e5=_0x5b09fe(_0x3daa08);await _0x36a60a[_0x42a41f(0x358)](t(_0x2a93e3(0x1f2)+_0x2a93e3(0x551),_0x383818,{'n':_0x3daa08,'eff':_0x3401e5}),{'parse_mode':_0x2a93e3(0x501)});return;}if(_0x53e110===_0x42a41f(0x379)){const {getSubAgentStats:_0x421459}=await import(_0x2a93e3(0x264)+_0x2a93e3(0x2ca)+_0x42a41f(0x31d)),_0xb15495=_0x421459(),_0x33a7a9=_0x5b80fd=>_0x5b80fd<0x1fd*0x7+-0x2ed+0x716*-0x1?''+_0x5b80fd:(_0x5b80fd/(-0x9e4+-0x679+0x1445))[_0x42a41f(0x2ed)](-0x293*-0x1+-0x1*-0x24b1+-0x17*0x1b5)+'k',_0x1b1224=_0x45206d=>{const _0x4281bb=_0x2a93e3,_0x1ea55c=_0x42a41f,_0x22ac49=Math[_0x4281bb(0x39a)](_0x45206d/(-0x4*-0x4bd+-0x1*-0xad1+-0x19dd));if(_0x22ac49<-0xcd3+-0x1dda*0x1+0x2ae9)return _0x22ac49+'s';const _0x355fe9=Math[_0x1ea55c(0x39a)](_0x22ac49/(0x7a1+-0x206b+0x2*0xc83));return _0x355fe9+'m';},_0x5658ae=[_0x2a93e3(0x1bd)+_0x2a93e3(0x525)+'—\x20last\x20'+_0xb15495[_0x42a41f(0x214)+'s']+'h','',_0x42a41f(0x553)+_0xb15495[_0x2a93e3(0x500)]['runs']+_0x2a93e3(0x58e)+_0x33a7a9(_0xb15495[_0x2a93e3(0x500)][_0x42a41f(0x3cc)+'s'])+_0x2a93e3(0x3d7)+_0x33a7a9(_0xb15495[_0x42a41f(0x500)][_0x42a41f(0x36d)+'ns'])+'\x20out\x20·\x20'+_0x1b1224(_0xb15495['total'][_0x42a41f(0x46a)+_0x42a41f(0x2fe)]),'',_0x42a41f(0x79f)+':*',_0x42a41f(0x39f)+_0x2a93e3(0x7a2)+_0xb15495['bySource']['user'][_0x2a93e3(0x70c)]+_0x2a93e3(0x58e)+_0x33a7a9(_0xb15495[_0x42a41f(0x668)][_0x2a93e3(0x232)][_0x42a41f(0x3cc)+'s'])+_0x42a41f(0x3d7)+_0x33a7a9(_0xb15495['bySource'][_0x2a93e3(0x232)][_0x42a41f(0x36d)+'ns'])+_0x2a93e3(0x221),_0x42a41f(0x499)+_0x2a93e3(0x7a2)+_0xb15495['bySource']['cron']['runs']+_0x2a93e3(0x58e)+_0x33a7a9(_0xb15495['bySource'][_0x2a93e3(0x584)][_0x42a41f(0x3cc)+'s'])+_0x2a93e3(0x3d7)+_0x33a7a9(_0xb15495[_0x2a93e3(0x668)][_0x2a93e3(0x584)][_0x2a93e3(0x36d)+'ns'])+_0x42a41f(0x221),_0x2a93e3(0x670)+_0x42a41f(0x722)+_0xb15495[_0x42a41f(0x668)][_0x2a93e3(0x4e3)][_0x2a93e3(0x70c)]+_0x2a93e3(0x58e)+_0x33a7a9(_0xb15495[_0x42a41f(0x668)][_0x42a41f(0x4e3)]['inputToken'+'s'])+_0x42a41f(0x3d7)+_0x33a7a9(_0xb15495['bySource']['implicit'][_0x42a41f(0x36d)+'ns'])+_0x42a41f(0x221),'','*By\x20status'+':*',_0x2a93e3(0x30f)+_0x2a93e3(0x309)+_0xb15495[_0x2a93e3(0x5d2)][_0x2a93e3(0x494)],'\x20\x20⚠️\x20cancel'+_0x42a41f(0x289)+_0xb15495[_0x42a41f(0x5d2)]['cancelled'],'\x20\x20⏱️\x20timeou'+_0x42a41f(0x436)+_0xb15495['byStatus'][_0x2a93e3(0x786)],_0x2a93e3(0x6fe)+_0x42a41f(0x390)+_0xb15495['byStatus']['error']];await _0x36a60a[_0x2a93e3(0x358)](_0x5658ae[_0x2a93e3(0x1d7)]('\x0a'),{'parse_mode':_0x2a93e3(0x501)});return;}if(_0x53e110===_0x42a41f(0x786)){const _0x36f8dd=_0xc6b91[0x1*-0x1141+0x692*-0x4+0x2b8a],_0x4e8f91=_0xdbde60=>{const _0x5c2738=_0x2a93e3,_0x26f47b=_0x2a93e3;if(_0xdbde60<=0x74b+0x1*0x1a1e+-0x2169)return'∞\x20(unlimit'+_0x5c2738(0x720);if(_0xdbde60<-0x5*-0x6d9+-0xe99*0x1+0x26*-0x6a)return _0xdbde60+'ms';const _0x362b3a=_0xdbde60/(-0x1c2e+0x9*0x234+0xc42*0x1);if(_0x362b3a<0x8*-0x41b+0x2*-0xd4+0x22bc)return _0x362b3a+'s';const _0x119d61=_0x362b3a/(0x19d2+-0xbd0+-0xdc6);if(_0x119d61<-0xa3*-0x3d+-0x25af+-0xec)return _0x119d61['toFixed'](_0x119d61<-0xef*0x26+-0x248c*0x1+0x4810?0x101*0x1+0x2e*0xb2+-0x20fc:-0x4*-0x74+-0x15a3+0x7*0x2d5)+_0x5c2738(0x266);return(_0x119d61/(-0x102f*-0x1+0xd1f+0xe89*-0x2))[_0x5c2738(0x2ed)](0x29*0xbf+0x8f8+-0x278e)+'h';};if(!_0x36f8dd){const _0x17a123=_0x4646cd();await _0x36a60a[_0x2a93e3(0x358)](_0x2a93e3(0x2e9)+_0x42a41f(0x790)+_0x2a93e3(0x65d)+_0x4e8f91(_0x17a123)+_0x2a93e3(0x3b6)+(_0x42a41f(0x42b)+'ubagents\x20t'+'imeout\x20<se'+'c>`\x20·\x20`/su'+_0x42a41f(0x241)+_0x42a41f(0x3a5)+'\x0a')+(_0x42a41f(0x438)+_0x42a41f(0x508)+_0x42a41f(0x493)+_0x42a41f(0x34b)+'\x20Timeout.\x20')+('Gilt\x20für\x20n'+_0x42a41f(0x3a4)+_0x42a41f(0x3fa)+'-query\x20Cro'+'n-Jobs\x20ohn'+_0x42a41f(0x51d)+'Wert.'),{'parse_mode':_0x42a41f(0x501)});return;}const _0x58781c=_0x36f8dd[_0x2a93e3(0x2d5)+'e']();let _0x33faee;if([_0x42a41f(0x702),'unlimited',_0x42a41f(0x675),'-1','0'][_0x2a93e3(0x3ee)](_0x58781c))_0x33faee=-(0x42a+-0x199*0x11+0x1*0x1700);else{const _0x46d3de=Number(_0x36f8dd);if(!Number[_0x42a41f(0x5cf)](_0x46d3de)||_0x46d3de<-0x11b7*0x1+-0x2b8*-0x5+0xd3*0x5){await _0x36a60a[_0x42a41f(0x358)](_0x42a41f(0x40d)+_0x42a41f(0x4e5)+_0x36f8dd+(_0x2a93e3(0x6a7)+'ekunden\x20(z'+_0x2a93e3(0x4a0)+'\x20oder\x20`off'+'`.'),{'parse_mode':_0x42a41f(0x501)});return;}_0x33faee=Math[_0x2a93e3(0x39a)](_0x46d3de*(-0x8*-0x496+-0x23a4+0x2dc));}const _0x379d62=_0x322c97(_0x33faee);await _0x36a60a[_0x2a93e3(0x358)](_0x2a93e3(0x2b5)+_0x42a41f(0x790)+_0x42a41f(0x65d)+_0x4e8f91(_0x379d62)+'*',{'parse_mode':_0x42a41f(0x501)});return;}if(_0x53e110===_0x2a93e3(0x2f0)){const _0x592bc0=parseInt(_0xc6b91[0xad1+0x666*0x3+-0x1e02]||'',0x69e+-0xc7*0x12+0x76a);if(isNaN(_0x592bc0)){const _0x4a5cbb=_0x3eb0f2();await _0x36a60a['reply'](_0x2a93e3(0x33b)+'\x20*'+_0x4a5cbb+_0x2a93e3(0x401)+(_0x4a5cbb===-0xf8*-0x4+0x1571*0x1+-0x1951?_0x42a41f(0x5b5):_0x2a93e3(0x719))+(')\x0aUsage:\x20`'+_0x42a41f(0x217)+_0x2a93e3(0x47a)+_0x2a93e3(0x409)+_0x2a93e3(0x62f)+_0x2a93e3(0x2af)+_0x2a93e3(0x4ec)),{'parse_mode':_0x42a41f(0x501)});return;}const _0x1e8d95=_0x506dd0(_0x592bc0);await _0x36a60a[_0x42a41f(0x358)](_0x42a41f(0x629)+_0x2a93e3(0x454)+_0x1e8d95+'*\x20'+(_0x1e8d95===0x221c+0x24b*0x11+-0x4917?_0x42a41f(0x430)+'abled\x20—\x20fu'+_0x42a41f(0x4c4)+'jects\x20imme'+_0x42a41f(0x361):''),{'parse_mode':_0x42a41f(0x501)});return;}if(_0x53e110===_0x2a93e3(0x762)){const _0x565348=_0xc6b91[-0x25d9+0x12a3*-0x1+-0x387d*-0x1];if(!_0x565348){const _0x500379=_0x13fa77();await _0x36a60a[_0x2a93e3(0x358)](t(_0x42a41f(0x1f2)+'nts.visibi'+_0x2a93e3(0x314),_0x383818)+'\x20*'+_0x500379+_0x42a41f(0x3b6)+t(_0x42a41f(0x1f2)+_0x2a93e3(0x378),_0x383818),{'parse_mode':_0x42a41f(0x501)});return;}try{_0x3cdc37(_0x565348),await _0x36a60a[_0x42a41f(0x358)](t(_0x42a41f(0x1f2)+_0x42a41f(0x597)+'litySet',_0x383818,{'mode':_0x565348}),{'parse_mode':_0x42a41f(0x501)});}catch{await _0x36a60a[_0x2a93e3(0x358)](t(_0x42a41f(0x1f2)+_0x42a41f(0x597)+_0x2a93e3(0x42c)+'d',_0x383818,{'mode':_0x565348}),{'parse_mode':_0x42a41f(0x501)});}return;}if(_0x53e110===_0x42a41f(0x49f)){const _0x3b52c3=await _0x5406b0();if(_0x3b52c3[_0x2a93e3(0x77d)]===-0xfab*-0x1+-0x13d+-0xe6e){await _0x36a60a[_0x42a41f(0x358)](t(_0x2a93e3(0x1f2)+_0x42a41f(0x302)+_0x42a41f(0x279),_0x383818));return;}const _0x1629ee=_0x3b52c3[_0x2a93e3(0x6aa)](_0x4c224e)[_0x42a41f(0x1d7)]('\x0a');await _0x36a60a[_0x2a93e3(0x358)](t(_0x42a41f(0x1f2)+_0x2a93e3(0x716)+'Header',_0x383818)+'\x0a'+_0x1629ee,{'parse_mode':_0x2a93e3(0x501)});return;}if(_0x53e110===_0x2a93e3(0x7a3)){const _0x41c836=_0xc6b91[-0x1*-0x96d+0x1657+0xad*-0x2f]||'';if(!_0x41c836){await _0x36a60a[_0x2a93e3(0x358)](t('bot.subage'+_0x42a41f(0x378),_0x383818),{'parse_mode':'Markdown'});return;}const _0x6a4016=_0x33dce3(_0x41c836,{'ambiguousAsList':!![]});if(_0x6a4016&&'ambiguous'in _0x6a4016){const _0x534fea=_0x6a4016[_0x2a93e3(0x328)][_0x2a93e3(0x6aa)](_0x4d3a1f=>'•\x20'+_0x4d3a1f[_0x42a41f(0x712)])[_0x42a41f(0x1d7)]('\x0a');await _0x36a60a[_0x42a41f(0x358)](_0x42a41f(0x53b)+_0x42a41f(0x5de)+_0x42a41f(0x5ed)+'?\x0a'+_0x534fea+(_0x2a93e3(0x412)+_0x2a93e3(0x5fd)+_0x2a93e3(0x36e)+'.B.\x20`')+_0x6a4016[_0x2a93e3(0x328)][-0xfd*0xb+-0x1072+-0x309*-0x9]['name']+_0x42a41f(0x76c),{'parse_mode':_0x2a93e3(0x501)});return;}let _0x1b2c50=null,_0x32eb87=_0x41c836;if(_0x6a4016&&!(_0x42a41f(0x45b)in _0x6a4016))_0x1b2c50=_0x6a4016['id'],_0x32eb87=_0x6a4016[_0x2a93e3(0x712)];else{const _0x1b59f5=_0x2027fd(),_0x2e3fcb=_0x1b59f5[_0x2a93e3(0x484)](_0x30b371=>_0x30b371['id'][_0x42a41f(0x245)](_0x41c836));_0x2e3fcb&&(_0x1b2c50=_0x2e3fcb['id'],_0x32eb87=_0x2e3fcb[_0x42a41f(0x712)]);}if(!_0x1b2c50||!_0x442ce9(_0x1b2c50)){await _0x36a60a[_0x42a41f(0x358)](t(_0x2a93e3(0x1f2)+'nts.notFou'+'nd',_0x383818,{'id':_0x41c836}));return;}await _0x36a60a[_0x42a41f(0x358)](t(_0x42a41f(0x1f2)+_0x2a93e3(0x52b)+_0x42a41f(0x6cb),_0x383818,{'id':_0x32eb87}));return;}if(_0x53e110===_0x2a93e3(0x45a)){const _0x42ad3a=_0xc6b91[-0xfe9+0x10d5+-0xeb]||'';if(!_0x42ad3a){await _0x36a60a[_0x42a41f(0x358)](t(_0x2a93e3(0x1f2)+_0x42a41f(0x378),_0x383818),{'parse_mode':'Markdown'});return;}const _0xec45e=_0x33dce3(_0x42ad3a,{'ambiguousAsList':!![]});if(_0xec45e&&_0x42a41f(0x45b)in _0xec45e){const _0x4504cf=_0xec45e[_0x42a41f(0x328)][_0x42a41f(0x6aa)](_0xa09ece=>'•\x20'+_0xa09ece[_0x2a93e3(0x712)])[_0x42a41f(0x1d7)]('\x0a');await _0x36a60a[_0x2a93e3(0x358)](_0x42a41f(0x53b)+'\x20—\x20welchen'+'\x20meinst\x20du'+'?\x0a'+_0x4504cf,{'parse_mode':'Markdown'});return;}let _0x34f8b7=null;if(_0xec45e&&!('ambiguous'in _0xec45e))_0x34f8b7={'id':_0xec45e['id'],'name':_0xec45e[_0x2a93e3(0x712)]};else{const _0x2af5a7=_0x2027fd(),_0x10101a=_0x2af5a7[_0x42a41f(0x484)](_0x152a27=>_0x152a27['id']['startsWith'](_0x42ad3a));if(_0x10101a)_0x34f8b7={'id':_0x10101a['id'],'name':_0x10101a[_0x2a93e3(0x712)]};}if(!_0x34f8b7){await _0x36a60a[_0x42a41f(0x358)](t(_0x42a41f(0x1f2)+'nts.notFou'+'nd',_0x383818,{'id':_0x42ad3a}));return;}const _0x147834=_0x4a9559(_0x34f8b7['id']);if(!_0x147834){await _0x36a60a[_0x42a41f(0x358)](t(_0x42a41f(0x1f2)+_0x2a93e3(0x371)+'nd',_0x383818,{'id':_0x42ad3a}));return;}const _0x593b94=Math[_0x2a93e3(0x39a)](_0x147834[_0x2a93e3(0x20b)]/(0x161+0x20*-0xe0+0x1e87)),_0x41687b=t(_0x2a93e3(0x1f2)+_0x42a41f(0x758)+_0x42a41f(0x725),_0x383818,{'name':_0x147834['name'],'status':_0x147834[_0x42a41f(0x5e8)]}),_0x2a07cf=t(_0x2a93e3(0x1f2)+_0x42a41f(0x758)+_0x42a41f(0x2ab),_0x383818,{'sec':_0x593b94,'in':_0x147834[_0x2a93e3(0x40c)][_0x2a93e3(0x1cf)],'out':_0x147834[_0x42a41f(0x40c)][_0x42a41f(0x435)]}),_0x2ccea3=_0x147834['output'][_0x42a41f(0x77d)]>-0x134f+-0x161b*-0x1+0xae0?_0x147834['output'][_0x42a41f(0x450)](0x20c8+-0x365+0x1*-0x1d63,-0x814+0x20cd*0x1+-0xb0d)+(_0x42a41f(0x55d)+_0x2a93e3(0x2c1)):_0x147834['output'];await _0x36a60a['reply'](_0x41687b+'\x0a'+_0x2a07cf+'\x0a\x0a'+(_0x2ccea3||_0x147834[_0x42a41f(0x713)]||'(no\x20output'+')'),{'parse_mode':'Markdown'})['catch'](()=>_0x36a60a['reply'](_0x41687b+'\x0a'+_0x2a07cf+'\x0a\x0a'+(_0x2ccea3||_0x147834['error']||'(no\x20output'+')')));return;}const _0x454343=_0x2bca62(),_0x14c680=_0x369f1e(),_0x4bcd4d=_0x454343===0x21b1*-0x1+0x195+0x201c?t(_0x42a41f(0x1f2)+_0x42a41f(0x472)+'el',_0x383818)+_0x42a41f(0x2ea)+t(_0x2a93e3(0x1f2)+_0x2a93e3(0x4c3)+_0x2a93e3(0x788),_0x383818,{'n':_0x14c680}):t(_0x42a41f(0x1f2)+_0x42a41f(0x472)+'el',_0x383818)+'\x20'+_0x454343,_0x39156d=t(_0x2a93e3(0x1f2)+_0x2a93e3(0x597)+'lityLabel',_0x383818)+'\x20*'+_0x13fa77()+'*',_0x1acb7e=_0x4646cd(),_0x793453=_0x1acb7e<=-0x1f6a*0x1+-0x2a9+0x2213?_0x2a93e3(0x5a4)+_0x42a41f(0x260)+_0x2a93e3(0x4cf):_0x2a93e3(0x5a4)+'\x20*'+Math[_0x42a41f(0x604)](_0x1acb7e/(-0x97a*0x1+0x1*0x16d+0xbf5))+'s*',_0x5d3b32=await _0x5406b0();let _0x3de494='';_0x5d3b32[_0x42a41f(0x77d)]===0x217+0x487*-0x4+0x1*0x1005?_0x3de494='\x0a'+t(_0x2a93e3(0x1f2)+_0x42a41f(0x302)+_0x2a93e3(0x279),_0x383818):_0x3de494='\x0a'+t(_0x42a41f(0x1f2)+'nts.active'+'Header',_0x383818)+'\x0a'+_0x5d3b32[_0x2a93e3(0x6aa)](_0x4c224e)[_0x2a93e3(0x1d7)]('\x0a');const _0x2d520f=t(_0x2a93e3(0x1f2)+_0x2a93e3(0x517),_0x383818),_0xc5967e='\x0a\x0a'+t(_0x42a41f(0x1f2)+'nts.usage',_0x383818),_0x30ad8a=_0x2d520f+'\x0a'+_0x4bcd4d+'\x0a'+_0x39156d+'\x0a'+_0x793453+_0x3de494+_0xc5967e;await _0x36a60a[_0x42a41f(0x358)](_0x30ad8a,{'parse_mode':_0x42a41f(0x501)})[_0x42a41f(0x442)](()=>_0x36a60a['reply'](_0x30ad8a));});}
|