alvin-bot 5.7.0 → 5.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +25 -31
- package/dist/claude.js +1 -102
- package/dist/config.js +1 -96
- package/dist/engine.js +1 -90
- package/dist/find-claude-binary.js +1 -98
- package/dist/handlers/async-agent-chunk-handler.js +1 -50
- package/dist/handlers/background-bypass.js +1 -75
- package/dist/handlers/commands.js +1 -2336
- package/dist/handlers/cron-progress.js +1 -52
- package/dist/handlers/document.js +1 -194
- package/dist/handlers/message.js +1 -959
- package/dist/handlers/photo.js +1 -154
- package/dist/handlers/platform-message.js +1 -360
- package/dist/handlers/stuck-timer.js +1 -54
- package/dist/handlers/video.js +1 -237
- package/dist/handlers/voice.js +1 -148
- package/dist/i18n.js +1 -805
- package/dist/index.js +1 -697
- package/dist/init-data-dir.js +1 -98
- package/dist/middleware/auth.js +1 -233
- package/dist/migrate.js +1 -162
- package/dist/paths.js +1 -146
- package/dist/platforms/discord.js +1 -175
- package/dist/platforms/index.js +1 -130
- package/dist/platforms/signal.js +1 -205
- package/dist/platforms/slack-slash-parser.js +1 -32
- package/dist/platforms/slack.js +1 -501
- package/dist/platforms/telegram.js +1 -111
- package/dist/platforms/types.js +1 -8
- package/dist/platforms/whatsapp-auth-helpers.js +1 -53
- package/dist/platforms/whatsapp.js +1 -707
- package/dist/providers/claude-sdk-provider.js +1 -565
- package/dist/providers/codex-cli-provider.js +1 -134
- package/dist/providers/index.js +1 -7
- package/dist/providers/ollama-provider.js +1 -32
- package/dist/providers/openai-compatible.js +1 -406
- package/dist/providers/registry.js +1 -352
- package/dist/providers/runtime-header.js +1 -45
- package/dist/providers/tool-executor.js +1 -475
- package/dist/providers/types.js +1 -227
- package/dist/services/access.js +1 -144
- package/dist/services/allowed-users-gate.js +1 -56
- package/dist/services/alvin-dispatch.js +1 -174
- package/dist/services/alvin-mcp-tools.js +1 -104
- package/dist/services/asset-index.js +1 -224
- package/dist/services/async-agent-parser.js +1 -418
- package/dist/services/async-agent-watcher.js +1 -583
- package/dist/services/auto-diagnostic.js +1 -228
- package/dist/services/broadcast.js +1 -52
- package/dist/services/browser-manager.js +1 -562
- package/dist/services/browser-webfetch.js +1 -127
- package/dist/services/browser.js +1 -121
- package/dist/services/cdp-bootstrap.js +1 -357
- package/dist/services/compaction.js +1 -144
- package/dist/services/critical-notify.js +1 -203
- package/dist/services/cron-resolver.js +1 -58
- package/dist/services/cron-scheduling.js +1 -310
- package/dist/services/cron.js +1 -861
- package/dist/services/custom-tools.js +1 -317
- package/dist/services/delivery-queue.js +1 -173
- package/dist/services/delivery-registry.js +1 -21
- package/dist/services/disk-cleanup.js +1 -203
- package/dist/services/elevenlabs.js +1 -58
- package/dist/services/embeddings/auto-detect.js +1 -74
- package/dist/services/embeddings/fts5.js +1 -108
- package/dist/services/embeddings/gemini.js +1 -65
- package/dist/services/embeddings/index.js +1 -496
- package/dist/services/embeddings/ollama.js +1 -78
- package/dist/services/embeddings/openai.js +1 -49
- package/dist/services/embeddings/provider.js +1 -22
- package/dist/services/embeddings/vector-base.js +1 -113
- package/dist/services/embeddings-migration.js +1 -193
- package/dist/services/embeddings.js +1 -9
- package/dist/services/env-file.js +1 -50
- package/dist/services/exec-guard.js +1 -71
- package/dist/services/fallback-order.js +1 -154
- package/dist/services/file-permissions.js +1 -93
- package/dist/services/heartbeat-file.js +1 -65
- package/dist/services/heartbeat.js +1 -313
- package/dist/services/hooks.js +1 -44
- package/dist/services/imagegen.js +1 -72
- package/dist/services/language-detect.js +1 -154
- package/dist/services/markdown.js +1 -63
- package/dist/services/mcp.js +1 -263
- package/dist/services/memory-extractor.js +1 -178
- package/dist/services/memory-inject-mode.js +1 -43
- package/dist/services/memory-layers.js +1 -156
- package/dist/services/memory.js +1 -146
- package/dist/services/ollama-manager.js +1 -339
- package/dist/services/permissions-wizard.js +1 -291
- package/dist/services/personality.js +1 -376
- package/dist/services/plugins.js +1 -171
- package/dist/services/preflight.js +1 -292
- package/dist/services/process-manager.js +1 -291
- package/dist/services/release-highlights.js +1 -79
- package/dist/services/reminders.js +1 -97
- package/dist/services/restart.js +1 -48
- package/dist/services/security-audit.js +1 -74
- package/dist/services/self-diagnosis.js +1 -272
- package/dist/services/self-search.js +1 -129
- package/dist/services/session-persistence.js +1 -237
- package/dist/services/session.js +1 -282
- package/dist/services/skills.js +1 -290
- package/dist/services/ssrf-guard.js +1 -162
- package/dist/services/standing-orders.js +1 -29
- package/dist/services/steer-channel.js +1 -46
- package/dist/services/stop-controller.js +1 -52
- package/dist/services/subagent-dedup.js +1 -86
- package/dist/services/subagent-delivery.js +1 -452
- package/dist/services/subagent-stats.js +1 -123
- package/dist/services/subagents.js +1 -814
- package/dist/services/sudo.js +1 -329
- package/dist/services/telegram.js +1 -158
- package/dist/services/timing-safe-bearer.js +1 -51
- package/dist/services/tool-discovery.js +1 -214
- package/dist/services/trends.js +1 -580
- package/dist/services/updater.js +1 -291
- package/dist/services/usage-tracker.js +1 -144
- package/dist/services/users.js +1 -271
- package/dist/services/voice.js +1 -104
- package/dist/services/watchdog-brake.js +1 -154
- package/dist/services/watchdog.js +1 -311
- package/dist/services/workspaces.js +1 -276
- package/dist/tui/index.js +1 -667
- package/dist/util/console-formatter.js +1 -109
- package/dist/util/debounce.js +1 -24
- package/dist/util/telegram-error-filter.js +1 -62
- package/dist/version.js +1 -24
- package/dist/web/bind-strategy.js +1 -42
- package/dist/web/canvas.js +1 -30
- package/dist/web/doctor-api.js +1 -604
- package/dist/web/openai-compat.js +1 -252
- package/dist/web/server.js +1 -1902
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
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)]);
|