alvin-bot 5.6.2 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -1
  3. package/dist/claude.js +1 -102
  4. package/dist/config.js +1 -96
  5. package/dist/engine.js +1 -90
  6. package/dist/find-claude-binary.js +1 -98
  7. package/dist/handlers/async-agent-chunk-handler.js +1 -50
  8. package/dist/handlers/background-bypass.js +1 -75
  9. package/dist/handlers/commands.js +1 -2336
  10. package/dist/handlers/cron-progress.js +1 -52
  11. package/dist/handlers/document.js +1 -194
  12. package/dist/handlers/message.js +1 -959
  13. package/dist/handlers/photo.js +1 -154
  14. package/dist/handlers/platform-message.js +1 -360
  15. package/dist/handlers/stuck-timer.js +1 -54
  16. package/dist/handlers/video.js +1 -237
  17. package/dist/handlers/voice.js +1 -148
  18. package/dist/i18n.js +1 -805
  19. package/dist/index.js +1 -697
  20. package/dist/init-data-dir.js +1 -98
  21. package/dist/middleware/auth.js +1 -233
  22. package/dist/migrate.js +1 -162
  23. package/dist/paths.js +1 -146
  24. package/dist/platforms/discord.js +1 -175
  25. package/dist/platforms/index.js +1 -130
  26. package/dist/platforms/signal.js +1 -205
  27. package/dist/platforms/slack-slash-parser.js +1 -32
  28. package/dist/platforms/slack.js +1 -501
  29. package/dist/platforms/telegram.js +1 -111
  30. package/dist/platforms/types.js +1 -8
  31. package/dist/platforms/whatsapp-auth-helpers.js +1 -53
  32. package/dist/platforms/whatsapp.js +1 -707
  33. package/dist/providers/claude-sdk-provider.js +1 -565
  34. package/dist/providers/codex-cli-provider.js +1 -134
  35. package/dist/providers/index.js +1 -7
  36. package/dist/providers/ollama-provider.js +1 -32
  37. package/dist/providers/openai-compatible.js +1 -406
  38. package/dist/providers/registry.js +1 -352
  39. package/dist/providers/runtime-header.js +1 -45
  40. package/dist/providers/tool-executor.js +1 -475
  41. package/dist/providers/types.js +1 -227
  42. package/dist/services/access.js +1 -144
  43. package/dist/services/allowed-users-gate.js +1 -56
  44. package/dist/services/alvin-dispatch.js +1 -130
  45. package/dist/services/alvin-mcp-tools.js +1 -104
  46. package/dist/services/asset-index.js +1 -224
  47. package/dist/services/async-agent-parser.js +1 -418
  48. package/dist/services/async-agent-watcher.js +1 -443
  49. package/dist/services/auto-diagnostic.js +1 -228
  50. package/dist/services/broadcast.js +1 -52
  51. package/dist/services/browser-manager.js +1 -562
  52. package/dist/services/browser-webfetch.js +1 -127
  53. package/dist/services/browser.js +1 -121
  54. package/dist/services/cdp-bootstrap.js +1 -357
  55. package/dist/services/compaction.js +1 -144
  56. package/dist/services/critical-notify.js +1 -203
  57. package/dist/services/cron-resolver.js +1 -58
  58. package/dist/services/cron-scheduling.js +1 -310
  59. package/dist/services/cron.js +1 -861
  60. package/dist/services/custom-tools.js +1 -317
  61. package/dist/services/delivery-queue.js +1 -173
  62. package/dist/services/delivery-registry.js +1 -21
  63. package/dist/services/disk-cleanup.js +1 -203
  64. package/dist/services/elevenlabs.js +1 -58
  65. package/dist/services/embeddings/auto-detect.js +1 -74
  66. package/dist/services/embeddings/fts5.js +1 -108
  67. package/dist/services/embeddings/gemini.js +1 -65
  68. package/dist/services/embeddings/index.js +1 -496
  69. package/dist/services/embeddings/ollama.js +1 -78
  70. package/dist/services/embeddings/openai.js +1 -49
  71. package/dist/services/embeddings/provider.js +1 -22
  72. package/dist/services/embeddings/vector-base.js +1 -113
  73. package/dist/services/embeddings-migration.js +1 -193
  74. package/dist/services/embeddings.js +1 -9
  75. package/dist/services/env-file.js +1 -50
  76. package/dist/services/exec-guard.js +1 -71
  77. package/dist/services/fallback-order.js +1 -154
  78. package/dist/services/file-permissions.js +1 -93
  79. package/dist/services/heartbeat-file.js +1 -65
  80. package/dist/services/heartbeat.js +1 -313
  81. package/dist/services/hooks.js +1 -44
  82. package/dist/services/imagegen.js +1 -72
  83. package/dist/services/language-detect.js +1 -154
  84. package/dist/services/markdown.js +1 -63
  85. package/dist/services/mcp.js +1 -263
  86. package/dist/services/memory-extractor.js +1 -178
  87. package/dist/services/memory-inject-mode.js +1 -43
  88. package/dist/services/memory-layers.js +1 -156
  89. package/dist/services/memory.js +1 -146
  90. package/dist/services/ollama-manager.js +1 -339
  91. package/dist/services/permissions-wizard.js +1 -291
  92. package/dist/services/personality.js +1 -376
  93. package/dist/services/plugins.js +1 -171
  94. package/dist/services/preflight.js +1 -292
  95. package/dist/services/process-manager.js +1 -291
  96. package/dist/services/release-highlights.js +1 -79
  97. package/dist/services/reminders.js +1 -97
  98. package/dist/services/restart.js +1 -48
  99. package/dist/services/security-audit.js +1 -74
  100. package/dist/services/self-diagnosis.js +1 -272
  101. package/dist/services/self-search.js +1 -129
  102. package/dist/services/session-persistence.js +1 -237
  103. package/dist/services/session.js +1 -282
  104. package/dist/services/skills.js +1 -290
  105. package/dist/services/ssrf-guard.js +1 -162
  106. package/dist/services/standing-orders.js +1 -29
  107. package/dist/services/steer-channel.js +1 -46
  108. package/dist/services/stop-controller.js +1 -52
  109. package/dist/services/subagent-dedup.js +1 -0
  110. package/dist/services/subagent-delivery.js +1 -452
  111. package/dist/services/subagent-stats.js +1 -123
  112. package/dist/services/subagents.js +1 -814
  113. package/dist/services/sudo.js +1 -329
  114. package/dist/services/telegram.js +1 -158
  115. package/dist/services/timing-safe-bearer.js +1 -51
  116. package/dist/services/tool-discovery.js +1 -214
  117. package/dist/services/trends.js +1 -580
  118. package/dist/services/updater.js +1 -291
  119. package/dist/services/usage-tracker.js +1 -144
  120. package/dist/services/users.js +1 -271
  121. package/dist/services/voice.js +1 -104
  122. package/dist/services/watchdog-brake.js +1 -154
  123. package/dist/services/watchdog.js +1 -311
  124. package/dist/services/workspaces.js +1 -276
  125. package/dist/tui/index.js +1 -667
  126. package/dist/util/console-formatter.js +1 -109
  127. package/dist/util/debounce.js +1 -24
  128. package/dist/util/telegram-error-filter.js +1 -62
  129. package/dist/version.js +1 -24
  130. package/dist/web/bind-strategy.js +1 -42
  131. package/dist/web/canvas.js +1 -30
  132. package/dist/web/doctor-api.js +1 -604
  133. package/dist/web/openai-compat.js +1 -252
  134. package/dist/web/server.js +1 -1831
  135. package/dist/web/setup-api.js +1 -1101
  136. package/package.json +5 -2
  137. package/dist/.metadata_never_index +0 -0
