ai-cli-online 2.1.1 → 2.1.3
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/README.md +3 -1
- package/package.json +1 -1
- package/server/.env.example +4 -0
- package/server/dist/files.d.ts +5 -1
- package/server/dist/files.js +4 -2
- package/server/dist/index.js +50 -19
- package/server/dist/pty.d.ts +4 -0
- package/server/dist/pty.js +12 -0
- package/server/dist/websocket.d.ts +2 -0
- package/server/dist/websocket.js +26 -5
- package/server/package.json +4 -2
- package/shared/package.json +1 -1
- package/web/dist/assets/index-BjydL1Uc.js +38 -0
- package/web/dist/assets/index-HMXsQ8Et.css +32 -0
- package/web/dist/assets/markdown-BERZKN_L.js +60 -0
- package/web/dist/assets/react-vendor-BCIvbQoU.js +32 -0
- package/web/dist/assets/terminal-CFozNkMS.js +108 -0
- package/web/dist/index.html +5 -2
- package/web/package.json +1 -1
- package/web/dist/assets/index-79TY7o1G.css +0 -32
- package/web/dist/assets/index-mcWZLwbP.js +0 -235
package/README.md
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
|
-
A lightweight web terminal for accessing Claude Code
|
|
7
|
+
A lightweight web terminal for accessing Claude Code / Codex or any CLI from your browser. Ideal for **unstable networks** where SSH drops frequently, and as a **local stateful terminal** that preserves sessions, layouts, and drafts across refreshes.
|
|
8
8
|
|
|
9
9
|
**npm:** https://www.npmjs.com/package/ai-cli-online | **GitHub:** https://github.com/huacheng/ai-cli-online
|
|
10
10
|
|
|
11
11
|
[**中文文档**](README.zh-CN.md)
|
|
12
12
|
|
|
13
|
+

