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 CHANGED
@@ -4,12 +4,14 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
5
5
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green.svg)](https://nodejs.org/)
6
6
 
7
- A lightweight web terminal for accessing Claude Code (or any CLI) from your browser via xterm.js + tmux. Especially suited for **unstable network environments where SSH sessions frequently drop** — tmux keeps your processes alive through disconnects, and you can reconnect instantly from any browser. Also works great locally as a **stateful terminal** that preserves sessions, layouts, and editor drafts across browser refreshes.
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
+ ![screenshot](screenshot.jpg)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "AI-Cli Online - Web Terminal for Claude Code via xterm.js + tmux",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -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)
@@ -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<FileEntry[]>;
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.
@@ -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 at 1000 entries to prevent excessive memory/bandwidth usage on huge directories
32
- return results.slice(0, 1000);
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.
@@ -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 on API endpoints
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: 60,
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
- // Close all WebSocket connections
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
- server.close(() => {
447
- try {
448
- closeDb();
449
- }
450
- catch { /* ignore */ }
451
- console.log('[shutdown] Server closed');
452
- process.exit(0);
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');
@@ -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
  }
@@ -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;
@@ -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
- // Ignore malformed messages
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
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online-server",
3
- "version": "2.0.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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cli-online-shared",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Shared types for CLI-Online",
5
5
  "type": "module",
6
6
  "main": "dist/types.js",
@@ -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,{})})}));