package/dist/tui/index.js CHANGED
@@ -1,668 +1,2 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Alvin Bot TUI — Terminal Chat Interface
4
- *
5
- * A full-screen terminal UI that connects to the running Alvin Bot instance
6
- * via WebSocket (same as Web UI). Features:
7
- *
8
- * - Streaming chat with AI responses
9
- * - Tool use indicators
10
- * - Model switching (/model)
11
- * - Status bar (model, cost, uptime)
12
- * - Color-coded messages
13
- * - Input history (↑/↓)
14
- * - Multi-line input (Shift+Enter)
15
- * - i18n: English (default) / German (--lang de or ALVIN_LANG=de)
16
- *
17
- * Usage: alvin-bot tui [--port 3100] [--host localhost] [--lang en|de]
18
- */
19
- import { createInterface, cursorTo, clearLine as rlClearLine } from "readline";
20
- import WebSocket from "ws";
21
- import http from "http";
22
- import { initI18n, t } from "../i18n.js";
23
- import { BOT_VERSION } from "../version.js";
24
- // Init i18n before anything else
25
- initI18n();
26
- // ── ANSI Colors & Styles ────────────────────────────────
27
- const C = {
28
- reset: "\x1b[0m",
29
- bold: "\x1b[1m",
30
- dim: "\x1b[2m",
31
- italic: "\x1b[3m",
32
- underline: "\x1b[4m",
33
- black: "\x1b[30m",
34
- red: "\x1b[31m",
35
- green: "\x1b[32m",
36
- yellow: "\x1b[33m",
37
- blue: "\x1b[34m",
38
- magenta: "\x1b[35m",
39
- cyan: "\x1b[36m",
40
- white: "\x1b[37m",
41
- gray: "\x1b[90m",
42
- brightRed: "\x1b[91m",
43
- brightGreen: "\x1b[92m",
44
- brightYellow: "\x1b[93m",
45
- brightBlue: "\x1b[94m",
46
- brightMagenta: "\x1b[95m",
47
- brightCyan: "\x1b[96m",
48
- brightWhite: "\x1b[97m",
49
- bgBlack: "\x1b[40m",
50
- bgBlue: "\x1b[44m",
51
- bgMagenta: "\x1b[45m",
52
- bgGray: "\x1b[100m",
53
- };
54
- // ── State ───────────────────────────────────────────────
55
- let ws = null;
56
- let rl;
57
- let connected = false;
58
- let currentModel = "loading...";
59
- let totalCost = 0;
60
- let isStreaming = false;
61
- let isMirrorStreaming = false;
62
- let currentResponse = "";
63
- let currentToolName = "";
64
- let toolCount = 0;
65
- const inputHistory = [];
66
- let historyIndex = -1;
67
- let activeTarget = "tui";
68
- let observerEnabled = true;
69
- // TUI's own session key — either ephemeral (new every start) or persistent
70
- // ("tui:local") if --resume is passed. Set once in startTUI().
71
- let tuiSessionKey = `tui:ephemeral:${Date.now()}`;
72
- const host = process.argv.includes("--host")
73
- ? process.argv[process.argv.indexOf("--host") + 1] || "localhost"
74
- : "localhost";
75
- const port = process.argv.includes("--port")
76
- ? parseInt(process.argv[process.argv.indexOf("--port") + 1]) || 3100
77
- : 3100;
78
- const baseUrl = `http://${host}:${port}`;
79
- const wsUrl = `ws://${host}:${port}`;
80
- // Track header line count for redraw
81
- const HEADER_LINES = 3;
82
- // ── Screen Drawing ──────────────────────────────────────
83
- function getWidth() {
84
- return process.stdout.columns || 80;
85
- }
86
- /**
87
- * Clear the current readline input line so we can write content "above" the
88
- * prompt cleanly. Uses readline's own cursor API instead of raw escape
89
- * sequences — this cooperates with readline's internal cursor tracking.
90
- */
91
- function clearCurrentLine() {
92
- cursorTo(process.stdout, 0);
93
- rlClearLine(process.stdout, 0);
94
- }
95
- function drawHeader() {
96
- const w = getWidth();
97
- const statusDot = connected ? `${C.brightGreen}●${C.reset}` : `${C.red}●${C.reset}`;
98
- const status = connected ? t("tui.connected") : t("tui.disconnected");
99
- const modelStr = `${C.brightMagenta}${currentModel}${C.reset}`;
100
- const costStr = totalCost > 0 ? ` ${C.gray}· $${totalCost.toFixed(4)}${C.reset}` : "";
101
- const targetStr = ` ${C.gray}│${C.reset} ${C.brightYellow}${activeTarget === "telegram" ? "→ Telegram" : "TUI session"}${C.reset}`;
102
- const title = `${C.bold}${C.brightCyan}${t("tui.title")}${C.reset}`;
103
- const right = `${statusDot} ${status} ${C.gray}│${C.reset} ${modelStr}${costStr}${targetStr}`;
104
- console.log(`${C.gray}${"─".repeat(w)}${C.reset}`);
105
- console.log(` ${title}${"".padEnd(10)}${right}`);
106
- console.log(`${C.gray}${"─".repeat(w)}${C.reset}`);
107
- }
108
- /**
109
- * Redraw the header. The old "in-place" implementation used cursor save/
110
- * restore escape sequences and jumped to \x1b[H — but once the terminal
111
- * has scrolled past the original header, \x1b[H resolves to the current
112
- * viewport top (not the document top), which means the header gets
113
- * re-rendered inline in the middle of the content. That's what produced
114
- * the "header appears in the middle of the bot response" bug in 4.5.0.
115
- *
116
- * The only safe way to redraw the header in a scrolling terminal is to
117
- * clear the whole screen and redraw from scratch. Do that only in
118
- * explicit reset contexts (/clear, SIGWINCH resize, initial connect).
119
- * For mid-session cost/status updates, use inline info messages instead.
120
- */
121
- function redrawHeader(opts = {}) {
122
- if (isStreaming)
123
- return;
124
- if (opts.clearScreen) {
125
- console.clear();
126
- }
127
- drawHeader();
128
- if (rl && !isStreaming)
129
- rl.prompt(true);
130
- }
131
- function drawHelp() {
132
- console.log(`
133
- ${C.bold}${t("help.title")}${C.reset}
134
- ${C.cyan}/model${C.reset} ${t("help.model")}
135
- ${C.cyan}/status${C.reset} ${t("help.status")}
136
- ${C.cyan}/clear${C.reset} ${t("help.clear")}
137
- ${C.cyan}/cron${C.reset} ${t("help.cron")}
138
- ${C.cyan}/doctor${C.reset} ${t("help.doctor")}
139
- ${C.cyan}/backup${C.reset} ${t("help.backup")}
140
- ${C.cyan}/restart${C.reset} ${t("help.restart")}
141
- ${C.cyan}/target tui${C.reset}|${C.cyan}telegram${C.reset} Switch where your messages go
142
- ${C.cyan}/observe on${C.reset}|${C.cyan}off${C.reset} Mirror Telegram activity (default: on)
143
- ${C.cyan}/help${C.reset} ${t("help.help")}
144
- ${C.cyan}/quit${C.reset} ${t("help.quit")}
145
-
146
- ${C.dim}${t("help.footer")}${C.reset}
147
- `);
148
- }
149
- function printUser(text) {
150
- clearCurrentLine();
151
- console.log(`\n${C.bold}${C.brightGreen}${t("tui.you")}:${C.reset} ${text}`);
152
- }
153
- function printAssistantStart() {
154
- clearCurrentLine();
155
- const targetTag = activeTarget === "telegram" ? ` ${C.dim}[→ Tel]${C.reset}` : "";
156
- process.stdout.write(`\n${C.bold}${C.brightBlue}Alvin Bot${targetTag}:${C.reset} `);
157
- }
158
- function printAssistantDelta(text) {
159
- process.stdout.write(text);
160
- }
161
- function printAssistantEnd(cost) {
162
- const costStr = cost && cost > 0 ? ` ${C.dim}($${cost.toFixed(4)})${C.reset}` : "";
163
- process.stdout.write(costStr + "\n");
164
- }
165
- function printTool(name) {
166
- clearCurrentLine();
167
- process.stdout.write(` ${C.yellow}⚙ ${name}...${C.reset}`);
168
- }
169
- function printToolDone() {
170
- clearCurrentLine();
171
- if (toolCount > 0) {
172
- const label = toolCount > 1 ? t("tui.toolsUsed") : t("tui.toolUsed");
173
- console.log(` ${C.dim}${C.yellow}⚙ ${toolCount} ${label}${C.reset}`);
174
- }
175
- toolCount = 0;
176
- }
177
- function printError(msg) {
178
- clearCurrentLine();
179
- console.log(`\n${C.red}✖ ${msg}${C.reset}`);
180
- }
181
- function printInfo(msg) {
182
- clearCurrentLine();
183
- console.log(`${C.cyan}ℹ ${msg}${C.reset}`);
184
- }
185
- function printSuccess(msg) {
186
- clearCurrentLine();
187
- console.log(`${C.green}✔ ${msg}${C.reset}`);
188
- }
189
- /**
190
- * Render the mirror of a Telegram event (user message or bot response).
191
- * Distinct styling: dim, phone prefix, grayed color.
192
- */
193
- function printMirrorUser(text) {
194
- clearCurrentLine();
195
- console.log(`\n${C.dim}${C.gray}📱 Tel User: ${text}${C.reset}`);
196
- }
197
- function printMirrorAssistantStart() {
198
- clearCurrentLine();
199
- process.stdout.write(`\n${C.dim}${C.gray}📱 Tel Bot: ${C.reset}`);
200
- }
201
- function printMirrorAssistantDelta(text) {
202
- // Dim styling while streaming the mirrored response
203
- process.stdout.write(`${C.dim}${C.gray}${text}${C.reset}`);
204
- }
205
- function printMirrorAssistantEnd() {
206
- process.stdout.write("\n");
207
- }
208
- /**
209
- * The single source of truth for rendering the input prompt. Only ever
210
- * called at state-transition points (connect, done, error, command result)
211
- * and no-ops during streaming so the prompt never races with delta writes.
212
- */
213
- function showPrompt() {
214
- if (isStreaming || !rl)
215
- return;
216
- rl.setPrompt(`${C.brightGreen}❯${C.reset} `);
217
- rl.prompt(true);
218
- }
219
- // ── WebSocket Connection ────────────────────────────────
220
- function connectWebSocket() {
221
- ws = new WebSocket(wsUrl);
222
- ws.on("open", () => {
223
- connected = true;
224
- // No header redraw here — the header was already drawn at startTUI().
225
- // Calling redrawHeader() in a scrolled terminal re-renders it inline.
226
- printInfo(t("tui.connectedTo"));
227
- showPrompt();
228
- });
229
- ws.on("message", (data) => {
230
- try {
231
- const msg = JSON.parse(data.toString());
232
- handleMessage(msg);
233
- }
234
- catch { /* ignore */ }
235
- });
236
- ws.on("close", () => {
237
- connected = false;
238
- isStreaming = false;
239
- // No header redraw — it would appear inline mid-chat.
240
- printError(t("tui.connectionLost"));
241
- setTimeout(connectWebSocket, 3000);
242
- });
243
- ws.on("error", () => {
244
- // Error is followed by close event
245
- });
246
- }
247
- function handleMessage(msg) {
248
- switch (msg.type) {
249
- case "text":
250
- if (!isStreaming) {
251
- isStreaming = true;
252
- if (currentToolName) {
253
- printToolDone();
254
- currentToolName = "";
255
- }
256
- printAssistantStart();
257
- }
258
- if (msg.delta) {
259
- printAssistantDelta(msg.delta);
260
- currentResponse += msg.delta;
261
- }
262
- break;
263
- case "tool":
264
- if (!isStreaming)
265
- isStreaming = true;
266
- toolCount++;
267
- currentToolName = msg.name || "tool";
268
- printTool(currentToolName);
269
- break;
270
- case "fallback":
271
- printInfo(`${t("tui.fallback")} ${msg.from} → ${msg.to}`);
272
- break;
273
- case "done":
274
- if (isStreaming) {
275
- printAssistantEnd(msg.cost);
276
- }
277
- if (msg.cost)
278
- totalCost += msg.cost;
279
- isStreaming = false;
280
- currentResponse = "";
281
- currentToolName = "";
282
- // NOTE: do NOT call redrawHeader() here. On a scrolled terminal it
283
- // renders the header inline at the viewport top, which looks like
284
- // the header appeared in the middle of the conversation. The total
285
- // cost is already shown inline at the end of each response.
286
- showPrompt();
287
- break;
288
- case "error":
289
- printError(msg.error || "Unknown error");
290
- isStreaming = false;
291
- showPrompt();
292
- break;
293
- case "reset":
294
- printInfo(t("tui.sessionReset"));
295
- showPrompt();
296
- break;
297
- // ── v4.5.0: Telegram activity mirror events ────────────────────────
298
- // These arrive whenever someone interacts with the bot via Telegram,
299
- // regardless of what the TUI is currently doing. We render them
300
- // distinctly (dim + 📱 prefix) so they don't confuse themselves with
301
- // the user's own session.
302
- case "mirror:user_msg":
303
- if (!observerEnabled)
304
- break;
305
- printMirrorUser(msg.text || "");
306
- break;
307
- case "mirror:response_start":
308
- if (!observerEnabled)
309
- break;
310
- isMirrorStreaming = true;
311
- printMirrorAssistantStart();
312
- break;
313
- case "mirror:response_delta":
314
- if (!observerEnabled)
315
- break;
316
- if (!isMirrorStreaming) {
317
- isMirrorStreaming = true;
318
- printMirrorAssistantStart();
319
- }
320
- printMirrorAssistantDelta(msg.delta || "");
321
- break;
322
- case "mirror:response_done":
323
- if (!observerEnabled)
324
- break;
325
- if (isMirrorStreaming) {
326
- printMirrorAssistantEnd();
327
- isMirrorStreaming = false;
328
- }
329
- // Don't call showPrompt here — the user's own prompt state is
330
- // independent of mirror activity.
331
- break;
332
- }
333
- }
334
- // ── API Calls ───────────────────────────────────────────
335
- async function apiGet(path) {
336
- return new Promise((resolve, reject) => {
337
- http.get(`${baseUrl}${path}`, (res) => {
338
- let data = "";
339
- res.on("data", (c) => data += c);
340
- res.on("end", () => {
341
- try {
342
- resolve(JSON.parse(data));
343
- }
344
- catch {
345
- reject(new Error("Invalid JSON"));
346
- }
347
- });
348
- }).on("error", reject);
349
- });
350
- }
351
- async function apiPost(path, body) {
352
- return new Promise((resolve, reject) => {
353
- const postData = JSON.stringify(body);
354
- const req = http.request(`${baseUrl}${path}`, {
355
- method: "POST",
356
- headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) },
357
- }, (res) => {
358
- let data = "";
359
- res.on("data", (c) => data += c);
360
- res.on("end", () => {
361
- try {
362
- resolve(JSON.parse(data));
363
- }
364
- catch {
365
- reject(new Error("Invalid JSON"));
366
- }
367
- });
368
- });
369
- req.on("error", reject);
370
- req.write(postData);
371
- req.end();
372
- });
373
- }
374
- // ── Commands ────────────────────────────────────────────
375
- async function handleCommand(cmd) {
376
- const parts = cmd.slice(1).split(/\s+/);
377
- const command = parts[0].toLowerCase();
378
- switch (command) {
379
- case "help":
380
- case "h":
381
- drawHelp();
382
- break;
383
- case "model":
384
- case "m": {
385
- try {
386
- const data = await apiGet("/api/models");
387
- console.log(`\n${C.bold}${t("tui.models")}:${C.reset}`);
388
- if (data.models) {
389
- for (const m of data.models) {
390
- const active = m.key === data.active ? `${C.brightGreen} ◀ ${t("tui.active")}${C.reset}` : "";
391
- const status = m.status === "ready" ? `${C.green}✓${C.reset}` : `${C.dim}✗${C.reset}`;
392
- console.log(` ${status} ${C.bold}${m.key}${C.reset} ${C.dim}(${m.model || m.name})${C.reset}${active}`);
393
- }
394
- }
395
- console.log(`\n${C.dim}${t("tui.switchModel")} /model <key>${C.reset}`);
396
- if (parts[1]) {
397
- const res = await apiPost("/api/models/switch", { key: parts[1] });
398
- if (res.ok) {
399
- currentModel = res.active || parts[1];
400
- printSuccess(`${t("tui.switchedTo")}: ${currentModel}`);
401
- // Header stays as-is (would appear inline otherwise) —
402
- // next /clear redraws it with the new model.
403
- }
404
- else {
405
- printError(res.error || t("tui.switchError"));
406
- }
407
- }
408
- }
409
- catch (err) {
410
- printError(`${t("tui.modelsError")}: ${err.message}`);
411
- }
412
- break;
413
- }
414
- case "version":
415
- case "v": {
416
- console.log(`\n${C.bold}${C.brightCyan}🤖 Alvin Bot${C.reset} ${C.dim}v${BOT_VERSION}${C.reset}`);
417
- console.log(`${C.dim}Node ${process.version} · ${process.platform}/${process.arch}${C.reset}\n`);
418
- break;
419
- }
420
- case "status":
421
- case "s": {
422
- try {
423
- const data = await apiGet("/api/status");
424
- console.log(`\n${C.bold}${C.brightCyan}🤖 Alvin Bot${C.reset} ${C.dim}v${BOT_VERSION}${C.reset}`);
425
- console.log(`${C.gray}${"─".repeat(40)}${C.reset}`);
426
- if (data.model) {
427
- console.log(` ${C.cyan}${t("status.model")}${C.reset} ${data.model.model || data.model.name || "?"}`);
428
- console.log(` ${C.cyan}${t("status.provider")}${C.reset} ${data.model.name || "?"}`);
429
- console.log(` ${C.cyan}${t("status.status")}${C.reset} ${data.model.status || "?"}`);
430
- }
431
- if (data.bot) {
432
- const upH = Math.floor((data.bot.uptime || 0) / 3600);
433
- const upM = Math.floor(((data.bot.uptime || 0) % 3600) / 60);
434
- console.log(` ${C.cyan}${t("status.version")}${C.reset} ${data.bot.version || "?"}`);
435
- console.log(` ${C.cyan}${t("status.uptime")}${C.reset} ${upH}h ${upM}m`);
436
- }
437
- if (data.memory) {
438
- console.log(` ${C.cyan}${t("status.memory")}${C.reset} ${data.memory.vectors || 0} ${t("status.embeddings")}`);
439
- }
440
- console.log(` ${C.cyan}${t("status.plugins")}${C.reset} ${data.plugins || 0}`);
441
- console.log(` ${C.cyan}${t("status.tools")}${C.reset} ${data.tools || 0}`);
442
- console.log(` ${C.cyan}${t("status.users")}${C.reset} ${data.users || 0}`);
443
- console.log("");
444
- }
445
- catch (err) {
446
- printError(`${t("tui.statusError")}: ${err.message}`);
447
- }
448
- break;
449
- }
450
- case "cron": {
451
- try {
452
- const data = await apiGet("/api/cron");
453
- console.log(`\n${C.bold}Cron Jobs${C.reset}`);
454
- console.log(`${C.gray}${"─".repeat(40)}${C.reset}`);
455
- if (!data.jobs || data.jobs.length === 0) {
456
- console.log(` ${C.dim}${t("tui.noCronJobs")}${C.reset}`);
457
- }
458
- else {
459
- for (const job of data.jobs) {
460
- const status = job.enabled ? `${C.green}●${C.reset}` : `${C.red}●${C.reset}`;
461
- const schedule = job.schedule || job.interval || "?";
462
- console.log(` ${status} ${C.bold}${job.name}${C.reset} ${C.dim}(${schedule})${C.reset} — ${job.type}`);
463
- }
464
- }
465
- console.log("");
466
- }
467
- catch (err) {
468
- printError(`${t("tui.cronError")}: ${err.message}`);
469
- }
470
- break;
471
- }
472
- case "doctor": {
473
- try {
474
- printInfo(t("tui.scanning"));
475
- const data = await apiGet("/api/doctor");
476
- const icons = { error: `${C.red}✖`, warning: `${C.yellow}⚠`, info: `${C.blue}ℹ` };
477
- console.log(`\n${C.bold}Health-Check${C.reset}`);
478
- console.log(`${C.gray}${"─".repeat(40)}${C.reset}`);
479
- for (const issue of data.issues || []) {
480
- const icon = icons[issue.severity] || "?";
481
- console.log(` ${icon} ${C.bold}${issue.category}${C.reset} — ${issue.message}${C.reset}`);
482
- if (issue.fix)
483
- console.log(` ${C.dim}💡 ${issue.fix}${C.reset}`);
484
- }
485
- console.log("");
486
- }
487
- catch (err) {
488
- printError(`${t("tui.doctorError")}: ${err.message}`);
489
- }
490
- break;
491
- }
492
- case "backup": {
493
- try {
494
- printInfo(t("tui.creatingBackup"));
495
- const data = await apiPost("/api/backups/create", {});
496
- if (data.ok) {
497
- printSuccess(`${t("tui.backupCreated")} "${data.id}" (${data.files.length} files)`);
498
- }
499
- else {
500
- printError(data.error || t("tui.backupFailed"));
501
- }
502
- }
503
- catch (err) {
504
- printError(`${t("tui.backupError")}: ${err.message}`);
505
- }
506
- break;
507
- }
508
- case "restart": {
509
- printInfo(t("tui.botRestarting"));
510
- try {
511
- await apiPost("/api/restart", {});
512
- printSuccess(t("tui.restartTriggered"));
513
- }
514
- catch {
515
- printError(t("tui.restartFailed"));
516
- }
517
- break;
518
- }
519
- case "clear":
520
- case "c":
521
- // /clear is the ONLY command that safely redraws the header, because
522
- // it wipes the entire screen first.
523
- redrawHeader({ clearScreen: true });
524
- if (ws?.readyState === WebSocket.OPEN) {
525
- ws.send(JSON.stringify({
526
- type: "reset",
527
- target: activeTarget,
528
- sessionKey: activeTarget === "tui" ? tuiSessionKey : undefined,
529
- }));
530
- }
531
- break;
532
- case "target":
533
- case "t": {
534
- const val = (parts[1] || "").toLowerCase();
535
- if (val === "tui") {
536
- activeTarget = "tui";
537
- printSuccess("Target: TUI (your own isolated session)");
538
- }
539
- else if (val === "telegram" || val === "tel") {
540
- activeTarget = "telegram";
541
- printSuccess("Target: Telegram (your messages now go into the Telegram session — the bot replies in Telegram AND here)");
542
- }
543
- else {
544
- printInfo(`Current target: ${activeTarget}. Use /target tui or /target telegram.`);
545
- }
546
- break;
547
- }
548
- case "observe":
549
- case "o": {
550
- const val = (parts[1] || "").toLowerCase();
551
- if (val === "on" || val === "1" || val === "true") {
552
- observerEnabled = true;
553
- printSuccess("Observer mode: ON — Telegram activity will be mirrored here (dim)");
554
- }
555
- else if (val === "off" || val === "0" || val === "false") {
556
- observerEnabled = false;
557
- printSuccess("Observer mode: OFF — Telegram activity will NOT be shown here");
558
- }
559
- else {
560
- printInfo(`Observer: ${observerEnabled ? "on" : "off"}. Use /observe on or /observe off.`);
561
- }
562
- break;
563
- }
564
- case "quit":
565
- case "q":
566
- case "exit":
567
- console.log(`\n${C.dim}${t("tui.bye")}${C.reset}\n`);
568
- process.exit(0);
569
- break;
570
- default:
571
- sendChat(cmd);
572
- return;
573
- }
574
- showPrompt();
575
- }
576
- function sendChat(text) {
577
- if (!ws || ws.readyState !== WebSocket.OPEN) {
578
- printError(t("tui.notConnected"));
579
- showPrompt();
580
- return;
581
- }
582
- printUser(text);
583
- // v4.5.0: include target + sessionKey so the web server routes the
584
- // message to the right session. For target=tui, sessionKey is the
585
- // TUI's own ephemeral (or persistent) key; for target=telegram,
586
- // the server resolves it to the primary Telegram user's key.
587
- ws.send(JSON.stringify({
588
- type: "chat",
589
- text,
590
- target: activeTarget,
591
- sessionKey: activeTarget === "tui" ? tuiSessionKey : undefined,
592
- }));
593
- if (inputHistory[0] !== text) {
594
- inputHistory.unshift(text);
595
- if (inputHistory.length > 100)
596
- inputHistory.pop();
597
- }
598
- historyIndex = -1;
599
- }
600
- // ── Init ────────────────────────────────────────────────
601
- async function fetchInitialModel() {
602
- try {
603
- const data = await apiGet("/api/status");
604
- if (data.model?.model) {
605
- currentModel = data.model.model;
606
- }
607
- else if (data.model?.name) {
608
- currentModel = data.model.name;
609
- }
610
- }
611
- catch { /* will get it on connect */ }
612
- }
613
- export async function startTUI() {
614
- // --resume: use persistent TUI session (survives restarts).
615
- // Default: ephemeral session, fresh every TUI start.
616
- const wantResume = process.argv.includes("--resume");
617
- tuiSessionKey = wantResume ? "tui:local" : `tui:ephemeral:${Date.now()}`;
618
- console.clear();
619
- drawHeader();
620
- console.log(`${C.dim}${t("tui.connecting")} ${baseUrl}...${C.reset}`);
621
- console.log(`${C.dim}Session: ${wantResume ? "resuming tui:local (persistent)" : "new ephemeral session"}${C.reset}\n`);
622
- drawHelp();
623
- rl = createInterface({
624
- input: process.stdin,
625
- output: process.stdout,
626
- terminal: true,
627
- historySize: 100,
628
- });
629
- rl.on("line", (line) => {
630
- const text = line.trim();
631
- if (!text) {
632
- showPrompt();
633
- return;
634
- }
635
- if (text.startsWith("/")) {
636
- handleCommand(text);
637
- }
638
- else {
639
- sendChat(text);
640
- }
641
- });
642
- rl.on("close", () => {
643
- console.log(`\n${C.dim}${t("tui.bye")}${C.reset}\n`);
644
- process.exit(0);
645
- });
646
- process.on("SIGINT", () => {
647
- console.log(`\n${C.dim}${t("tui.bye")}${C.reset}\n`);
648
- process.exit(0);
649
- });
650
- // NOTE: Do NOT call process.stdin.setRawMode(false) here. readline with
651
- // `terminal: true` already controls the terminal mode, and forcing cooked
652
- // mode on top of that causes every keystroke to be echoed TWICE (once by
653
- // the terminal, once by readline's line editor) — producing the classic
654
- // "hheelllloo" double-echo bug. Let readline manage the tty mode itself.
655
- // Handle terminal resize — we can't safely redraw the header in place
656
- // on a scrolled buffer. Just re-render the prompt so readline picks up
657
- // the new width for its line editor.
658
- process.stdout.on("resize", () => {
659
- if (!isStreaming)
660
- showPrompt();
661
- });
662
- await fetchInitialModel();
663
- connectWebSocket();
664
- }
665
- const isDirectRun = process.argv[1]?.includes("tui");
666
- if (isDirectRun) {
667
- startTUI().catch(console.error);
668
- }
2
+ const _0x390fd8=_0x1799,_0x223830=_0x1799;(function(_0x4c2842,_0x10a3ef){const _0x25a4cf=_0x1799,_0x6d23c9=_0x1799,_0x8e526b=_0x4c2842();while(!![]){try{const _0x4fe27a=parseInt(_0x25a4cf(0x131))/(0x3*-0x6c3+-0x8*-0x430+0x2*-0x69b)+parseInt(_0x6d23c9(0x164))/(0x178e+-0x5*0x5b8+0x50c)+parseInt(_0x25a4cf(0x206))/(-0x217f+0x1*0x945+0x183d)*(parseInt(_0x25a4cf(0x1aa))/(0x4*-0x8b3+0x1*0x6af+-0x1c21*-0x1))+-parseInt(_0x6d23c9(0x23a))/(0x6*0x5b3+-0xbab+0x2*-0xb41)*(parseInt(_0x6d23c9(0x236))/(-0x2446+0x2a3*0x5+-0x3d*-0x61))+parseInt(_0x6d23c9(0x242))/(0x2309*0x1+-0x12a*0x10+0x6*-0x2bb)*(parseInt(_0x6d23c9(0x17e))/(0x308+0x21f0+-0x24f0))+parseInt(_0x6d23c9(0x1dc))/(-0x1*-0x1961+-0xe21+-0xb37)*(parseInt(_0x25a4cf(0x215))/(-0x1240+0xd7d+0x1*0x4cd))+-parseInt(_0x6d23c9(0x1a9))/(-0x265*0x3+-0x1*-0x1951+-0x1217);if(_0x4fe27a===_0x10a3ef)break;else _0x8e526b['push'](_0x8e526b['shift']());}catch(_0x51ad49){_0x8e526b['push'](_0x8e526b['shift']());}}}(_0x55f1,-0x1*0x68a4f+-0x2243*-0x57+0x1*0x94062));const _0x191002=(function(){let _0x2c14a5=!![];return function(_0x4db392,_0x35087b){const _0x243f53=_0x2c14a5?function(){if(_0x35087b){const _0x3854d1=_0x35087b['apply'](_0x4db392,arguments);return _0x35087b=null,_0x3854d1;}}:function(){};return _0x2c14a5=![],_0x243f53;};}()),_0x4955a5=_0x191002(this,function(){const _0x54c3d8=_0x1799,_0x43a99b=_0x1799;return _0x4955a5[_0x54c3d8(0x1d2)]()[_0x43a99b(0x18b)]('(((.+)+)+)'+'+$')[_0x43a99b(0x1d2)]()['constructo'+'r'](_0x4955a5)['search'](_0x43a99b(0x158)+'+$');});_0x4955a5();import{createInterface,cursorTo,clearLine as _0x578d14}from'readline';import _0x288f36 from'ws';import _0x3727dd from'http';import{initI18n,t}from'../i18n.js';import{BOT_VERSION}from'../version.js';initI18n();const C={'reset':_0x390fd8(0x142),'bold':_0x390fd8(0x14d),'dim':'\x1b[2m','italic':_0x390fd8(0x1d9),'underline':'\x1b[4m','black':_0x390fd8(0x1b1),'red':_0x390fd8(0x23c),'green':_0x390fd8(0x1d8),'yellow':'\x1b[33m','blue':'\x1b[34m','magenta':'\x1b[35m','cyan':_0x390fd8(0x1d3),'white':_0x223830(0x1c4),'gray':_0x223830(0x160),'brightRed':_0x390fd8(0x1df),'brightGreen':_0x390fd8(0x1c7),'brightYellow':_0x223830(0x1c0),'brightBlue':_0x390fd8(0x222),'brightMagenta':_0x390fd8(0x172),'brightCyan':_0x223830(0x20d),'brightWhite':'\x1b[97m','bgBlack':_0x390fd8(0x22c),'bgBlue':_0x223830(0x1a8),'bgMagenta':_0x390fd8(0x13f),'bgGray':'\x1b[100m'};let ws=null,rl,connected=![],currentModel='loading...',totalCost=-0x2*0x8d3+-0xeaf+-0x2055*-0x1,isStreaming=![],isMirrorStreaming=![],currentResponse='',currentToolName='',toolCount=0x9fe+0x74e*0x3+-0x7fa*0x4;const inputHistory=[];let historyIndex=-(0x1*0xdf6+0xb8c*0x1+-0x1*0x1981),activeTarget=_0x390fd8(0x1a7),observerEnabled=!![],tuiSessionKey=_0x390fd8(0x1af)+_0x390fd8(0x14c)+Date[_0x223830(0x141)]();const host=process[_0x223830(0x15d)][_0x223830(0x1c9)](_0x223830(0x1e1))?process[_0x223830(0x15d)][process[_0x223830(0x15d)]['indexOf'](_0x223830(0x1e1))+(-0x171d+0x1*0x6d7+0x9*0x1cf)]||_0x223830(0x1ea):_0x223830(0x1ea),port=process[_0x223830(0x15d)][_0x390fd8(0x1c9)](_0x390fd8(0x1e2))?parseInt(process[_0x223830(0x15d)][process[_0x390fd8(0x15d)][_0x223830(0x1b7)](_0x223830(0x1e2))+(-0x14a4*-0x1+0x1*-0x18eb+0x4*0x112)])||0x140b+-0x4a7+-0x348:-0x71*0xb+-0x1020+0x2117,baseUrl='http://'+host+':'+port,wsUrl=_0x390fd8(0x1e8)+host+':'+port,HEADER_LINES=-0x1*-0x18c3+0x9e6+-0x6ee*0x5;function getWidth(){return process['stdout']['columns']||-0x38c*-0x3+-0x151e+0xaca;}function clearCurrentLine(){const _0x442b81=_0x223830;cursorTo(process['stdout'],-0x4*0x2b6+0x622+0x2*0x25b),_0x578d14(process[_0x442b81(0x235)],-0x1*0x1d3c+0x23a2+-0x666);}function drawHeader(){const _0xb33a31=_0x223830,_0x4b9aea=_0x223830,_0x140ac2=getWidth(),_0x1df431=connected?C[_0xb33a31(0x1e3)+'n']+'●'+C[_0xb33a31(0x192)]:C[_0x4b9aea(0x196)]+'●'+C['reset'],_0x45f119=connected?t(_0x4b9aea(0x1b9)+'ted'):t(_0x4b9aea(0x156)+_0xb33a31(0x193)),_0x39b278=''+C['brightMage'+'nta']+currentModel+C[_0xb33a31(0x192)],_0x518909=totalCost>0x97a+0x58+-0x9d2?'\x20'+C[_0xb33a31(0x147)]+_0xb33a31(0x18e)+totalCost[_0xb33a31(0x181)](-0x964*-0x4+-0x7*0x3b3+-0xba7)+C['reset']:'',_0x45b125='\x20'+C[_0xb33a31(0x147)]+'│'+C[_0x4b9aea(0x192)]+'\x20'+C[_0x4b9aea(0x17d)+'ow']+(activeTarget===_0x4b9aea(0x1dd)?'→\x20Telegram':_0x4b9aea(0x1b8)+'n')+C[_0x4b9aea(0x192)],_0x24a3b9=''+C[_0xb33a31(0x218)]+C[_0xb33a31(0x1ce)]+t(_0xb33a31(0x221))+C[_0xb33a31(0x192)],_0x1dbf74=_0x1df431+'\x20'+_0x45f119+'\x20'+C[_0x4b9aea(0x147)]+'│'+C[_0xb33a31(0x192)]+'\x20'+_0x39b278+_0x518909+_0x45b125;console[_0xb33a31(0x1ac)](''+C[_0xb33a31(0x147)]+'─'[_0xb33a31(0x135)](_0x140ac2)+C[_0xb33a31(0x192)]),console[_0x4b9aea(0x1ac)]('\x20\x20'+_0x24a3b9+''['padEnd'](-0x481+-0x5bb+0xa46)+_0x1dbf74),console['log'](''+C[_0x4b9aea(0x147)]+'─'[_0xb33a31(0x135)](_0x140ac2)+C[_0x4b9aea(0x192)]);}function redrawHeader(_0x52c198={}){const _0x490a80=_0x223830,_0xc0cfdd=_0x223830;if(isStreaming)return;_0x52c198[_0x490a80(0x1a5)+'n']&&console['clear']();drawHeader();if(rl&&!isStreaming)rl[_0xc0cfdd(0x212)](!![]);}function drawHelp(){const _0x1090fc=_0x223830,_0x35ef89=_0x223830;console[_0x1090fc(0x1ac)]('\x0a'+C['bold']+t(_0x35ef89(0x161))+C[_0x1090fc(0x192)]+'\x0a\x20\x20'+C[_0x1090fc(0x1bb)]+_0x1090fc(0x233)+C[_0x1090fc(0x192)]+(_0x1090fc(0x1c3)+_0x1090fc(0x208))+t(_0x35ef89(0x154))+_0x35ef89(0x15b)+C[_0x35ef89(0x1bb)]+_0x35ef89(0x230)+C['reset']+(_0x35ef89(0x1c3)+_0x35ef89(0x23f))+t(_0x35ef89(0x1ab)+'s')+_0x1090fc(0x15b)+C[_0x35ef89(0x1bb)]+_0x35ef89(0x203)+C[_0x1090fc(0x192)]+(_0x1090fc(0x1c3)+_0x1090fc(0x208))+t(_0x1090fc(0x17c))+_0x35ef89(0x15b)+C[_0x35ef89(0x1bb)]+'/cron'+C[_0x1090fc(0x192)]+(_0x35ef89(0x1c3)+_0x35ef89(0x21d))+t('help.cron')+_0x35ef89(0x15b)+C[_0x1090fc(0x1bb)]+_0x35ef89(0x232)+C[_0x35ef89(0x192)]+(_0x1090fc(0x1c3)+_0x1090fc(0x23f))+t(_0x1090fc(0x16c)+'r')+_0x35ef89(0x15b)+C[_0x35ef89(0x1bb)]+'/backup'+C[_0x1090fc(0x192)]+(_0x35ef89(0x1c3)+'\x20\x20\x20')+t('help.backu'+'p')+_0x35ef89(0x15b)+C[_0x1090fc(0x1bb)]+_0x35ef89(0x13d)+C[_0x1090fc(0x192)]+('\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+'\x20\x20')+t(_0x1090fc(0x16e)+'rt')+'\x0a\x20\x20'+C[_0x1090fc(0x1bb)]+(_0x1090fc(0x138)+'i')+C[_0x1090fc(0x192)]+'|'+C[_0x35ef89(0x1bb)]+_0x1090fc(0x1dd)+C[_0x35ef89(0x192)]+('\x20\x20Switch\x20w'+_0x1090fc(0x19e)+_0x1090fc(0x157)+'o\x0a\x20\x20')+C[_0x35ef89(0x1bb)]+(_0x35ef89(0x174)+'n')+C[_0x1090fc(0x192)]+'|'+C['cyan']+_0x1090fc(0x149)+C[_0x1090fc(0x192)]+('\x20\x20\x20\x20\x20\x20\x20Mir'+_0x35ef89(0x210)+_0x35ef89(0x1d7)+_0x35ef89(0x1f0)+':\x20on)\x0a\x20\x20')+C[_0x1090fc(0x1bb)]+_0x35ef89(0x23b)+C[_0x1090fc(0x192)]+(_0x1090fc(0x1c3)+_0x35ef89(0x21d))+t(_0x35ef89(0x1eb))+_0x1090fc(0x15b)+C[_0x1090fc(0x1bb)]+_0x35ef89(0x177)+C['reset']+(_0x1090fc(0x1c3)+_0x35ef89(0x21d))+t(_0x35ef89(0x137))+'\x0a\x0a'+C[_0x35ef89(0x1a6)]+t('help.foote'+'r')+C[_0x35ef89(0x192)]+'\x0a');}function printUser(_0x1a536f){const _0x5a9790=_0x223830,_0x24d56d=_0x390fd8;clearCurrentLine(),console[_0x5a9790(0x1ac)]('\x0a'+C[_0x5a9790(0x218)]+C[_0x24d56d(0x1e3)+'n']+t(_0x5a9790(0x1c5))+':'+C[_0x5a9790(0x192)]+'\x20'+_0x1a536f);}function printAssistantStart(){const _0x57d94a=_0x223830,_0x57da3a=_0x223830;clearCurrentLine();const _0x4fc8cb=activeTarget==='telegram'?'\x20'+C[_0x57d94a(0x1a6)]+_0x57d94a(0x244)+C[_0x57d94a(0x192)]:'';process[_0x57da3a(0x235)]['write']('\x0a'+C[_0x57d94a(0x218)]+C[_0x57d94a(0x1bc)]+'Alvin\x20Bot'+_0x4fc8cb+':'+C[_0x57d94a(0x192)]+'\x20');}function printAssistantDelta(_0x2d5ef8){const _0x4df855=_0x223830,_0x11c113=_0x223830;process[_0x4df855(0x235)][_0x4df855(0x1cb)](_0x2d5ef8);}function printAssistantEnd(_0x14792a){const _0x384449=_0x223830,_0x242fef=_0x223830,_0x3c5dc9=_0x14792a&&_0x14792a>-0x1c23+0x812+0x1411?'\x20'+C[_0x384449(0x1a6)]+'($'+_0x14792a[_0x242fef(0x181)](0x2142+-0x240+-0x1efe)+')'+C[_0x242fef(0x192)]:'';process[_0x384449(0x235)][_0x384449(0x1cb)](_0x3c5dc9+'\x0a');}function printTool(_0x4fa2c8){const _0x1ffc21=_0x223830,_0x4a80a6=_0x223830;clearCurrentLine(),process[_0x1ffc21(0x235)]['write']('\x20\x20'+C['yellow']+'⚙\x20'+_0x4fa2c8+_0x1ffc21(0x1e0)+C['reset']);}function _0x55f1(){const _0x5c17f3=['BwvTB3j5','Dhj1zq','C2vHCMnO','ic9TB2rLBca8AW','BgvNCMfTihnLCW','WRCGja','CYbUB3CGz28GAq','B2rLoIbptIdIGjqG','zwrKAw5NCW','CMvZzxq','BMvJDgvK','zxj2zsbVBIbVCG','vgfYz2v0oIbuzq','CMvK','l2fWAs9ZDgf0Dq','DgfYz2v0','CY9ZD2L0y2G','C3rHDhvZlNrVBW','C3rYAw5NAwz5','zg9Uzq','Aw1L','AgvYzsb5B3vYia','DMLKzxi','B3bLBG','q3jVBIbkB2jZ','Dg9VBhm','q3jLyxrLza','t1bftG','y2XLyxjty3jLzq','zgLT','DhvP','g1S0ng0','mZe4odm3mdLcsMnrthi','mZi4otjIr3r1EMC','AgvSCc5ZDgf0Dq','Bg9N','CL9TC2C','DhvPlMjVDfjLCW','DhvPoMvWAgvTzq','DhvPlMnYB25fCG','g1SZmg0','ChmVy3jLyxrL','CMvZDw1PBMCGDa','C3rHDhvZlNzLCG','tw9KzwW','l2fWAs9IywnRDq','Aw5KzxHpzG','vfvjihnLC3nPBW','DhvPlMnVBM5LyW','iokxGca','y3LHBG','yNjPz2H0qMX1zq','t2jZzxj2zxiGBq','8j+tSsbuzwWGqM90oG','DhjPBq','g1S5m20','DMvYC2LVBG','vgfYz2v0oIbuvq','icaGicaGicaGia','g1SZn20','DhvPlNLVDq','u2vZC2LVBJOG','g1S5mM0','CMDLDdOG','Aw5JBhvKzxm','zMfSBgjHy2S','D3jPDgu','zNjVBq','Dxb0Aw1L','yNjPz2H0q3LHBG','y29ZDa','C3rHDhvZlNbYBW','yMfJA3vW','Dg9tDhjPBMC','g1SZnM0','iokgKIa','ywn0AxzL','C3rHDhvZlM1Vza','yw0Gywn0AxzPDa','g1SZmM0','g1SZBq','BgvUz3rO','CxvPDa','oti4mtD5r3HxBKS','DgvSzwDYyw0','C3rKAw4','g1S5mw0','lI4U','ls1OB3n0','ls1WB3j0','yNjPz2H0r3jLzq','igjVDcbYzxbSAq','BwvZC2fNzq','q3vYCMvUDcb0yq','zg9JDg9Y','D3m6lY8','BLjLC2v0','Bg9JywXOB3n0','AgvSCc5OzwXW','DhvPlM5Vq3jVBG','rMfPBgvK','l2fWAs9Yzxn0yq','8j+sOsa','EsaOzgvMyxvSDa','l2fWAs9TB2rLBa','y2XLyxi','zw5HyMXLza','DhLWzq','BI9QC29U','Bw9KzwW','8j+KLIbbBhzPBIbcBW','DhvPlMj5zq','Bw9KzwXZ','zgvSDge','C2nOzwr1Bgu','C3rHDhvZ','DhvPlMfJDgL2zq','BwLYCM9YoNjLCW','zxjYB3i','Aw50zxj2ywW','8j+tSsbuzwWGvxnLCG','sw52ywXPzcbkuW','l2nSzwfY','C2vUza','DhvPlM1VzgvSCW','mta1s0HoCM9X','DhvPlNn0yxr1CW','icaGia','tM9Kzsa','CgfYC2u','AxnZDwvZ','AM9ICW','g1S5nM0','Dgv4Da','C3rHDhvZlM1LBq','CM9YifrLBgvNCG','DgLVBKXVC3q','ChjVBxb0','BgLUzq','zML4','mtC3mfbmqLb1qq','BwLYCM9YoNvZzq','zxHPDa','yM9Sza','DfrYAwDNzxjLza','AwXSie5pvcbIzq','yxjJAa','z3jHBsbbtKqGAa','icaGica','DMvJDg9YCW','DhvPlMnYzwf0Aq','DhvPlMjHy2T1Ca','DhvPlNrPDgXL','g1S5ng0','C3rHDhvZlNvWDa','B3jLzcbOzxjLia','z3jLzw4','y2f0y2G','zxK+','DhvPlNjLC3rHCG','B2zMlG','vw5RBM93BIbLCG','zwruBW','g1S0mg0','CgXHDgzVCM0','DhvZ','BMfTzq','l3n0yxr1CW','y2XVC2u','l2rVy3rVCG','l21VzgvS','iokaLca','C3rKB3v0','mZa1nJm3nMvYDePuAG','yxbWBgLJyxrPBW','DgvS','C2LVBIdIGjqGDgHL','nu5wEfvesq','l2HLBha','g1SZmw0','iIaO','l2fWAs9JCM9U','icaG','lIbvC2uGl3rHCG','CMfSihnLC3nPBW','mtuZmtm0mxf3zKHRza','kgrPBsK','w+kgKIbuzwXD','DhvPlNrVB2XvCW','ndmWmtG1ENzKENvn','DhvPlNrVB2XZvq','EwvSBg93','CMvXDwvZDa','CMvWzwf0','B2jZzxj2zq','AgvSCc5XDwL0','l3rHCMDLDcb0Dq','BMDcywnRDxa','DhvPlNn3AxrJAa','ssaOEw91CIbVDW','zMLSzxm','l3jLC3rHCNq','AgvSCa','g1S0nw0','sgvHBhrOlunOzq','BM93','g1SWBq','C3rHDhvZlNbSDq','zw5K','CMvHzhLtDgf0zq','C2v0uhjVBxb0','z3jHEq','DhvPlNnJyw5UAq','B2zM','BIbPC29SyxrLza','BgWGyMuGBwLYCG','CMfSoG','g1SXBq','C3bSAxq','CM9Y','ywn0AxzPDhKGDW','zxjLkq','B3j5','DhvPlM5VDenVBG','AgvSCc5TB2rLBa','C2XPy2u','DhvPlMrPC2nVBG','BwvZC2fNzxmGzW','kcGOlISPkYKRkq','C3rHDhvZlNvZzq','yNL0zuXLBMD0Aa','cIaG','zMXVB3i','yxjNDG','DhvPoMXVy2fS','ihnOB3DUigHLCG','g1S5mg0','AgvSCc50AxrSzq','DezHAwXLza','l2fWAs9KB2n0BW','otG1ndeYBg1uALvn','rxjYB3i','Dg9VBa','Cg9W','u0Lhsu5u','CMvZDgfYDa','C2v2zxjPDhK','zMfSC2u','AgvSCc5KB2n0BW','ls1Yzxn1Bwu','AgvSCc5Yzxn0yq','sM9ICW','BMv3igvWAgvTzq','yM90','g1S5nw0','CMvHzhK','l29IC2vYDMuGBW','ifrLBgvNCMfTia','B2rLoIbprKyG4Ocu','l3f1Axq','BNrVihrOzsbuzq','igzPBgvZkq','DxiGBwvZC2fNzq','zgf0yq','AgvSCc5JBgvHCG','yNjPz2H0wwvSBa','ndHvwfbouKe','DgvKvg8','ue9tva','Dg9gAxHLza','yMX1zq','C3rHCNrZv2L0Aa','A2v5','DhvPlMzHBgXIyq','z2v0','Dg9mB3DLCKnHCW','Cg9UC2vFzgvSDa'];_0x55f1=function(){return _0x5c17f3;};return _0x55f1();}function _0x1799(_0x5eb7ce,_0x53fd4d){_0x5eb7ce=_0x5eb7ce-(0x6d*0x3b+0xf6f+-0x13af*0x2);const _0x498623=_0x55f1();let _0x2adee7=_0x498623[_0x5eb7ce];if(_0x1799['LXyCxy']===undefined){var _0x4c7c92=function(_0x3665a0){const _0x42ab6d='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x494575='',_0x3b93af='',_0x44e4bf=_0x494575+_0x4c7c92;for(let _0x4dd60c=-0x1492*0x1+0x26e1+-0x2b*0x6d,_0xa7ad4d,_0xc74847,_0x4ffcce=-0xeaf+0x252+-0xc5d*-0x1;_0xc74847=_0x3665a0['charAt'](_0x4ffcce++);~_0xc74847&&(_0xa7ad4d=_0x4dd60c%(0x9fe+0x74e*0x3+-0x13a*0x1a)?_0xa7ad4d*(0x1*0xdf6+0xb8c*0x1+-0x2*0xca1)+_0xc74847:_0xc74847,_0x4dd60c++%(-0x171d+0x1*0x6d7+0xf*0x116))?_0x494575+=_0x44e4bf['charCodeAt'](_0x4ffcce+(-0x14a4*-0x1+0x1*-0x18eb+0xd*0x55))-(0x140b+-0x4a7+-0xf5a)!==-0x71*0xb+-0x1020+0x14fb?String['fromCharCode'](-0x1*-0x18c3+0x9e6+-0x116*0x1f&_0xa7ad4d>>(-(-0x38c*-0x3+-0x151e+0xa7c)*_0x4dd60c&-0x4*0x2b6+0x622+0x2*0x25e)):_0x4dd60c:-0x1*0x1d3c+0x23a2+-0x666){_0xc74847=_0x42ab6d['indexOf'](_0xc74847);}for(let _0x4c0399=0x97a+0x58+-0x9d2,_0x5d7243=_0x494575['length'];_0x4c0399<_0x5d7243;_0x4c0399++){_0x3b93af+='%'+('00'+_0x494575['charCodeAt'](_0x4c0399)['toString'](-0x964*-0x4+-0x7*0x3b3+-0xb9b))['slice'](-(-0x481+-0x5bb+0xa3e));}return decodeURIComponent(_0x3b93af);};_0x1799['ohaBhP']=_0x4c7c92,_0x1799['QSghjV']={},_0x1799['LXyCxy']=!![];}const _0x20f914=_0x498623[-0x1c23+0x812+0x1411],_0x2cb8e6=_0x5eb7ce+_0x20f914,_0x2a5a79=_0x1799['QSghjV'][_0x2cb8e6];if(!_0x2a5a79){const _0x4a6548=function(_0x1f6745){this['YdwmBZ']=_0x1f6745,this['gjYaFc']=[0x2142+-0x240+-0x1f01,-0x2018+-0x2124+-0x14*-0x343,0x1e81+0x566+-0x23e7],this['aWBKRv']=function(){return'newState';},this['yqEApK']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['cmhCnR']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x4a6548['prototype']['pxDiOX']=function(){const _0x31fb2a=new RegExp(this['yqEApK']+this['cmhCnR']),_0x3ecc27=_0x31fb2a['test'](this['aWBKRv']['toString']())?--this['gjYaFc'][0x1c78+-0x1d9f*0x1+0x128]:--this['gjYaFc'][0x1*-0x9d7+-0xaa5+0x147c];return this['vGItor'](_0x3ecc27);},_0x4a6548['prototype']['vGItor']=function(_0x182db5){if(!Boolean(~_0x182db5))return _0x182db5;return this['WRGRtN'](this['YdwmBZ']);},_0x4a6548['prototype']['WRGRtN']=function(_0x490138){for(let _0x6e2434=-0xd*0x1c6+0x5f5+-0x3*-0x5b3,_0x196232=this['gjYaFc']['length'];_0x6e2434<_0x196232;_0x6e2434++){this['gjYaFc']['push'](Math['round'](Math['random']())),_0x196232=this['gjYaFc']['length'];}return _0x490138(this['gjYaFc'][0x2132+0x345*0x3+-0x6d*0x65]);},new _0x4a6548(_0x1799)['pxDiOX'](),_0x2adee7=_0x1799['ohaBhP'](_0x2adee7),_0x1799['QSghjV'][_0x2cb8e6]=_0x2adee7;}else _0x2adee7=_0x2a5a79;return _0x2adee7;}function printToolDone(){const _0xb01e2=_0x390fd8,_0x1edad1=_0x390fd8;clearCurrentLine();if(toolCount>-0x2018+-0x2124+-0x14*-0x343){const _0x26a937=toolCount>0x1e81+0x566+-0x23e6?t(_0xb01e2(0x132)+'sed'):t(_0x1edad1(0x130)+'ed');console[_0x1edad1(0x1ac)]('\x20\x20'+C[_0xb01e2(0x1a6)]+C['yellow']+'⚙\x20'+toolCount+'\x20'+_0x26a937+C[_0xb01e2(0x192)]);}toolCount=0x1c78+-0x1d9f*0x1+0x127;}function printError(_0x22540b){const _0x47d77d=_0x223830;clearCurrentLine(),console[_0x47d77d(0x1ac)]('\x0a'+C['red']+'✖\x20'+_0x22540b+C['reset']);}function printInfo(_0xdabe8){const _0xbbb4b9=_0x390fd8,_0x52f175=_0x390fd8;clearCurrentLine(),console[_0xbbb4b9(0x1ac)](C[_0x52f175(0x1bb)]+'ℹ\x20'+_0xdabe8+C[_0x52f175(0x192)]);}function printSuccess(_0xe09544){const _0x5064f9=_0x390fd8,_0x2f420d=_0x223830;clearCurrentLine(),console[_0x5064f9(0x1ac)](C[_0x2f420d(0x225)]+'✔\x20'+_0xe09544+C['reset']);}function printMirrorUser(_0x584314){const _0x34226c=_0x223830,_0x41e0ab=_0x223830;clearCurrentLine(),console[_0x34226c(0x1ac)]('\x0a'+C[_0x34226c(0x1a6)]+C['gray']+(_0x41e0ab(0x201)+':\x20')+_0x584314+C[_0x34226c(0x192)]);}function printMirrorAssistantStart(){const _0x542c59=_0x390fd8,_0x2c2b70=_0x390fd8;clearCurrentLine(),process[_0x542c59(0x235)][_0x542c59(0x1cb)]('\x0a'+C[_0x542c59(0x1a6)]+C['gray']+(_0x2c2b70(0x1be)+'\x20')+C[_0x2c2b70(0x192)]);}function printMirrorAssistantDelta(_0x1e0d4a){const _0x225247=_0x223830,_0x11d126=_0x390fd8;process[_0x225247(0x235)][_0x11d126(0x1cb)](''+C[_0x11d126(0x1a6)]+C[_0x225247(0x147)]+_0x1e0d4a+C['reset']);}function printMirrorAssistantEnd(){const _0x4d1965=_0x390fd8,_0x356d77=_0x390fd8;process[_0x4d1965(0x235)][_0x356d77(0x1cb)]('\x0a');}function showPrompt(){const _0x1e95aa=_0x223830,_0x478257=_0x223830;if(isStreaming||!rl)return;rl[_0x1e95aa(0x146)](C['brightGree'+'n']+'❯'+C[_0x1e95aa(0x192)]+'\x20'),rl[_0x1e95aa(0x212)](!![]);}function connectWebSocket(){const _0x4ce590=_0x223830,_0x189258=_0x223830;ws=new _0x288f36(wsUrl),ws['on'](_0x4ce590(0x1a0),()=>{const _0x3a937c=_0x4ce590;connected=!![],printInfo(t('tui.connec'+_0x3a937c(0x17f))),showPrompt();}),ws['on']('message',_0xb34868=>{const _0x191dd6=_0x4ce590;try{const _0x3c3d51=JSON[_0x191dd6(0x20a)](_0xb34868['toString']());handleMessage(_0x3c3d51);}catch{}}),ws['on']('close',()=>{const _0x20d215=_0x4ce590,_0x2103d6=_0x4ce590;connected=![],isStreaming=![],printError(t(_0x20d215(0x1b9)+_0x2103d6(0x211))),setTimeout(connectWebSocket,0x1*-0x9d7+-0xaa5+0x2034);}),ws['on'](_0x189258(0x1ff),()=>{});}function handleMessage(_0x469002){const _0x18a10d=_0x390fd8,_0x51007c=_0x390fd8;switch(_0x469002[_0x18a10d(0x1f4)]){case _0x18a10d(0x20e):!isStreaming&&(isStreaming=!![],currentToolName&&(printToolDone(),currentToolName=''),printAssistantStart());_0x469002['delta']&&(printAssistantDelta(_0x469002[_0x51007c(0x1fa)]),currentResponse+=_0x469002['delta']);break;case _0x18a10d(0x166):if(!isStreaming)isStreaming=!![];toolCount++,currentToolName=_0x469002[_0x51007c(0x22f)]||_0x51007c(0x166),printTool(currentToolName);break;case _0x18a10d(0x1ca):printInfo(t(_0x51007c(0x185)+'ck')+'\x20'+_0x469002[_0x18a10d(0x1cc)]+_0x18a10d(0x1d4)+_0x469002['to']);break;case _0x51007c(0x19c):isStreaming&&printAssistantEnd(_0x469002['cost']);if(_0x469002[_0x51007c(0x1cf)])totalCost+=_0x469002['cost'];isStreaming=![],currentResponse='',currentToolName='',showPrompt();break;case _0x51007c(0x1ff):printError(_0x469002[_0x51007c(0x1ff)]||_0x18a10d(0x22a)+_0x18a10d(0x14f)),isStreaming=![],showPrompt();break;case _0x18a10d(0x192):printInfo(t('tui.sessio'+_0x51007c(0x1e9))),showPrompt();break;case _0x51007c(0x216)+_0x51007c(0x1ad):if(!observerEnabled)break;printMirrorUser(_0x469002['text']||'');break;case _0x18a10d(0x1fe)+'ponse_star'+'t':if(!observerEnabled)break;isMirrorStreaming=!![],printMirrorAssistantStart();break;case _0x51007c(0x1fe)+_0x18a10d(0x188)+'a':if(!observerEnabled)break;!isMirrorStreaming&&(isMirrorStreaming=!![],printMirrorAssistantStart());printMirrorAssistantDelta(_0x469002[_0x18a10d(0x1fa)]||'');break;case _0x18a10d(0x1fe)+'ponse_done':if(!observerEnabled)break;isMirrorStreaming&&(printMirrorAssistantEnd(),isMirrorStreaming=![]);break;}}async function apiGet(_0x3f035e){return new Promise((_0x2a63b3,_0x149e98)=>{const _0x33b80c=_0x1799;_0x3727dd[_0x33b80c(0x186)](''+baseUrl+_0x3f035e,_0x438454=>{const _0x4e17fc=_0x33b80c,_0x4c46d3=_0x33b80c;let _0x43fa32='';_0x438454['on'](_0x4e17fc(0x17b),_0x1af429=>_0x43fa32+=_0x1af429),_0x438454['on'](_0x4e17fc(0x144),()=>{const _0xd640a0=_0x4c46d3,_0x22ea35=_0x4c46d3;try{_0x2a63b3(JSON[_0xd640a0(0x20a)](_0x43fa32));}catch{_0x149e98(new Error(_0xd640a0(0x202)+'ON'));}});})['on']('error',_0x149e98);});}async function apiPost(_0x4f50d1,_0xe351bb){return new Promise((_0x3eee04,_0x422152)=>{const _0x2724fb=_0x1799,_0x6ed896=_0x1799,_0x2ce5d9=JSON[_0x2724fb(0x19b)](_0xe351bb),_0x50a3ee=_0x3727dd[_0x2724fb(0x134)](''+baseUrl+_0x4f50d1,{'method':_0x6ed896(0x180),'headers':{'Content-Type':_0x2724fb(0x237)+_0x6ed896(0x1f5),'Content-Length':Buffer[_0x2724fb(0x15a)](_0x2ce5d9)}},_0x4e10e5=>{const _0x1d7ea8=_0x2724fb,_0x42057a=_0x6ed896;let _0x332a31='';_0x4e10e5['on'](_0x1d7ea8(0x17b),_0x177109=>_0x332a31+=_0x177109),_0x4e10e5['on'](_0x42057a(0x144),()=>{const _0x4435d4=_0x42057a,_0x30f419=_0x42057a;try{_0x3eee04(JSON[_0x4435d4(0x20a)](_0x332a31));}catch{_0x422152(new Error(_0x30f419(0x202)+'ON'));}});});_0x50a3ee['on']('error',_0x422152),_0x50a3ee[_0x2724fb(0x1cb)](_0x2ce5d9),_0x50a3ee['end']();});}async function handleCommand(_0x5decad){const _0xfbd0b=_0x223830,_0x1540c7=_0x223830,_0x698b88=_0x5decad[_0xfbd0b(0x155)](-0xd*0x1c6+0x5f5+-0xb*-0x18e)[_0xfbd0b(0x14e)](/\s+/),_0x4637c8=_0x698b88[0x2132+0x345*0x3+-0x6d*0x65]['toLowerCas'+'e']();switch(_0x4637c8){case _0x1540c7(0x13e):case'h':drawHelp();break;case'model':case'm':{try{const _0x2bf194=await apiGet(_0x1540c7(0x1f1)+'s');console[_0xfbd0b(0x1ac)]('\x0a'+C[_0x1540c7(0x218)]+t(_0x1540c7(0x205))+':'+C[_0xfbd0b(0x192)]);if(_0x2bf194['models'])for(const _0x1e6025 of _0x2bf194[_0xfbd0b(0x1f9)]){const _0xe7757e=_0x1e6025[_0x1540c7(0x184)]===_0x2bf194[_0x1540c7(0x1d5)]?C['brightGree'+'n']+_0xfbd0b(0x1ba)+t(_0xfbd0b(0x1fd))+C['reset']:'',_0x654df=_0x1e6025[_0x1540c7(0x1fc)]===_0x1540c7(0x173)?C['green']+'✓'+C[_0xfbd0b(0x192)]:C['dim']+'✗'+C[_0x1540c7(0x192)];console[_0xfbd0b(0x1ac)]('\x20\x20'+_0x654df+'\x20'+C[_0x1540c7(0x218)]+_0x1e6025[_0x1540c7(0x184)]+C[_0x1540c7(0x192)]+'\x20'+C[_0xfbd0b(0x1a6)]+'('+(_0x1e6025['model']||_0x1e6025['name'])+')'+C[_0xfbd0b(0x192)]+_0xe7757e);}console[_0x1540c7(0x1ac)]('\x0a'+C['dim']+t(_0xfbd0b(0x13a)+_0x1540c7(0x1b5))+(_0x1540c7(0x18c)+_0xfbd0b(0x227))+C['reset']);if(_0x698b88[-0x3*-0xcd8+-0x1b*-0x11a+-0x4445]){const _0x406804=await apiPost(_0xfbd0b(0x1f1)+_0x1540c7(0x199),{'key':_0x698b88[0x175*-0x3+0x15*0x43+-0x11f*0x1]});_0x406804['ok']?(currentModel=_0x406804[_0xfbd0b(0x1d5)]||_0x698b88[-0x1cde+0x10f*0x19+0x268],printSuccess(t(_0x1540c7(0x13a)+_0x1540c7(0x22b))+':\x20'+currentModel)):printError(_0x406804[_0x1540c7(0x1ff)]||t(_0x1540c7(0x13a)+_0x1540c7(0x165)));}}catch(_0x18d74e){printError(t(_0xfbd0b(0x205)+'Error')+':\x20'+_0x18d74e['message']);}break;}case _0xfbd0b(0x1c1):case'v':{console[_0xfbd0b(0x1ac)]('\x0a'+C[_0x1540c7(0x218)]+C[_0x1540c7(0x1ce)]+('🤖\x20Alvin\x20Bo'+'t')+C[_0xfbd0b(0x192)]+'\x20'+C[_0x1540c7(0x1a6)]+'v'+BOT_VERSION+C[_0xfbd0b(0x192)]),console[_0x1540c7(0x1ac)](C[_0x1540c7(0x1a6)]+_0xfbd0b(0x209)+process['version']+'\x20·\x20'+process[_0xfbd0b(0x22d)]+'/'+process[_0xfbd0b(0x21b)]+C[_0x1540c7(0x192)]+'\x0a');break;}case'status':case's':{try{const _0x39c5c5=await apiGet(_0x1540c7(0x197)+'s');console['log']('\x0a'+C['bold']+C[_0xfbd0b(0x1ce)]+(_0x1540c7(0x1f7)+'t')+C[_0x1540c7(0x192)]+'\x20'+C[_0x1540c7(0x1a6)]+'v'+BOT_VERSION+C[_0x1540c7(0x192)]),console['log'](''+C[_0xfbd0b(0x147)]+'─'[_0x1540c7(0x135)](0x1e1+-0xc61*-0x1+-0xe1a)+C['reset']);_0x39c5c5['model']&&(console[_0x1540c7(0x1ac)]('\x20\x20'+C['cyan']+t(_0x1540c7(0x1d6)+'el')+C[_0xfbd0b(0x192)]+'\x20\x20\x20\x20'+(_0x39c5c5[_0xfbd0b(0x1f6)][_0x1540c7(0x1f6)]||_0x39c5c5['model'][_0xfbd0b(0x22f)]||'?')),console['log']('\x20\x20'+C[_0xfbd0b(0x1bb)]+t(_0x1540c7(0x1d0)+_0xfbd0b(0x19f))+C[_0x1540c7(0x192)]+'\x20'+(_0x39c5c5[_0xfbd0b(0x1f6)][_0x1540c7(0x22f)]||'?')),console[_0x1540c7(0x1ac)]('\x20\x20'+C[_0xfbd0b(0x1bb)]+t('status.sta'+_0xfbd0b(0x22e))+C[_0x1540c7(0x192)]+_0xfbd0b(0x23f)+(_0x39c5c5[_0x1540c7(0x1f6)][_0xfbd0b(0x1fc)]||'?')));if(_0x39c5c5['bot']){const _0x5043b5=Math[_0x1540c7(0x15c)]((_0x39c5c5[_0x1540c7(0x171)][_0xfbd0b(0x1cd)]||0x59*0x41+-0x1ac2+-0x47*-0xf)/(0x167d+-0x1*0x17bf+-0x35*-0x4a)),_0xc3f829=Math[_0xfbd0b(0x15c)]((_0x39c5c5[_0xfbd0b(0x171)]['uptime']||0x23e7+0x93*-0x19+-0x158c)%(0x20f7+0xd*0x19b+-0x27c6)/(-0x7d8+-0x979+0x118d));console[_0xfbd0b(0x1ac)]('\x20\x20'+C[_0xfbd0b(0x1bb)]+t(_0x1540c7(0x1b4)+'sion')+C['reset']+'\x20\x20'+(_0x39c5c5[_0x1540c7(0x171)][_0xfbd0b(0x1c1)]||'?')),console['log']('\x20\x20'+C[_0xfbd0b(0x1bb)]+t(_0x1540c7(0x223)+_0x1540c7(0x19d))+C['reset']+_0x1540c7(0x23f)+_0x5043b5+'h\x20'+_0xc3f829+'m');}_0x39c5c5[_0x1540c7(0x189)]&&console[_0x1540c7(0x1ac)]('\x20\x20'+C[_0x1540c7(0x1bb)]+t(_0xfbd0b(0x20f)+_0xfbd0b(0x152))+C['reset']+_0xfbd0b(0x23f)+(_0x39c5c5[_0x1540c7(0x189)][_0xfbd0b(0x21e)]||-0x20b0+0xc2*-0x5+0x247a)+'\x20'+t('status.emb'+_0x1540c7(0x191))),console[_0xfbd0b(0x1ac)]('\x20\x20'+C['cyan']+t(_0xfbd0b(0x143)+'gins')+C['reset']+'\x20\x20'+(_0x39c5c5['plugins']||-0x1*0x4b1+-0x1b*-0x36+-0x101*0x1)),console[_0x1540c7(0x1ac)]('\x20\x20'+C['cyan']+t(_0x1540c7(0x19a)+'ls')+C[_0x1540c7(0x192)]+_0x1540c7(0x208)+(_0x39c5c5[_0xfbd0b(0x1a2)]||0x3b0+0x1088+0x1438*-0x1)),console[_0xfbd0b(0x1ac)]('\x20\x20'+C['cyan']+t(_0x1540c7(0x159)+'rs')+C[_0x1540c7(0x192)]+_0x1540c7(0x208)+(_0x39c5c5['users']||-0x1*-0x982+0x269b*0x1+-0x301d)),console[_0x1540c7(0x1ac)]('');}catch(_0x411623){printError(t(_0x1540c7(0x207)+_0xfbd0b(0x165))+':\x20'+_0x411623[_0xfbd0b(0x1e5)]);}break;}case'cron':{try{const _0x246042=await apiGet(_0x1540c7(0x23e));console[_0x1540c7(0x1ac)]('\x0a'+C[_0x1540c7(0x218)]+_0x1540c7(0x1a1)+C[_0x1540c7(0x192)]),console[_0xfbd0b(0x1ac)](''+C[_0xfbd0b(0x147)]+'─'[_0xfbd0b(0x135)](-0x24e1+-0x15*-0x1bc+0x9d)+C[_0x1540c7(0x192)]);if(!_0x246042[_0x1540c7(0x20c)]||_0x246042['jobs']['length']===0x213f+0x1b3+-0x2*0x1179)console['log']('\x20\x20'+C['dim']+t(_0xfbd0b(0x1ec)+_0xfbd0b(0x16f))+C['reset']);else for(const _0x2a436e of _0x246042['jobs']){const _0x346a00=_0x2a436e[_0x1540c7(0x1f3)]?C[_0x1540c7(0x225)]+'●'+C[_0xfbd0b(0x192)]:C[_0x1540c7(0x196)]+'●'+C[_0xfbd0b(0x192)],_0x5dc599=_0x2a436e[_0xfbd0b(0x1fb)]||_0x2a436e[_0x1540c7(0x200)]||'?';console[_0x1540c7(0x1ac)]('\x20\x20'+_0x346a00+'\x20'+C[_0x1540c7(0x218)]+_0x2a436e['name']+C[_0x1540c7(0x192)]+'\x20'+C[_0xfbd0b(0x1a6)]+'('+_0x5dc599+')'+C[_0xfbd0b(0x192)]+_0xfbd0b(0x234)+_0x2a436e[_0xfbd0b(0x1f4)]);}console['log']('');}catch(_0x466c19){printError(t(_0xfbd0b(0x1b0)+_0x1540c7(0x14f))+':\x20'+_0x466c19['message']);}break;}case _0xfbd0b(0x1e7):{try{printInfo(t(_0x1540c7(0x148)+'ng'));const _0x181c56=await apiGet(_0x1540c7(0x163)+'r'),_0x3b6156={'error':C[_0xfbd0b(0x196)]+'✖','warning':C[_0x1540c7(0x133)]+'⚠','info':C[_0x1540c7(0x182)]+'ℹ'};console[_0x1540c7(0x1ac)]('\x0a'+C['bold']+(_0xfbd0b(0x140)+'ck')+C[_0xfbd0b(0x192)]),console['log'](''+C[_0xfbd0b(0x147)]+'─'[_0x1540c7(0x135)](-0x9*-0x16d+0x10c7+-0x2*0xeba)+C[_0x1540c7(0x192)]);for(const _0x24f031 of _0x181c56[_0x1540c7(0x20b)]||[]){const _0x3d1376=_0x3b6156[_0x24f031[_0x1540c7(0x16a)]]||'?';console[_0xfbd0b(0x1ac)]('\x20\x20'+_0x3d1376+'\x20'+C[_0x1540c7(0x218)]+_0x24f031['category']+C[_0x1540c7(0x192)]+_0xfbd0b(0x234)+_0x24f031[_0x1540c7(0x1e5)]+C[_0x1540c7(0x192)]);if(_0x24f031[_0x1540c7(0x214)])console[_0x1540c7(0x1ac)](_0xfbd0b(0x208)+C['dim']+_0x1540c7(0x1ef)+_0x24f031[_0x1540c7(0x214)]+C[_0xfbd0b(0x192)]);}console['log']('');}catch(_0x33501e){printError(t('tui.doctor'+_0xfbd0b(0x165))+':\x20'+_0x33501e[_0xfbd0b(0x1e5)]);}break;}case _0xfbd0b(0x1d1):{try{printInfo(t(_0xfbd0b(0x21f)+_0x1540c7(0x139)));const _0x4be91c=await apiPost(_0xfbd0b(0x1b6)+_0xfbd0b(0x1b2),{});_0x4be91c['ok']?printSuccess(t('tui.backup'+_0x1540c7(0x1a3))+'\x20\x22'+_0x4be91c['id']+_0x1540c7(0x23d)+_0x4be91c[_0xfbd0b(0x13c)][_0xfbd0b(0x1da)]+_0xfbd0b(0x179)):printError(_0x4be91c[_0x1540c7(0x1ff)]||t(_0x1540c7(0x220)+_0xfbd0b(0x1ed)));}catch(_0x5c4024){printError(t(_0x1540c7(0x220)+_0x1540c7(0x165))+':\x20'+_0x5c4024[_0xfbd0b(0x1e5)]);}break;}case _0x1540c7(0x169):{printInfo(t(_0x1540c7(0x1ae)+'tarting'));try{await apiPost(_0x1540c7(0x1ee)+'rt',{}),printSuccess(t(_0x1540c7(0x228)+_0xfbd0b(0x219)));}catch{printError(t('tui.restar'+_0xfbd0b(0x162)));}break;}case'clear':case'c':redrawHeader({'clearScreen':!![]});ws?.[_0xfbd0b(0x145)]===_0x288f36[_0x1540c7(0x1a4)]&&ws[_0xfbd0b(0x204)](JSON[_0x1540c7(0x19b)]({'type':_0xfbd0b(0x192),'target':activeTarget,'sessionKey':activeTarget==='tui'?tuiSessionKey:undefined}));break;case _0xfbd0b(0x198):case't':{const _0x5a4925=(_0x698b88[-0x5d+0x1*-0xed6+0xf34*0x1]||'')[_0x1540c7(0x187)+'e']();if(_0x5a4925===_0xfbd0b(0x1a7))activeTarget=_0x1540c7(0x1a7),printSuccess(_0x1540c7(0x1c2)+_0xfbd0b(0x13b)+_0x1540c7(0x14a)+'\x20session)');else _0x5a4925==='telegram'||_0x5a4925===_0xfbd0b(0x238)?(activeTarget=_0x1540c7(0x1dd),printSuccess(_0xfbd0b(0x195)+'legram\x20(yo'+_0xfbd0b(0x17a)+_0xfbd0b(0x18f)+_0xfbd0b(0x178)+_0xfbd0b(0x18d)+_0xfbd0b(0x239)+_0xfbd0b(0x1e4)+'es\x20in\x20Tele'+_0x1540c7(0x21c)+_0xfbd0b(0x151))):printInfo(_0x1540c7(0x1e6)+_0xfbd0b(0x1c8)+activeTarget+(_0x1540c7(0x240)+'get\x20tui\x20or'+'\x20/target\x20t'+'elegram.'));break;}case _0x1540c7(0x136):case'o':{const _0x1844d2=(_0x698b88[-0x1af9*0x1+0x17b*0x19+-0xa09*0x1]||'')[_0x1540c7(0x187)+'e']();if(_0x1844d2==='on'||_0x1844d2==='1'||_0x1844d2===_0xfbd0b(0x18a))observerEnabled=!![],printSuccess(_0xfbd0b(0x1bd)+_0x1540c7(0x190)+'Telegram\x20a'+'ctivity\x20wi'+_0x1540c7(0x14b)+_0x1540c7(0x224)+_0x1540c7(0x243));else _0x1844d2===_0xfbd0b(0x149)||_0x1844d2==='0'||_0x1844d2===_0x1540c7(0x16b)?(observerEnabled=![],printSuccess(_0xfbd0b(0x1bd)+_0x1540c7(0x176)+_0xfbd0b(0x175)+_0x1540c7(0x150)+_0xfbd0b(0x21a)+_0xfbd0b(0x15f)+'e')):printInfo('Observer:\x20'+(observerEnabled?'on':'off')+('.\x20Use\x20/obs'+_0x1540c7(0x194)+'\x20/observe\x20'+_0xfbd0b(0x229)));break;}case _0xfbd0b(0x1db):case'q':case'exit':console[_0xfbd0b(0x1ac)]('\x0a'+C[_0x1540c7(0x1a6)]+t('tui.bye')+C[_0xfbd0b(0x192)]+'\x0a'),process[_0xfbd0b(0x217)](-0x43+0x15b9+-0x2*0xabb);break;default:sendChat(_0x5decad);return;}showPrompt();}function sendChat(_0x3a3df8){const _0x193e3e=_0x390fd8,_0x56b186=_0x390fd8;if(!ws||ws[_0x193e3e(0x145)]!==_0x288f36[_0x193e3e(0x1a4)]){printError(t(_0x56b186(0x153)+'nected')),showPrompt();return;}printUser(_0x3a3df8),ws['send'](JSON[_0x56b186(0x19b)]({'type':'chat','text':_0x3a3df8,'target':activeTarget,'sessionKey':activeTarget===_0x56b186(0x1a7)?tuiSessionKey:undefined}));if(inputHistory[-0x1dcd+-0x3*0xa06+-0x189*-0x27]!==_0x3a3df8){inputHistory['unshift'](_0x3a3df8);if(inputHistory[_0x56b186(0x1da)]>-0xd*0x2a1+0x33*-0x4+0xb*0x337)inputHistory[_0x56b186(0x167)]();}historyIndex=-(0x15a5+0x2072+-0x3616);}async function fetchInitialModel(){const _0x3586f7=_0x390fd8,_0x5b6750=_0x390fd8;try{const _0x49b072=await apiGet(_0x3586f7(0x197)+'s');if(_0x49b072['model']?.[_0x3586f7(0x1f6)])currentModel=_0x49b072[_0x5b6750(0x1f6)][_0x5b6750(0x1f6)];else _0x49b072['model']?.['name']&&(currentModel=_0x49b072[_0x5b6750(0x1f6)][_0x5b6750(0x22f)]);}catch{}}export async function startTUI(){const _0x4e60c9=_0x223830,_0x4a7498=_0x223830,_0x2a1335=process[_0x4e60c9(0x15d)][_0x4e60c9(0x1c9)](_0x4a7498(0x16d));tuiSessionKey=_0x2a1335?_0x4a7498(0x15e):_0x4a7498(0x1af)+'ral:'+Date[_0x4a7498(0x141)](),console[_0x4e60c9(0x1f2)](),drawHeader(),console[_0x4e60c9(0x1ac)](''+C['dim']+t(_0x4e60c9(0x1b9)+'ting')+'\x20'+baseUrl+_0x4a7498(0x1e0)+C['reset']),console[_0x4a7498(0x1ac)](C['dim']+_0x4a7498(0x1c6)+(_0x2a1335?_0x4a7498(0x1b3)+'ui:local\x20('+'persistent'+')':_0x4a7498(0x170)+_0x4a7498(0x241)+'n')+C[_0x4a7498(0x192)]+'\x0a'),drawHelp(),rl=createInterface({'input':process[_0x4e60c9(0x1de)],'output':process[_0x4a7498(0x235)],'terminal':!![],'historySize':0x64}),rl['on'](_0x4a7498(0x213),_0x206b73=>{const _0x5dd778=_0x4a7498,_0x7e4281=_0x4e60c9,_0x4f14e8=_0x206b73[_0x5dd778(0x1bf)]();if(!_0x4f14e8){showPrompt();return;}_0x4f14e8[_0x5dd778(0x183)]('/')?handleCommand(_0x4f14e8):sendChat(_0x4f14e8);}),rl['on'](_0x4e60c9(0x231),()=>{const _0xacd1a2=_0x4a7498,_0x5e2925=_0x4e60c9;console[_0xacd1a2(0x1ac)]('\x0a'+C['dim']+t(_0xacd1a2(0x1f8))+C[_0x5e2925(0x192)]+'\x0a'),process[_0x5e2925(0x217)](-0x137*0x17+0x959+0x1298);}),process['on'](_0x4a7498(0x168),()=>{const _0xe5f06a=_0x4a7498,_0xb9d9e5=_0x4a7498;console[_0xe5f06a(0x1ac)]('\x0a'+C[_0xb9d9e5(0x1a6)]+t(_0xb9d9e5(0x1f8))+C[_0xb9d9e5(0x192)]+'\x0a'),process[_0xb9d9e5(0x217)](-0xa9+-0x17e9*-0x1+-0x6*0x3e0);}),process['stdout']['on']('resize',()=>{if(!isStreaming)showPrompt();}),await fetchInitialModel(),connectWebSocket();}const isDirectRun=process['argv'][0x1c35+0x22b*-0x1+-0x1*0x1a09]?.[_0x390fd8(0x1c9)](_0x223830(0x1a7));isDirectRun&&startTUI()[_0x223830(0x226)](console['error']);