|
|
14
|
+
|
|
13
15
|
## Features
|
|
14
16
|
|
|
15
17
|
- **Full Web Terminal** — xterm.js with WebGL rendering, binary protocol for ultra-low latency
|
package/package.json
CHANGED
package/server/.env.example
CHANGED
|
@@ -16,3 +16,7 @@ AUTH_TOKEN=
|
|
|
16
16
|
|
|
17
17
|
# Default working directory for terminal sessions
|
|
18
18
|
DEFAULT_WORKING_DIR=/home/ubuntu
|
|
19
|
+
|
|
20
|
+
# Rate limiting (requests per minute)
|
|
21
|
+
# RATE_LIMIT_READ=180 # Read-only/polling endpoints (files, cwd, draft, pane-command)
|
|
22
|
+
# RATE_LIMIT_WRITE=60 # Write endpoints (upload, settings, delete)
|
package/server/dist/files.d.ts
CHANGED
|
@@ -2,8 +2,12 @@ import type { FileEntry } from './types.js';
|
|
|
2
2
|
export type { FileEntry };
|
|
3
3
|
export declare const MAX_UPLOAD_SIZE: number;
|
|
4
4
|
export declare const MAX_DOWNLOAD_SIZE: number;
|
|
5
|
+
export interface ListFilesResult {
|
|
6
|
+
files: FileEntry[];
|
|
7
|
+
truncated: boolean;
|
|
8
|
+
}
|
|
5
9
|
/** List files in a directory, directories first, then alphabetical */
|
|
6
|
-
export declare function listFiles(dirPath: string): Promise<
|
|
10
|
+
export declare function listFiles(dirPath: string): Promise<ListFilesResult>;
|
|
7
11
|
/**
|
|
8
12
|
* Validate and resolve a requested path against a base CWD.
|
|
9
13
|
* Returns the resolved absolute path, or null if invalid.
|
package/server/dist/files.js
CHANGED
|
@@ -2,6 +2,7 @@ import { readdir, stat, realpath } from 'fs/promises';
|
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
export const MAX_UPLOAD_SIZE = 100 * 1024 * 1024; // 100 MB
|
|
4
4
|
export const MAX_DOWNLOAD_SIZE = 100 * 1024 * 1024; // 100 MB
|
|
5
|
+
const MAX_DIR_ENTRIES = 1000;
|
|
5
6
|
/** List files in a directory, directories first, then alphabetical */
|
|
6
7
|
export async function listFiles(dirPath) {
|
|
7
8
|
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
@@ -28,8 +29,9 @@ export async function listFiles(dirPath) {
|
|
|
28
29
|
return a.type === 'directory' ? -1 : 1;
|
|
29
30
|
return a.name.localeCompare(b.name);
|
|
30
31
|
});
|
|
31
|
-
// Cap
|
|
32
|
-
|
|
32
|
+
// Cap entries to prevent excessive memory/bandwidth usage on huge directories
|
|
33
|
+
const truncated = results.length > MAX_DIR_ENTRIES;
|
|
34
|
+
return { files: truncated ? results.slice(0, MAX_DIR_ENTRIES) : results, truncated };
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* Validate and resolve a requested path against a base CWD.
|
package/server/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
+
import compression from 'compression';
|
|
2
3
|
import { createServer as createHttpServer } from 'http';
|
|
3
4
|
import { createServer as createHttpsServer } from 'https';
|
|
4
5
|
import { WebSocketServer } from 'ws';
|
|
@@ -11,7 +12,7 @@ import { copyFile, unlink, stat, mkdir, readFile } from 'fs/promises';
|
|
|
11
12
|
import { join, dirname, basename, extname } from 'path';
|
|
12
13
|
import { fileURLToPath } from 'url';
|
|
13
14
|
import { createHash } from 'crypto';
|
|
14
|
-
import { setupWebSocket, getActiveSessionNames } from './websocket.js';
|
|
15
|
+
import { setupWebSocket, getActiveSessionNames, clearWsIntervals } from './websocket.js';
|
|
15
16
|
import { isTmuxAvailable, listSessions, buildSessionName, killSession, isValidSessionId, cleanupStaleSessions, getCwd, getPaneCommand } from './tmux.js';
|
|
16
17
|
import { listFiles, validatePath, MAX_DOWNLOAD_SIZE, MAX_UPLOAD_SIZE } from './files.js';
|
|
17
18
|
import { getDraft, saveDraft as saveDraftDb, deleteDraft, cleanupOldDrafts, getSetting, saveSetting, closeDb } from './db.js';
|
|
@@ -27,8 +28,14 @@ const CORS_ORIGIN = process.env.CORS_ORIGIN || ''; // empty = no CORS headers (s
|
|
|
27
28
|
const TRUST_PROXY = process.env.TRUST_PROXY || ''; // set to '1' when behind a reverse proxy
|
|
28
29
|
const MAX_CONNECTIONS = parseInt(process.env.MAX_CONNECTIONS || '10', 10);
|
|
29
30
|
const SESSION_TTL_HOURS = parseInt(process.env.SESSION_TTL_HOURS || '24', 10);
|
|
31
|
+
const RATE_LIMIT_READ = parseInt(process.env.RATE_LIMIT_READ || '180', 10);
|
|
32
|
+
const RATE_LIMIT_WRITE = parseInt(process.env.RATE_LIMIT_WRITE || '60', 10);
|
|
30
33
|
const CERT_PATH = join(__dirname, '../certs/server.crt');
|
|
31
34
|
const KEY_PATH = join(__dirname, '../certs/server.key');
|
|
35
|
+
// Catch unhandled promise rejections to prevent silent crashes
|
|
36
|
+
process.on('unhandledRejection', (reason) => {
|
|
37
|
+
console.error('[FATAL] Unhandled promise rejection:', reason);
|
|
38
|
+
});
|
|
32
39
|
async function main() {
|
|
33
40
|
// Check tmux availability
|
|
34
41
|
if (!isTmuxAvailable()) {
|
|
@@ -42,6 +49,8 @@ async function main() {
|
|
|
42
49
|
if (TRUST_PROXY) {
|
|
43
50
|
app.set('trust proxy', parseInt(TRUST_PROXY, 10) || TRUST_PROXY);
|
|
44
51
|
}
|
|
52
|
+
// Compress HTTP responses (WebSocket has its own perMessageDeflate)
|
|
53
|
+
app.use(compression());
|
|
45
54
|
// Security headers
|
|
46
55
|
app.use(helmet({
|
|
47
56
|
contentSecurityPolicy: {
|
|
@@ -49,15 +58,16 @@ async function main() {
|
|
|
49
58
|
defaultSrc: ["'self'"],
|
|
50
59
|
scriptSrc: ["'self'"],
|
|
51
60
|
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
61
|
+
imgSrc: ["'self'", "https:", "data:"],
|
|
52
62
|
connectSrc: ["'self'", "wss:", "ws:"],
|
|
53
63
|
},
|
|
54
64
|
},
|
|
55
65
|
frameguard: { action: 'deny' },
|
|
56
66
|
}));
|
|
57
|
-
// Rate limiting
|
|
67
|
+
// Rate limiting — higher limit for read-only GET, lower for mutations
|
|
58
68
|
app.use('/api/', rateLimit({
|
|
59
69
|
windowMs: 60 * 1000,
|
|
60
|
-
max:
|
|
70
|
+
max: (req) => req.method === 'GET' ? RATE_LIMIT_READ : RATE_LIMIT_WRITE,
|
|
61
71
|
standardHeaders: true,
|
|
62
72
|
legacyHeaders: false,
|
|
63
73
|
message: { error: 'Too many requests' },
|
|
@@ -155,7 +165,8 @@ async function main() {
|
|
|
155
165
|
const cwd = await getCwd(sessionName);
|
|
156
166
|
res.json({ cwd });
|
|
157
167
|
}
|
|
158
|
-
catch {
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.error(`[api:cwd] ${sessionName}:`, err);
|
|
159
170
|
res.status(404).json({ error: 'Session not found or not running' });
|
|
160
171
|
}
|
|
161
172
|
});
|
|
@@ -172,10 +183,11 @@ async function main() {
|
|
|
172
183
|
res.status(400).json({ error: 'Invalid path' });
|
|
173
184
|
return;
|
|
174
185
|
}
|
|
175
|
-
const files = await listFiles(targetDir);
|
|
176
|
-
res.json({ cwd: targetDir, files });
|
|
186
|
+
const { files, truncated } = await listFiles(targetDir);
|
|
187
|
+
res.json({ cwd: targetDir, files, truncated });
|
|
177
188
|
}
|
|
178
|
-
catch {
|
|
189
|
+
catch (err) {
|
|
190
|
+
console.error(`[api:files] ${sessionName}:`, err);
|
|
179
191
|
res.status(404).json({ error: 'Session not found or directory not accessible' });
|
|
180
192
|
}
|
|
181
193
|
});
|
|
@@ -249,7 +261,8 @@ async function main() {
|
|
|
249
261
|
res.setHeader('Content-Length', fileStat.size);
|
|
250
262
|
createReadStream(resolved).pipe(res);
|
|
251
263
|
}
|
|
252
|
-
catch {
|
|
264
|
+
catch (err) {
|
|
265
|
+
console.error(`[api:download] ${sessionName}:`, err);
|
|
253
266
|
res.status(404).json({ error: 'File not found' });
|
|
254
267
|
}
|
|
255
268
|
});
|
|
@@ -358,7 +371,8 @@ async function main() {
|
|
|
358
371
|
encoding: isPdf ? 'base64' : 'utf-8',
|
|
359
372
|
});
|
|
360
373
|
}
|
|
361
|
-
catch {
|
|
374
|
+
catch (err) {
|
|
375
|
+
console.error(`[api:file-content] ${sessionName}:`, err);
|
|
362
376
|
res.status(404).json({ error: 'File not found' });
|
|
363
377
|
}
|
|
364
378
|
});
|
|
@@ -422,10 +436,20 @@ async function main() {
|
|
|
422
436
|
console.log('='.repeat(50));
|
|
423
437
|
console.log('');
|
|
424
438
|
});
|
|
439
|
+
// Run startup cleanup immediately (clear stale drafts from previous runs)
|
|
440
|
+
try {
|
|
441
|
+
const purged = cleanupOldDrafts(7);
|
|
442
|
+
if (purged > 0)
|
|
443
|
+
console.log(`[startup] Cleaned up ${purged} stale drafts`);
|
|
444
|
+
}
|
|
445
|
+
catch (e) {
|
|
446
|
+
console.error('[startup:drafts]', e);
|
|
447
|
+
}
|
|
425
448
|
// Periodic cleanup of stale tmux sessions
|
|
449
|
+
let cleanupTimer = null;
|
|
426
450
|
if (SESSION_TTL_HOURS > 0) {
|
|
427
451
|
const CLEANUP_INTERVAL = 60 * 60 * 1000; // every hour
|
|
428
|
-
setInterval(() => {
|
|
452
|
+
cleanupTimer = setInterval(() => {
|
|
429
453
|
cleanupStaleSessions(SESSION_TTL_HOURS).catch((e) => console.error('[cleanup]', e));
|
|
430
454
|
try {
|
|
431
455
|
cleanupOldDrafts(7);
|
|
@@ -439,18 +463,25 @@ async function main() {
|
|
|
439
463
|
// Graceful shutdown
|
|
440
464
|
const shutdown = () => {
|
|
441
465
|
console.log('\n[shutdown] Closing server...');
|
|
442
|
-
//
|
|
466
|
+
// Clear all intervals to allow event loop to drain
|
|
467
|
+
clearWsIntervals();
|
|
468
|
+
if (cleanupTimer)
|
|
469
|
+
clearInterval(cleanupTimer);
|
|
470
|
+
// Close all WebSocket connections (triggers ws 'close' handlers which kill PTYs)
|
|
443
471
|
wss.clients.forEach((client) => {
|
|
444
472
|
client.close(1001, 'Server shutting down');
|
|
445
473
|
});
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
474
|
+
// Allow 500ms for WebSocket close handlers to fire and clean up PTYs
|
|
475
|
+
setTimeout(() => {
|
|
476
|
+
server.close(() => {
|
|
477
|
+
try {
|
|
478
|
+
closeDb();
|
|
479
|
+
}
|
|
480
|
+
catch { /* ignore */ }
|
|
481
|
+
console.log('[shutdown] Server closed');
|
|
482
|
+
process.exit(0);
|
|
483
|
+
});
|
|
484
|
+
}, 500);
|
|
454
485
|
// Force exit after 5s if graceful close hangs
|
|
455
486
|
setTimeout(() => {
|
|
456
487
|
console.log('[shutdown] Forced exit');
|
package/server/dist/pty.d.ts
CHANGED
|
@@ -10,6 +10,10 @@ export declare class PtySession {
|
|
|
10
10
|
onExit(cb: ExitCallback): void;
|
|
11
11
|
write(data: string): void;
|
|
12
12
|
resize(cols: number, rows: number): void;
|
|
13
|
+
/** Pause PTY output (backpressure from WebSocket) */
|
|
14
|
+
pause(): void;
|
|
15
|
+
/** Resume PTY output after backpressure relief */
|
|
16
|
+
resume(): void;
|
|
13
17
|
kill(): void;
|
|
14
18
|
isAlive(): boolean;
|
|
15
19
|
}
|
package/server/dist/pty.js
CHANGED
|
@@ -55,6 +55,18 @@ export class PtySession {
|
|
|
55
55
|
this.proc.resize(cols, rows);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
/** Pause PTY output (backpressure from WebSocket) */
|
|
59
|
+
pause() {
|
|
60
|
+
if (this.alive) {
|
|
61
|
+
this.proc.pause();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Resume PTY output after backpressure relief */
|
|
65
|
+
resume() {
|
|
66
|
+
if (this.alive) {
|
|
67
|
+
this.proc.resume();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
58
70
|
kill() {
|
|
59
71
|
if (this.alive) {
|
|
60
72
|
this.alive = false;
|
|
@@ -2,3 +2,5 @@ import { WebSocketServer } from 'ws';
|
|
|
2
2
|
/** Get the set of session names with active open WebSocket connections */
|
|
3
3
|
export declare function getActiveSessionNames(): Set<string>;
|
|
4
4
|
export declare function setupWebSocket(wss: WebSocketServer, authToken: string, defaultCwd: string, tokenCompare: (a: string, b: string) => boolean, maxConnections?: number): void;
|
|
5
|
+
/** Clear WebSocket module intervals for graceful shutdown */
|
|
6
|
+
export declare function clearWsIntervals(): void;
|
package/server/dist/websocket.js
CHANGED
|
@@ -17,7 +17,7 @@ const authFailures = new Map();
|
|
|
17
17
|
const AUTH_FAIL_MAX = 5;
|
|
18
18
|
const AUTH_FAIL_WINDOW_MS = 60_000;
|
|
19
19
|
// Periodically prune expired entries to prevent unbounded memory growth
|
|
20
|
-
setInterval(() => {
|
|
20
|
+
const authPruneInterval = setInterval(() => {
|
|
21
21
|
const now = Date.now();
|
|
22
22
|
for (const [ip, entry] of authFailures) {
|
|
23
23
|
if (now > entry.resetAt)
|
|
@@ -78,9 +78,10 @@ function sendBinary(ws, typePrefix, data) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
/** Server-side keepalive: ping all clients every 30s, terminate if no pong */
|
|
81
|
+
let keepAliveInterval = null;
|
|
81
82
|
function startKeepAlive(wss) {
|
|
82
83
|
const KEEPALIVE_INTERVAL = 30_000;
|
|
83
|
-
setInterval(() => {
|
|
84
|
+
keepAliveInterval = setInterval(() => {
|
|
84
85
|
for (const ws of wss.clients) {
|
|
85
86
|
const alive = ws;
|
|
86
87
|
if (alive._isAlive === false) {
|
|
@@ -191,8 +192,22 @@ export function setupWebSocket(wss, authToken, defaultCwd, tokenCompare, maxConn
|
|
|
191
192
|
ws.close(4003, 'PTY attach failed');
|
|
192
193
|
return;
|
|
193
194
|
}
|
|
195
|
+
// Backpressure: pause PTY when WebSocket send buffer is full
|
|
196
|
+
const HIGH_WATER_MARK = 1024 * 1024; // 1MB
|
|
197
|
+
let ptyPaused = false;
|
|
194
198
|
ptySession.onData((data) => {
|
|
195
199
|
sendBinary(ws, BIN_TYPE_OUTPUT, data);
|
|
200
|
+
if (!ptyPaused && ws.bufferedAmount > HIGH_WATER_MARK) {
|
|
201
|
+
ptyPaused = true;
|
|
202
|
+
ptySession.pause();
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
// Resume PTY when WebSocket buffer drains
|
|
206
|
+
ws.on('drain', () => {
|
|
207
|
+
if (ptyPaused && ws.bufferedAmount < HIGH_WATER_MARK / 2) {
|
|
208
|
+
ptyPaused = false;
|
|
209
|
+
ptySession?.resume();
|
|
210
|
+
}
|
|
196
211
|
});
|
|
197
212
|
ptySession.onExit((code, signal) => {
|
|
198
213
|
console.log(`[WS] PTY exited for session ${sessionName}, code: ${code}, signal: ${signal}`);
|
|
@@ -261,7 +276,7 @@ export function setupWebSocket(wss, authToken, defaultCwd, tokenCompare, maxConn
|
|
|
261
276
|
const r = Math.max(1, Math.min(500, Math.floor(msg.rows || 24)));
|
|
262
277
|
// PTY resize (sync) and tmux resize (async subprocess) are independent — run in parallel
|
|
263
278
|
ptySession?.resize(c, r);
|
|
264
|
-
resizeSession(sessionName, c, r);
|
|
279
|
+
resizeSession(sessionName, c, r).catch(() => { });
|
|
265
280
|
break;
|
|
266
281
|
}
|
|
267
282
|
case 'ping':
|
|
@@ -281,8 +296,8 @@ export function setupWebSocket(wss, authToken, defaultCwd, tokenCompare, maxConn
|
|
|
281
296
|
}
|
|
282
297
|
}
|
|
283
298
|
}
|
|
284
|
-
catch {
|
|
285
|
-
|
|
299
|
+
catch (err) {
|
|
300
|
+
console.error(`[WS] Message handling error${sessionName ? ` for ${sessionName}` : ''}:`, err);
|
|
286
301
|
}
|
|
287
302
|
});
|
|
288
303
|
ws.on('close', () => {
|
|
@@ -302,3 +317,9 @@ export function setupWebSocket(wss, authToken, defaultCwd, tokenCompare, maxConn
|
|
|
302
317
|
});
|
|
303
318
|
});
|
|
304
319
|
}
|
|
320
|
+
/** Clear WebSocket module intervals for graceful shutdown */
|
|
321
|
+
export function clearWsIntervals() {
|
|
322
|
+
clearInterval(authPruneInterval);
|
|
323
|
+
if (keepAliveInterval)
|
|
324
|
+
clearInterval(keepAliveInterval);
|
|
325
|
+
}
|
package/server/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-cli-online-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "CLI-Online Backend Server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
"start": "node dist/index.js"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"better-sqlite3": "^12.6.2",
|
|
14
13
|
"ai-cli-online-shared": "*",
|
|
14
|
+
"better-sqlite3": "^12.6.2",
|
|
15
|
+
"compression": "^1.8.1",
|
|
15
16
|
"dotenv": "^16.3.1",
|
|
16
17
|
"express": "^4.18.2",
|
|
17
18
|
"express-rate-limit": "^8.2.1",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@types/better-sqlite3": "^7.6.13",
|
|
26
|
+
"@types/compression": "^1.8.1",
|
|
25
27
|
"@types/express": "^4.17.21",
|
|
26
28
|
"@types/multer": "^2.0.0",
|
|
27
29
|
"@types/node": "^20.10.0",
|
package/shared/package.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var nt=Object.defineProperty;var rt=(t,e,o)=>e in t?nt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o;var we=(t,e,o)=>rt(t,typeof e!="symbol"?e+"":e,o);import{r as d,a as ot,g as st,R as xe}from"./react-vendor-BCIvbQoU.js";import{D as _e,o as Ae,x as it}from"./terminal-CFozNkMS.js";import{d as at,p as lt}from"./markdown-BERZKN_L.js";(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))n(r);new MutationObserver(r=>{for(const a of r)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&n(l)}).observe(document,{childList:!0,subtree:!0});function o(r){const a={};return r.integrity&&(a.integrity=r.integrity),r.referrerPolicy&&(a.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?a.credentials="include":r.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function n(r){if(r.ep)return;r.ep=!0;const a=o(r);fetch(r.href,a)}})();var $e={exports:{}},ie={};/**
|
|
2
|
+
* @license React
|
|
3
|
+
* react-jsx-runtime.production.min.js
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/var ct=d,dt=Symbol.for("react.element"),ut=Symbol.for("react.fragment"),ft=Object.prototype.hasOwnProperty,pt=ct.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,mt={key:!0,ref:!0,__self:!0,__source:!0};function Pe(t,e,o){var n,r={},a=null,l=null;o!==void 0&&(a=""+o),e.key!==void 0&&(a=""+e.key),e.ref!==void 0&&(l=e.ref);for(n in e)ft.call(e,n)&&!mt.hasOwnProperty(n)&&(r[n]=e[n]);if(t&&t.defaultProps)for(n in e=t.defaultProps,e)r[n]===void 0&&(r[n]=e[n]);return{$$typeof:dt,type:t,key:a,ref:l,props:r,_owner:pt.current}}ie.Fragment=ut;ie.jsx=Pe;ie.jsxs=Pe;$e.exports=ie;var s=$e.exports,pe={},ve=ot;pe.createRoot=ve.createRoot,pe.hydrateRoot=ve.hydrateRoot;const ht={},Se=t=>{let e;const o=new Set,n=(p,u)=>{const m=typeof p=="function"?p(e):p;if(!Object.is(m,e)){const h=e;e=u??(typeof m!="object"||m===null)?m:Object.assign({},e,m),o.forEach(b=>b(e,h))}},r=()=>e,c={setState:n,getState:r,getInitialState:()=>f,subscribe:p=>(o.add(p),()=>o.delete(p)),destroy:()=>{o.clear()}},f=e=t(n,r,c);return c},xt=t=>t?Se(t):Se;var Fe={exports:{}},We={},Be={exports:{}},Ue={};/**
|
|
10
|
+
* @license React
|
|
11
|
+
* use-sync-external-store-shim.production.js
|
|
12
|
+
*
|
|
13
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the MIT license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/var ee=d;function bt(t,e){return t===e&&(t!==0||1/t===1/e)||t!==t&&e!==e}var yt=typeof Object.is=="function"?Object.is:bt,gt=ee.useState,wt=ee.useEffect,vt=ee.useLayoutEffect,St=ee.useDebugValue;function Tt(t,e){var o=e(),n=gt({inst:{value:o,getSnapshot:e}}),r=n[0].inst,a=n[1];return vt(function(){r.value=o,r.getSnapshot=e,ue(r)&&a({inst:r})},[t,o,e]),wt(function(){return ue(r)&&a({inst:r}),t(function(){ue(r)&&a({inst:r})})},[t]),St(o),o}function ue(t){var e=t.getSnapshot;t=t.value;try{var o=e();return!yt(t,o)}catch{return!0}}function kt(t,e){return e()}var Ct=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?kt:Tt;Ue.useSyncExternalStore=ee.useSyncExternalStore!==void 0?ee.useSyncExternalStore:Ct;Be.exports=Ue;var It=Be.exports;/**
|
|
18
|
+
* @license React
|
|
19
|
+
* use-sync-external-store-shim/with-selector.production.js
|
|
20
|
+
*
|
|
21
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
22
|
+
*
|
|
23
|
+
* This source code is licensed under the MIT license found in the
|
|
24
|
+
* LICENSE file in the root directory of this source tree.
|
|
25
|
+
*/var ae=d,jt=It;function Et(t,e){return t===e&&(t!==0||1/t===1/e)||t!==t&&e!==e}var Rt=typeof Object.is=="function"?Object.is:Et,zt=jt.useSyncExternalStore,Lt=ae.useRef,Dt=ae.useEffect,Nt=ae.useMemo,Mt=ae.useDebugValue;We.useSyncExternalStoreWithSelector=function(t,e,o,n,r){var a=Lt(null);if(a.current===null){var l={hasValue:!1,value:null};a.current=l}else l=a.current;a=Nt(function(){function c(h){if(!f){if(f=!0,p=h,h=n(h),r!==void 0&&l.hasValue){var b=l.value;if(r(b,h))return u=b}return u=h}if(b=u,Rt(p,h))return b;var v=n(h);return r!==void 0&&r(b,v)?(p=h,b):(p=h,u=v)}var f=!1,p,u,m=o===void 0?null:o;return[function(){return c(e())},m===null?void 0:function(){return c(m())}]},[e,o,n,r]);var i=zt(t,a[0],a[1]);return Dt(function(){l.hasValue=!0,l.value=i},[i]),Mt(i),i};Fe.exports=We;var Ot=Fe.exports;const _t=st(Ot),He={},{useDebugValue:At}=xe,{useSyncExternalStoreWithSelector:$t}=_t;let Te=!1;const Pt=t=>t;function Ft(t,e=Pt,o){(He?"production":void 0)!=="production"&&o&&!Te&&(Te=!0);const n=$t(t.subscribe,t.getState,t.getServerState||t.getInitialState,e,o);return At(n),n}const ke=t=>{const e=typeof t=="function"?xt(t):t,o=(n,r)=>Ft(e,n,r);return Object.assign(o,e),o},Wt=t=>t?ke(t):ke,V="";function q(t){return{Authorization:`Bearer ${t}`}}async function Bt(t){try{const e=await fetch(`${V}/api/settings/font-size`,{headers:q(t)});return e.ok?(await e.json()).fontSize:14}catch{return 14}}async function Ut(t,e){try{await fetch(`${V}/api/settings/font-size`,{method:"PUT",headers:{...q(t),"Content-Type":"application/json"},body:JSON.stringify({fontSize:e})})}catch{}}const se="ai-cli-online-tabs",Ce="ai-cli-online-layout",Ie="ai-cli-online-session-names";function me(t,e){if(t.type==="leaf")return t.terminalId===e?null:t;const o=[],n=[];for(let l=0;l<t.children.length;l++){const i=me(t.children[l],e);i!==null&&(o.push(i),n.push(t.sizes[l]))}if(o.length===0)return null;if(o.length===1)return o[0];const r=n.reduce((l,i)=>l+i,0),a=n.map(l=>l/r*100);return{...t,children:o,sizes:a}}function Ve(t,e,o,n,r){return t.type==="leaf"?t.terminalId===e?{id:r,type:"split",direction:o,children:[t,n],sizes:[50,50]}:t:{...t,children:t.children.map(a=>Ve(a,e,o,n,r))}}function Ge(t,e,o){return t.type==="leaf"?t:t.id===e?{...t,sizes:o}:{...t,children:t.children.map(n=>Ge(n,e,o))}}function fe(t){return t.tabs.find(e=>e.id===t.activeTabId)}function X(t,e,o){return t.map(n=>n.id===e?o(n):n)}function U(t){const e={version:2,activeTabId:t.activeTabId,nextId:t.nextId,nextSplitId:t.nextSplitId,nextTabId:t.nextTabId,tabs:t.tabs};try{localStorage.setItem(se,JSON.stringify(e))}catch{}}let te=null,ne=null;function Ht(t){te&&clearTimeout(te),te=setTimeout(()=>{te=null,U(t)},500)}function Vt(){try{const t=localStorage.getItem(se);if(t){const e=JSON.parse(t);if(e.version===2)return e}}catch{}try{const t=localStorage.getItem(Ce);if(t){const e=JSON.parse(t);let o="Default";try{const a=localStorage.getItem(Ie);if(a){const l=JSON.parse(a),i=Object.values(l)[0];i&&(o=i)}}catch{}const n={id:"tab1",name:o,status:"open",terminalIds:e.terminalIds,layout:e.layout,createdAt:Date.now()},r={version:2,activeTabId:"tab1",nextId:e.nextId,nextSplitId:e.nextSplitId,nextTabId:2,tabs:[n]};try{localStorage.setItem(se,JSON.stringify(r))}catch{}return localStorage.removeItem(Ce),localStorage.removeItem(Ie),r}}catch{}return null}function B(t){return{tabs:t.tabs,activeTabId:t.activeTabId,nextId:t.nextId,nextSplitId:t.nextSplitId,nextTabId:t.nextTabId}}const k=Wt((t,e)=>({token:null,setToken:o=>{if(o){try{localStorage.setItem("ai-cli-online-token",o)}catch{}Bt(o).then(r=>{e().token===o&&t({fontSize:r})});const n=Vt();if(n&&n.tabs.length>0){const r={};for(const i of n.tabs)if(i.status==="open")for(const c of i.terminalIds)r[c]={id:c,connected:!1,sessionResumed:!1,error:null};const a=n.tabs.find(i=>i.id===n.activeTabId&&i.status==="open")||n.tabs.find(i=>i.status==="open"),l=(a==null?void 0:a.id)||"";t({token:o,terminalsMap:r,tabs:n.tabs,activeTabId:l,nextId:n.nextId,nextSplitId:n.nextSplitId,nextTabId:n.nextTabId,terminalIds:(a==null?void 0:a.terminalIds)||[],layout:(a==null?void 0:a.layout)||null});return}}else localStorage.removeItem("ai-cli-online-token"),localStorage.removeItem(se);t({token:o,terminalsMap:{},tabs:[],activeTabId:"",nextId:1,nextSplitId:1,nextTabId:1,terminalIds:[],layout:null})},terminalsMap:{},terminalIds:[],layout:null,nextId:1,nextSplitId:1,tabs:[],activeTabId:"",nextTabId:1,addTab:o=>{const n=e(),r=`tab${n.nextTabId}`,a=`t${n.nextId}`,l={id:a,connected:!1,sessionResumed:!1,error:null},i={type:"leaf",terminalId:a},c={id:r,name:o||`Tab ${n.nextTabId}`,status:"open",terminalIds:[a],layout:i,createdAt:Date.now()};return t({tabs:[...n.tabs,c],activeTabId:r,nextTabId:n.nextTabId+1,nextId:n.nextId+1,terminalsMap:{...n.terminalsMap,[a]:l},terminalIds:c.terminalIds,layout:c.layout}),U(B(e())),r},switchTab:o=>{const r=e().tabs.find(a=>a.id===o);!r||r.status!=="open"||(t({activeTabId:o,terminalIds:r.terminalIds,layout:r.layout}),U(B(e())))},closeTab:o=>{const n=e(),r=n.tabs.find(u=>u.id===o);if(!r||r.status!=="open"||n.tabs.filter(u=>u.status==="open").length<=1)return;const l={...n.terminalsMap};for(const u of r.terminalIds)delete l[u];const i=X(n.tabs,o,u=>({...u,status:"closed"}));let c=n.activeTabId,f=n.terminalIds,p=n.layout;if(n.activeTabId===o){const u=n.tabs.findIndex(b=>b.id===o),m=i.filter(b=>b.status==="open"),h=m.find(b=>i.findIndex(T=>T.id===b.id)>u)||m[m.length-1];h&&(c=h.id,f=h.terminalIds,p=h.layout)}t({tabs:i,activeTabId:c,terminalsMap:l,terminalIds:f,layout:p}),U(B(e()))},reopenTab:o=>{const n=e(),r=n.tabs.find(i=>i.id===o);if(!r||r.status!=="closed")return;const a={...n.terminalsMap};for(const i of r.terminalIds)a[i]={id:i,connected:!1,sessionResumed:!1,error:null};const l=X(n.tabs,o,i=>({...i,status:"open"}));t({tabs:l,activeTabId:o,terminalsMap:a,terminalIds:r.terminalIds,layout:r.layout}),U(B(e()))},deleteTab:async o=>{const n=e(),r=n.tabs.find(h=>h.id===o);if(!r)return;const a=n.token;a&&await Promise.all(r.terminalIds.map(h=>fetch(`${V}/api/sessions/${encodeURIComponent(h)}`,{method:"DELETE",headers:q(a)}).catch(()=>{})));const l=e(),i=l.tabs.find(h=>h.id===o);if(!i)return;const c={...l.terminalsMap};for(const h of i.terminalIds)delete c[h];const f=l.tabs.filter(h=>h.id!==o);let p=l.activeTabId,u=l.terminalIds,m=l.layout;if(l.activeTabId===o){const h=f.find(b=>b.status==="open");h?(p=h.id,u=h.terminalIds,m=h.layout):(p="",u=[],m=null)}t({tabs:f,activeTabId:p,terminalsMap:c,terminalIds:u,layout:m}),U(B(e())),setTimeout(()=>e().fetchSessions(),500)},renameTab:(o,n)=>{const r=X(e().tabs,o,a=>({...a,name:n}));t({tabs:r}),U(B(e()))},addTerminal:(o,n)=>{const r=e();if(n&&r.terminalsMap[n])return n;const a=fe(r);if(!a){const C=`tab${r.nextTabId}`,D=n||`t${r.nextId}`;let z=r.nextId;const I=D.match(/^t(\d+)$/);I&&(z=Math.max(z,parseInt(I[1],10)+1));const x=n?z:z+1,R={id:D,connected:!1,sessionResumed:!1,error:null},L={type:"leaf",terminalId:D},A={id:C,name:`Tab ${r.nextTabId}`,status:"open",terminalIds:[D],layout:L,createdAt:Date.now()};return t({tabs:[...r.tabs,A],activeTabId:C,nextTabId:r.nextTabId+1,nextId:x,terminalsMap:{...r.terminalsMap,[D]:R},terminalIds:[D],layout:L}),U(B(e())),D}const{nextId:l,nextSplitId:i,terminalsMap:c}=r,{terminalIds:f,layout:p}=a,u=n||`t${l}`;let m=l;const h=u.match(/^t(\d+)$/);h&&(m=Math.max(m,parseInt(h[1],10)+1));const b={id:u,connected:!1,sessionResumed:!1,error:null},v={type:"leaf",terminalId:u};let T,w=i;if(!p)T=v;else if(p.type==="leaf"){const C=o||"horizontal";T={id:`s${w}`,type:"split",direction:C,children:[p,v],sizes:[50,50]},w++}else if(p.direction===(o||"horizontal")){const D=100/(p.children.length+1),z=(100-D)/100,I=[...p.sizes.map(x=>x*z),D];T={...p,children:[...p.children,v],sizes:I}}else{const C=o||"horizontal";T={id:`s${w}`,type:"split",direction:C,children:[p,v],sizes:[50,50]},w++}const E=[...f,u],N=n?m:m+1,g=X(r.tabs,a.id,C=>({...C,terminalIds:E,layout:T}));return t({terminalsMap:{...c,[u]:b},terminalIds:E,layout:T,tabs:g,nextId:N,nextSplitId:w}),U(B(e())),u},splitTerminal:(o,n)=>{const r=e(),a=fe(r);if(!a||!a.layout)return"";const{nextId:l,nextSplitId:i,terminalsMap:c}=r,f=`t${l}`,p={id:f,connected:!1,sessionResumed:!1,error:null},u={type:"leaf",terminalId:f},m=`s${i}`,h=Ve(a.layout,o,n,u,m),b=[...a.terminalIds,f],v=l+1,T=i+1,w=X(r.tabs,a.id,E=>({...E,terminalIds:b,layout:h}));return t({terminalsMap:{...c,[f]:p},terminalIds:b,layout:h,tabs:w,nextId:v,nextSplitId:T}),U(B(e())),f},removeTerminal:o=>{const n=e(),r=n.tabs.find(p=>p.terminalIds.includes(o));if(!r){const{[o]:p,...u}=n.terminalsMap;t({terminalsMap:u});return}const a=r.terminalIds.filter(p=>p!==o),l=r.layout?me(r.layout,o):null,i=X(n.tabs,r.id,p=>({...p,terminalIds:a,layout:l})),{[o]:c,...f}=n.terminalsMap;r.id===n.activeTabId?t({terminalsMap:f,terminalIds:a,layout:l,tabs:i}):t({terminalsMap:f,tabs:i}),U(B(e()))},setTerminalConnected:(o,n)=>{t(r=>{const a=r.terminalsMap[o];return!a||a.connected===n?r:{terminalsMap:{...r.terminalsMap,[o]:{...a,connected:n}}}})},setTerminalResumed:(o,n)=>{t(r=>{const a=r.terminalsMap[o];return!a||a.sessionResumed===n?r:{terminalsMap:{...r.terminalsMap,[o]:{...a,sessionResumed:n}}}})},setTerminalError:(o,n)=>{t(r=>{const a=r.terminalsMap[o];return!a||a.error===n?r:{terminalsMap:{...r.terminalsMap,[o]:{...a,error:n}}}})},setSplitSizes:(o,n)=>{const r=e(),a=fe(r);if(!a||!a.layout)return;const l=Ge(a.layout,o,n),i=X(r.tabs,a.id,c=>({...c,layout:l}));t({layout:l,tabs:i}),Ht(B(e()))},fontSize:14,setFontSize:o=>{const n=Math.max(10,Math.min(24,o));t({fontSize:n}),ne&&clearTimeout(ne),ne=setTimeout(()=>{ne=null;const r=e().token;r&&Ut(r,n)},500)},latency:null,setLatency:o=>t({latency:o}),sidebarOpen:!1,toggleSidebar:()=>t(o=>({sidebarOpen:!o.sidebarOpen})),serverSessions:[],fetchSessions:async()=>{const o=e().token;if(o)try{const n=await fetch(`${V}/api/sessions`,{headers:q(o)});if(!n.ok)return;const r=await n.json();t({serverSessions:r})}catch{}},killServerSession:async o=>{const n=e().token;if(!n)return;try{await fetch(`${V}/api/sessions/${encodeURIComponent(o)}`,{method:"DELETE",headers:q(n)})}catch{}const r=e(),a=r.tabs.find(l=>l.terminalIds.includes(o));if(a){const l=a.terminalIds.filter(u=>u!==o),i=a.layout?me(a.layout,o):null,c=X(r.tabs,a.id,u=>({...u,terminalIds:l,layout:i})),{[o]:f,...p}=r.terminalsMap;a.id===r.activeTabId?t({terminalsMap:p,terminalIds:l,layout:i,tabs:c}):t({terminalsMap:p,tabs:c}),U(B(e()))}else{const{[o]:l,...i}=r.terminalsMap;t({terminalsMap:i})}setTimeout(()=>e().fetchSessions(),500)}}));function Gt(){const[t,e]=d.useState(""),o=k(r=>r.setToken),n=r=>{r.preventDefault(),t.trim()&&o(t.trim())};return s.jsx("div",{style:{minHeight:"100vh",backgroundColor:"#1a1b26",display:"flex",alignItems:"center",justifyContent:"center",padding:"16px",background:"radial-gradient(ellipse at 50% 0%, rgba(122, 162, 247, 0.08) 0%, #1a1b26 70%)"},children:s.jsxs("div",{className:"login-card",style:{backgroundColor:"#24283b",borderRadius:"12px",padding:"40px 36px",width:"100%",maxWidth:"400px",border:"1px solid #292e42"},children:[s.jsxs("div",{style:{textAlign:"center",marginBottom:"36px"},children:[s.jsx("div",{style:{width:"56px",height:"56px",margin:"0 auto 16px",borderRadius:"14px",background:"linear-gradient(135deg, #7aa2f7 0%, #bb9af7 100%)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"24px",color:"#1a1b26",fontWeight:"bold",boxShadow:"0 4px 16px rgba(122, 162, 247, 0.3)"},children:">_"}),s.jsx("h1",{style:{fontSize:"22px",fontWeight:"bold",color:"#c0caf5",marginBottom:"6px",letterSpacing:"0.5px"},children:"AI-Cli Online"}),s.jsx("p",{style:{color:"#565f89",fontSize:"13px"},children:"Terminal in your browser"})]}),s.jsxs("form",{onSubmit:n,children:[s.jsxs("div",{style:{marginBottom:"20px"},children:[s.jsx("label",{htmlFor:"token",style:{display:"block",fontSize:"12px",color:"#7aa2f7",marginBottom:"8px",fontWeight:500,textTransform:"uppercase",letterSpacing:"0.5px"},children:"Auth Token"}),s.jsx("input",{type:"password",id:"token",className:"login-input",value:t,onChange:r=>e(r.target.value),placeholder:"Enter your AUTH_TOKEN",autoFocus:!0,autoComplete:"current-password",style:{width:"100%",padding:"11px 14px",backgroundColor:"#1a1b26",color:"#c0caf5",border:"1px solid #292e42",borderRadius:"8px",fontSize:"14px",outline:"none"}})]}),s.jsx("button",{type:"submit",className:"login-submit",disabled:!t.trim(),style:{width:"100%",padding:"11px",background:t.trim()?"linear-gradient(135deg, #7aa2f7 0%, #7dcfff 100%)":"#292e42",color:t.trim()?"#1a1b26":"#565f89",border:"none",borderRadius:"8px",fontSize:"14px",fontWeight:600,cursor:t.trim()?"pointer":"not-allowed",letterSpacing:"0.3px"},children:"Connect"})]}),s.jsx("div",{style:{marginTop:"28px",textAlign:"center",color:"#414868",fontSize:"11px"},children:s.jsxs("p",{children:["Token is configured in"," ",s.jsx("code",{style:{backgroundColor:"#1a1b26",padding:"2px 6px",borderRadius:"4px",border:"1px solid #292e42",fontSize:"11px"},children:"server/.env"})]})})]})})}/**
|
|
26
|
+
* Copyright (c) 2014-2024 The xterm.js authors. All rights reserved.
|
|
27
|
+
* @license MIT
|
|
28
|
+
*
|
|
29
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
30
|
+
* @license MIT
|
|
31
|
+
*
|
|
32
|
+
* Originally forked from (with the author's permission):
|
|
33
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
34
|
+
* http://bellard.org/jslinux/
|
|
35
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
36
|
+
*/var qt=class{constructor(t,e,o,n={}){this._terminal=t,this._regex=e,this._handler=o,this._options=n}provideLinks(t,e){let o=Yt.computeLink(t,this._regex,this._terminal,this._handler);e(this._addCallbacks(o))}_addCallbacks(t){return t.map(e=>(e.leave=this._options.leave,e.hover=(o,n)=>{if(this._options.hover){let{range:r}=e;this._options.hover(o,n,r)}},e))}};function Kt(t){try{let e=new URL(t),o=e.password&&e.username?`${e.protocol}//${e.username}:${e.password}@${e.host}`:e.username?`${e.protocol}//${e.username}@${e.host}`:`${e.protocol}//${e.host}`;return t.toLocaleLowerCase().startsWith(o.toLocaleLowerCase())}catch{return!1}}var Yt=class re{static computeLink(e,o,n,r){let a=new RegExp(o.source,(o.flags||"")+"g"),[l,i]=re._getWindowedLineStrings(e-1,n),c=l.join(""),f,p=[];for(;f=a.exec(c);){let u=f[0];if(!Kt(u))continue;let[m,h]=re._mapStrIdx(n,i,0,f.index),[b,v]=re._mapStrIdx(n,m,h,u.length);if(m===-1||h===-1||b===-1||v===-1)continue;let T={start:{x:h+1,y:m+1},end:{x:v,y:b+1}};p.push({range:T,text:u,activate:r})}return p}static _getWindowedLineStrings(e,o){let n,r=e,a=e,l=0,i="",c=[];if(n=o.buffer.active.getLine(e)){let f=n.translateToString(!0);if(n.isWrapped&&f[0]!==" "){for(l=0;(n=o.buffer.active.getLine(--r))&&l<2048&&(i=n.translateToString(!0),l+=i.length,c.push(i),!(!n.isWrapped||i.indexOf(" ")!==-1)););c.reverse()}for(c.push(f),l=0;(n=o.buffer.active.getLine(++a))&&n.isWrapped&&l<2048&&(i=n.translateToString(!0),l+=i.length,c.push(i),i.indexOf(" ")===-1););}return[c,r]}static _mapStrIdx(e,o,n,r){let a=e.buffer.active,l=a.getNullCell(),i=n;for(;r;){let c=a.getLine(o);if(!c)return[-1,-1];for(let f=i;f<c.length;++f){c.getCell(f,l);let p=l.getChars();if(l.getWidth()&&(r-=p.length||1,f===c.length-1&&p==="")){let u=a.getLine(o+1);u&&u.isWrapped&&(u.getCell(0,l),l.getWidth()===2&&(r+=1))}if(r<0)return[o,f]}o++,i=0}return[o,i]}},Jt=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function Xt(t,e){let o=window.open();if(o){try{o.opener=null}catch{}o.location.href=e}}var Zt=class{constructor(t=Xt,e={}){this._handler=t,this._options=e}activate(t){this._terminal=t;let e=this._options,o=e.urlRegex||Jt;this._linkProvider=this._terminal.registerLinkProvider(new qt(this._terminal,o,this._handler,e))}dispose(){var t;(t=this._linkProvider)==null||t.dispose()}};const Qt=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/ws`,je=500,en=15e3,tn=15e3,nn=5e3,rn=1e4,on=5,sn=64*1024,an=1,Ee=2,ln=3,cn=4,dn=new TextDecoder,un=new TextEncoder;function Re(t,e){const o=un.encode(e),n=new Uint8Array(1+o.length);return n[0]=t,n.set(o,1),n.buffer}function fn(t,e,o){const n=d.useRef(null),r=d.useRef(je),a=d.useRef(null),l=d.useRef(null),i=d.useRef(null),c=d.useRef(null),f=d.useRef(!1),p=d.useRef(o),u=d.useRef(!1),m=d.useRef(0),h=d.useRef(""),b=d.useRef(null),v=d.useRef("");p.current=o;const T=d.useCallback(()=>{l.current&&(clearInterval(l.current),l.current=null),i.current&&(clearTimeout(i.current),i.current=null),a.current&&(clearTimeout(a.current),a.current=null),c.current&&(clearTimeout(c.current),c.current=null),b.current&&(clearTimeout(b.current),b.current=null)},[]),w=d.useCallback(()=>{const{token:C,setTerminalError:D}=k.getState();if(!C||f.current)return;if(n.current){const R=n.current.readyState;if(R===WebSocket.OPEN||R===WebSocket.CONNECTING)return}u.current=!1;const z=`${Qt}?sessionId=${encodeURIComponent(e)}`,I=new WebSocket(z);I.binaryType="arraybuffer",c.current=window.setTimeout(()=>{I.readyState===WebSocket.CONNECTING&&I.close()},rn);const x=()=>{I.readyState===WebSocket.OPEN&&(m.current=performance.now(),I.send(JSON.stringify({type:"ping"})),i.current=window.setTimeout(()=>{m.current>0&&(m.current=0,I.close())},nn))};I.onopen=()=>{c.current&&(clearTimeout(c.current),c.current=null),I.send(JSON.stringify({type:"auth",token:C})),D(e,null),r.current=je},I.onclose=R=>{const{setTerminalConnected:L,setTerminalError:A,setToken:P}=k.getState();if(L(e,!1),T(),u.current)return;if(R.code===4001){f.current=!0,A(e,"Authentication failed"),P(null),localStorage.removeItem("ai-cli-online-token");return}if(R.code===4002)return;if(R.code===4005){A(e,"Connection limit reached");return}const M=r.current;r.current=Math.min(M*2,en);const j=Math.round(M*(.5+Math.random()));a.current=window.setTimeout(()=>{w()},j)},I.onerror=()=>{},I.onmessage=R=>{var L;try{const A=t.current;if(R.data instanceof ArrayBuffer){const M=new Uint8Array(R.data);if(M.length<1)return;const j=M[0],_=M.subarray(1);switch(j){case an:A==null||A.write(_);break;case ln:A==null||A.write(_);break;case cn:{(L=p.current)==null||L.call(p,dn.decode(_));break}}return}const P=JSON.parse(R.data);switch(P.type){case"connected":{const M=k.getState();M.setTerminalConnected(e,!0),M.setTerminalResumed(e,P.resumed);const j=t.current;j&&I.readyState===WebSocket.OPEN&&I.send(JSON.stringify({type:"resize",cols:j.cols,rows:j.rows})),v.current&&(I.send(Re(Ee,v.current)),v.current=""),x(),l.current=window.setInterval(x,tn);break}case"error":k.getState().setTerminalError(e,P.error);break;case"pong":{if(i.current&&(clearTimeout(i.current),i.current=null),m.current>0){const M=Math.round(performance.now()-m.current),j=k.getState();(j.terminalIds.length===0||j.terminalIds[0]===e)&&j.setLatency(M),m.current=0}break}}}catch{}},n.current=I},[e,t,T]),E=d.useCallback(C=>{const D=n.current;if(!D||D.readyState!==WebSocket.OPEN){v.current.length<sn&&(v.current+=C);return}h.current+=C,b.current||(b.current=window.setTimeout(()=>{const z=h.current;h.current="",b.current=null,z&&D.readyState===WebSocket.OPEN&&D.send(Re(Ee,z))},on))},[]),N=d.useCallback((C,D)=>{var z;((z=n.current)==null?void 0:z.readyState)===WebSocket.OPEN&&n.current.send(JSON.stringify({type:"resize",cols:C,rows:D}))},[]),g=d.useCallback(()=>{var C;((C=n.current)==null?void 0:C.readyState)===WebSocket.OPEN&&n.current.send(JSON.stringify({type:"capture-scrollback"}))},[]);return d.useEffect(()=>(k.getState().token&&(f.current=!1,w()),()=>{u.current=!0,T(),n.current&&(n.current.close(),n.current=null)}),[w,T]),{sendInput:E,sendResize:N,requestScrollback:g}}const qe={background:"#1a1b26",foreground:"#a9b1d6",cursor:"#c0caf5",selectionBackground:"#33467c",black:"#15161e",red:"#f7768e",green:"#9ece6a",yellow:"#e0af68",blue:"#7aa2f7",magenta:"#bb9af7",cyan:"#7dcfff",white:"#a9b1d6",brightBlack:"#414868",brightRed:"#f7768e",brightGreen:"#9ece6a",brightYellow:"#e0af68",brightBlue:"#7aa2f7",brightMagenta:"#bb9af7",brightCyan:"#7dcfff",brightWhite:"#c0caf5"},Ke="'Maple Mono CN', 'JetBrains Mono', Menlo, Monaco, 'Courier New', monospace",pn=d.forwardRef(function({sessionId:e},o){const n=d.useRef(null),r=d.useRef(null),a=d.useRef(null),[l,i]=d.useState(!1),[c,f]=d.useState(""),p=k(w=>w.fontSize),u=d.useCallback(w=>{f(w),i(!0)},[]),{sendInput:m,sendResize:h,requestScrollback:b}=fn(r,e,u);d.useImperativeHandle(o,()=>({sendInput:m}),[m]);const v=d.useRef(m),T=d.useRef(h);return v.current=m,T.current=h,d.useEffect(()=>{if(!n.current)return;let w=!1,E=null,N=null,g=null,C=null;const D=()=>{if(w||!n.current)return;const z=new _e({cursorBlink:!0,scrollback:1e4,fontSize:k.getState().fontSize,fontFamily:Ke,theme:qe,allowProposedApi:!0}),I=new Ae;z.loadAddon(I),z.loadAddon(new Zt((L,A)=>{window.open(A,"_blank","noopener,noreferrer")})),z.open(n.current);try{const L=new it;L.onContextLoss(()=>{L.dispose()}),z.loadAddon(L)}catch{}r.current=z,a.current=I;const x=()=>{try{const L=n.current;if(L&&L.clientWidth>0&&L.clientHeight>0)return I.fit(),T.current(z.cols,z.rows),!0}catch{}return!1};requestAnimationFrame(()=>x());let R=0;E=setInterval(()=>{R++,(x()||R>=10)&&(clearInterval(E),E=null)},100),z.onData(L=>{v.current(L)}),C=new ResizeObserver(()=>{N||(N=requestAnimationFrame(()=>{N=null;try{I.fit(),g&&clearTimeout(g),g=setTimeout(()=>{g=null,T.current(z.cols,z.rows)},50)}catch{}}))}),C.observe(n.current)};return document.fonts.ready.then(D),()=>{w=!0,E&&clearInterval(E),N&&cancelAnimationFrame(N),g&&clearTimeout(g),C&&C.disconnect(),r.current&&(r.current.dispose(),r.current=null),a.current=null}},[e]),d.useEffect(()=>{const w=r.current,E=a.current;if(!(!w||!E)&&w.options.fontSize!==p){w.options.fontSize=p;try{E.fit()}catch{}T.current(w.cols,w.rows)}},[p]),s.jsxs("div",{style:{width:"100%",height:"100%",position:"relative"},children:[s.jsx("div",{ref:n,style:{width:"100%",height:"100%",backgroundColor:"#1a1b26",contain:"strict",willChange:"transform",isolation:"isolate"}}),s.jsx("button",{onClick:()=>{l?(i(!1),f("")):b()},title:"Toggle scrollback history",style:{position:"absolute",top:4,right:4,zIndex:10,background:l?"#7aa2f7":"rgba(65, 72, 104, 0.7)",color:"#c0caf5",border:"none",borderRadius:4,padding:"2px 8px",fontSize:12,cursor:"pointer",opacity:.8,lineHeight:"20px"},onMouseEnter:w=>{w.currentTarget.style.opacity="1"},onMouseLeave:w=>{w.currentTarget.style.opacity="0.8"},children:l?"✕":"↑"}),l&&s.jsx(mn,{data:c,onClose:()=>{i(!1),f("")}})]})});function mn({data:t,onClose:e}){const o=d.useRef(null),n=d.useRef(e);n.current=e;const r=k(i=>i.fontSize),a=d.useRef(null),l=d.useRef(null);return d.useEffect(()=>{if(!o.current)return;const i=new _e({cursorBlink:!1,disableStdin:!0,scrollback:5e4,fontSize:r,fontFamily:Ke,theme:qe});a.current=i;const c=new Ae;l.current=c,i.loadAddon(c),i.open(o.current),requestAnimationFrame(()=>{try{c.fit()}catch{}i.write(t,()=>{i.scrollToBottom()})});let f=null;const p=new ResizeObserver(()=>{f||(f=requestAnimationFrame(()=>{f=null;try{c.fit()}catch{}}))});p.observe(o.current);const u=m=>{m.key==="Escape"&&n.current()};return document.addEventListener("keydown",u),()=>{f&&cancelAnimationFrame(f),document.removeEventListener("keydown",u),p.disconnect(),i.dispose(),a.current=null,l.current=null}},[t]),d.useEffect(()=>{var i;if(a.current){a.current.options.fontSize=r;try{(i=l.current)==null||i.fit()}catch{}}},[r]),s.jsxs("div",{style:{position:"absolute",inset:0,zIndex:5,backgroundColor:"#1a1b26",display:"flex",flexDirection:"column"},children:[s.jsx("div",{style:{padding:"4px 12px",background:"#24283b",color:"#7aa2f7",fontSize:12,borderBottom:"1px solid #414868",flexShrink:0,display:"flex",justifyContent:"space-between",alignItems:"center"},children:s.jsx("span",{children:"Scrollback History (mouse wheel to scroll, ESC to close)"})}),s.jsx("div",{ref:o,style:{flex:1,overflow:"hidden"}})]})}async function oe(t,e,o){const n=o?`?path=${encodeURIComponent(o)}`:"",r=await fetch(`${V}/api/sessions/${encodeURIComponent(e)}/files${n}`,{headers:q(t)});if(!r.ok)throw new Error("Failed to list files");return r.json()}function hn(t,e,o,n){return new Promise((r,a)=>{const l=new FormData;for(const c of o)l.append("files",c);const i=new XMLHttpRequest;i.open("POST",`${V}/api/sessions/${encodeURIComponent(e)}/upload`),i.setRequestHeader("Authorization",`Bearer ${t}`),i.upload.addEventListener("progress",c=>{c.lengthComputable&&n&&n(Math.round(c.loaded/c.total*100))}),i.addEventListener("load",()=>{i.status>=200&&i.status<300?r():a(new Error(`Upload failed: ${i.status}`))}),i.addEventListener("error",()=>a(new Error("Upload network error"))),i.addEventListener("abort",()=>a(new Error("Upload aborted"))),i.send(l)})}async function xn(t,e,o){const n=await fetch(`${V}/api/sessions/${encodeURIComponent(e)}/download?path=${encodeURIComponent(o)}`,{headers:q(t)});if(!n.ok)throw new Error("Download failed");const r=await n.blob(),a=URL.createObjectURL(r),l=document.createElement("a");l.href=a,l.download=o.split("/").pop()||"download",document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(a)}function be({sessionId:t,onClose:e,filter:o}){const n=k(w=>w.token),[r,a]=d.useState(""),[l,i]=d.useState([]),[c,f]=d.useState(!0),[p,u]=d.useState(null),m=d.useCallback(async w=>{if(n){f(!0),u(null);try{const E=await oe(n,t,w);a(E.cwd),i(o?o(E.files):E.files)}catch(E){u(E instanceof Error?E.message:"Failed to load files")}finally{f(!1)}}},[n,t,o]);d.useEffect(()=>{m()},[m]);const h=d.useRef(e);h.current=e,d.useEffect(()=>{const w=E=>{E.key==="Escape"&&h.current()};return document.addEventListener("keydown",w),()=>document.removeEventListener("keydown",w)},[]);const b=d.useCallback(w=>{m(r+"/"+w)},[m,r]),v=d.useCallback(()=>{const w=r.replace(/\/[^/]+$/,"")||"/";m(w)},[m,r]),T=d.useCallback(()=>{m(r)},[m,r]);return{cwd:r,files:l,loading:c,error:p,setError:u,handleNavigate:b,handleGoUp:v,handleRefresh:T}}function bn(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:t<1024*1024*1024?`${(t/(1024*1024)).toFixed(1)} MB`:`${(t/(1024*1024*1024)).toFixed(1)} GB`}function Ye(t){const e=new Date(t*1e3),o=n=>String(n).padStart(2,"0");return`${o(e.getMonth()+1)}-${o(e.getDate())} ${o(e.getHours())}:${o(e.getMinutes())}`}function ye({cwd:t,onGoUp:e,onRefresh:o,onClose:n}){return s.jsxs("div",{style:{padding:"6px 12px",background:"#24283b",borderBottom:"1px solid #414868",flexShrink:0,display:"flex",justifyContent:"space-between",alignItems:"center"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",minWidth:0},children:[s.jsx("button",{onClick:e,style:{background:"none",border:"1px solid #414868",color:"#7aa2f7",borderRadius:3,padding:"1px 8px",fontSize:12,cursor:"pointer",flexShrink:0},title:"Go to parent directory",children:".."}),s.jsx("span",{style:{color:"#7aa2f7",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t||"..."})]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",flexShrink:0},children:[s.jsx("button",{onClick:o,style:{background:"none",border:"none",color:"#565f89",fontSize:14,cursor:"pointer",padding:"0 4px"},title:"Refresh",children:"↻"}),s.jsx("button",{onClick:n,style:{background:"none",border:"none",color:"#565f89",fontSize:14,cursor:"pointer",padding:"0 4px"},title:"Close (ESC)",children:"✕"})]})]})}function ge({loading:t,error:e,empty:o,emptyText:n="Empty directory"}){return t?s.jsx("div",{style:{padding:"20px",textAlign:"center",color:"#565f89",fontSize:13},children:"Loading..."}):e?s.jsx("div",{style:{padding:"12px",color:"#f7768e",fontSize:12},children:e}):o?s.jsx("div",{style:{padding:"20px",textAlign:"center",color:"#565f89",fontSize:13},children:n}):null}function yn({sessionId:t,onClose:e}){const o=k(b=>b.token),{cwd:n,files:r,loading:a,error:l,setError:i,handleNavigate:c,handleGoUp:f,handleRefresh:p}=be({sessionId:t,onClose:e}),[u,m]=d.useState(null),h=async b=>{if(o){m(b);try{await xn(o,t,n+"/"+b)}catch(v){i(v instanceof Error?v.message:"Download failed")}finally{m(null)}}};return s.jsxs("div",{style:{position:"absolute",inset:0,zIndex:5,backgroundColor:"#1a1b26",display:"flex",flexDirection:"column",fontFamily:"inherit"},children:[s.jsx(ye,{cwd:n,onGoUp:f,onRefresh:p,onClose:e}),s.jsxs("div",{style:{flex:1,overflow:"auto",padding:"4px 0"},children:[s.jsx(ge,{loading:a,error:l,empty:r.length===0,emptyText:"Empty directory"}),!a&&!l&&r.map(b=>s.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"3px 12px",fontSize:13,cursor:b.type==="directory"?"pointer":"default",borderBottom:"1px solid #1e2030"},onMouseEnter:v=>{v.currentTarget.style.backgroundColor="#24283b"},onMouseLeave:v=>{v.currentTarget.style.backgroundColor="transparent"},onClick:()=>{b.type==="directory"&&c(b.name)},children:[b.type==="file"?s.jsx("button",{onClick:v=>{v.stopPropagation(),h(b.name)},disabled:u===b.name,style:{background:"none",border:"1px solid #414868",color:u===b.name?"#565f89":"#9ece6a",borderRadius:3,padding:"1px 8px",fontSize:11,cursor:u===b.name?"wait":"pointer",flexShrink:0,marginRight:6},children:u===b.name?"...":"↓"}):s.jsx("span",{style:{width:26,flexShrink:0,marginRight:6}}),s.jsx("span",{style:{width:20,flexShrink:0,color:b.type==="directory"?"#7aa2f7":"#565f89"},children:b.type==="directory"?"📁":"📄"}),s.jsx("span",{style:{flex:1,color:b.type==="directory"?"#7aa2f7":"#a9b1d6",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0},children:b.name}),s.jsx("span",{style:{width:80,textAlign:"right",color:"#565f89",fontSize:11,flexShrink:0},children:b.type==="file"?bn(b.size):""})]},b.name))]})]})}function gn({content:t}){const e=k(n=>n.fontSize),o=d.useMemo(()=>{if(!t)return"";const n=at.parse(t,{async:!1});return lt.sanitize(n,{ADD_TAGS:["img"],ADD_ATTR:["src","alt","title","width","height"]})},[t]);return t?s.jsx("div",{className:"md-preview",style:{height:"100%",overflowY:"auto",userSelect:"text",padding:"12px 16px",fontSize:`${e}px`},dangerouslySetInnerHTML:{__html:o}}):s.jsx("div",{className:"md-preview",style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",color:"#414868",fontStyle:"italic",fontSize:"13px"},children:"Waiting for plan output..."})}async function wn(t,e){const o=await fetch(`${V}/api/sessions/${encodeURIComponent(e)}/draft`,{headers:q(t)});return o.ok?(await o.json()).content??"":""}async function ze(t,e,o){await fetch(`${V}/api/sessions/${encodeURIComponent(e)}/draft`,{method:"PUT",headers:{...q(t),"Content-Type":"application/json"},body:JSON.stringify({content:o})})}const Le=[{cmd:"/plan",desc:"Enter plan mode"},{cmd:"/help",desc:"Get help"},{cmd:"/compact",desc:"Compact conversation"},{cmd:"/clear",desc:"Clear conversation"},{cmd:"/model",desc:"Switch model"},{cmd:"/cost",desc:"Show token usage"},{cmd:"/status",desc:"Show status"},{cmd:"/init",desc:"Initialize project CLAUDE.md"},{cmd:"/memory",desc:"Edit memory files"},{cmd:"/review",desc:"Review code"},{cmd:"/bug",desc:"Report a bug"},{cmd:"/login",desc:"Login to Anthropic"},{cmd:"/doctor",desc:"Run diagnostics"},{cmd:"/permissions",desc:"Manage permissions"},{cmd:"/mcp",desc:"MCP server management"},{cmd:"/terminal-setup",desc:"Configure terminal"},{cmd:"/vim",desc:"Toggle vim mode"},{cmd:"/oh-my-claudecode:autopilot",desc:"Full autonomous execution"},{cmd:"/oh-my-claudecode:ralph",desc:"Persistence loop until done"},{cmd:"/oh-my-claudecode:ultrawork",desc:"Max parallel execution"},{cmd:"/oh-my-claudecode:ecomode",desc:"Token-efficient execution"},{cmd:"/oh-my-claudecode:plan",desc:"Strategic planning session"},{cmd:"/oh-my-claudecode:ralplan",desc:"Iterative planning consensus"},{cmd:"/oh-my-claudecode:ultrapilot",desc:"Parallel autopilot (3-5x faster)"},{cmd:"/oh-my-claudecode:analyze",desc:"Deep analysis/investigation"},{cmd:"/oh-my-claudecode:deepsearch",desc:"Thorough codebase search"},{cmd:"/oh-my-claudecode:deepinit",desc:"Generate AGENTS.md hierarchy"},{cmd:"/oh-my-claudecode:ultraqa",desc:"QA cycling: test/fix/repeat"},{cmd:"/oh-my-claudecode:tdd",desc:"Test-driven development"},{cmd:"/oh-my-claudecode:code-review",desc:"Comprehensive code review"},{cmd:"/oh-my-claudecode:security-review",desc:"Security vulnerability review"},{cmd:"/oh-my-claudecode:build-fix",desc:"Fix build/TypeScript errors"},{cmd:"/oh-my-claudecode:research",desc:"Parallel research orchestration"},{cmd:"/oh-my-claudecode:swarm",desc:"N coordinated agents"},{cmd:"/oh-my-claudecode:pipeline",desc:"Sequential agent chaining"},{cmd:"/oh-my-claudecode:learner",desc:"Extract skill from session"},{cmd:"/oh-my-claudecode:note",desc:"Save notes to notepad"},{cmd:"/oh-my-claudecode:cancel",desc:"Cancel active OMC mode"},{cmd:"/oh-my-claudecode:help",desc:"OMC usage guide"},{cmd:"/oh-my-claudecode:doctor",desc:"Diagnose OMC issues"},{cmd:"/oh-my-claudecode:omc-setup",desc:"One-time OMC setup"},{cmd:"/oh-my-claudecode:hud",desc:"Configure HUD statusline"},{cmd:"/oh-my-claudecode:release",desc:"Automated release workflow"},{cmd:"/oh-my-claudecode:ralph-init",desc:"Initialize PRD for ralph"},{cmd:"/oh-my-claudecode:review",desc:"Review plan with Critic"},{cmd:"/oh-my-claudecode:git-master",desc:"Git expert for commits"},{cmd:"/oh-my-claudecode:mcp-setup",desc:"Configure MCP servers"},{cmd:"/oh-my-claudecode:skill",desc:"Manage local skills"},{cmd:"/oh-my-claudecode:writer-memory",desc:"Writer memory system"},{cmd:"/oh-my-claudecode:psm",desc:"Project session manager"},{cmd:"/oh-my-claudecode:trace",desc:"Agent flow trace timeline"}],vn=d.forwardRef(function({onSend:e,onContentChange:o,sessionId:n,token:r},a){const l=k(y=>y.fontSize),[i,c]=d.useState(""),f=d.useRef(null),p=d.useRef(),u=d.useRef(!1),[m,h]=d.useState(!1),[b,v]=d.useState(""),[T,w]=d.useState(0),[E,N]=d.useState(!1),[g,C]=d.useState(""),[D,z]=d.useState(""),[I,x]=d.useState(0),[R,L]=d.useState([]),[A,P]=d.useState(!1),M=d.useRef(""),j=d.useRef(null),_=d.useMemo(()=>{if(!b)return Le;const y=b.toLowerCase();return Le.filter(S=>S.cmd.toLowerCase().includes(y)||S.desc.toLowerCase().includes(y))},[b]),$=d.useMemo(()=>{let y=R;if(g){const S=g.toLowerCase();y=y.filter(O=>O.name.toLowerCase().includes(S))}return[...y].sort((S,O)=>S.type==="directory"&&O.type!=="directory"?-1:S.type!=="directory"&&O.type==="directory"?1:S.name.localeCompare(O.name))},[R,g]);d.useEffect(()=>{let y=!1;return wn(r,n).then(S=>{!y&&S&&c(S),u.current=!0}).catch(()=>{u.current=!0}),()=>{y=!0}},[r,n]),d.useEffect(()=>{if(u.current)return p.current&&clearTimeout(p.current),p.current=setTimeout(()=>{ze(r,n,i).catch(()=>{})},500),()=>{p.current&&clearTimeout(p.current)}},[i,r,n]),d.useEffect(()=>{var y;(y=f.current)==null||y.focus()},[]),d.useEffect(()=>{if(!E)return;let y=!1;return P(!0),(async()=>{try{if(D){if(!M.current){const F=await oe(r,n);if(y)return;M.current=F.cwd}const S=`${M.current}/${D.replace(/\/$/,"")}`,O=await oe(r,n,S);if(y)return;L(O.files)}else{const S=await oe(r,n);if(y)return;M.current=S.cwd,L(S.files)}P(!1)}catch{if(y)return;L([]),P(!1)}})(),()=>{y=!0}},[E,D,r,n]),d.useEffect(()=>{if(!E||!j.current)return;const y=j.current.querySelector(".file-item--active");y==null||y.scrollIntoView({block:"nearest"})},[I,E]);const J=d.useCallback(()=>{const y=i.trim();y&&(e(y),c(""),ze(r,n,"").catch(()=>{}))},[i,e,r,n]);d.useImperativeHandle(a,()=>({send:J}),[J]),d.useEffect(()=>{o==null||o(i.trim().length>0)},[i,o]);const le=d.useCallback(y=>{const S=f.current;if(!S)return;const O=S.selectionStart,F=i.slice(0,O),K=i.slice(O),G=F.lastIndexOf(`
|
|
37
|
+
`)+1,H=F.slice(G).match(/\/[a-zA-Z-]*$/);if(H){const W=G+(H.index??0),Q=y+" ",de=i.slice(0,W)+Q+K;c(de);const tt=W+Q.length;requestAnimationFrame(()=>{S.selectionStart=S.selectionEnd=tt,S.focus()})}else{const W=F+y+K;c(W);const Q=O+y.length;requestAnimationFrame(()=>{S.selectionStart=S.selectionEnd=Q,S.focus()})}h(!1),v(""),w(0)},[i]),ce=d.useCallback(y=>{const S=f.current;if(!S)return;const O=S.selectionStart,F=i.slice(0,O),K=i.slice(O),Z=F.match(/@([a-zA-Z0-9_.\-/]*)$/);if(!Z)return;const G=F.length-Z[0].length;if(y.type==="directory"){const Y="@"+D+y.name+"/",H=i.slice(0,G)+Y+K;c(H);const W=G+Y.length;z(D+y.name+"/"),C(""),x(0),requestAnimationFrame(()=>{S.selectionStart=S.selectionEnd=W,S.focus()})}else{const Y=y.name+" ",H=i.slice(0,G)+Y+K;c(H);const W=G+Y.length;N(!1),C(""),z(""),x(0),L([]),M.current="",requestAnimationFrame(()=>{S.selectionStart=S.selectionEnd=W,S.focus()})}},[i,D]),Qe=d.useCallback(y=>{const S=y.target.value;c(S);const O=y.target.selectionStart,F=S.slice(0,O),K=F.lastIndexOf(`
|
|
38
|
+
`),G=F.slice(K+1).match(/^\/([a-zA-Z-]*)$/);if(G)h(!0),v(G[1]),w(0),N(!1);else{h(!1);const Y=F.match(/@([a-zA-Z0-9_.\-/]*)$/);if(Y){const H=Y[1],W=H.lastIndexOf("/"),Q=W>=0?H.slice(0,W+1):"",de=W>=0?H.slice(W+1):H;C(de),x(0),z(Q),N(!0)}else N(!1)}},[]),et=d.useCallback(y=>{if(m&&_.length>0){if(y.key==="ArrowDown"){y.preventDefault(),w(S=>(S+1)%_.length);return}if(y.key==="ArrowUp"){y.preventDefault(),w(S=>(S-1+_.length)%_.length);return}if(y.key==="Enter"||y.key==="Tab"){y.preventDefault(),le(_[T].cmd);return}if(y.key==="Escape"){y.preventDefault(),h(!1);return}}if(E&&$.length>0){if(y.key==="ArrowDown"){y.preventDefault(),x(S=>(S+1)%$.length);return}if(y.key==="ArrowUp"){y.preventDefault(),x(S=>(S-1+$.length)%$.length);return}if(y.key==="Tab"||y.key==="Enter"){y.preventDefault(),ce($[I]);return}if(y.key==="Escape"){y.preventDefault(),N(!1);return}}if(y.key==="Tab"){y.preventDefault();const S=f.current;if(S){const O=S.selectionStart,F=S.selectionEnd,K=i.slice(0,O)+" "+i.slice(F);c(K);const Z=O+2;requestAnimationFrame(()=>{S.selectionStart=S.selectionEnd=Z})}return}y.key==="Enter"&&(y.ctrlKey||y.metaKey)&&(y.preventDefault(),J())},[J,m,_,T,le,i,E,$,I,ce]);return s.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",backgroundColor:"#1a1b26",overflow:"hidden"},children:[m&&_.length>0&&s.jsx("div",{className:"slash-dropdown",children:_.map((y,S)=>s.jsxs("div",{className:`slash-item${S===T?" slash-item--active":""}`,onMouseDown:O=>{O.preventDefault(),le(y.cmd)},onMouseEnter:()=>w(S),children:[s.jsx("span",{className:"slash-cmd",children:y.cmd}),s.jsx("span",{className:"slash-desc",children:y.desc})]},y.cmd))}),E&&(A||$.length>0)&&s.jsx("div",{className:"file-dropdown",ref:j,children:A?s.jsx("div",{className:"file-item file-loading",children:"Loading..."}):$.map((y,S)=>s.jsxs("div",{className:`file-item${S===I?" file-item--active":""}`,onMouseDown:O=>{O.preventDefault(),ce(y)},onMouseEnter:()=>x(S),children:[s.jsx("span",{className:"file-icon",children:y.type==="directory"?"📁":"📄"}),s.jsx("span",{className:"file-name",children:y.name})]},y.name))}),s.jsx("textarea",{ref:f,className:"md-editor-textarea",value:i,onChange:Qe,onKeyDown:et,placeholder:"Type / for commands, @ for files, Ctrl+Enter to send",spellCheck:!1,style:{flex:1,fontSize:`${l}px`}})]})}),Sn=new Set([".md",".html",".htm",".pdf"]);function Tn(t){const e=t.lastIndexOf(".");return e===-1?!1:Sn.has(t.slice(e).toLowerCase())}function kn(t){const e=t.slice(t.lastIndexOf(".")).toLowerCase();return e===".pdf"?"📕":e===".html"||e===".htm"?"🌐":"📝"}const Cn=t=>t.filter(e=>e.type==="directory"||Tn(e.name));function In({sessionId:t,onSelect:e,onClose:o}){const n=d.useCallback(Cn,[]),{cwd:r,files:a,loading:l,error:i,handleNavigate:c,handleGoUp:f,handleRefresh:p}=be({sessionId:t,onClose:o,filter:n}),u=m=>{e(r+"/"+m)};return s.jsxs("div",{style:{position:"absolute",inset:0,zIndex:5,backgroundColor:"#1a1b26",display:"flex",flexDirection:"column",fontFamily:"inherit"},children:[s.jsx(ye,{cwd:r,onGoUp:f,onRefresh:p,onClose:o}),s.jsxs("div",{style:{flex:1,overflow:"auto",padding:"4px 0"},children:[s.jsx(ge,{loading:l,error:i,empty:a.length===0,emptyText:"No documents found"}),!l&&!i&&a.map(m=>s.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"3px 12px",fontSize:13,cursor:"pointer",borderBottom:"1px solid #1e2030"},onMouseEnter:h=>{h.currentTarget.style.backgroundColor="#24283b"},onMouseLeave:h=>{h.currentTarget.style.backgroundColor="transparent"},onClick:()=>{m.type==="directory"?c(m.name):u(m.name)},children:[s.jsx("span",{style:{width:20,flexShrink:0,marginRight:6,color:m.type==="directory"?"#7aa2f7":"#565f89"},children:m.type==="directory"?"📁":kn(m.name)}),s.jsx("span",{style:{flex:1,color:m.type==="directory"?"#7aa2f7":"#a9b1d6",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0},children:m.name}),m.type==="file"&&s.jsx("span",{style:{fontSize:10,color:"#565f89",background:"#24283b",padding:"1px 5px",borderRadius:3,marginLeft:6,flexShrink:0},children:m.name.slice(m.name.lastIndexOf(".")).toLowerCase()})]},m.name))]})]})}const jn="modulepreload",En=function(t){return"/"+t},De={},Rn=function(e,o,n){let r=Promise.resolve();if(o&&o.length>0){document.getElementsByTagName("link");const l=document.querySelector("meta[property=csp-nonce]"),i=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));r=Promise.allSettled(o.map(c=>{if(c=En(c),c in De)return;De[c]=!0;const f=c.endsWith(".css"),p=f?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${p}`))return;const u=document.createElement("link");if(u.rel=f?"stylesheet":jn,f||(u.as="script"),u.crossOrigin="",u.href=c,i&&u.setAttribute("nonce",i),document.head.appendChild(u),f)return new Promise((m,h)=>{u.addEventListener("load",m),u.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${c}`)))})}))}function a(l){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=l,window.dispatchEvent(i),!i.defaultPrevented)throw l}return r.then(l=>{for(const i of l||[])i.status==="rejected"&&a(i.reason);return e().catch(a)})};let he=null;const zn=Rn(()=>import("./pdf-Tk4_4Bu3.js"),[]).then(t=>(he=t,t.GlobalWorkerOptions.workerSrc=new URL("/assets/pdf.worker-BA9kU3Pw.mjs",import.meta.url).toString(),t));function Ln({data:t,scrollRef:e}){const o=d.useRef(null),[n,r]=d.useState(null),[a,l]=d.useState(!0),i=d.useRef(0),c=f=>{o.current=f,e==null||e(f)};return d.useEffect(()=>{if(!t)return;const f=++i.current;return l(!0),r(null),(async()=>{try{if(await zn,!he||f!==i.current)return;const p=atob(t),u=new Uint8Array(p.length);for(let v=0;v<p.length;v++)u[v]=p.charCodeAt(v);const m=await he.getDocument({data:u}).promise;if(f!==i.current)return;const h=o.current;if(!h)return;for(;h.firstChild;)h.removeChild(h.firstChild);const b=h.clientWidth-24;for(let v=1;v<=m.numPages;v++){const T=await m.getPage(v);if(f!==i.current)return;const w=T.getViewport({scale:1}),E=Math.min(b/w.width,2),N=T.getViewport({scale:E}),g=document.createElement("canvas");g.width=N.width,g.height=N.height,g.style.display="block",g.style.margin="0 auto 8px",g.style.maxWidth="100%";const C=g.getContext("2d");if(C){if(await T.render({canvasContext:C,viewport:N,canvas:g}).promise,f!==i.current)return;h.appendChild(g)}}l(!1)}catch(p){if(f!==i.current)return;r(p instanceof Error?p.message:"Failed to render PDF"),l(!1)}})(),()=>{i.current++}},[t]),s.jsxs("div",{ref:c,className:"pdf-renderer",children:[a&&s.jsx("div",{style:{padding:"20px",textAlign:"center",color:"#565f89",fontSize:13},children:"Loading PDF..."}),n&&s.jsxs("div",{style:{padding:"12px",color:"#f7768e",fontSize:12},children:["PDF Error: ",n]})]})}async function Ne(t,e,o,n){const r=new URLSearchParams({path:o});n&&r.set("since",String(n));const a=await fetch(`${V}/api/sessions/${encodeURIComponent(e)}/file-content?${r}`,{headers:q(t)});if(a.status===304)return null;if(!a.ok)throw new Error("Failed to fetch file content");return a.json()}function Dn(t=50,e=20,o=80){const[n,r]=d.useState(t),a=d.useRef(null),l=d.useCallback(i=>{i.preventDefault();const c=a.current;if(!c)return;const f=c.getBoundingClientRect(),p=f.width;document.body.classList.add("resizing-panes-h");let u=null;const m=b=>{u||(u=requestAnimationFrame(()=>{u=null;const v=b.clientX-f.left,T=Math.min(o,Math.max(e,v/p*100));r(T)}))},h=()=>{u&&cancelAnimationFrame(u),document.body.classList.remove("resizing-panes-h"),document.removeEventListener("mousemove",m),document.removeEventListener("mouseup",h)};document.addEventListener("mousemove",m),document.addEventListener("mouseup",h)},[e,o]);return{leftWidthPercent:n,containerRef:a,onDividerMouseDown:l}}const Nn=3e3;function Mn(t){const e=t.slice(t.lastIndexOf(".")).toLowerCase();return e===".md"?"md":e===".html"||e===".htm"?"html":e===".pdf"?"pdf":null}function Me(t){return t.split("/").pop()||t}const On=new Set([".md",".html",".htm",".pdf"]);function _n(t){if(t.type==="directory")return!0;const e=t.name.lastIndexOf(".");return e===-1?!1:On.has(t.name.slice(e).toLowerCase())}function An(t){if(t.type==="directory")return"📁";const e=t.name.slice(t.name.lastIndexOf(".")).toLowerCase();return e===".pdf"?"📕":e===".html"||e===".htm"?"🌐":"📝"}const $n=t=>t.filter(_n);function Pn({sessionId:t,onSelect:e}){const o=d.useCallback(()=>{},[]),n=d.useCallback($n,[]),{cwd:r,files:a,loading:l,error:i,handleNavigate:c,handleGoUp:f,handleRefresh:p}=be({sessionId:t,onClose:o,filter:n});return s.jsxs("div",{style:{height:"100%",display:"flex",flexDirection:"column",overflow:"hidden"},children:[s.jsx(ye,{cwd:r,onGoUp:f,onRefresh:p,onClose:o}),s.jsxs("div",{style:{flex:1,overflow:"auto",padding:"4px 0"},children:[s.jsx(ge,{loading:l,error:i,empty:a.length===0,emptyText:"No documents found"}),!l&&!i&&a.map(u=>s.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"3px 12px",fontSize:13,cursor:"pointer",borderBottom:"1px solid #1e2030"},onMouseEnter:m=>{m.currentTarget.style.backgroundColor="#24283b"},onMouseLeave:m=>{m.currentTarget.style.backgroundColor="transparent"},onClick:()=>{u.type==="directory"?c(u.name):e(r+"/"+u.name)},children:[s.jsx("span",{style:{width:20,flexShrink:0,marginRight:6,color:u.type==="directory"?"#7aa2f7":"#565f89"},children:An(u)}),s.jsx("span",{style:{flex:1,color:u.type==="directory"?"#7aa2f7":"#a9b1d6",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0},children:u.name}),u.type==="file"&&s.jsx("span",{style:{fontSize:10,color:"#565f89",background:"#24283b",padding:"1px 5px",borderRadius:3,marginLeft:6,flexShrink:0},children:u.name.slice(u.name.lastIndexOf(".")).toLowerCase()})]},u.name))]})]})}function Fn({sessionId:t,token:e,onClose:o,onSend:n}){const[r,a]=d.useState(null),[l,i]=d.useState(""),[c,f]=d.useState(null),p=d.useRef(0),[u,m]=d.useState(!1),[h,b]=d.useState(!1),[v,T]=d.useState(!1),{leftWidthPercent:w,containerRef:E,onDividerMouseDown:N}=Dn(50),g=d.useRef(null),[C,D]=d.useState(!1),z=d.useRef(new Map),I=d.useRef(null),x=d.useRef(null),R=d.useCallback(()=>{if(!r)return;const j=h?x.current:I.current;j&&z.current.set(r,j.scrollTop)},[r,h]),L=d.useCallback(j=>{const _=z.current.get(j);_!=null&&requestAnimationFrame(()=>{const $=h?x.current:I.current;$&&($.scrollTop=_)})},[h]),A=d.useCallback(j=>{R();const _=Mn(j);a(j),f(_),i(""),p.current=0,m(!1),Ne(e,t,j).then($=>{$&&(i($.content),p.current=$.mtime,requestAnimationFrame(()=>L(j)))}).catch(()=>{})},[e,t,R,L]);d.useEffect(()=>{if(!r)return;let j=!1;const $=setInterval(async()=>{if(!j)try{const J=await Ne(e,t,r,p.current);if(j)return;J&&(i(J.content),p.current=J.mtime)}catch{}},Nn);return()=>{j=!0,clearInterval($)}},[e,t,r]);const P=d.useCallback(()=>{r&&navigator.clipboard.writeText(r).then(()=>{T(!0),setTimeout(()=>T(!1),1500)}).catch(()=>{})},[r]);d.useEffect(()=>{if(!h)return;const j=_=>{_.key==="Escape"&&(R(),b(!1))};return document.addEventListener("keydown",j),()=>document.removeEventListener("keydown",j)},[h,R]),d.useEffect(()=>{r&&L(r)},[h,r,L]);const M=j=>!r||!c?s.jsx(Pn,{sessionId:t,onSelect:A}):!l&&c!=="pdf"?s.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",color:"#565f89",fontSize:"13px"},children:"Loading..."}):c==="md"?s.jsx("div",{ref:j,style:{height:"100%",overflow:"auto"},children:s.jsx(gn,{content:l})}):c==="html"?s.jsx("div",{ref:j,style:{height:"100%",overflow:"auto"},children:s.jsx("iframe",{srcDoc:l,sandbox:"allow-same-origin",style:{width:"100%",height:"100%",border:"none",backgroundColor:"#fff"},title:"HTML Preview"})}):c==="pdf"?s.jsx(Ln,{data:l,scrollRef:j}):null;return s.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",backgroundColor:"#1a1b26",overflow:"hidden"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",height:"28px",flexShrink:0,backgroundColor:"#16161e",borderBottom:"1px solid #292e42"},children:[s.jsxs("div",{style:{width:`${w}%`,flexShrink:0,display:"flex",alignItems:"center",gap:"4px",padding:"0 8px",minWidth:0},children:[s.jsx("button",{className:"pane-btn",onClick:()=>m(j=>!j),title:"Open document",style:{color:"#7aa2f7"},children:"Open"}),r&&s.jsxs(s.Fragment,{children:[s.jsx("span",{style:{fontSize:"11px",color:"#565f89",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0,cursor:"pointer"},onClick:P,title:v?"Copied!":`Click to copy: ${r}`,children:v?"Copied!":Me(r)}),s.jsx("button",{className:"pane-btn",onClick:()=>{R(),b(!0)},title:"Expand document view",style:{fontSize:"12px"},children:"⛶"})]})]}),s.jsx("div",{style:{width:"4px",flexShrink:0}}),s.jsxs("div",{style:{flex:1,display:"flex",alignItems:"center",justifyContent:"space-between",padding:"0 8px",minWidth:0},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[s.jsx("button",{className:"pane-btn",onClick:()=>{var j;return(j=g.current)==null?void 0:j.send()},disabled:!C,title:"Send to terminal (Ctrl+Enter)",style:C?{color:"#9ece6a"}:{opacity:.4,cursor:"default"},children:"Send"}),s.jsx("span",{style:{fontSize:"10px",color:"#414868"},children:"Ctrl+Enter"})]}),s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:o,title:"Close Doc panel",children:"×"})]})]}),s.jsxs("div",{ref:E,className:"plan-panel-body",style:{position:"relative"},children:[s.jsxs("div",{className:"plan-renderer",style:{width:`${w}%`,flexShrink:0},children:[M(j=>{I.current=j}),u&&s.jsx(In,{sessionId:t,onSelect:A,onClose:()=>m(!1)})]}),s.jsx("div",{className:"plan-divider-h",onMouseDown:N}),s.jsx("div",{className:"plan-editor-wrap",children:s.jsx(vn,{ref:g,onSend:n,onContentChange:D,sessionId:t,token:e})})]}),h&&s.jsxs("div",{className:"doc-expanded-overlay",children:[s.jsxs("div",{className:"doc-expanded-header",children:[s.jsx("span",{style:{fontSize:"12px",color:"#a9b1d6",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:r?Me(r):""}),s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:()=>{R(),b(!1)},title:"Close expanded view (ESC)",children:"×"})]}),s.jsx("div",{style:{flex:1,overflow:"hidden"},children:M(j=>{x.current=j})})]})]})}const Wn=100,Bn=600;function Un(){return d.useSyncExternalStore(t=>(window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)),()=>window.innerWidth)}const Hn=d.memo(function({terminal:e,canClose:o}){const r=Un()<Bn,a=k(x=>x.killServerSession),l=k(x=>x.splitTerminal),i=k(x=>x.token),c=d.useRef(null),f=d.useRef(null),[p,u]=d.useState(!1),[m,h]=d.useState(!1),[b,v]=d.useState(0),[T,w]=d.useState(!1),[E,N]=d.useState(50),g=d.useRef(null),C=async x=>{const R=x.target.files;if(!(!R||R.length===0||!i)){h(!0),v(0);try{await hn(i,e.id,R,L=>{v(L)})}catch(L){alert(`Upload failed: ${L instanceof Error?L.message:"Unknown error"}`)}finally{h(!1),v(0),c.current&&(c.current.value="")}}},D=d.useRef(),z=d.useCallback(x=>{if(f.current){const R=x.replace(/\r?\n/g," ").trimEnd();f.current.sendInput(R),D.current=window.setTimeout(()=>{var L;return(L=f.current)==null?void 0:L.sendInput("\r")},50)}},[]);d.useEffect(()=>()=>{D.current&&clearTimeout(D.current)},[]);const I=d.useCallback(x=>{x.preventDefault();const R=g.current;if(!R)return;const L=R.getBoundingClientRect(),A=L.height;document.body.classList.add("resizing-panes-v");const P=j=>{const _=(j.clientY-L.top)/A*100,$=Math.min(80,Math.max(20,_));N(100-$)},M=()=>{document.body.classList.remove("resizing-panes-v"),document.removeEventListener("mousemove",P),document.removeEventListener("mouseup",M)};document.addEventListener("mousemove",P),document.addEventListener("mouseup",M)},[]);return s.jsxs("div",{ref:g,style:{display:"flex",flexDirection:"column",height:"100%",minWidth:0,minHeight:0},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"2px 8px",backgroundColor:"#16161e",borderBottom:"1px solid #292e42",flexShrink:0,height:"24px"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[s.jsx("span",{style:{display:"inline-block",width:"6px",height:"6px",borderRadius:"50%",backgroundColor:e.connected?"#9ece6a":"#f7768e"}}),s.jsxs("span",{style:{fontSize:"11px",color:"#565f89"},children:[e.id,e.connected?e.sessionResumed?" (resumed)":"":" (disconnected)"]})]}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"4px"},children:[s.jsx("input",{ref:c,type:"file",multiple:!0,style:{display:"none"},onChange:C}),s.jsx("button",{className:"pane-btn",onClick:()=>{var x;return(x=c.current)==null?void 0:x.click()},disabled:m,style:m?{color:"#e0af68"}:void 0,title:m?`Uploading ${b}%`:"Upload files","aria-label":"Upload files",children:m?`${b}%`:"↑"}),s.jsx("button",{className:"pane-btn",onClick:()=>u(x=>!x),style:p?{color:"#7aa2f7"}:void 0,title:"Browse files","aria-label":"Browse files",children:"↓"}),s.jsx("button",{className:`pane-btn${T?" pane-btn--active":""}`,onClick:()=>w(x=>!x),title:"Toggle Document browser","aria-label":"Toggle Document browser",children:"Doc"}),s.jsx("button",{className:"pane-btn",onClick:()=>l(e.id,r?"vertical":"horizontal"),title:r?"Split vertical (screen too narrow for horizontal)":"Split horizontal (left/right)","aria-label":"Split horizontal",children:"|"}),s.jsx("button",{className:"pane-btn",onClick:()=>l(e.id,"vertical"),title:"Split vertical (top/bottom)","aria-label":"Split vertical",children:"─"}),o&&s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:()=>a(e.id),title:"Close terminal","aria-label":"Close terminal",children:"×"})]})]}),s.jsxs("div",{style:{flex:1,overflow:"hidden",position:"relative",minHeight:"80px"},children:[s.jsx(pn,{ref:f,sessionId:e.id}),!e.connected&&s.jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"rgba(26, 27, 38, 0.85)",zIndex:2,pointerEvents:"none"},children:s.jsx("span",{style:{color:"#565f89",fontSize:"13px",fontStyle:"italic"},children:"Connecting..."})}),p&&s.jsx(yn,{sessionId:e.id,onClose:()=>u(!1)})]}),T&&s.jsxs(s.Fragment,{children:[s.jsx("div",{className:"md-editor-divider",onMouseDown:I}),s.jsx("div",{style:{height:`${E}%`,minHeight:Wn,flexShrink:0,overflow:"hidden"},children:s.jsx(Fn,{onSend:z,onClose:()=>w(!1),sessionId:e.id,token:i||""})})]}),e.error&&s.jsx("div",{style:{padding:"2px 8px",backgroundColor:"#3b2029",borderTop:"1px solid #f7768e",color:"#f7768e",fontSize:"11px",flexShrink:0},children:e.error})]})});class Je extends d.Component{constructor(){super(...arguments);we(this,"state",{hasError:!1,error:null})}static getDerivedStateFromError(o){return{hasError:!0,error:o}}componentDidCatch(o,n){}render(){var o,n;return this.state.hasError?this.props.inline?s.jsxs("div",{style:{height:"100%",backgroundColor:"#1a1b26",display:"flex",alignItems:"center",justifyContent:"center",flexDirection:"column",gap:"8px",color:"#c0caf5",fontFamily:"monospace",padding:"16px"},children:[s.jsx("div",{style:{fontSize:"14px",color:"#f7768e"},children:"Pane crashed"}),s.jsx("div",{style:{fontSize:"12px",color:"#565f89",textAlign:"center"},children:((o=this.state.error)==null?void 0:o.message)||"An unexpected error occurred"}),s.jsx("button",{onClick:()=>this.setState({hasError:!1,error:null}),style:{background:"#292e42",border:"1px solid #414868",color:"#c0caf5",padding:"4px 12px",borderRadius:"4px",cursor:"pointer",fontSize:"12px"},children:"Retry"})]}):s.jsxs("div",{style:{minHeight:"100vh",backgroundColor:"#1a1b26",display:"flex",alignItems:"center",justifyContent:"center",flexDirection:"column",gap:"16px",color:"#c0caf5",fontFamily:"monospace"},children:[s.jsx("div",{style:{fontSize:"18px",color:"#f7768e"},children:"Something went wrong"}),s.jsx("div",{style:{fontSize:"13px",color:"#565f89",maxWidth:"500px",textAlign:"center"},children:((n=this.state.error)==null?void 0:n.message)||"An unexpected error occurred"}),s.jsx("button",{onClick:()=>window.location.reload(),style:{background:"linear-gradient(135deg, #7aa2f7 0%, #bb9af7 100%)",border:"none",color:"#1a1b26",padding:"8px 24px",borderRadius:"6px",cursor:"pointer",fontSize:"14px",fontWeight:"bold"},children:"Reload"})]}):this.props.children}}const Vn=4,Oe=10;function Gn(){const t=k(r=>r.layout),e=k(r=>r.terminalIds.length),o=k(r=>r.addTerminal);if(!t)return s.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%",backgroundColor:"#1a1b26"},children:s.jsx("button",{onClick:()=>o(),style:{background:"none",border:"1px dashed #292e42",color:"#565f89",padding:"16px 32px",borderRadius:"8px",cursor:"pointer",fontSize:"14px"},children:"+ Add Terminal"})});const n=e>1;return s.jsx("div",{style:{height:"100%",width:"100%",overflow:"hidden"},children:s.jsx(Xe,{node:t,canClose:n})})}const Xe=d.memo(function({node:e,canClose:o}){return e.type==="leaf"?s.jsx(qn,{terminalId:e.terminalId,canClose:o}):s.jsx(Kn,{node:e,canClose:o})}),qn=d.memo(function({terminalId:e,canClose:o}){const n=k(r=>r.terminalsMap[e]);return n?s.jsx(Je,{inline:!0,children:s.jsx(Hn,{terminal:n,canClose:o})}):null}),Kn=d.memo(function({node:e,canClose:o}){const n=k(f=>f.setSplitSizes),r=d.useRef(null),a=e.direction==="horizontal",l=d.useRef(e.sizes);l.current=e.sizes;const i=d.useCallback((f,p)=>{p.preventDefault();const u=a?"resizing-panes":"resizing-panes-v";document.body.classList.add(u);const m=a?p.clientX:p.clientY,h=[...l.current],b=r.current,v=a?(b==null?void 0:b.clientWidth)||1:(b==null?void 0:b.clientHeight)||1;let T=null;const w=N=>{T||(T=requestAnimationFrame(()=>{T=null;const D=((a?N.clientX:N.clientY)-m)/v*100,z=h[f]+D,I=h[f+1]-D;if(z>=Oe&&I>=Oe){const x=[...h];x[f]=z,x[f+1]=I,n(e.id,x)}}))},E=()=>{T&&cancelAnimationFrame(T),document.body.classList.remove(u),document.removeEventListener("mousemove",w),document.removeEventListener("mouseup",E)};document.addEventListener("mousemove",w),document.addEventListener("mouseup",E)},[a,e.id,n]),c=[];return e.children.forEach((f,p)=>{const u=f.type==="leaf"?f.terminalId:f.id;c.push(s.jsx("div",{style:{flex:`${e.sizes[p]} 0 0`,minWidth:0,minHeight:0,overflow:"hidden"},children:s.jsx(Xe,{node:f,canClose:o})},u)),p<e.children.length-1&&c.push(s.jsx("div",{onMouseDown:m=>i(p,m),style:{flex:`0 0 ${Vn}px`,cursor:a?"col-resize":"row-resize",backgroundColor:"#292e42",transition:"background-color 0.15s"},onMouseEnter:m=>{m.currentTarget.style.backgroundColor="#7aa2f7"},onMouseLeave:m=>{m.currentTarget.style.backgroundColor="#292e42"}},`divider-${e.id}-${p}`))}),s.jsx("div",{ref:r,style:{display:"flex",flexDirection:a?"row":"column",height:"100%",width:"100%",overflow:"hidden"},children:c})});function Yn({tabId:t}){const e=k(x=>x.tabs.find(R=>R.id===t)),o=k(x=>x.activeTabId),n=k(x=>x.switchTab),r=k(x=>x.closeTab),a=k(x=>x.reopenTab),l=k(x=>x.deleteTab),i=k(x=>x.renameTab),c=k(x=>e?e.terminalIds.map(R=>{const L=x.terminalsMap[R];return L?{id:R,connected:L.connected}:{id:R,connected:!1}}):[]),[f,p]=d.useState(!1),[u,m]=d.useState(""),[h,b]=d.useState(!1),v=d.useRef(null);if(!e)return null;const T=o===t,w=e.status==="open",E=()=>{w&&n(t)},N=x=>{w&&(x.stopPropagation(),m(e.name),p(!0),setTimeout(()=>{var R;return(R=v.current)==null?void 0:R.focus()},0))},g=()=>{const x=u.trim();x&&i(t,x),p(!1)},C=x=>{x.stopPropagation(),a(t)},D=x=>{x.stopPropagation(),r(t)},z=async x=>{x.stopPropagation(),window.confirm(`Delete tab "${e.name}"? This will kill all tmux sessions in this tab.`)&&await l(t)},I=x=>{x.stopPropagation(),b(!h)};return s.jsxs("div",{children:[s.jsxs("div",{onClick:E,style:{padding:"8px 12px",cursor:w?"pointer":"default",borderLeft:T?"3px solid #7aa2f7":"3px solid transparent",backgroundColor:T?"rgba(122, 162, 247, 0.08)":"transparent",display:"flex",alignItems:"center",gap:"8px",borderBottom:"1px solid #292e42",transition:"background-color 0.15s",opacity:w?1:.5},onMouseEnter:x=>{w&&!T&&(x.currentTarget.style.backgroundColor="rgba(122, 162, 247, 0.05)")},onMouseLeave:x=>{T||(x.currentTarget.style.backgroundColor="transparent")},children:[w&&e.terminalIds.length>0&&s.jsx("button",{onClick:I,style:{background:"none",border:"none",color:"#565f89",cursor:"pointer",fontSize:"10px",padding:0,width:14,height:14,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0},children:h?"▼":"▶"}),s.jsxs("div",{style:{flex:1,minWidth:0},children:[f?s.jsx("input",{ref:v,value:u,onChange:x=>m(x.target.value),onBlur:g,onKeyDown:x=>{x.key==="Enter"&&g(),x.key==="Escape"&&p(!1)},style:{width:"100%",background:"#1a1b26",border:"1px solid #7aa2f7",color:"#c0caf5",borderRadius:"3px",padding:"1px 4px",fontSize:"13px",outline:"none"}}):s.jsx("div",{onDoubleClick:N,style:{color:"#c0caf5",fontSize:"13px",fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:w?"Double-click to rename":e.name,children:e.name}),s.jsxs("div",{style:{color:"#565f89",fontSize:"11px",marginTop:"2px"},children:[e.terminalIds.length," terminal",e.terminalIds.length!==1?"s":""," · ",Ye(Math.floor(e.createdAt/1e3))]})]}),w?s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:D,style:{flexShrink:0},title:"Close tab",children:"×"}):s.jsxs("div",{style:{display:"flex",gap:"4px",flexShrink:0},children:[s.jsx("button",{className:"pane-btn",onClick:C,title:"Reopen tab",style:{fontSize:"11px",padding:"2px 6px"},children:"↻"}),s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:z,title:"Delete tab",children:"×"})]})]}),w&&h&&c.length>0&&s.jsx("div",{style:{paddingLeft:"28px",backgroundColor:"rgba(0, 0, 0, 0.2)"},children:c.map(x=>s.jsxs("div",{style:{padding:"4px 8px",fontSize:"11px",color:"#565f89",borderBottom:"1px solid rgba(41, 46, 66, 0.5)"},title:`Connected: ${x.connected}`,children:[s.jsx("span",{style:{fontFamily:"monospace"},children:x.id}),s.jsx("span",{style:{marginLeft:"8px",color:x.connected?"#9ece6a":"#f7768e"},children:x.connected?"●":"○"})]},x.id))})]})}function Jn({sessionId:t,active:e,createdAt:o}){const n=k(i=>i.addTerminal),r=k(i=>i.killServerSession),a=()=>{n("horizontal",t)},l=i=>{i.stopPropagation(),window.confirm(`Delete orphaned session "${t}"? This will kill the tmux session.`)&&r(t)};return s.jsxs("div",{onClick:a,style:{padding:"8px 12px",cursor:"pointer",display:"flex",alignItems:"center",gap:"8px",borderBottom:"1px solid #292e42",transition:"background-color 0.15s"},onMouseEnter:i=>{i.currentTarget.style.backgroundColor="rgba(122, 162, 247, 0.05)"},onMouseLeave:i=>{i.currentTarget.style.backgroundColor="transparent"},children:[s.jsx("span",{style:{width:8,height:8,borderRadius:"50%",backgroundColor:e?"#9ece6a":"#565f89",flexShrink:0}}),s.jsxs("div",{style:{flex:1,minWidth:0},children:[s.jsx("div",{style:{color:"#c0caf5",fontSize:"13px",fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t}),s.jsx("div",{style:{color:"#565f89",fontSize:"11px",marginTop:"2px"},children:Ye(o)})]}),s.jsx("button",{className:"pane-btn pane-btn--danger",onClick:l,style:{flexShrink:0},title:"Delete session",children:"×"})]})}function Xn(){const t=k(c=>c.sidebarOpen),e=k(c=>c.toggleSidebar),o=k(c=>c.serverSessions),n=k(c=>c.fetchSessions),r=k(c=>c.tabs),a=k(c=>c.terminalIds),l=new Set(r.flatMap(c=>c.terminalIds)),i=o.filter(c=>!l.has(c.sessionId));return d.useEffect(()=>{if(!t)return;n();let c=setInterval(n,5e3);const f=()=>{document.hidden?c&&(clearInterval(c),c=null):(n(),c||(c=setInterval(n,5e3)))};return document.addEventListener("visibilitychange",f),()=>{c&&clearInterval(c),document.removeEventListener("visibilitychange",f)}},[t,n]),d.useEffect(()=>{if(!t)return;const c=setTimeout(n,800);return()=>clearTimeout(c)},[a.length,t,n]),s.jsxs("div",{className:"session-sidebar",style:{width:t?280:0,height:"100%",backgroundColor:"#16161e",borderLeft:t?"1px solid #292e42":"none",display:"flex",flexDirection:"column",flexShrink:0,overflow:"hidden",transition:"width 0.2s ease"},children:[s.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",borderBottom:"1px solid #292e42",flexShrink:0},children:[s.jsx("span",{style:{color:"#7aa2f7",fontSize:"14px",fontWeight:"bold"},children:"Tabs & Sessions"}),s.jsx("button",{onClick:e,style:{background:"none",border:"none",color:"#565f89",cursor:"pointer",fontSize:"16px",padding:"0 4px",lineHeight:1},title:"Close sidebar",children:"×"})]}),s.jsxs("div",{style:{flex:1,overflowY:"auto"},children:[s.jsxs("div",{children:[s.jsx("div",{style:{padding:"8px 12px",color:"#7aa2f7",fontSize:"12px",fontWeight:"bold",backgroundColor:"rgba(122, 162, 247, 0.05)",borderBottom:"1px solid #292e42"},children:"TABS"}),r.length===0?s.jsx("div",{style:{color:"#565f89",fontSize:"13px",textAlign:"center",padding:"12px"},children:"No tabs"}):r.map(c=>s.jsx(Yn,{tabId:c.id},c.id))]}),i.length>0&&s.jsxs("div",{style:{marginTop:"16px"},children:[s.jsx("div",{style:{padding:"8px 12px",color:"#e0af68",fontSize:"12px",fontWeight:"bold",backgroundColor:"rgba(224, 175, 104, 0.05)",borderBottom:"1px solid #292e42"},children:"ORPHANED SESSIONS"}),i.map(c=>s.jsx(Jn,{sessionId:c.sessionId,active:c.active,createdAt:c.createdAt},c.sessionId))]})]})]})}const Ze=xe.memo(()=>{const t=k(g=>g.tabs),e=k(g=>g.activeTabId),o=k(g=>g.addTab),n=k(g=>g.switchTab),r=k(g=>g.closeTab),a=k(g=>g.renameTab),[l,i]=d.useState(null),[c,f]=d.useState(""),p=d.useRef(null),u=t.filter(g=>g.status==="open");d.useEffect(()=>{l&&p.current&&(p.current.focus(),p.current.select())},[l]);const m=g=>{i(g.id),f(g.name)},h=()=>{l&&c.trim()&&a(l,c.trim()),i(null),f("")},b=()=>{i(null),f("")},v=g=>{g.key==="Enter"?h():g.key==="Escape"&&b()},T=g=>{l||n(g)},w=(g,C)=>{g.stopPropagation(),r(C)},E=(g,C)=>{g.button===1&&(g.preventDefault(),r(C))},N=u.length>1;return s.jsxs("div",{className:"tab-bar",children:[u.map(g=>{const C=g.id===e,D=l===g.id,z=g.terminalIds.length;return s.jsx("div",{className:`tab-item ${C?"tab-item--active":""}`,onClick:()=>T(g.id),onDoubleClick:()=>m(g),onMouseDown:I=>E(I,g.id),children:D?s.jsx("input",{ref:p,type:"text",value:c,onChange:I=>f(I.target.value),onBlur:h,onKeyDown:v,className:"tab-item__rename-input"}):s.jsxs(s.Fragment,{children:[s.jsxs("span",{className:"tab-item__name",children:[g.name," ",z>0&&`(${z})`]}),N&&s.jsx("button",{className:"tab-item__close",onClick:I=>w(I,g.id),title:"Close tab","aria-label":"Close tab",children:"×"})]})},g.id)}),s.jsx("button",{className:"tab-bar-add",onClick:()=>o(),title:"New tab","aria-label":"Add new tab",children:"+"})]})});Ze.displayName="TabBar";function Zn(){return localStorage.getItem("ai-cli-online-token")}function Qn(){const t=k(i=>i.token),e=k(i=>i.setToken),o=k(i=>i.tabs),n=k(i=>i.addTab),r=k(i=>i.toggleSidebar),a=k(i=>i.fontSize),l=k(i=>i.setFontSize);return d.useEffect(()=>{const i=Zn();i&&!t&&e(i)},[]),d.useEffect(()=>{t&&o.filter(i=>i.status==="open").length===0&&n("Default")},[t]),t?s.jsxs("div",{style:{height:"100vh",display:"flex",flexDirection:"column",backgroundColor:"#1a1b26"},children:[s.jsxs("header",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"6px 16px",backgroundColor:"#16161e",borderBottom:"1px solid #292e42",flexShrink:0},children:[s.jsx("div",{style:{display:"flex",alignItems:"center",gap:"10px"},children:s.jsx("span",{style:{fontSize:"15px",fontWeight:"bold",color:"#7aa2f7",letterSpacing:"0.5px"},children:"AI-Cli Online"})}),s.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[s.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:"2px",padding:"1px 4px",borderRadius:"6px",backgroundColor:"rgba(0,0,0,0.2)"},children:[s.jsx("button",{className:"header-btn",onClick:()=>l(a-1),disabled:a<=10,title:"Decrease font size",style:{fontSize:"11px",padding:"1px 5px",minWidth:0},children:"A−"}),s.jsx("span",{style:{fontSize:"11px",color:"#a9b1d6",minWidth:"20px",textAlign:"center"},children:a}),s.jsx("button",{className:"header-btn",onClick:()=>l(a+1),disabled:a>=24,title:"Increase font size",style:{fontSize:"11px",padding:"1px 5px",minWidth:0},children:"A+"})]}),s.jsx(tr,{}),s.jsx("button",{className:"header-btn",onClick:r,title:"Toggle Tabs & Sessions Sidebar","aria-label":"Toggle sidebar",children:"☰"}),s.jsx("button",{className:"header-btn header-btn--muted",onClick:()=>{window.confirm("Logout will close all terminals. Continue?")&&e(null)},children:"Logout"})]})]}),s.jsxs("div",{style:{flex:1,display:"flex",overflow:"hidden"},children:[s.jsx("main",{style:{flex:1,overflow:"hidden"},children:s.jsx(Gn,{})}),s.jsx(Xn,{})]}),s.jsx(Ze,{})]}):s.jsx(Gt,{})}const er=[1,2,3,4];function tr(){const t=k(n=>n.latency);if(t===null)return s.jsx("span",{style:{fontSize:"10px",color:"#414868"},title:"Measuring latency...",children:"--ms"});let e,o;return t<50?(e="#9ece6a",o=4):t<150?(e="#e0af68",o=3):t<300?(e="#ff9e64",o=2):(e="#f7768e",o=1),s.jsxs("span",{style:{display:"inline-flex",alignItems:"end",gap:"1.5px",padding:"2px 8px",borderRadius:"10px",backgroundColor:"rgba(0,0,0,0.2)"},title:`Latency: ${t}ms`,children:[er.map(n=>s.jsx("span",{style:{display:"inline-block",width:"2.5px",height:`${3+n*2}px`,backgroundColor:n<=o?e:"#292e42",borderRadius:"1px",transition:"background-color 0.3s ease"}},n)),s.jsxs("span",{style:{fontSize:"10px",color:e,marginLeft:"4px",fontWeight:500},children:[t,"ms"]})]})}pe.createRoot(document.getElementById("root")).render(s.jsx(xe.StrictMode,{children:s.jsx(Je,{children:s.jsx(Qn,{})})}));
|