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.
Files changed (137) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +25 -31
  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 -174
  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 -583
  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 -86
  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 -1902
  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 _0x4092f0=_0x21a2,_0x146b88=_0x21a2;(function(_0xfe8e16,_0x214513){const _0x2c9b79=_0x21a2,_0x21139=_0x21a2,_0x44b663=_0xfe8e16();while(!![]){try{const _0x431c88=parseInt(_0x2c9b79(0x1bf))/(-0x39+-0xeed*0x1+0xf27)*(-parseInt(_0x21139(0x238))/(-0x2*0xf72+-0x1*0xa3b+0x2921))+parseInt(_0x21139(0x218))/(0x120e+-0x636*0x1+-0xbd5*0x1)+-parseInt(_0x2c9b79(0x1c8))/(0x23*-0x5b+-0x2d8+-0xf4d*-0x1)+parseInt(_0x2c9b79(0x274))/(-0x1460*0x1+-0xea1+0x2306*0x1)+-parseInt(_0x21139(0x265))/(-0x2583*-0x1+0x2616+-0x4b93)*(parseInt(_0x2c9b79(0x239))/(-0x10*0x13d+0x1*-0x213f+0x2d*0x12e))+-parseInt(_0x2c9b79(0x21b))/(-0xfec+-0x47d+0x1471)*(parseInt(_0x2c9b79(0x259))/(-0x1d13+-0x1*-0x234b+-0x1*0x62f))+-parseInt(_0x21139(0x1b4))/(-0x2d+-0x1*-0x38b+-0x354)*(-parseInt(_0x2c9b79(0x1d7))/(-0xcdd*-0x1+-0x1*0xeda+0x208));if(_0x431c88===_0x214513)break;else _0x44b663['push'](_0x44b663['shift']());}catch(_0x2534e7){_0x44b663['push'](_0x44b663['shift']());}}}(_0x57d3,-0xc82d2+-0x2251d*-0x3+0xc963a));const _0x3e8118=(function(){let _0x26cbbf=!![];return function(_0x345e92,_0x402441){const _0xf9efe4=_0x26cbbf?function(){const _0x2991cd=_0x21a2;if(_0x402441){const _0x522f9d=_0x402441[_0x2991cd(0x24e)](_0x345e92,arguments);return _0x402441=null,_0x522f9d;}}:function(){};return _0x26cbbf=![],_0xf9efe4;};}()),_0x165f0f=_0x3e8118(this,function(){const _0x476042=_0x21a2,_0x59bde5=_0x21a2;return _0x165f0f['toString']()[_0x476042(0x1ee)](_0x476042(0x20e)+'+$')[_0x59bde5(0x267)]()[_0x476042(0x205)+'r'](_0x165f0f)[_0x59bde5(0x1ee)](_0x476042(0x20e)+'+$');});_0x165f0f();import{createInterface,cursorTo,clearLine as _0x1f3bec}from'readline';import _0x52fb9d from'ws';import _0x3fa16a from'http';import{initI18n,t}from'../i18n.js';import{BOT_VERSION}from'../version.js';initI18n();const C={'reset':_0x4092f0(0x228),'bold':_0x4092f0(0x23e),'dim':'\x1b[2m','italic':_0x4092f0(0x1db),'underline':_0x4092f0(0x235),'black':_0x4092f0(0x1f8),'red':_0x146b88(0x1c2),'green':'\x1b[32m','yellow':_0x4092f0(0x1ff),'blue':'\x1b[34m','magenta':_0x146b88(0x227),'cyan':_0x4092f0(0x1f6),'white':_0x4092f0(0x224),'gray':'\x1b[90m','brightRed':_0x146b88(0x253),'brightGreen':_0x4092f0(0x1eb),'brightYellow':_0x4092f0(0x214),'brightBlue':_0x146b88(0x1ef),'brightMagenta':_0x146b88(0x1a9),'brightCyan':_0x4092f0(0x243),'brightWhite':_0x146b88(0x27f),'bgBlack':_0x4092f0(0x229),'bgBlue':_0x146b88(0x27e),'bgMagenta':'\x1b[45m','bgGray':'\x1b[100m'};let ws=null,rl,connected=![],currentModel=_0x4092f0(0x295),totalCost=0xd84+-0x1e21+0x109d,isStreaming=![],isMirrorStreaming=![],currentResponse='',currentToolName='',toolCount=-0x473+0x1*0xede+0x7*-0x17d;const inputHistory=[];let historyIndex=-(0x340+-0xc3*-0xd+-0xd26),activeTarget='tui',observerEnabled=!![],tuiSessionKey=_0x146b88(0x1c5)+_0x146b88(0x217)+Date[_0x146b88(0x20b)]();const host=process[_0x4092f0(0x19f)][_0x146b88(0x298)]('--host')?process[_0x4092f0(0x19f)][process['argv'][_0x4092f0(0x1d8)](_0x146b88(0x1b8))+(-0x1*0xa3+0xd42+-0x13*0xaa)]||_0x4092f0(0x255):_0x146b88(0x255),port=process[_0x146b88(0x19f)][_0x4092f0(0x298)](_0x4092f0(0x299))?parseInt(process[_0x4092f0(0x19f)][process[_0x146b88(0x19f)]['indexOf'](_0x146b88(0x299))+(0x2327+-0x3*-0xb81+-0x45a9)])||-0x1682+0x1*-0xf05+0x83*0x61:0x89*-0x3a+0xa*-0x7e+-0x6*-0x803,baseUrl=_0x4092f0(0x1e5)+host+':'+port,wsUrl=_0x146b88(0x1e6)+host+':'+port,HEADER_LINES=0x1155+0x1*0x295+-0x5*0x3fb;function getWidth(){const _0x20af3=_0x146b88,_0x5eac74=_0x146b88;return process[_0x20af3(0x1e7)][_0x5eac74(0x26a)]||-0x806+0x1aaf+-0x1ab*0xb;}function clearCurrentLine(){const _0x3429eb=_0x4092f0;cursorTo(process[_0x3429eb(0x1e7)],-0x7c0*0x2+-0x1*-0x23a7+0x7*-0x2e1),_0x1f3bec(process['stdout'],-0xb14+-0x345+0xe59);}function drawHeader(){const _0x17da68=_0x146b88,_0x3aca0a=_0x146b88,_0x139656=getWidth(),_0x474c06=connected?C['brightGree'+'n']+'●'+C[_0x17da68(0x212)]:C['red']+'●'+C[_0x3aca0a(0x212)],_0xfce33c=connected?t(_0x17da68(0x22c)+_0x17da68(0x1f2)):t(_0x17da68(0x192)+_0x17da68(0x296)),_0x4a7911=''+C[_0x3aca0a(0x1d4)+_0x3aca0a(0x28f)]+currentModel+C[_0x17da68(0x212)],_0x1ebcea=totalCost>0x1*0x8cc+0x12ed+-0x1*0x1bb9?'\x20'+C[_0x3aca0a(0x221)]+_0x17da68(0x234)+totalCost[_0x3aca0a(0x1a5)](-0x253a+0x111f+0x141f)+C[_0x17da68(0x212)]:'',_0x2edf56='\x20'+C['gray']+'│'+C[_0x17da68(0x212)]+'\x20'+C[_0x17da68(0x1b6)+'ow']+(activeTarget===_0x17da68(0x268)?'→\x20Telegram':'TUI\x20sessio'+'n')+C[_0x3aca0a(0x212)],_0x19f12b=''+C[_0x17da68(0x22a)]+C[_0x3aca0a(0x22f)]+t(_0x17da68(0x1f5))+C['reset'],_0x1cd83f=_0x474c06+'\x20'+_0xfce33c+'\x20'+C[_0x17da68(0x221)]+'│'+C[_0x3aca0a(0x212)]+'\x20'+_0x4a7911+_0x1ebcea+_0x2edf56;console[_0x17da68(0x1ec)](''+C['gray']+'─'[_0x3aca0a(0x1e0)](_0x139656)+C[_0x17da68(0x212)]),console[_0x17da68(0x1ec)]('\x20\x20'+_0x19f12b+''[_0x17da68(0x287)](0x2471+0x125a+-0x36c1)+_0x1cd83f),console[_0x17da68(0x1ec)](''+C[_0x3aca0a(0x221)]+'─'['repeat'](_0x139656)+C['reset']);}function redrawHeader(_0x47dd38={}){const _0xe9c991=_0x146b88,_0x2db5b4=_0x4092f0;if(isStreaming)return;_0x47dd38[_0xe9c991(0x201)+'n']&&console[_0x2db5b4(0x1c0)]();drawHeader();if(rl&&!isStreaming)rl['prompt'](!![]);}function drawHelp(){const _0xbd3b7c=_0x4092f0,_0x5de9ab=_0x146b88;console[_0xbd3b7c(0x1ec)]('\x0a'+C[_0xbd3b7c(0x22a)]+t(_0xbd3b7c(0x21a))+C[_0xbd3b7c(0x212)]+_0xbd3b7c(0x1ed)+C['cyan']+_0x5de9ab(0x1d3)+C[_0x5de9ab(0x212)]+(_0xbd3b7c(0x1d0)+_0x5de9ab(0x233))+t(_0x5de9ab(0x263))+'\x0a\x20\x20'+C[_0xbd3b7c(0x278)]+_0x5de9ab(0x1bc)+C[_0xbd3b7c(0x212)]+(_0xbd3b7c(0x1d0)+_0xbd3b7c(0x19a))+t('help.statu'+'s')+_0x5de9ab(0x1ed)+C[_0xbd3b7c(0x278)]+_0x5de9ab(0x226)+C['reset']+('\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0xbd3b7c(0x233))+t(_0xbd3b7c(0x23c))+_0xbd3b7c(0x1ed)+C[_0x5de9ab(0x278)]+_0xbd3b7c(0x195)+C[_0x5de9ab(0x212)]+(_0xbd3b7c(0x1d0)+_0xbd3b7c(0x237))+t(_0x5de9ab(0x248))+_0x5de9ab(0x1ed)+C[_0xbd3b7c(0x278)]+_0x5de9ab(0x29f)+C['reset']+(_0xbd3b7c(0x1d0)+_0xbd3b7c(0x19a))+t('help.docto'+'r')+_0xbd3b7c(0x1ed)+C[_0xbd3b7c(0x278)]+_0xbd3b7c(0x26d)+C['reset']+('\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20'+_0x5de9ab(0x19a))+t(_0xbd3b7c(0x1a0)+'p')+_0x5de9ab(0x1ed)+C[_0xbd3b7c(0x278)]+_0xbd3b7c(0x1f9)+C[_0xbd3b7c(0x212)]+(_0xbd3b7c(0x1d0)+'\x20\x20')+t(_0x5de9ab(0x1f7)+'rt')+_0x5de9ab(0x1ed)+C[_0xbd3b7c(0x278)]+(_0x5de9ab(0x1ca)+'i')+C['reset']+'|'+C['cyan']+_0xbd3b7c(0x268)+C['reset']+(_0xbd3b7c(0x199)+'here\x20your\x20'+'messages\x20g'+_0xbd3b7c(0x20f))+C[_0x5de9ab(0x278)]+(_0x5de9ab(0x1cc)+'n')+C[_0xbd3b7c(0x212)]+'|'+C[_0x5de9ab(0x278)]+_0x5de9ab(0x222)+C[_0xbd3b7c(0x212)]+(_0x5de9ab(0x1a1)+_0x5de9ab(0x1e8)+_0x5de9ab(0x249)+_0xbd3b7c(0x1b9)+_0x5de9ab(0x1e1))+C[_0x5de9ab(0x278)]+_0xbd3b7c(0x291)+C[_0x5de9ab(0x212)]+(_0xbd3b7c(0x1d0)+_0x5de9ab(0x237))+t(_0x5de9ab(0x23f))+_0x5de9ab(0x1ed)+C[_0x5de9ab(0x278)]+'/quit'+C['reset']+(_0xbd3b7c(0x1d0)+_0x5de9ab(0x237))+t(_0xbd3b7c(0x196))+'\x0a\x0a'+C[_0x5de9ab(0x1de)]+t(_0xbd3b7c(0x24d)+'r')+C[_0xbd3b7c(0x212)]+'\x0a');}function _0x57d3(){const _0x57de99=['lIbvC2uGl29ICW','AwXSie5pvcbIzq','iokgKIa','C3rHDhvZlNbYBW','BgLUzq','CL9TC2C','zxjYB3i','C3rHDhvZlNvWDa','AgvSCc5TB2rLBa','CgvYC2LZDgvUDa','mJCWALf4vhbh','ic90yxjNzxqGDa','Dg9tDhjPBMC','DgvSzwDYyw0','CYbUB3CGz28GAq','y29SDw1UCW','Dg9mB3DLCKnHCW','B2rLoIbptIdIGjqG','l2jHy2T1Ca','DezHAwXLza','C3rHDhvZlNvZzq','CMvZDw1PBMCGDa','DMvJDg9YCW','q3jLyxrLza','DhvPlM1VzgvSCW','mJq1odK1mfLct01yzW','DhvP','DwK6Bg9JywWGka','BgvNCMfTihnLCW','y3LHBG','vgvSzwDYyw0Gyq','y29ZDa','C2vUza','8j+KLIbbBhzPBIbcBW','BwvTB3j5','g1S0ng0','g1S5n20','DhvPlNjLC3rHCG','DhvPlMfJDgL2zq','Dg9VBhm','iokaLca','C3rHCNrZv2L0Aa','CMfSihnLC3nPBW','zw5K','CgfKrw5K','w+kgKIbuzwXD','yMfJA3vW','zMLSzxm','CMDLDdOG','AxnZDwvZ','iokxGca','zxHPDa','BNrH','BMfTzq','l2HLBha','zw5HyMXLza','zgvSDge','EwvSBg93','Bg9HzgLUzY4UlG','BMvJDgvK','y2HHDa','Aw5JBhvKzxm','ls1WB3j0','DxiGBwvZC2fNzq','zMfSBgjHy2S','yNjPz2H0r3jLzq','ssaOEw91CIbVDW','u2vZC2LVBJOG','l2rVy3rVCG','tM9Kzsa','CM9Y','C3rYAw5NAwz5','C3rHDhvZlNrVBW','DhvPlMrPC2nVBG','DhvPlNnLC3nPBW','C2LVBIdIGjqGDgHL','l2nYB24','AgvSCc5XDwL0','zwrKAw5NCW','B3j5','icbtD2L0y2GGDW','icaG','sgvHBhrOlunOzq','rMfPBgvK','C2v2zxjPDhK','l2fWAs9IywnRDq','yxjNDG','AgvSCc5IywnRDq','icaGicaGie1PCG','l2fWAs9JCM9U','8j+sOsa','CY9ZD2L0y2G','Dg9gAxHLza','A2v5','C3bSAxq','q3vYCMvUDcb0yq','g1S5nw0','yNjPz2H0qMX1zq','C3rHDhvZlNn0yq','BMv3igvWAgvTzq','B3bLBG','BgWGyMuGBwLYCG','CgX1z2LUCW','BIbPC29SyxrLza','DhvPlNn0yxr1CW','ywn0AxzL','igzPBgvZkq','mtm3mJi1ntbOtMrosxe','BNrVihrOzsbuzq','yNjPz2H0wwvSBa','zML4','ls1OB3n0','EsaOzgvMyxvSDa','Bw9KzwXZ','DgfYz2v0','l3n0yxr1CW','t2jZzxj2zxiGBq','iIaO','nJm3ndG3wu90ANnd','y2XLyxi','Dg9VBa','g1SZmw0','8j+tSsbuzwWGvxnLCG','Dw5ZAgLMDa','DhvPoMvWAgvTzq','DMvYC2LVBG','DhvPlNn3AxrJAa','ntm1nZqWtgvTwg55','vgfYz2v0oIbuzq','l3rHCMDLDcb0Dq','ChjVBxb0','l29IC2vYDMuGBW','DhLWzq','C3rKAw4','Dxb0Aw1L','icaGicaGicaGia','l2fWAs9ZDgf0Dq','zwXLz3jHBs4','l21VzgvS','yNjPz2H0twfNzq','Dgv4Da','DhvPlMj5zq','mtf3zK1IBLm','Aw5KzxHpzG','yM90','y3jVBG','g1SZBq','Cg9UC2vFzgvSDa','CMvZDgfYDa','zgLT','yxjJAa','CMvWzwf0','oIbVBIKkica','C3rHDhvZlNzLCG','y2XVC2u','z3jLzw4','Ahr0CdOVlW','D3m6lY8','C3rKB3v0','CM9YifrLBgvNCG','l2fWAs9Yzxn0yq','DhvPlNnJyw5UAq','g1S5mM0','Bg9N','cIaG','C2vHCMnO','g1S5ng0','ifrLBgvNCMfTia','igjVDcbYzxbSAq','DgvK','DhvPlMnYB25fCG','yMX1zq','DhvPlNrPDgXL','g1SZnM0','AgvSCc5Yzxn0yq','g1SZmg0','l3jLC3rHCNq','DhvPlMzHBgXIyq','Cg9UC2vFzg9Uzq','AM9ICW','z2LUCW','CMvK','g1SZm20','z3jHBsbbtKqGAa','y2XLyxjty3jLzq','lI4U','BwLYCM9YoNjLCW','DhvPlMrVy3rVCG','y29UC3rYDwn0BW','BgvNCMfTicH5BW','l2fWAs9KB2n0BW','CMvHzhK','D3jPDgu','Cg9UC2vFC3rHCG','BM93','DhvPlNrVB2XvCW','DgLUzW','kcGOlISPkYKRkq','BWOGia','ywn0AxzPDhKGDW','BLjLC2v0','CMvZzxq','Aw50zxj2ywW','g1S5m20','CMvHzhLtDgf0zq','sw52ywXPzcbkuW','CMfSoG','mJu0ntaXmvfqr3zjrW','ic9VyNnLCNzLia','AgvSCc50AxrSzq','ntzYsLfZAK8','ue9tva','CMvXDwvZDa','BwvZC2fNzq','l2fWAs9TB2rLBa','zg9Uzq','z3jHEq','B2zM','z2v0ihr1AsbVCG','g1SZn20','C3rHDhvZlM1LBq','l2nSzwfY','g1SZnw0','g1SWBq','g1S0mg0','yM9Sza','Bw9KzwW','DhvPlMnVBM5LyW','DhvPoMXVy2fS','C2v0uhjVBxb0','yNjPz2H0q3LHBG','B2jZzxj2zq','yNL0zuXLBMD0Aa','8j+tSsbuzwWGqM90oG','icaGia','WRCGja','g1S0Bq','CgfYC2u','icaGica','mNDYq050AG','mti0nZmZCNbpA21V','vgfYz2v0oIbuvq','lIbvC2uGl3rHCG','AgvSCc5JBgvHCG','DgfYDgLUzW','g1SXBq','AgvSCc5OzwXW','DhvPlMjHy2T1Ca','rxjYB3i','zxmGAw4GvgvSzq','g1S5nM0','t1bftG','DgvS','tw9KzwW','DhvPlNLVDq','AgvSCc5JCM9U','yw0Gywn0AxzPDa','ihnLC3nPB24P','yxbWBgLJyxrPBW','DhvZ','AgvSCc5MB290zq','yxbWBhK','BMDcywnRDxa','z2v0','vw5RBM93BIbLCG','AgvSCa','g1S5mw0','B2rLoIbprKyG4Ocu','Bg9JywXOB3n0','BwLYCM9YoNvZzq','DhvPlMnYzwf0Aq','zMXVB3i','ote1oty2quPht1PT','C3rHDhvZ'];_0x57d3=function(){return _0x57de99;};return _0x57d3();}function printUser(_0x25591a){const _0x497083=_0x146b88,_0x4df589=_0x146b88;clearCurrentLine(),console[_0x497083(0x1ec)]('\x0a'+C[_0x4df589(0x22a)]+C[_0x4df589(0x29c)+'n']+t(_0x497083(0x247))+':'+C[_0x497083(0x212)]+'\x20'+_0x25591a);}function printAssistantStart(){const _0x57e02c=_0x146b88,_0x31ac29=_0x4092f0;clearCurrentLine();const _0x1c8dc0=activeTarget==='telegram'?'\x20'+C['dim']+_0x57e02c(0x288)+C[_0x57e02c(0x212)]:'';process[_0x57e02c(0x1e7)][_0x57e02c(0x209)]('\x0a'+C[_0x31ac29(0x22a)]+C[_0x57e02c(0x1aa)]+'Alvin\x20Bot'+_0x1c8dc0+':'+C['reset']+'\x20');}function printAssistantDelta(_0x4fe569){const _0x436e99=_0x146b88,_0x26ec86=_0x146b88;process[_0x436e99(0x1e7)][_0x26ec86(0x209)](_0x4fe569);}function printAssistantEnd(_0x31f520){const _0x559cda=_0x4092f0,_0x34925d=_0x4092f0,_0x457e6f=_0x31f520&&_0x31f520>-0x23c3+-0xc22+-0x3d*-0xc9?'\x20'+C[_0x559cda(0x1de)]+'($'+_0x31f520[_0x34925d(0x1a5)](-0x180f+-0xb9b+0x23ae)+')'+C[_0x34925d(0x212)]:'';process[_0x559cda(0x1e7)]['write'](_0x457e6f+'\x0a');}function printTool(_0x392a4d){const _0x4e6531=_0x4092f0,_0x3dde13=_0x4092f0;clearCurrentLine(),process['stdout'][_0x4e6531(0x209)]('\x20\x20'+C['yellow']+'⚙\x20'+_0x392a4d+_0x4e6531(0x202)+C[_0x4e6531(0x212)]);}function _0x21a2(_0x17dea5,_0x2cebc6){_0x17dea5=_0x17dea5-(-0x1a05*0x1+0x692*0x1+0x1503);const _0xa60c5f=_0x57d3();let _0x523bd9=_0xa60c5f[_0x17dea5];if(_0x21a2['FlZnQx']===undefined){var _0x32fc63=function(_0x20b0a){const _0x5a14e9='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x22097d='',_0x185b7c='',_0x353d2a=_0x22097d+_0x32fc63;for(let _0xf4a072=-0x182d+-0x1654+0x94d*0x5,_0x3e1998,_0x3ad12e,_0xaa64a5=0xd84+-0x1e21+0x109d;_0x3ad12e=_0x20b0a['charAt'](_0xaa64a5++);~_0x3ad12e&&(_0x3e1998=_0xf4a072%(-0x473+0x1*0xede+0x1*-0xa67)?_0x3e1998*(0x340+-0xc3*-0xd+-0xce7)+_0x3ad12e:_0x3ad12e,_0xf4a072++%(-0x1*0xa3+0xd42+-0x7*0x1cd))?_0x22097d+=_0x353d2a['charCodeAt'](_0xaa64a5+(0x2327+-0x3*-0xb81+-0x45a0))-(-0x1682+0x1*-0xf05+0xa3*0x3b)!==0x89*-0x3a+0xa*-0x7e+-0x1*-0x23f6?String['fromCharCode'](0x1155+0x1*0x295+-0x1d*0xa7&_0x3e1998>>(-(-0x806+0x1aaf+-0x3bb*0x5)*_0xf4a072&-0x7c0*0x2+-0x1*-0x23a7+0x1*-0x1421)):_0xf4a072:-0xb14+-0x345+0xe59){_0x3ad12e=_0x5a14e9['indexOf'](_0x3ad12e);}for(let _0x13abe4=0x1*0x8cc+0x12ed+-0x1*0x1bb9,_0x3b2bcb=_0x22097d['length'];_0x13abe4<_0x3b2bcb;_0x13abe4++){_0x185b7c+='%'+('00'+_0x22097d['charCodeAt'](_0x13abe4)['toString'](-0x253a+0x111f+0x142b))['slice'](-(0x2471+0x125a+-0x36c9));}return decodeURIComponent(_0x185b7c);};_0x21a2['EcmkyF']=_0x32fc63,_0x21a2['QTkPhO']={},_0x21a2['FlZnQx']=!![];}const _0x45ec0f=_0xa60c5f[-0x23c3+-0xc22+-0x3d*-0xc9],_0x5118e2=_0x17dea5+_0x45ec0f,_0x21155b=_0x21a2['QTkPhO'][_0x5118e2];if(!_0x21155b){const _0x134641=function(_0x155224){this['METZVr']=_0x155224,this['RCNgJG']=[-0x180f+-0xb9b+0x23ab,0xec6*-0x2+0x231b+0x1*-0x58f,0xe54+-0x24cc+0x59e*0x4],this['MgSsoL']=function(){return'newState';},this['nnDXtE']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['LqyjXA']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x134641['prototype']['EMFfCE']=function(){const _0x43feeb=new RegExp(this['nnDXtE']+this['LqyjXA']),_0x37743c=_0x43feeb['test'](this['MgSsoL']['toString']())?--this['RCNgJG'][-0x29*-0xa+-0x9f7*0x1+-0x132*-0x7]:--this['RCNgJG'][-0x15a*0xe+-0x138+0x1424];return this['IZsZdp'](_0x37743c);},_0x134641['prototype']['IZsZdp']=function(_0x37d406){if(!Boolean(~_0x37d406))return _0x37d406;return this['YMnSNK'](this['METZVr']);},_0x134641['prototype']['YMnSNK']=function(_0x46f647){for(let _0xe62589=0x1e33*0x1+0x23a5+-0x41d8,_0x4faa3c=this['RCNgJG']['length'];_0xe62589<_0x4faa3c;_0xe62589++){this['RCNgJG']['push'](Math['round'](Math['random']())),_0x4faa3c=this['RCNgJG']['length'];}return _0x46f647(this['RCNgJG'][-0x1339+-0x12a2+0x25db]);},new _0x134641(_0x21a2)['EMFfCE'](),_0x523bd9=_0x21a2['EcmkyF'](_0x523bd9),_0x21a2['QTkPhO'][_0x5118e2]=_0x523bd9;}else _0x523bd9=_0x21155b;return _0x523bd9;}function printToolDone(){const _0x2eaa13=_0x4092f0,_0x560f63=_0x146b88;clearCurrentLine();if(toolCount>0xec6*-0x2+0x231b+0x1*-0x58f){const _0x31a5c7=toolCount>0xe54+-0x24cc+0x20b*0xb?t('tui.toolsU'+'sed'):t(_0x2eaa13(0x20c)+'ed');console['log']('\x20\x20'+C[_0x2eaa13(0x1de)]+C['yellow']+'⚙\x20'+toolCount+'\x20'+_0x31a5c7+C[_0x2eaa13(0x212)]);}toolCount=-0x29*-0xa+-0x9f7*0x1+-0x85d*-0x1;}function printError(_0x486760){const _0x1e24b0=_0x146b88,_0x29fa7e=_0x146b88;clearCurrentLine(),console[_0x1e24b0(0x1ec)]('\x0a'+C['red']+'✖\x20'+_0x486760+C[_0x29fa7e(0x212)]);}function printInfo(_0xd07e14){const _0x4328a9=_0x146b88,_0xa9c58b=_0x4092f0;clearCurrentLine(),console[_0x4328a9(0x1ec)](C['cyan']+'ℹ\x20'+_0xd07e14+C[_0x4328a9(0x212)]);}function printSuccess(_0x1ede50){const _0x4c3421=_0x146b88,_0x18871a=_0x146b88;clearCurrentLine(),console[_0x4c3421(0x1ec)](C[_0x18871a(0x1e4)]+'✔\x20'+_0x1ede50+C[_0x18871a(0x212)]);}function printMirrorUser(_0xeb442c){const _0x3168d3=_0x4092f0,_0xdd3645=_0x4092f0;clearCurrentLine(),console[_0x3168d3(0x1ec)]('\x0a'+C[_0x3168d3(0x1de)]+C['gray']+(_0x3168d3(0x1c3)+':\x20')+_0xeb442c+C['reset']);}function printMirrorAssistantStart(){const _0x153cfc=_0x146b88,_0x2519ba=_0x4092f0;clearCurrentLine(),process['stdout']['write']('\x0a'+C[_0x153cfc(0x1de)]+C[_0x153cfc(0x221)]+(_0x2519ba(0x232)+'\x20')+C[_0x2519ba(0x212)]);}function printMirrorAssistantDelta(_0x36df4b){const _0x5a67df=_0x146b88,_0x255c62=_0x146b88;process[_0x5a67df(0x1e7)][_0x255c62(0x209)](''+C[_0x255c62(0x1de)]+C['gray']+_0x36df4b+C[_0x255c62(0x212)]);}function printMirrorAssistantEnd(){const _0x509a4b=_0x146b88;process['stdout'][_0x509a4b(0x209)]('\x0a');}function showPrompt(){const _0xaa90e7=_0x146b88,_0x5b1dfd=_0x146b88;if(isStreaming||!rl)return;rl[_0xaa90e7(0x22e)](C[_0xaa90e7(0x29c)+'n']+'❯'+C['reset']+'\x20'),rl[_0x5b1dfd(0x1cb)](!![]);}function connectWebSocket(){const _0x596c9b=_0x146b88,_0x8ab03=_0x146b88;ws=new _0x52fb9d(wsUrl),ws['on'](_0x596c9b(0x1ad),()=>{const _0x36140a=_0x596c9b;connected=!![],printInfo(t(_0x36140a(0x22c)+'tedTo')),showPrompt();}),ws['on'](_0x596c9b(0x21e),_0x59dc0d=>{const _0x154ad9=_0x596c9b;try{const _0x13e5b0=JSON[_0x154ad9(0x236)](_0x59dc0d['toString']());handleMessage(_0x13e5b0);}catch{}}),ws['on'](_0x596c9b(0x1e3),()=>{const _0x3e892d=_0x8ab03;connected=![],isStreaming=![],printError(t(_0x3e892d(0x22c)+'tionLost')),setTimeout(connectWebSocket,-0x15a*0xe+-0x138+0x1fdc);}),ws['on'](_0x596c9b(0x261),()=>{});}function handleMessage(_0x480739){const _0x2eae81=_0x146b88,_0x2871dd=_0x4092f0;switch(_0x480739[_0x2eae81(0x1cd)]){case _0x2871dd(0x1d5):!isStreaming&&(isStreaming=!![],currentToolName&&(printToolDone(),currentToolName=''),printAssistantStart());_0x480739[_0x2871dd(0x293)]&&(printAssistantDelta(_0x480739[_0x2eae81(0x293)]),currentResponse+=_0x480739[_0x2eae81(0x293)]);break;case _0x2871dd(0x1c1):if(!isStreaming)isStreaming=!![];toolCount++,currentToolName=_0x480739['name']||_0x2eae81(0x1c1),printTool(currentToolName);break;case _0x2871dd(0x29b):printInfo(t(_0x2eae81(0x1fa)+'ck')+'\x20'+_0x480739['from']+_0x2eae81(0x25d)+_0x480739['to']);break;case _0x2871dd(0x220):isStreaming&&printAssistantEnd(_0x480739[_0x2871dd(0x27a)]);if(_0x480739[_0x2eae81(0x27a)])totalCost+=_0x480739[_0x2eae81(0x27a)];isStreaming=![],currentResponse='',currentToolName='',showPrompt();break;case'error':printError(_0x480739[_0x2871dd(0x261)]||_0x2eae81(0x251)+_0x2eae81(0x2a1)),isStreaming=![],showPrompt();break;case _0x2871dd(0x212):printInfo(t(_0x2eae81(0x193)+_0x2871dd(0x211))),showPrompt();break;case _0x2eae81(0x256)+_0x2871dd(0x260):if(!observerEnabled)break;printMirrorUser(_0x480739[_0x2eae81(0x1d5)]||'');break;case _0x2871dd(0x203)+_0x2871dd(0x20a)+'t':if(!observerEnabled)break;isMirrorStreaming=!![],printMirrorAssistantStart();break;case _0x2871dd(0x203)+_0x2eae81(0x1dc)+'a':if(!observerEnabled)break;!isMirrorStreaming&&(isMirrorStreaming=!![],printMirrorAssistantStart());printMirrorAssistantDelta(_0x480739[_0x2eae81(0x293)]||'');break;case _0x2871dd(0x203)+_0x2871dd(0x1fb):if(!observerEnabled)break;isMirrorStreaming&&(printMirrorAssistantEnd(),isMirrorStreaming=![]);break;}}async function apiGet(_0x3a27ec){return new Promise((_0x166756,_0x2bf798)=>{const _0x1349cb=_0x21a2,_0x5c0971=_0x21a2;_0x3fa16a[_0x1349cb(0x250)](''+baseUrl+_0x3a27ec,_0x5e69a7=>{const _0x1aabb5=_0x1349cb;let _0x13c5b5='';_0x5e69a7['on']('data',_0x1bad66=>_0x13c5b5+=_0x1bad66),_0x5e69a7['on'](_0x1aabb5(0x286),()=>{const _0x5c6546=_0x1aabb5,_0x18155b=_0x1aabb5;try{_0x166756(JSON[_0x5c6546(0x236)](_0x13c5b5));}catch{_0x2bf798(new Error(_0x5c6546(0x216)+'ON'));}});})['on'](_0x5c0971(0x261),_0x2bf798);});}async function apiPost(_0x494a42,_0x2fe478){return new Promise((_0xa05d8c,_0x507efb)=>{const _0x5a495d=_0x21a2,_0x2df718=_0x21a2,_0xa19ff4=JSON[_0x5a495d(0x190)](_0x2fe478),_0x5a17bf=_0x3fa16a[_0x5a495d(0x21d)](''+baseUrl+_0x494a42,{'method':_0x2df718(0x21c),'headers':{'Content-Type':_0x2df718(0x24b)+'n/json','Content-Length':Buffer[_0x5a495d(0x231)](_0xa19ff4)}},_0x987daa=>{const _0x2e40c4=_0x5a495d;let _0x4dc44c='';_0x987daa['on']('data',_0x1b1f6c=>_0x4dc44c+=_0x1b1f6c),_0x987daa['on'](_0x2e40c4(0x286),()=>{const _0x47c301=_0x2e40c4,_0x2d7df7=_0x2e40c4;try{_0xa05d8c(JSON[_0x47c301(0x236)](_0x4dc44c));}catch{_0x507efb(new Error(_0x47c301(0x216)+'ON'));}});});_0x5a17bf['on'](_0x5a495d(0x261),_0x507efb),_0x5a17bf['write'](_0xa19ff4),_0x5a17bf['end']();});}async function handleCommand(_0x16dfbb){const _0x3c6f7b=_0x146b88,_0x5b8c53=_0x4092f0,_0x5f55e0=_0x16dfbb['slice'](0x1e33*0x1+0x23a5+-0x41d7)[_0x3c6f7b(0x1a7)](/\s+/),_0x2c2432=_0x5f55e0[-0x1339+-0x12a2+0x25db][_0x3c6f7b(0x26b)+'e']();switch(_0x2c2432){case _0x5b8c53(0x252):case'h':drawHelp();break;case _0x5b8c53(0x22b):case'm':{try{const _0x40f54d=await apiGet('/api/model'+'s');console[_0x5b8c53(0x1ec)]('\x0a'+C['bold']+t(_0x5b8c53(0x273))+':'+C['reset']);if(_0x40f54d[_0x5b8c53(0x1ba)])for(const _0x4a083b of _0x40f54d['models']){const _0x53942b=_0x4a083b[_0x5b8c53(0x1a6)]===_0x40f54d[_0x5b8c53(0x1b2)]?C['brightGree'+'n']+_0x3c6f7b(0x28d)+t(_0x5b8c53(0x281))+C[_0x5b8c53(0x212)]:'',_0xc3d337=_0x4a083b[_0x3c6f7b(0x25a)]===_0x5b8c53(0x208)?C['green']+'✓'+C[_0x3c6f7b(0x212)]:C[_0x5b8c53(0x1de)]+'✗'+C[_0x3c6f7b(0x212)];console[_0x3c6f7b(0x1ec)]('\x20\x20'+_0xc3d337+'\x20'+C['bold']+_0x4a083b[_0x3c6f7b(0x1a6)]+C['reset']+'\x20'+C[_0x3c6f7b(0x1de)]+'('+(_0x4a083b[_0x3c6f7b(0x22b)]||_0x4a083b[_0x5b8c53(0x290)])+')'+C[_0x3c6f7b(0x212)]+_0x53942b);}console[_0x5b8c53(0x1ec)]('\x0a'+C[_0x3c6f7b(0x1de)]+t(_0x3c6f7b(0x1c7)+_0x5b8c53(0x246))+('\x20/model\x20<k'+'ey>')+C[_0x3c6f7b(0x212)]);if(_0x5f55e0[-0x1384+0x1*-0x244+0x1ad*0xd]){const _0x67464e=await apiPost(_0x5b8c53(0x21f)+_0x5b8c53(0x1a4),{'key':_0x5f55e0[-0x3*0x3fd+-0x26f8+-0x32f*-0x10]});_0x67464e['ok']?(currentModel=_0x67464e['active']||_0x5f55e0[0xbcf+0x91e+-0xce*0x1a],printSuccess(t(_0x3c6f7b(0x1c7)+'edTo')+':\x20'+currentModel)):printError(_0x67464e['error']||t('tui.switch'+_0x3c6f7b(0x241)));}}catch(_0xcf2790){printError(t(_0x5b8c53(0x273)+_0x3c6f7b(0x241))+':\x20'+_0xcf2790['message']);}break;}case _0x3c6f7b(0x1c6):case'v':{console['log']('\x0a'+C[_0x5b8c53(0x22a)]+C[_0x5b8c53(0x22f)]+(_0x5b8c53(0x27c)+'t')+C[_0x3c6f7b(0x212)]+'\x20'+C['dim']+'v'+BOT_VERSION+C[_0x5b8c53(0x212)]),console[_0x5b8c53(0x1ec)](C[_0x5b8c53(0x1de)]+_0x3c6f7b(0x2a0)+process[_0x3c6f7b(0x1c6)]+'\x20·\x20'+process['platform']+'/'+process[_0x3c6f7b(0x1df)]+C[_0x5b8c53(0x212)]+'\x0a');break;}case _0x3c6f7b(0x25a):case's':{try{const _0x2a119a=await apiGet('/api/statu'+'s');console['log']('\x0a'+C[_0x3c6f7b(0x22a)]+C[_0x3c6f7b(0x22f)]+(_0x5b8c53(0x27c)+'t')+C[_0x3c6f7b(0x212)]+'\x20'+C[_0x5b8c53(0x1de)]+'v'+BOT_VERSION+C['reset']),console[_0x5b8c53(0x1ec)](''+C['gray']+'─'[_0x3c6f7b(0x1e0)](0x1*-0x159b+-0x10a3*-0x1+0x29*0x20)+C[_0x5b8c53(0x212)]);_0x2a119a[_0x5b8c53(0x22b)]&&(console[_0x5b8c53(0x1ec)]('\x20\x20'+C[_0x5b8c53(0x278)]+t('status.mod'+'el')+C['reset']+'\x20\x20\x20\x20'+(_0x2a119a[_0x5b8c53(0x22b)][_0x3c6f7b(0x22b)]||_0x2a119a['model'][_0x5b8c53(0x290)]||'?')),console[_0x5b8c53(0x1ec)]('\x20\x20'+C['cyan']+t(_0x5b8c53(0x25e)+'vider')+C[_0x3c6f7b(0x212)]+'\x20'+(_0x2a119a[_0x5b8c53(0x22b)][_0x5b8c53(0x290)]||'?')),console[_0x5b8c53(0x1ec)]('\x20\x20'+C['cyan']+t(_0x5b8c53(0x1ab)+_0x3c6f7b(0x24c))+C[_0x5b8c53(0x212)]+_0x5b8c53(0x19a)+(_0x2a119a['model'][_0x3c6f7b(0x25a)]||'?')));if(_0x2a119a[_0x3c6f7b(0x1d9)]){const _0xb6ab6e=Math[_0x3c6f7b(0x258)]((_0x2a119a['bot'][_0x5b8c53(0x1cf)]||-0x4d*0x38+0x1*0x1d3+0x5*0x301)/(-0x373+0x194e+-0x7cb)),_0x52afcf=Math[_0x3c6f7b(0x258)]((_0x2a119a[_0x3c6f7b(0x1d9)][_0x5b8c53(0x1cf)]||0x3*0x162+-0x8d9+0x4b3)%(-0x740*0x5+-0x167*0xc+0x1*0x4324)/(0x1ba5+-0x353*0xa+0x5d5));console[_0x5b8c53(0x1ec)]('\x20\x20'+C['cyan']+t(_0x5b8c53(0x1e2)+'sion')+C['reset']+'\x20\x20'+(_0x2a119a[_0x3c6f7b(0x1d9)]['version']||'?')),console[_0x3c6f7b(0x1ec)]('\x20\x20'+C['cyan']+t(_0x3c6f7b(0x262)+'ime')+C[_0x3c6f7b(0x212)]+_0x3c6f7b(0x19a)+_0xb6ab6e+'h\x20'+_0x52afcf+'m');}_0x2a119a[_0x3c6f7b(0x27d)]&&console['log']('\x20\x20'+C[_0x3c6f7b(0x278)]+t(_0x3c6f7b(0x225)+_0x5b8c53(0x198))+C[_0x5b8c53(0x212)]+_0x3c6f7b(0x19a)+(_0x2a119a['memory'][_0x3c6f7b(0x271)]||0x19*-0x7a+0xb0*-0x18+-0x1*-0x1c6a)+'\x20'+t('status.emb'+_0x3c6f7b(0x197))),console[_0x3c6f7b(0x1ec)]('\x20\x20'+C[_0x5b8c53(0x278)]+t('status.plu'+_0x3c6f7b(0x1fd))+C[_0x5b8c53(0x212)]+'\x20\x20'+(_0x2a119a[_0x5b8c53(0x1af)]||0x26d3+-0x175b+-0xf78)),console[_0x3c6f7b(0x1ec)]('\x20\x20'+C[_0x3c6f7b(0x278)]+t(_0x3c6f7b(0x191)+'ls')+C[_0x5b8c53(0x212)]+'\x20\x20\x20\x20'+(_0x2a119a[_0x3c6f7b(0x282)]||0xdc8*0x1+-0x265a*0x1+-0xaa*-0x25)),console[_0x5b8c53(0x1ec)]('\x20\x20'+C[_0x5b8c53(0x278)]+t(_0x3c6f7b(0x26f)+'rs')+C['reset']+_0x3c6f7b(0x233)+(_0x2a119a['users']||0x123b+-0x1f*0x97+0xe*0x1)),console[_0x3c6f7b(0x1ec)]('');}catch(_0xfd2225){printError(t(_0x5b8c53(0x1b1)+_0x5b8c53(0x241))+':\x20'+_0xfd2225[_0x3c6f7b(0x21e)]);}break;}case _0x3c6f7b(0x1da):{try{const _0x491359=await apiGet(_0x5b8c53(0x1a2));console[_0x5b8c53(0x1ec)]('\x0a'+C[_0x5b8c53(0x22a)]+'Cron\x20Jobs'+C[_0x5b8c53(0x212)]),console['log'](''+C[_0x5b8c53(0x221)]+'─'[_0x3c6f7b(0x1e0)](-0x2bb+-0x2587*0x1+-0x5c6*-0x7)+C['reset']);if(!_0x491359[_0x3c6f7b(0x1fc)]||_0x491359['jobs']['length']===0xbac+-0x1*0x2504+0x1958)console[_0x5b8c53(0x1ec)]('\x20\x20'+C['dim']+t('tui.noCron'+'Jobs')+C['reset']);else for(const _0x5a7688 of _0x491359[_0x3c6f7b(0x1fc)]){const _0x223d9d=_0x5a7688[_0x3c6f7b(0x292)]?C[_0x5b8c53(0x1e4)]+'●'+C[_0x5b8c53(0x212)]:C[_0x3c6f7b(0x1fe)]+'●'+C[_0x5b8c53(0x212)],_0x56e34e=_0x5a7688['schedule']||_0x5a7688[_0x5b8c53(0x213)]||'?';console[_0x5b8c53(0x1ec)]('\x20\x20'+_0x223d9d+'\x20'+C[_0x3c6f7b(0x22a)]+_0x5a7688[_0x3c6f7b(0x290)]+C[_0x5b8c53(0x212)]+'\x20'+C['dim']+'('+_0x56e34e+')'+C[_0x3c6f7b(0x212)]+_0x5b8c53(0x283)+_0x5a7688[_0x3c6f7b(0x1cd)]);}console[_0x5b8c53(0x1ec)]('');}catch(_0x398f25){printError(t(_0x5b8c53(0x1f3)+_0x5b8c53(0x2a1))+':\x20'+_0x398f25['message']);}break;}case'doctor':{try{printInfo(t(_0x3c6f7b(0x1ea)+'ng'));const _0x5955ed=await apiGet(_0x5b8c53(0x207)+'r'),_0xb74de3={'error':C[_0x5b8c53(0x1fe)]+'✖','warning':C[_0x5b8c53(0x294)]+'⚠','info':C[_0x3c6f7b(0x1f4)]+'ℹ'};console[_0x5b8c53(0x1ec)]('\x0a'+C['bold']+(_0x3c6f7b(0x19b)+'ck')+C[_0x5b8c53(0x212)]),console[_0x3c6f7b(0x1ec)](''+C[_0x3c6f7b(0x221)]+'─'[_0x5b8c53(0x1e0)](-0x91a+-0xb*-0x29b+-0x1367)+C[_0x5b8c53(0x212)]);for(const _0x607f5f of _0x5955ed[_0x5b8c53(0x28c)]||[]){const _0x5d7a93=_0xb74de3[_0x607f5f[_0x3c6f7b(0x19d)]]||'?';console[_0x5b8c53(0x1ec)]('\x20\x20'+_0x5d7a93+'\x20'+C['bold']+_0x607f5f['category']+C[_0x5b8c53(0x212)]+_0x5b8c53(0x283)+_0x607f5f[_0x5b8c53(0x21e)]+C[_0x5b8c53(0x212)]);if(_0x607f5f[_0x5b8c53(0x1b7)])console['log'](_0x3c6f7b(0x233)+C['dim']+_0x3c6f7b(0x1a3)+_0x607f5f[_0x5b8c53(0x1b7)]+C[_0x3c6f7b(0x212)]);}console[_0x5b8c53(0x1ec)]('');}catch(_0x2ac66c){printError(t(_0x3c6f7b(0x204)+_0x5b8c53(0x241))+':\x20'+_0x2ac66c['message']);}break;}case _0x5b8c53(0x289):{try{printInfo(t(_0x3c6f7b(0x257)+_0x5b8c53(0x24f)));const _0xbe63ff=await apiPost(_0x5b8c53(0x19e)+'ps/create',{});_0xbe63ff['ok']?printSuccess(t(_0x3c6f7b(0x240)+_0x5b8c53(0x272))+'\x20\x22'+_0xbe63ff['id']+_0x5b8c53(0x1be)+_0xbe63ff[_0x5b8c53(0x28a)]['length']+_0x5b8c53(0x1b3)):printError(_0xbe63ff['error']||t(_0x5b8c53(0x240)+_0x5b8c53(0x19c)));}catch(_0x4490e6){printError(t(_0x3c6f7b(0x240)+_0x5b8c53(0x241))+':\x20'+_0x4490e6['message']);}break;}case _0x3c6f7b(0x1dd):{printInfo(t('tui.botRes'+_0x5b8c53(0x23d)));try{await apiPost(_0x3c6f7b(0x1e9)+'rt',{}),printSuccess(t(_0x3c6f7b(0x280)+'tTriggered'));}catch{printError(t(_0x5b8c53(0x280)+_0x3c6f7b(0x26e)));}break;}case _0x5b8c53(0x1c0):case'c':redrawHeader({'clearScreen':!![]});ws?.[_0x3c6f7b(0x215)]===_0x52fb9d[_0x3c6f7b(0x244)]&&ws[_0x3c6f7b(0x27b)](JSON[_0x3c6f7b(0x190)]({'type':_0x5b8c53(0x212),'target':activeTarget,'sessionKey':activeTarget===_0x5b8c53(0x275)?tuiSessionKey:undefined}));break;case _0x3c6f7b(0x1bb):case't':{const _0x3b8454=(_0x5f55e0[-0x24af+-0x192e+0x3dde]||'')[_0x5b8c53(0x26b)+'e']();if(_0x3b8454===_0x5b8c53(0x275))activeTarget=_0x5b8c53(0x275),printSuccess(_0x5b8c53(0x23a)+_0x5b8c53(0x29d)+_0x3c6f7b(0x1b0)+_0x3c6f7b(0x24a));else _0x3b8454===_0x3c6f7b(0x268)||_0x3b8454===_0x3c6f7b(0x245)?(activeTarget=_0x5b8c53(0x268),printSuccess(_0x5b8c53(0x1c9)+_0x3c6f7b(0x206)+_0x3c6f7b(0x29a)+_0x3c6f7b(0x269)+_0x5b8c53(0x1b5)+_0x3c6f7b(0x277)+_0x5b8c53(0x194)+_0x5b8c53(0x1f1)+_0x3c6f7b(0x242)+_0x3c6f7b(0x200)+'ere)')):printInfo(_0x3c6f7b(0x1a8)+_0x3c6f7b(0x28b)+activeTarget+(_0x3c6f7b(0x23b)+_0x5b8c53(0x223)+_0x3c6f7b(0x266)+_0x3c6f7b(0x1d2)));break;}case _0x5b8c53(0x230):case'o':{const _0x55bb6d=(_0x5f55e0[0x6a3+-0x960+0x4e*0x9]||'')[_0x3c6f7b(0x26b)+'e']();if(_0x55bb6d==='on'||_0x55bb6d==='1'||_0x55bb6d==='true')observerEnabled=!![],printSuccess(_0x5b8c53(0x1bd)+_0x3c6f7b(0x26c)+_0x3c6f7b(0x279)+'ctivity\x20wi'+_0x3c6f7b(0x1ae)+'ored\x20here\x20'+'(dim)');else _0x55bb6d===_0x5b8c53(0x222)||_0x55bb6d==='0'||_0x55bb6d==='false'?(observerEnabled=![],printSuccess('Observer\x20m'+_0x5b8c53(0x254)+_0x5b8c53(0x1f0)+_0x5b8c53(0x210)+_0x5b8c53(0x25c)+'\x20shown\x20her'+'e')):printInfo('Observer:\x20'+(observerEnabled?'on':'off')+(_0x3c6f7b(0x25b)+'erve\x20on\x20or'+_0x3c6f7b(0x219)+'off.'));break;}case'quit':case'q':case'exit':console[_0x3c6f7b(0x1ec)]('\x0a'+C['dim']+t(_0x5b8c53(0x1d6))+C['reset']+'\x0a'),process['exit'](0x1*-0x1d7e+0x45*-0x79+0x3e1b);break;default:sendChat(_0x16dfbb);return;}showPrompt();}function sendChat(_0x2d2b5e){const _0x2817f9=_0x4092f0,_0x1d60d6=_0x146b88;if(!ws||ws['readyState']!==_0x52fb9d['OPEN']){printError(t('tui.notCon'+'nected')),showPrompt();return;}printUser(_0x2d2b5e),ws[_0x2817f9(0x27b)](JSON[_0x2817f9(0x190)]({'type':_0x1d60d6(0x297),'text':_0x2d2b5e,'target':activeTarget,'sessionKey':activeTarget===_0x1d60d6(0x275)?tuiSessionKey:undefined}));if(inputHistory[0x212c+-0xff9+-0x77*0x25]!==_0x2d2b5e){inputHistory[_0x2817f9(0x1c4)](_0x2d2b5e);if(inputHistory['length']>-0x2001+0xf99*-0x1+0x2ffe)inputHistory['pop']();}historyIndex=-(0x134a+-0x3bb*-0x8+-0x3121);}async function fetchInitialModel(){const _0x2a788c=_0x146b88,_0x2b9f89=_0x146b88;try{const _0x5dc750=await apiGet(_0x2a788c(0x1d1)+'s');if(_0x5dc750[_0x2a788c(0x22b)]?.[_0x2b9f89(0x22b)])currentModel=_0x5dc750[_0x2b9f89(0x22b)]['model'];else _0x5dc750[_0x2b9f89(0x22b)]?.[_0x2a788c(0x290)]&&(currentModel=_0x5dc750[_0x2b9f89(0x22b)][_0x2b9f89(0x290)]);}catch{}}export async function startTUI(){const _0x33aec2=_0x4092f0,_0x5c72cf=_0x4092f0,_0x239ff7=process['argv']['includes']('--resume');tuiSessionKey=_0x239ff7?_0x33aec2(0x22d):_0x5c72cf(0x1c5)+_0x5c72cf(0x217)+Date[_0x5c72cf(0x20b)](),console[_0x5c72cf(0x1c0)](),drawHeader(),console[_0x33aec2(0x1ec)](''+C['dim']+t(_0x33aec2(0x22c)+_0x33aec2(0x20d))+'\x20'+baseUrl+'...'+C['reset']),console[_0x33aec2(0x1ec)](C[_0x33aec2(0x1de)]+_0x33aec2(0x29e)+(_0x239ff7?_0x5c72cf(0x270)+_0x5c72cf(0x276)+_0x5c72cf(0x264)+')':_0x33aec2(0x1ac)+_0x33aec2(0x285)+'n')+C[_0x5c72cf(0x212)]+'\x0a'),drawHelp(),rl=createInterface({'input':process[_0x5c72cf(0x1ce)],'output':process[_0x33aec2(0x1e7)],'terminal':!![],'historySize':0x64}),rl['on'](_0x5c72cf(0x25f),_0x595531=>{const _0x41692c=_0x33aec2,_0x13ae51=_0x595531['trim']();if(!_0x13ae51){showPrompt();return;}_0x13ae51[_0x41692c(0x284)]('/')?handleCommand(_0x13ae51):sendChat(_0x13ae51);}),rl['on'](_0x33aec2(0x1e3),()=>{const _0x4a9db=_0x33aec2,_0x56e3f0=_0x5c72cf;console['log']('\x0a'+C[_0x4a9db(0x1de)]+t(_0x4a9db(0x1d6))+C[_0x4a9db(0x212)]+'\x0a'),process[_0x56e3f0(0x28e)](-0x215b+0x1*0x9d1+0x83*0x2e);}),process['on']('SIGINT',()=>{const _0x55ccd3=_0x33aec2,_0x3309a9=_0x5c72cf;console[_0x55ccd3(0x1ec)]('\x0a'+C['dim']+t('tui.bye')+C[_0x55ccd3(0x212)]+'\x0a'),process['exit'](0x13c8+-0x31*-0x8a+-0x2e32);}),process[_0x33aec2(0x1e7)]['on']('resize',()=>{if(!isStreaming)showPrompt();}),await fetchInitialModel(),connectWebSocket();}const isDirectRun=process[_0x146b88(0x19f)][0x17*-0xd9+-0x1*0xc5b+0x1fdb]?.[_0x4092f0(0x298)](_0x4092f0(0x275));isDirectRun&&startTUI()['catch'](console[_0x4092f0(0x261)]);