{
  "version": 3,
  "sources": ["../src/constants/timeouts.ts", "../src/services/systemd-manager.ts", "../src/cli.ts", "../src/utils/logger.ts", "../src/utils/terminal.ts", "../src/constants/ui-symbols.ts", "../src/utils/icons.ts", "../src/utils/error-formatter.ts", "../src/utils/errors.ts", "../src/constants/error-codes.ts", "../src/constants/exit-codes.ts", "../src/utils/preflight.ts", "../src/constants/paths.ts", "../src/constants/review.ts", "../src/utils/review-id.ts", "../src/services/review/repo-scanner.ts", "../src/utils/repo-scan.ts", "../src/services/review/summary-builder.ts", "../src/services/review/evidence.ts", "../src/services/review/areas/community.ts", "../src/services/review/areas/contribution.ts", "../src/services/review/areas/documentation.ts", "../src/services/review/areas/license.ts", "../src/services/review/areas/quality.ts", "../src/services/review/areas/security.ts", "../src/services/review/review-engine.ts", "../src/services/review/report-renderer.ts", "../src/utils/report-output.ts", "../src/commands/review.ts", "../src/commands/clash.ts", "../src/utils/validator.ts", "../src/utils/vless-link.ts", "../src/services/clash-config.ts", "../src/components/design-system/ThemeProvider.tsx", "../src/components/design-system/theme.ts", "../src/contexts/I18nContext.tsx", "../src/config/i18n.ts", "../src/contexts/ServiceContext.tsx", "../src/services/config-manager.ts", "../src/services/user-manager.ts", "../src/services/public-ip-manager.ts", "../src/constants/supported-distros.ts", "../src/utils/network.ts", "../src/services/user-metadata-manager.ts", "../src/services/quota-manager.ts", "../src/types/quota.ts", "../src/constants/quota.ts", "../src/services/traffic-manager.ts", "../src/services/log-manager.ts", "../src/utils/which.ts", "../src/services/stats-config-manager.ts", "../src/contexts/NavigationContext.tsx", "../src/app/routes.ts", "../src/contexts/NotificationContext.tsx", "../src/app/AppShell.tsx", "../src/components/design-system/Header.tsx", "../src/components/design-system/StatusBar.tsx", "../src/components/design-system/Divider.tsx", "../src/components/Breadcrumb.tsx", "../src/components/Dashboard.tsx", "../src/utils/format.ts", "../src/components/Toast.tsx", "../src/components/CommandPalette.tsx", "../src/screens/MainMenu.tsx", "../src/components/Select.tsx", "../src/components/Spinner.tsx", "../src/components/Confirm.tsx", "../src/screens/ServiceStatus.tsx", "../src/hooks/useServiceStatus.ts", "../src/components/StatusBadge.tsx", "../src/components/KeyValue.tsx", "../src/screens/UserManagement.tsx", "../src/hooks/useUsers.ts", "../src/components/Table.tsx", "../src/screens/UserAdd.tsx", "../src/components/TextInput.tsx", "../src/screens/UserDelete.tsx", "../src/screens/UserShare.tsx", "../src/screens/QuotaManagement.tsx", "../src/hooks/useQuotas.ts", "../src/components/ProgressBar.tsx", "../src/screens/QuotaSet.tsx", "../src/screens/QuotaDetails.tsx", "../src/screens/ConfigManagement.tsx", "../src/screens/LogViewer.tsx", "../src/screens/OnlineUsers.tsx", "../src/hooks/useOnlineUsers.ts", "../src/services/online-manager.ts", "../src/screens/SubscriptionManagement.tsx", "../src/services/subscription-server.ts", "../src/app/Router.tsx", "../src/hooks/useDashboardData.ts", "../src/services/system-monitor.ts", "../src/app/App.tsx"],
  "sourcesContent": ["/**\n * \u8D85\u65F6\u65F6\u95F4\u5E38\u91CF\u5B9A\u4E49\n * @module constants/timeouts\n */\n\n/**\n * \u8D85\u65F6\u914D\u7F6E\uFF08\u5355\u4F4D\uFF1A\u6BEB\u79D2\uFF09\n */\nexport const TIMEOUTS = {\n  /** systemctl \u547D\u4EE4\u9ED8\u8BA4\u8D85\u65F6 */\n  SYSTEMCTL_DEFAULT: 30000, // 30 \u79D2\n\n  /** \u670D\u52A1\u542F\u52A8\u8D85\u65F6 */\n  SERVICE_START: 15000, // 15 \u79D2\n\n  /** \u670D\u52A1\u505C\u6B62\u8D85\u65F6\uFF08\u4F18\u96C5\u5173\u95ED\uFF09 */\n  SERVICE_STOP: 10000, // 10 \u79D2\n\n  /** \u670D\u52A1\u91CD\u542F\u8D85\u65F6 */\n  SERVICE_RESTART: 25000, // 25 \u79D2\n\n  /** \u670D\u52A1\u72B6\u6001\u67E5\u8BE2\u8D85\u65F6 */\n  SERVICE_STATUS: 5000, // 5 \u79D2\n\n  /** \u914D\u7F6E\u6587\u4EF6\u8BFB\u5199\u8D85\u65F6 */\n  CONFIG_IO: 5000, // 5 \u79D2\n\n  /** \u914D\u7F6E\u5907\u4EFD\u64CD\u4F5C\u8D85\u65F6 */\n  CONFIG_BACKUP: 10000, // 10 \u79D2\n\n  /** \u65E5\u5FD7\u67E5\u8BE2\u8D85\u65F6 */\n  LOG_QUERY: 10000, // 10 \u79D2\n\n  /** \u7F51\u7EDC\u64CD\u4F5C\u8D85\u65F6\uFF08\u4E0B\u8F7D\u3001\u68C0\u67E5\u66F4\u65B0\uFF09 */\n  NETWORK: 30000, // 30 \u79D2\n\n  /** \u7528\u6237\u8F93\u5165\u8D85\u65F6\uFF08\u4EA4\u4E92\u5F0F\u83DC\u5355\uFF09 */\n  USER_INPUT: 60000, // 60 \u79D2\n\n  /** \u6587\u4EF6\u7CFB\u7EDF\u64CD\u4F5C\u8D85\u65F6 */\n  FILESYSTEM: 10000, // 10 \u79D2\n\n  /** \u4F18\u96C5\u5173\u95ED\u7B49\u5F85\u65F6\u95F4 */\n  GRACEFUL_SHUTDOWN: 10000, // 10 \u79D2\n\n  /** \u8FDB\u7A0B\u6740\u6B7B\u524D\u7B49\u5F85\u65F6\u95F4 */\n  KILL_WAIT: 2000, // 2 \u79D2\n\n  /** \u83DC\u5355\u5237\u65B0\u95F4\u9694 */\n  MENU_REFRESH: 1000, // 1 \u79D2\n\n  /** \u72B6\u6001\u8F6E\u8BE2\u95F4\u9694 */\n  STATUS_POLL: 500, // 500 \u6BEB\u79D2\n} as const;\n\n/**\n * \u6027\u80FD\u8981\u6C42\uFF08\u7528\u4E8E\u76D1\u63A7\u548C\u6D4B\u8BD5\uFF09\n */\nexport const PERFORMANCE_TARGETS = {\n  /** \u83DC\u5355\u542F\u52A8\u65F6\u95F4\u76EE\u6807 */\n  MENU_STARTUP: 500, // 500ms (SC-003)\n\n  /** \u83DC\u5355\u5BFC\u822A\u54CD\u5E94\u65F6\u95F4\u76EE\u6807 */\n  MENU_NAVIGATION: 100, // 100ms (SC-002)\n\n  /** \u6309\u952E\u54CD\u5E94\u65F6\u95F4\u76EE\u6807 */\n  KEY_RESPONSE: 50, // 50ms (SC-002)\n\n  /** \u670D\u52A1\u91CD\u542F\u4E2D\u65AD\u65F6\u95F4\u76EE\u6807 */\n  SERVICE_DOWNTIME: 10000, // 10s (FR-016)\n} as const;\n\n/**\n * \u91CD\u8BD5\u914D\u7F6E\n */\nexport const RETRY_CONFIG = {\n  /** \u9ED8\u8BA4\u91CD\u8BD5\u6B21\u6570 */\n  DEFAULT_ATTEMPTS: 3,\n\n  /** \u91CD\u8BD5\u95F4\u9694\uFF08\u6BEB\u79D2\uFF09 */\n  RETRY_DELAY: 1000, // 1 \u79D2\n\n  /** \u6307\u6570\u9000\u907F\u57FA\u6570 */\n  BACKOFF_MULTIPLIER: 2,\n\n  /** \u6700\u5927\u91CD\u8BD5\u95F4\u9694 */\n  MAX_RETRY_DELAY: 10000, // 10 \u79D2\n} as const;\n\n/**\n * \u8BA1\u7B97\u6307\u6570\u9000\u907F\u5EF6\u8FDF\n * @param attempt \u5F53\u524D\u5C1D\u8BD5\u6B21\u6570\uFF08\u4ECE 0 \u5F00\u59CB\uFF09\n * @returns \u5EF6\u8FDF\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\n */\nexport function getBackoffDelay(attempt: number): number {\n  const delay = RETRY_CONFIG.RETRY_DELAY * Math.pow(RETRY_CONFIG.BACKOFF_MULTIPLIER, attempt);\n  return Math.min(delay, RETRY_CONFIG.MAX_RETRY_DELAY);\n}\n\n/**\n * \u7761\u7720\u51FD\u6570\uFF08\u7528\u4E8E\u5EF6\u8FDF\uFF09\n * @param ms \u6BEB\u79D2\u6570\n */\nexport function sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * \u5E26\u8D85\u65F6\u7684 Promise\n * @param promise \u539F\u59CB Promise\n * @param timeoutMs \u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\n * @param errorMessage \u8D85\u65F6\u9519\u8BEF\u6D88\u606F\n */\nexport async function withTimeout<T>(\n  promise: Promise<T>,\n  timeoutMs: number,\n  errorMessage = '\u64CD\u4F5C\u8D85\u65F6'\n): Promise<T> {\n  let timeoutId: NodeJS.Timeout;\n\n  const timeoutPromise = new Promise<never>((_, reject) => {\n    timeoutId = setTimeout(() => {\n      reject(new Error(`${errorMessage} (${timeoutMs}ms)`));\n    }, timeoutMs);\n  });\n\n  try {\n    const result = await Promise.race([promise, timeoutPromise]);\n    clearTimeout(timeoutId!);\n    return result;\n  } catch (error) {\n    clearTimeout(timeoutId!);\n    throw error;\n  }\n}\n", "/**\n * SystemdManager - Service Management via systemctl\n *\n * Provides safe interface to systemd service management with:\n * - Command injection prevention\n * - Action and service name validation\n * - Graceful shutdown with configurable timeout\n * - Detailed status parsing\n *\n * @module services/systemd-manager\n */\n\nimport { spawn } from 'child_process';\nimport { TIMEOUTS } from '../constants/timeouts';\n\n/**\n * Service status information\n */\nexport interface ServiceStatus {\n  /** Service name */\n  serviceName: string;\n\n  /** Whether service is active */\n  active: boolean;\n\n  /** Active state (active, inactive, failed, etc.) */\n  activeState: string;\n\n  /** Sub state (running, dead, failed, etc.) */\n  subState: string;\n\n  /** Whether service is loaded */\n  loaded: boolean;\n\n  /** Whether service is healthy */\n  healthy: boolean;\n\n  /** Main process PID (null if not running) */\n  pid: number | null;\n\n  /** Memory usage (formatted string) */\n  memory?: string;\n\n  /** Number of restarts */\n  restarts?: number;\n\n  /** Uptime (formatted string) */\n  uptime?: string;\n\n  /** Start timestamp */\n  startTime?: Date;\n}\n\n/**\n * Service operation result\n */\nexport interface ServiceOperationResult {\n  /** Whether operation succeeded */\n  success: boolean;\n\n  /** Operation type */\n  operation: string;\n\n  /** Service name */\n  serviceName: string;\n\n  /** Exit code */\n  exitCode: number;\n\n  /** Duration in milliseconds */\n  duration: number;\n\n  /** Downtime in milliseconds (for restart) */\n  downtime?: number;\n\n  /** Standard output */\n  stdout?: string;\n\n  /** Standard error */\n  stderr?: string;\n}\n\n/**\n * Systemctl execution options\n */\nexport interface SystemctlOptions {\n  /** Timeout in milliseconds */\n  timeout?: number;\n}\n\n/**\n * Restart options\n */\nexport interface RestartOptions {\n  /** Graceful shutdown timeout in milliseconds */\n  gracefulTimeout?: number;\n\n  /** Whether to wait for active connections to complete */\n  waitForConnections?: boolean;\n}\n\n/**\n * SystemdManager - Safe systemctl wrapper\n */\nexport class SystemdManager {\n  private serviceName: string;\n\n  /** Valid systemctl actions (whitelist) */\n  private static readonly VALID_ACTIONS = [\n    'start',\n    'stop',\n    'restart',\n    'status',\n    'enable',\n    'disable',\n    'is-active',\n    'is-enabled',\n    'show',\n  ];\n\n  /**\n   * Create a new SystemdManager\n   *\n   * @param serviceName - Service name to manage\n   * @throws Error if service name is invalid\n   */\n  constructor(serviceName: string) {\n    this.validateServiceName(serviceName);\n    this.serviceName = serviceName;\n  }\n\n  /**\n   * Validate service name\n   *\n   * @param name - Service name to validate\n   * @throws Error if service name is invalid\n   */\n  private validateServiceName(name: string): void {\n    // Prevent empty names\n    if (!name || name.trim().length === 0) {\n      throw new Error('Service name cannot be empty');\n    }\n\n    // Prevent path traversal attempts\n    if (name.includes('/') || name.includes('\\\\') || name.includes('..')) {\n      throw new Error(`Invalid service name: ${name} (path traversal detected)`);\n    }\n\n    // Prevent command injection attempts\n    const dangerousChars = /[;&|`$()]/;\n    if (dangerousChars.test(name)) {\n      throw new Error(`Invalid service name: ${name} (potentially dangerous characters detected)`);\n    }\n\n    // Only allow alphanumeric, dash, underscore\n    const validPattern = /^[a-zA-Z0-9_-]+$/;\n    if (!validPattern.test(name)) {\n      throw new Error(\n        `Invalid service name: ${name} (only alphanumeric, dash, and underscore allowed)`\n      );\n    }\n  }\n\n  /**\n   * Validate systemctl action\n   *\n   * @param action - Action to validate\n   * @throws Error if action is invalid\n   */\n  validateAction(action: string): void {\n    if (!SystemdManager.VALID_ACTIONS.includes(action)) {\n      throw new Error(\n        `Invalid systemctl action: ${action} (must be one of: ${SystemdManager.VALID_ACTIONS.join(', ')})`\n      );\n    }\n\n    // Extra paranoia: check for command injection attempts\n    const dangerousChars = /[;&|`$()]/;\n    if (dangerousChars.test(action)) {\n      throw new Error(\n        `Invalid systemctl action: ${action} (potentially dangerous characters detected)`\n      );\n    }\n  }\n\n  /**\n   * Execute systemctl command\n   *\n   * @param action - Systemctl action to execute\n   * @param options - Execution options\n   * @returns Command output\n   */\n  async executeSystemctl(action: string, options?: SystemctlOptions): Promise<string> {\n    // Validate action to prevent command injection\n    this.validateAction(action);\n\n    const timeout = options?.timeout || TIMEOUTS.SYSTEMCTL_DEFAULT;\n\n    return new Promise((resolve, reject) => {\n      // Use spawn (not exec) to prevent shell injection\n      const child = spawn('systemctl', [action, this.serviceName], {\n        timeout,\n      });\n\n      let stdout = '';\n      let stderr = '';\n\n      child.stdout?.on('data', (data) => {\n        stdout += data.toString();\n      });\n\n      child.stderr?.on('data', (data) => {\n        stderr += data.toString();\n      });\n\n      child.on('close', (code) => {\n        if (code === 0) {\n          resolve(stdout);\n        } else {\n          const errorMessage = this.parseSystemdError(stderr || stdout, action);\n          reject(new Error(errorMessage));\n        }\n      });\n\n      child.on('error', (error) => {\n        reject(new Error(`Failed to execute systemctl: ${error.message}`));\n      });\n    });\n  }\n\n  /**\n   * Parse systemd error messages and provide suggestions\n   *\n   * @param errorOutput - Error output from systemctl\n   * @param action - Action that was attempted\n   * @returns User-friendly error message with suggestions\n   */\n  private parseSystemdError(errorOutput: string, action: string): string {\n    const lowerError = errorOutput.toLowerCase();\n\n    // Service not found\n    if (\n      lowerError.includes('not found') ||\n      lowerError.includes('does not exist') ||\n      lowerError.includes('could not be found')\n    ) {\n      return `\u670D\u52A1 '${this.serviceName}' \u4E0D\u5B58\u5728\u3002\u8BF7\u786E\u8BA4\u670D\u52A1\u540D\u79F0\u662F\u5426\u6B63\u786E\u3002`;\n    }\n\n    // Permission denied\n    if (\n      lowerError.includes('permission denied') ||\n      lowerError.includes('access denied') ||\n      lowerError.includes('authentication required')\n    ) {\n      return `\u6743\u9650\u4E0D\u8DB3: \u65E0\u6CD5\u6267\u884C ${action} \u64CD\u4F5C\u3002\u8BF7\u4F7F\u7528 sudo \u6216\u4EE5 root \u7528\u6237\u8FD0\u884C\u3002`;\n    }\n\n    // Timeout\n    if (lowerError.includes('timeout') || lowerError.includes('timed out')) {\n      return `\u64CD\u4F5C\u8D85\u65F6: ${action} \u64CD\u4F5C\u672A\u80FD\u5728\u89C4\u5B9A\u65F6\u95F4\u5185\u5B8C\u6210\u3002`;\n    }\n\n    // Already running/stopped\n    if (\n      action === 'start' &&\n      (lowerError.includes('already running') || lowerError.includes('already active'))\n    ) {\n      return `\u670D\u52A1 '${this.serviceName}' \u5DF2\u7ECF\u5728\u8FD0\u884C\u4E2D\u3002`;\n    }\n\n    if (\n      action === 'stop' &&\n      (lowerError.includes('already stopped') || lowerError.includes('inactive'))\n    ) {\n      return `\u670D\u52A1 '${this.serviceName}' \u5DF2\u7ECF\u505C\u6B62\u3002`;\n    }\n\n    // Generic error with original output\n    return `\u6267\u884C systemctl ${action} \u5931\u8D25: ${errorOutput}`;\n  }\n\n  /**\n   * Parse systemctl show output\n   *\n   * @param output - Raw output from systemctl show\n   * @returns Parsed service status\n   */\n  parseSystemdShow(output: string): ServiceStatus {\n    const lines = output.split('\\n');\n    const props: Record<string, string> = {};\n\n    // Parse key=value pairs\n    for (const line of lines) {\n      const trimmed = line.trim();\n      if (!trimmed || !trimmed.includes('=')) {\n        continue;\n      }\n\n      const [key, ...valueParts] = trimmed.split('=');\n      const value = valueParts.join('='); // Handle values with '=' in them\n      props[key] = value;\n    }\n\n    // Validate we have at least basic properties\n    if (!props.ActiveState && !props.SubState) {\n      throw new Error('Invalid systemctl show output: missing required fields (parse error)');\n    }\n\n    // Parse active state\n    const activeState = props.ActiveState || 'unknown';\n    const subState = props.SubState || 'unknown';\n    const active = activeState === 'active';\n\n    // Parse loaded state\n    const loaded = props.LoadState === 'loaded';\n\n    // Parse PID\n    const pidStr = props.MainPID || '0';\n    const pid = parseInt(pidStr, 10);\n    const pidValue = pid > 0 ? pid : null;\n\n    // Parse memory usage\n    const memoryBytes = parseInt(props.MemoryCurrent || '0', 10);\n    const memory = this.formatBytes(memoryBytes);\n\n    // Parse restart count\n    const restarts = parseInt(props.NRestarts || '0', 10);\n\n    // Parse start time and calculate uptime\n    const startTimestamp = props.ExecMainStartTimestamp;\n    let uptime: string | undefined;\n    let startTime: Date | undefined;\n\n    if (startTimestamp && startTimestamp.trim() !== '') {\n      try {\n        startTime = new Date(startTimestamp);\n        const now = Date.now();\n        const startMs = startTime.getTime();\n        const uptimeMs = now - startMs;\n        uptime = this.formatUptime(uptimeMs);\n      } catch {\n        // Ignore parse errors\n      }\n    }\n\n    // Determine health\n    const healthy = active && subState === 'running';\n\n    return {\n      serviceName: this.serviceName,\n      active,\n      activeState,\n      subState,\n      loaded,\n      healthy,\n      pid: pidValue,\n      memory,\n      restarts,\n      uptime,\n      startTime,\n    };\n  }\n\n  /**\n   * Format bytes to human-readable string\n   *\n   * @param bytes - Number of bytes\n   * @returns Formatted string (e.g., \"45.2 MB\")\n   */\n  private formatBytes(bytes: number): string {\n    if (bytes === 0) return '0 B';\n\n    const units = ['B', 'KB', 'MB', 'GB'];\n    const k = 1024;\n    const i = Math.floor(Math.log(bytes) / Math.log(k));\n    const value = bytes / Math.pow(k, i);\n\n    return `${value.toFixed(1)} ${units[i]}`;\n  }\n\n  /**\n   * Format uptime in milliseconds to human-readable string\n   *\n   * @param ms - Uptime in milliseconds\n   * @returns Formatted string (e.g., \"2\u5C0F\u65F615\u5206\u949F\")\n   */\n  private formatUptime(ms: number): string {\n    const seconds = Math.floor(ms / 1000);\n    const minutes = Math.floor(seconds / 60);\n    const hours = Math.floor(minutes / 60);\n    const days = Math.floor(hours / 24);\n\n    if (days > 0) {\n      return `${days}\u5929${hours % 24}\u5C0F\u65F6`;\n    } else if (hours > 0) {\n      return `${hours}\u5C0F\u65F6${minutes % 60}\u5206\u949F`;\n    } else if (minutes > 0) {\n      return `${minutes}\u5206\u949F`;\n    } else {\n      return `${seconds}\u79D2`;\n    }\n  }\n\n  /**\n   * Get service status\n   *\n   * @returns Service status information\n   */\n  async getStatus(): Promise<ServiceStatus> {\n    const output = await this.executeSystemctl('show');\n    return this.parseSystemdShow(output);\n  }\n\n  /**\n   * Start service\n   *\n   * @returns Operation result\n   */\n  async start(): Promise<ServiceOperationResult> {\n    const startTime = Date.now();\n\n    try {\n      const stdout = await this.executeSystemctl('start', {\n        timeout: TIMEOUTS.SERVICE_START,\n      });\n\n      const duration = Date.now() - startTime;\n\n      return {\n        success: true,\n        operation: 'start',\n        serviceName: this.serviceName,\n        exitCode: 0,\n        duration,\n        stdout,\n      };\n    } catch (error) {\n      const duration = Date.now() - startTime;\n\n      return {\n        success: false,\n        operation: 'start',\n        serviceName: this.serviceName,\n        exitCode: 1,\n        duration,\n        stderr: (error as Error).message,\n      };\n    }\n  }\n\n  /**\n   * Stop service\n   *\n   * @returns Operation result\n   */\n  async stop(): Promise<ServiceOperationResult> {\n    const startTime = Date.now();\n\n    try {\n      const stdout = await this.executeSystemctl('stop', {\n        timeout: TIMEOUTS.SERVICE_STOP,\n      });\n\n      const duration = Date.now() - startTime;\n\n      return {\n        success: true,\n        operation: 'stop',\n        serviceName: this.serviceName,\n        exitCode: 0,\n        duration,\n        stdout,\n      };\n    } catch (error) {\n      const duration = Date.now() - startTime;\n\n      return {\n        success: false,\n        operation: 'stop',\n        serviceName: this.serviceName,\n        exitCode: 1,\n        duration,\n        stderr: (error as Error).message,\n      };\n    }\n  }\n\n  /**\n   * Restart service with graceful shutdown\n   *\n   * @param options - Restart options\n   * @returns Operation result\n   */\n  async restart(options?: RestartOptions): Promise<ServiceOperationResult> {\n    const gracefulTimeout = options?.gracefulTimeout || 10000; // Default 10s (FR-016)\n    const restartStartTime = Date.now();\n\n    try {\n      // Measure service downtime\n      const downtimeStart = Date.now();\n\n      // Use systemctl restart which handles graceful shutdown internally\n      const stdout = await this.executeSystemctl('restart', {\n        timeout: TIMEOUTS.SERVICE_RESTART,\n      });\n\n      // Wait a moment for service to fully start\n      await this.waitForServiceReady(gracefulTimeout);\n\n      const downtimeEnd = Date.now();\n      const downtime = downtimeEnd - downtimeStart;\n      const duration = Date.now() - restartStartTime;\n\n      return {\n        success: true,\n        operation: 'restart',\n        serviceName: this.serviceName,\n        exitCode: 0,\n        duration,\n        downtime,\n        stdout,\n      };\n    } catch (error) {\n      const duration = Date.now() - restartStartTime;\n\n      return {\n        success: false,\n        operation: 'restart',\n        serviceName: this.serviceName,\n        exitCode: 1,\n        duration,\n        stderr: (error as Error).message,\n      };\n    }\n  }\n\n  /**\n   * Wait for service to be ready after start/restart\n   *\n   * @param maxWait - Maximum time to wait in milliseconds\n   */\n  private async waitForServiceReady(maxWait: number): Promise<void> {\n    const startTime = Date.now();\n    const pollInterval = 100; // Check every 100ms\n\n    while (Date.now() - startTime < maxWait) {\n      try {\n        const status = await this.getStatus();\n        if (status.active && status.subState === 'running') {\n          return; // Service is ready\n        }\n      } catch {\n        // Ignore errors during polling\n      }\n\n      // Wait before next poll\n      await new Promise((resolve) => setTimeout(resolve, pollInterval));\n    }\n\n    // If we get here, service didn't become ready in time\n    // But don't throw - let caller determine if this is critical\n  }\n\n  /**\n   * Check if running as root\n   *\n   * @returns True if running as root\n   */\n  isRoot(): boolean {\n    return !!(process.getuid && process.getuid() === 0);\n  }\n\n  /**\n   * Check if sudo is available\n   *\n   * @returns True if sudo is available\n   */\n  async canUseSudo(): Promise<boolean> {\n    return new Promise((resolve) => {\n      const child = spawn('which', ['sudo']);\n\n      child.on('close', (code) => {\n        resolve(code === 0);\n      });\n\n      child.on('error', () => {\n        resolve(false);\n      });\n    });\n  }\n\n  /**\n   * Get permission warning message\n   *\n   * @returns Warning message if not running with sufficient permissions\n   */\n  getPermissionWarning(): string | undefined {\n    if (this.isRoot()) {\n      return undefined;\n    }\n\n    return 'Not running as root - some operations may require sudo';\n  }\n\n  /**\n   * Estimate downtime for restart operation\n   *\n   * @returns Estimated downtime in milliseconds\n   */\n  estimateDowntime(): number {\n    // Estimate based on typical graceful shutdown time\n    // Conservative estimate: 5 seconds\n    return 5000;\n  }\n}\n", "/**\n * Xray Manager CLI Entry Point\n *\n * Renders the React+Ink based terminal UI.\n *\n * @module cli\n */\n\nimport { Command } from 'commander';\nimport updateNotifier from 'update-notifier';\nimport React from 'react';\nimport { render } from 'ink';\nimport logger from './utils/logger.js';\nimport { ExitCode, gracefulExit } from './constants/exit-codes.js';\nimport { preflightChecks } from './utils/preflight.js';\nimport { registerReviewCommand } from './commands/review.js';\nimport { registerClashCommand } from './commands/clash.js';\nimport { App } from './app/App.js';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\n\n// Read package.json for version\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));\n\n/**\n * Main CLI function\n */\nasync function main(): Promise<void> {\n  // Check for updates\n  const notifier = updateNotifier({\n    pkg: packageJson,\n    updateCheckInterval: 1000 * 60 * 60 * 24, // Daily\n  });\n\n  if (notifier.update) {\n    notifier.notify({ isGlobal: true, defer: false });\n  }\n\n  // Create Commander program\n  const program = new Command();\n\n  program\n    .name('xray-manager')\n    .description('Xray VPN Service Manager')\n    .version(packageJson.version, '-v, --version', 'Show version')\n    .helpOption('-h, --help', 'Show help');\n\n  // Global options\n  program\n    .option('--config <path>', 'Specify config file path')\n    .option('--service <name>', 'Specify service name', 'xray')\n    .option('--json', 'JSON output mode')\n    .option('--no-color', 'Disable colored output')\n    .option('--verbose', 'Verbose output mode');\n\n  registerReviewCommand(program);\n  registerClashCommand(program);\n\n  // Default action: start interactive Ink UI\n  program.action(async () => {\n    const options = program.opts();\n\n    if (options.noColor) {\n      logger.configure({ color: false });\n    }\n\n    try {\n      // Perform preflight checks\n      const preflightResult = await preflightChecks({\n        checkSystemd: true,\n        checkXray: false,\n        checkConfig: false,\n      });\n\n      if (!preflightResult.passed && preflightResult.critical) {\n        logger.error('Preflight check failed');\n        preflightResult.errors.forEach((error) => logger.error(`  \\u2022 ${error}`));\n\n        if (preflightResult.suggestions.length > 0) {\n          logger.hint('Suggestions:');\n          preflightResult.suggestions.forEach((s) => logger.info(`  \\u2022 ${s}`));\n        }\n\n        await gracefulExit(ExitCode.SERVICE_ERROR);\n      }\n\n      if (preflightResult.warnings.length > 0) {\n        preflightResult.warnings.forEach((w) => logger.warn(w));\n      }\n\n      // Render the Ink app\n      const { waitUntilExit } = render(\n        React.createElement(App, {\n          options: {\n            configPath: options.config,\n            serviceName: options.service,\n          },\n          version: packageJson.version,\n        })\n      );\n\n      await waitUntilExit();\n      await gracefulExit(ExitCode.SUCCESS);\n    } catch (error) {\n      logger.error('Error starting application:');\n      logger.error((error as Error).message);\n\n      if (options.verbose && error instanceof Error) {\n        logger.error(error.stack || 'No stack trace');\n      }\n\n      await gracefulExit(ExitCode.GENERAL_ERROR);\n    }\n  });\n\n  // Parse and execute\n  await program.parseAsync(process.argv);\n}\n\n// Handle uncaught errors\nprocess.on('uncaughtException', async (error) => {\n  logger.error(`Uncaught exception: ${error.message}`);\n  await gracefulExit(ExitCode.GENERAL_ERROR);\n});\n\nprocess.on('unhandledRejection', async (reason) => {\n  logger.error(`Unhandled rejection: ${String(reason)}`);\n  await gracefulExit(ExitCode.GENERAL_ERROR);\n});\n\n// Run\nmain().catch(async (error) => {\n  logger.error(`Fatal: ${error.message}`);\n  await gracefulExit(ExitCode.GENERAL_ERROR);\n});\n", "/**\n * \u65E5\u5FD7\u5DE5\u5177\u51FD\u6570\uFF08\u4F7F\u7528 chalk \u989C\u8272\u548C\u901A\u7528\u6587\u672C\u6307\u793A\u7B26\uFF09\n * @module utils/logger\n */\n\nimport chalk from 'chalk';\nimport { detectTerminalCapabilities } from './terminal';\nimport { resolveIcon, resolveSpecialIcon, getStatusIndicator } from './icons';\nimport { AppError } from './errors';\nimport { ErrorInfo } from '../constants/error-codes';\nimport {\n  formatAppError,\n  formatErrorInfo,\n  formatError as formatErrorUtil,\n  type FormatOptions,\n} from './error-formatter';\n\n/**\n * \u65E5\u5FD7\u7EA7\u522B\n */\n/* eslint-disable no-unused-vars */\nexport enum LogLevel {\n  DEBUG = 'debug',\n  INFO = 'info',\n  SUCCESS = 'success',\n  WARN = 'warn',\n  ERROR = 'error',\n}\n/* eslint-enable no-unused-vars */\n\n/**\n * \u8F93\u51FA\u6A21\u5F0F\n */\n/* eslint-disable no-unused-vars */\nexport enum OutputMode {\n  /** \u5B8C\u6574\u6A21\u5F0F\uFF1A\u989C\u8272 + \u683C\u5F0F\u5316 */\n  RICH = 'rich',\n  /** \u6734\u7D20\u6A21\u5F0F\uFF1A\u65E0\u989C\u8272 + \u683C\u5F0F\u5316 */\n  PLAIN_TTY = 'plain_tty',\n  /** \u7BA1\u9053\u6A21\u5F0F\uFF1A\u7EAF\u6587\u672C + \u65F6\u95F4\u6233 */\n  PIPE = 'pipe',\n}\n/* eslint-enable no-unused-vars */\n\n/**\n * \u65E5\u5FD7\u9009\u9879\n */\nexport interface LogOptions {\n  /** \u662F\u5426\u542F\u7528\u989C\u8272\uFF08\u9ED8\u8BA4 true\uFF09 */\n  color?: boolean;\n\n  /** \u662F\u5426\u663E\u793A\u65F6\u95F4\u6233\uFF08\u9ED8\u8BA4 false\uFF09 */\n  timestamp?: boolean;\n\n  /** \u65E5\u5FD7\u7EA7\u522B\uFF08\u7528\u4E8E\u8FC7\u6EE4\uFF09 */\n  level?: LogLevel;\n}\n\n/**\n * \u5168\u5C40\u65E5\u5FD7\u914D\u7F6E\n */\nlet globalOptions: LogOptions = {\n  color: true,\n  timestamp: false,\n  level: LogLevel.INFO,\n};\n\n/**\n * \u7F13\u5B58\u7684\u7EC8\u7AEF\u80FD\u529B\n */\nlet cachedCapabilities = detectTerminalCapabilities();\n\n/**\n * \u914D\u7F6E\u5168\u5C40\u65E5\u5FD7\u9009\u9879\n */\nexport function configureLogger(options: LogOptions): void {\n  globalOptions = { ...globalOptions, ...options };\n}\n\n/**\n * \u83B7\u53D6\u5F53\u524D\u8F93\u51FA\u6A21\u5F0F\n * @returns \u8F93\u51FA\u6A21\u5F0F\uFF08RICH, PLAIN_TTY, \u6216 PIPE\uFF09\n */\nexport function getOutputMode(): OutputMode {\n  const isTTY = cachedCapabilities.isTTY;\n  const colorEnabled = globalOptions.color !== false;\n\n  if (!isTTY) {\n    return OutputMode.PIPE;\n  }\n\n  if (!colorEnabled) {\n    return OutputMode.PLAIN_TTY;\n  }\n\n  return OutputMode.RICH;\n}\n\n/**\n * \u83B7\u53D6\u65F6\u95F4\u6233\u5B57\u7B26\u4E32\n */\nfunction getTimestamp(): string {\n  const now = new Date();\n  const hours = String(now.getHours()).padStart(2, '0');\n  const minutes = String(now.getMinutes()).padStart(2, '0');\n  const seconds = String(now.getSeconds()).padStart(2, '0');\n  return `[${hours}:${minutes}:${seconds}]`;\n}\n\n/**\n * \u683C\u5F0F\u5316\u65E5\u5FD7\u6D88\u606F\uFF08\u4F7F\u7528\u65B0\u7684\u8F93\u51FA\u6A21\u5F0F\u68C0\u6D4B\uFF09\n * @param level - \u65E5\u5FD7\u7EA7\u522B\n * @param message - \u6D88\u606F\u5185\u5BB9\n * @param includeIndicator - \u662F\u5426\u5305\u542B\u72B6\u6001\u6307\u793A\u7B26\uFF08\u9ED8\u8BA4 true\uFF09\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u6D88\u606F\n */\nfunction formatMessage(level: LogLevel, message: string, includeIndicator: boolean = true): string {\n  const mode = getOutputMode();\n  const indicator = includeIndicator ? resolveIcon(level, cachedCapabilities) : '';\n\n  switch (mode) {\n    case OutputMode.PIPE:\n      // \u7BA1\u9053\u6A21\u5F0F\uFF1A[timestamp] [LEVEL] message\n      const levelLabel = getStatusIndicator(level).ascii;\n      return `${getTimestamp()} ${levelLabel} ${message}`;\n\n    case OutputMode.PLAIN_TTY:\n      // \u6734\u7D20 TTY \u6A21\u5F0F\uFF1Aindicator message\uFF08\u65E0\u989C\u8272\uFF09\n      return includeIndicator ? `${indicator} ${message}` : message;\n\n    case OutputMode.RICH:\n    default:\n      // \u5B8C\u6574\u6A21\u5F0F\uFF1A\u989C\u8272 + indicator + message\n      const formattedMessage = includeIndicator ? `${indicator} ${message}` : message;\n\n      if (globalOptions.timestamp) {\n        return `${chalk.gray(getTimestamp())} ${formattedMessage}`;\n      }\n\n      return formattedMessage;\n  }\n}\n\n/**\n * \u5E94\u7528\u989C\u8272\uFF08\u4EC5\u5728 RICH \u6A21\u5F0F\u4E0B\uFF09\n * @param message - \u6D88\u606F\n * @param colorFn - Chalk \u989C\u8272\u51FD\u6570\n * @returns \u7740\u8272\u540E\u7684\u6D88\u606F\n */\nfunction applyColor(message: string, colorFn: (_text: string) => string): string {\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    return colorFn(message);\n  }\n\n  return message;\n}\n\n/**\n * \u8C03\u8BD5\u65E5\u5FD7\uFF08\u7070\u8272\uFF0C[DEBUG] \u6307\u793A\u7B26\uFF09\n */\nexport function debug(...args: unknown[]): void {\n  const message = args.join(' ');\n  const formatted = formatMessage(LogLevel.DEBUG, message);\n  console.debug(applyColor(formatted, chalk.gray));\n}\n\n/**\n * \u4FE1\u606F\u65E5\u5FD7\uFF08\u9ED8\u8BA4\u989C\u8272\uFF0C[INFO] \u6307\u793A\u7B26\uFF09\n */\nexport function info(...args: unknown[]): void {\n  const message = args.join(' ');\n  const formatted = formatMessage(LogLevel.INFO, message);\n  console.info(applyColor(formatted, chalk.cyan));\n}\n\n/**\n * \u6210\u529F\u65E5\u5FD7\uFF08\u7EFF\u8272\uFF0C\u2713 \u6216 [OK] \u6307\u793A\u7B26\uFF09\n */\nexport function success(...args: unknown[]): void {\n  const message = args.join(' ');\n  const formatted = formatMessage(LogLevel.SUCCESS, message);\n  console.log(applyColor(formatted, chalk.green));\n}\n\n/**\n * \u8B66\u544A\u65E5\u5FD7\uFF08\u9EC4\u8272\uFF0C! \u6216 [WARN] \u6307\u793A\u7B26\uFF09\n */\nexport function warn(...args: unknown[]): void {\n  const message = args.join(' ');\n  const formatted = formatMessage(LogLevel.WARN, message);\n  console.warn(applyColor(formatted, chalk.yellow));\n}\n\n/**\n * \u9519\u8BEF\u65E5\u5FD7\uFF08\u7EA2\u8272\uFF0C\u2717 \u6216 [ERROR] \u6307\u793A\u7B26\uFF09\n */\nexport function error(...args: unknown[]): void {\n  const message = args.join(' ');\n  const formatted = formatMessage(LogLevel.ERROR, message);\n  console.error(applyColor(formatted, chalk.red));\n}\n\n/**\n * \u6807\u9898\u65E5\u5FD7\uFF08\u9752\u8272\uFF0C\u52A0\u7C97\uFF09\n */\nexport function title(message: string): void {\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    console.log(chalk.cyan.bold(`\\n${message}\\n`));\n  } else {\n    console.log(`\\n=== ${message} ===\\n`);\n  }\n}\n\n/**\n * \u5206\u9694\u7EBF\uFF08\u81EA\u52A8\u9002\u5E94\u7EC8\u7AEF\u5BBD\u5EA6\uFF0C\u6700\u5927 80 \u5217\uFF09\n * @param char - \u5206\u9694\u7B26\u5B57\u7B26\n * @param length - \u5206\u9694\u7EBF\u957F\u5EA6\uFF08\u9ED8\u8BA4 50\uFF09\n */\nexport function separator(char: string = '\u2500', length: number = 50): void {\n  // Ensure separator doesn't exceed 80 columns\n  const maxWidth = 80;\n  const actualLength = Math.min(length, maxWidth);\n  const line = char.repeat(actualLength);\n  console.log(applyColor(line, chalk.gray));\n}\n\n/**\n * \u8868\u683C\u8868\u5934\uFF08\u5E26\u8FB9\u6846\uFF0C\u786E\u4FDD\u5728 80 \u5217\u5185\uFF09\n * @param titleText - \u6807\u9898\u6587\u672C\n */\nexport function tableHeader(titleText: string): void {\n  // Use 59 character width to ensure box drawing chars stay within 80 columns\n  // 59 (content) + 2 (borders) = 61 chars total\n  const width = 59;\n  const border = '\u2550'.repeat(width);\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    console.log(chalk.cyan(`\u2554${border}\u2557`));\n    console.log(\n      chalk.cyan(`\u2551${titleText.padStart((width + titleText.length) / 2).padEnd(width)}\u2551`)\n    );\n    console.log(chalk.cyan(`\u255A${border}\u255D`));\n  } else {\n    console.log(border);\n    console.log(titleText);\n    console.log(border);\n  }\n}\n\n/**\n * \u52A0\u8F7D\u52A8\u753B\u6D88\u606F\uFF08... \u6216 [...] \u6307\u793A\u7B26\uFF09\n */\nexport function loading(message: string): void {\n  const icon = resolveSpecialIcon('LOADING', cachedCapabilities);\n  const formatted = `${icon} ${message}...`;\n  console.log(applyColor(formatted, chalk.cyan));\n}\n\n/**\n * \u8FDB\u5EA6\u6D88\u606F\uFF08> \u6216 [>>] \u6307\u793A\u7B26\uFF09\n */\nexport function progress(message: string): void {\n  const icon = resolveSpecialIcon('PROGRESS', cachedCapabilities);\n  const formatted = `${icon} ${message}...`;\n  console.log(applyColor(formatted, chalk.blue));\n}\n\n/**\n * \u63D0\u793A\u6D88\u606F\uFF08* \u6216 [TIP] \u6307\u793A\u7B26\uFF09\n */\nexport function hint(message: string): void {\n  const icon = resolveSpecialIcon('HINT', cachedCapabilities);\n  const formatted = `${icon} \u63D0\u793A: ${message}`;\n  console.log(applyColor(formatted, chalk.cyan));\n}\n\n/**\n * \u5E26\u989C\u8272\u7684\u952E\u503C\u5BF9\u8F93\u51FA\n */\nexport function keyValue(key: string, value: string, keyColor = chalk.gray): void {\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    console.log(`  ${keyColor(key + ':')} ${value}`);\n  } else {\n    console.log(`  ${key}: ${value}`);\n  }\n}\n\n/**\n * \u6253\u5370\u7A7A\u884C\uFF08\u7528\u4E8E\u64CD\u4F5C\u4E4B\u95F4\u7684\u89C6\u89C9\u5206\u9694\uFF0C\u4FDD\u6301\u4E00\u81F4\u95F4\u8DDD\uFF09\n * @param count - \u7A7A\u884C\u6570\u91CF\uFF08\u9ED8\u8BA4 1\uFF09\n */\nexport function newline(count: number = 1): void {\n  console.log('\\n'.repeat(count - 1));\n}\n\n/**\n * \u5E26\u989C\u8272\u7684\u5217\u8868\u9879\n */\nexport function listItem(message: string, symbol: string = '\u2022'): void {\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    console.log(chalk.gray(`  ${symbol} `) + message);\n  } else {\n    console.log(`  ${symbol} ${message}`);\n  }\n}\n\n/**\n * \u4EE3\u7801\u5757\uFF08\u5E26\u7070\u8272\u80CC\u666F\uFF09\n */\nexport function code(codeText: string): void {\n  const mode = getOutputMode();\n\n  if (mode === OutputMode.RICH) {\n    console.log(chalk.bgGray.white(` ${codeText} `));\n  } else {\n    console.log(`\\`${codeText}\\``);\n  }\n}\n\n/**\n * \u8F93\u51FA\u683C\u5F0F\u5316\u7684 AppError\uFF08\u5E26\u539F\u56E0\u548C\u89E3\u51B3\u65B9\u6848\uFF09\n * @param err - AppError \u5B9E\u4F8B\n * @param options - \u683C\u5F0F\u5316\u9009\u9879\n */\nexport function formattedError(err: AppError, options?: FormatOptions): void {\n  const formatted = formatAppError(err, options);\n  console.error(formatted);\n}\n\n/**\n * \u8F93\u51FA\u683C\u5F0F\u5316\u7684\u9519\u8BEF\u4FE1\u606F\uFF08\u4ECE ErrorInfo \u5BF9\u8C61\uFF09\n * @param errorInfo - \u9519\u8BEF\u4FE1\u606F\u5B9A\u4E49\n * @param details - \u9644\u52A0\u8BE6\u60C5\n * @param options - \u683C\u5F0F\u5316\u9009\u9879\n */\nexport function formattedErrorInfo(\n  errorInfo: ErrorInfo,\n  details?: string,\n  options?: FormatOptions\n): void {\n  const formatted = formatErrorInfo(errorInfo, details, options);\n  console.error(formatted);\n}\n\n/**\n * \u8F93\u51FA\u683C\u5F0F\u5316\u7684\u901A\u7528\u9519\u8BEF\n * @param err - \u4EFB\u610F Error \u5BF9\u8C61\n * @param fallbackInfo - \u5982\u679C\u4E0D\u662F AppError\uFF0C\u4F7F\u7528\u7684\u56DE\u9000\u9519\u8BEF\u4FE1\u606F\n * @param options - \u683C\u5F0F\u5316\u9009\u9879\n */\nexport function formattedGenericError(\n  err: Error,\n  fallbackInfo?: ErrorInfo,\n  options?: FormatOptions\n): void {\n  const formatted = formatErrorUtil(err, fallbackInfo, options);\n  console.error(formatted);\n}\n\n/**\n * \u9ED8\u8BA4\u5BFC\u51FA\u5BF9\u8C61\n */\nexport default {\n  debug,\n  info,\n  success,\n  warn,\n  error,\n  title,\n  separator,\n  tableHeader,\n  loading,\n  progress,\n  hint,\n  keyValue,\n  newline,\n  listItem,\n  code,\n  configure: configureLogger,\n  getOutputMode,\n  formattedError,\n  formattedErrorInfo,\n  formattedGenericError,\n};\n", "/**\n * Terminal Capability Detection\n * @module utils/terminal\n *\n * Provides functions to detect terminal capabilities for adaptive output formatting.\n */\n\nimport chalk from 'chalk';\nimport { Platform, TerminalCapabilities } from '../types/terminal';\n\n/**\n * Detect current terminal capabilities\n * @returns Terminal capabilities object with detected features\n */\nexport function detectTerminalCapabilities(): TerminalCapabilities {\n  const platform = mapPlatform(process.platform);\n  const isTTY = process.stdout.isTTY || false;\n  const term = process.env.TERM;\n\n  return {\n    isTTY,\n    supportsColor: chalk.level > 0,\n    supportsUnicode: supportsUnicode(term, platform),\n    width: process.stdout.columns || 80,\n    height: process.stdout.rows,\n    platform,\n    term,\n  };\n}\n\n/**\n * Check if given platform is Windows\n * @param platform - Platform to check\n * @returns True if platform is Windows\n */\nexport function isWindows(platform: Platform): boolean {\n  return platform === Platform.WIN32;\n}\n\n/**\n * Determine if terminal supports Unicode characters\n * @param term - TERM environment variable value\n * @param platform - Operating system platform\n * @returns True if Unicode is supported\n */\nexport function supportsUnicode(term: string | undefined, platform: Platform): boolean {\n  // Windows CMD typically doesn't support Unicode well\n  if (platform === Platform.WIN32) {\n    return false;\n  }\n\n  // No TERM variable means no Unicode support\n  if (!term) {\n    return false;\n  }\n\n  // Dumb terminals don't support Unicode\n  if (term === 'dumb') {\n    return false;\n  }\n\n  // Legacy terminals don't support Unicode\n  if (term === 'vt100') {\n    return false;\n  }\n\n  // Modern terminals (xterm, screen, tmux variants) support Unicode\n  if (term.startsWith('xterm') || term.startsWith('screen') || term.startsWith('tmux')) {\n    return true;\n  }\n\n  // Default to false for unknown terminals to be safe\n  return false;\n}\n\n/**\n * Map Node.js platform string to Platform enum\n * @param nodePlatform - process.platform value\n * @returns Platform enum value\n */\nexport function mapPlatform(nodePlatform: string): Platform {\n  switch (nodePlatform) {\n    case 'win32':\n      return Platform.WIN32;\n    case 'linux':\n      return Platform.LINUX;\n    case 'darwin':\n      return Platform.DARWIN;\n    case 'freebsd':\n      return Platform.FREEBSD;\n    default:\n      return Platform.OTHER;\n  }\n}\n", "/**\n * UI Symbols Constants\n * @module constants/ui-symbols\n *\n * This file defines all text-based icons and status indicators\n * used throughout the CLI for universal terminal compatibility.\n */\n\n/**\n * Status icons for different message types\n * These replace emoji indicators with text-based alternatives\n */\nexport const statusIcons = {\n  SUCCESS: '[OK]',\n  ERROR: '[ERROR]',\n  WARN: '[WARN]',\n  INFO: '[INFO]',\n  DEBUG: '[DEBUG]',\n  LOADING: '[...]',\n  PROGRESS: '[>>]',\n  HINT: '[TIP]',\n} as const;\n\n/**\n * Menu icons for different CLI operations\n * These replace emoji in menu options with text labels\n */\nexport const menuIcons = {\n  STATUS: '[\u67E5\u770B]',\n  START: '[\u542F\u52A8]',\n  STOP: '[\u505C\u6B62]',\n  RESTART: '[\u91CD\u542F]',\n  USER: '[\u7528\u6237]',\n  CONFIG: '[\u914D\u7F6E]',\n  LOGS: '[\u65E5\u5FD7]',\n  LANGUAGE: '[\u8BED\u8A00]',\n  EXIT: '[\u9000\u51FA]',\n  STATS: '[\u6D41\u91CF]',\n  QUOTA: '[\u914D\u989D]',\n  VIEW: '[\u67E5\u770B]',\n  BACK: '[\u8FD4\u56DE]',\n  ERROR: '[\u9519\u8BEF]',\n  WARNING: '[\u8B66\u544A]',\n  BACKUP: '[\u5907\u4EFD]',\n  RESTORE: '[\u6062\u590D]',\n} as const;\n\n// Type exports for TypeScript support\nexport type StatusIcon = (typeof statusIcons)[keyof typeof statusIcons];\nexport type MenuIcon = (typeof menuIcons)[keyof typeof menuIcons];\n", "/**\n * Icon Resolver\n * @module utils/icons\n *\n * Resolves appropriate icons based on terminal capabilities and context.\n */\n\nimport { TerminalCapabilities } from '../types/terminal';\nimport { statusIcons, menuIcons } from '../constants/ui-symbols';\n\n// Import LogLevel type only to avoid circular dependency\nimport type { LogLevel } from './logger';\n\n/**\n * Status indicator with both Unicode and ASCII representations\n */\nexport interface StatusIndicator {\n  level: string; // Using string instead of LogLevel enum to avoid circular dependency\n  unicode: string;\n  ascii: string;\n  color: 'green' | 'red' | 'yellow' | 'cyan' | 'blue' | 'gray';\n}\n\n/**\n * Menu icon with emoji (deprecated) and text representations\n */\nexport interface MenuIcon {\n  emoji?: string;\n  text: string;\n}\n\n/**\n * Status indicator mappings for all log levels\n */\nconst STATUS_INDICATOR_MAP: Record<string, StatusIndicator> = {\n  success: {\n    level: 'success',\n    unicode: '\u2713',\n    ascii: statusIcons.SUCCESS,\n    color: 'green',\n  },\n  error: {\n    level: 'error',\n    unicode: '\u2717',\n    ascii: statusIcons.ERROR,\n    color: 'red',\n  },\n  warn: {\n    level: 'warn',\n    unicode: '!',\n    ascii: statusIcons.WARN,\n    color: 'yellow',\n  },\n  info: {\n    level: 'info',\n    unicode: 'i',\n    ascii: statusIcons.INFO,\n    color: 'cyan',\n  },\n  debug: {\n    level: 'debug',\n    unicode: '\u00B7',\n    ascii: statusIcons.DEBUG,\n    color: 'gray',\n  },\n};\n\n/**\n * Additional status indicators for special states\n */\nconst EXTRA_INDICATORS: Record<string, StatusIndicator> = {\n  LOADING: {\n    level: 'info',\n    unicode: '...',\n    ascii: statusIcons.LOADING,\n    color: 'cyan',\n  },\n  PROGRESS: {\n    level: 'info',\n    unicode: '>',\n    ascii: statusIcons.PROGRESS,\n    color: 'blue',\n  },\n  HINT: {\n    level: 'info',\n    unicode: '*',\n    ascii: statusIcons.HINT,\n    color: 'cyan',\n  },\n};\n\n/**\n * Menu icon mappings\n */\nconst MENU_ICON_MAP: Record<string, MenuIcon> = {\n  STATUS: { emoji: '\uD83D\uDCCA', text: menuIcons.STATUS },\n  START: { emoji: '\uD83D\uDE80', text: menuIcons.START },\n  STOP: { emoji: '\uD83D\uDED1', text: menuIcons.STOP },\n  RESTART: { emoji: '\uD83D\uDD04', text: menuIcons.RESTART },\n  USER: { emoji: '\uD83D\uDC65', text: menuIcons.USER },\n  CONFIG: { emoji: '\u2699\uFE0F', text: menuIcons.CONFIG },\n  LOGS: { emoji: '\uD83D\uDCDD', text: menuIcons.LOGS },\n  EXIT: { emoji: '\u274C', text: menuIcons.EXIT },\n};\n\n/**\n * Resolve appropriate icon based on log level and terminal capabilities\n * @param level - Log level\n * @param capabilities - Terminal capabilities\n * @returns Icon string (Unicode or ASCII)\n */\nexport function resolveIcon(level: LogLevel, capabilities: TerminalCapabilities): string {\n  const indicator = STATUS_INDICATOR_MAP[level as string];\n\n  if (!indicator) {\n    // Fallback for unknown levels\n    return capabilities.supportsUnicode ? '\u2022' : statusIcons.INFO;\n  }\n\n  // Use ASCII for terminals that don't support Unicode\n  if (!capabilities.supportsUnicode) {\n    return indicator.ascii;\n  }\n\n  // Use Unicode for modern terminals\n  return indicator.unicode;\n}\n\n/**\n * Resolve icon for special states (loading, progress, hint)\n * @param state - State name (LOADING, PROGRESS, HINT)\n * @param capabilities - Terminal capabilities\n * @returns Icon string\n */\nexport function resolveSpecialIcon(\n  state: 'LOADING' | 'PROGRESS' | 'HINT',\n  capabilities: TerminalCapabilities\n): string {\n  const indicator = EXTRA_INDICATORS[state];\n\n  if (!indicator) {\n    return capabilities.supportsUnicode ? '\u2022' : statusIcons.INFO;\n  }\n\n  return capabilities.supportsUnicode ? indicator.unicode : indicator.ascii;\n}\n\n/**\n * Get status indicator details for a log level\n * @param level - Log level\n * @returns Status indicator object\n * @throws Error if log level is invalid\n */\nexport function getStatusIndicator(level: LogLevel): StatusIndicator {\n  const indicator = STATUS_INDICATOR_MAP[level as string];\n\n  if (!indicator) {\n    throw new Error(`Invalid log level: ${level}`);\n  }\n\n  return indicator;\n}\n\n/**\n * Get menu icon for a specific key\n * @param key - Menu icon key (STATUS, START, STOP, etc.)\n * @returns Menu icon object\n * @throws Error if key is not found\n */\nexport function getMenuIcon(key: string): MenuIcon {\n  const icon = MENU_ICON_MAP[key.toUpperCase()];\n\n  if (!icon) {\n    throw new Error(`Unknown menu icon key: ${key}`);\n  }\n\n  return icon;\n}\n", "/**\n * Error Formatter Utility\n * @module utils/error-formatter\n *\n * Formats errors into user-friendly output with causes and solutions.\n */\n\nimport chalk from 'chalk';\nimport { AppError } from './errors';\nimport { ErrorInfo, findErrorByCode } from '../constants/error-codes';\nimport { detectTerminalCapabilities } from './terminal';\nimport { getOutputMode, OutputMode } from './logger';\n\n/**\n * Format options\n */\nexport interface FormatOptions {\n  /** Show causes section */\n  showCauses?: boolean;\n  /** Show solutions section */\n  showSolutions?: boolean;\n  /** Show stack trace (for debugging) */\n  showStack?: boolean;\n  /** Indentation string */\n  indent?: string;\n}\n\nconst DEFAULT_OPTIONS: FormatOptions = {\n  showCauses: true,\n  showSolutions: true,\n  showStack: false,\n  indent: '  ',\n};\n\n/**\n * Get error icon based on terminal capabilities\n */\nfunction getErrorIcon(): string {\n  const capabilities = detectTerminalCapabilities();\n  return capabilities.supportsUnicode ? '\u2717' : '[ERROR]';\n}\n\n/**\n * Format an AppError into user-friendly output\n * @param error - The AppError to format\n * @param options - Formatting options\n * @returns Formatted error string\n */\nexport function formatAppError(error: AppError, options?: FormatOptions): string {\n  const opts = { ...DEFAULT_OPTIONS, ...options };\n  const mode = getOutputMode();\n  const lines: string[] = [];\n  const indent = opts.indent || '  ';\n\n  // Header line: \u2717 \u9519\u8BEF [E101]: \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\n  const icon = getErrorIcon();\n  const headerText = `${icon} \u9519\u8BEF [${error.code}]: ${error.title}`;\n\n  if (mode === OutputMode.RICH) {\n    lines.push(chalk.red.bold(headerText));\n  } else {\n    lines.push(headerText);\n  }\n\n  // Details if present\n  if (error.details) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.gray(`${indent}${error.details}`));\n    } else {\n      lines.push(`${indent}${error.details}`);\n    }\n  }\n\n  // Causes section\n  if (opts.showCauses && error.causes.length > 0) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.yellow('\u53EF\u80FD\u7684\u539F\u56E0:'));\n    } else {\n      lines.push('\u53EF\u80FD\u7684\u539F\u56E0:');\n    }\n    error.causes.forEach((cause, index) => {\n      const bullet = `${indent}${index + 1}. ${cause}`;\n      if (mode === OutputMode.RICH) {\n        lines.push(chalk.gray(bullet));\n      } else {\n        lines.push(bullet);\n      }\n    });\n  }\n\n  // Solutions section\n  if (opts.showSolutions && error.solutions.length > 0) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.green('\u89E3\u51B3\u65B9\u6848:'));\n    } else {\n      lines.push('\u89E3\u51B3\u65B9\u6848:');\n    }\n    error.solutions.forEach((solution) => {\n      const bullet = `${indent}- ${solution}`;\n      if (mode === OutputMode.RICH) {\n        lines.push(chalk.cyan(bullet));\n      } else {\n        lines.push(bullet);\n      }\n    });\n  }\n\n  // Stack trace (for debugging)\n  if (opts.showStack && error.stack) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.gray('Stack trace:'));\n      lines.push(chalk.gray(error.stack));\n    } else {\n      lines.push('Stack trace:');\n      lines.push(error.stack);\n    }\n  }\n\n  return lines.join('\\n');\n}\n\n/**\n * Format an ErrorInfo object (without creating an AppError)\n * @param errorInfo - The error info to format\n * @param details - Additional details\n * @param options - Formatting options\n * @returns Formatted error string\n */\nexport function formatErrorInfo(\n  errorInfo: ErrorInfo,\n  details?: string,\n  options?: FormatOptions\n): string {\n  const opts = { ...DEFAULT_OPTIONS, ...options };\n  const mode = getOutputMode();\n  const lines: string[] = [];\n  const indent = opts.indent || '  ';\n\n  // Header line\n  const icon = getErrorIcon();\n  const headerText = `${icon} \u9519\u8BEF [${errorInfo.code}]: ${errorInfo.title}`;\n\n  if (mode === OutputMode.RICH) {\n    lines.push(chalk.red.bold(headerText));\n  } else {\n    lines.push(headerText);\n  }\n\n  // Details if present\n  if (details) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.gray(`${indent}${details}`));\n    } else {\n      lines.push(`${indent}${details}`);\n    }\n  }\n\n  // Causes section\n  if (opts.showCauses && errorInfo.causes.length > 0) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.yellow('\u53EF\u80FD\u7684\u539F\u56E0:'));\n    } else {\n      lines.push('\u53EF\u80FD\u7684\u539F\u56E0:');\n    }\n    errorInfo.causes.forEach((cause, index) => {\n      const bullet = `${indent}${index + 1}. ${cause}`;\n      if (mode === OutputMode.RICH) {\n        lines.push(chalk.gray(bullet));\n      } else {\n        lines.push(bullet);\n      }\n    });\n  }\n\n  // Solutions section\n  if (opts.showSolutions && errorInfo.solutions.length > 0) {\n    lines.push('');\n    if (mode === OutputMode.RICH) {\n      lines.push(chalk.green('\u89E3\u51B3\u65B9\u6848:'));\n    } else {\n      lines.push('\u89E3\u51B3\u65B9\u6848:');\n    }\n    errorInfo.solutions.forEach((solution) => {\n      const bullet = `${indent}- ${solution}`;\n      if (mode === OutputMode.RICH) {\n        lines.push(chalk.cyan(bullet));\n      } else {\n        lines.push(bullet);\n      }\n    });\n  }\n\n  return lines.join('\\n');\n}\n\n/**\n * Format a generic Error with fallback error info\n * @param error - The error to format\n * @param fallbackInfo - Fallback error info if not an AppError\n * @param options - Formatting options\n * @returns Formatted error string\n */\nexport function formatError(\n  error: Error,\n  fallbackInfo?: ErrorInfo,\n  options?: FormatOptions\n): string {\n  // If it's an AppError, format it directly\n  if (AppError.isAppError(error)) {\n    return formatAppError(error, options);\n  }\n\n  // If we have fallback info, use it\n  if (fallbackInfo) {\n    return formatErrorInfo(fallbackInfo, error.message, options);\n  }\n\n  // Simple fallback for generic errors\n  const mode = getOutputMode();\n  const icon = getErrorIcon();\n  const headerText = `${icon} \u9519\u8BEF: ${error.message}`;\n\n  if (mode === OutputMode.RICH) {\n    return chalk.red(headerText);\n  }\n  return headerText;\n}\n\n/**\n * Format error by looking up error code\n * @param code - Error code (e.g., \"E101\")\n * @param details - Additional details\n * @param options - Formatting options\n * @returns Formatted error string or undefined if code not found\n */\nexport function formatByCode(\n  code: string,\n  details?: string,\n  options?: FormatOptions\n): string | undefined {\n  const errorInfo = findErrorByCode(code);\n  if (!errorInfo) {\n    return undefined;\n  }\n  return formatErrorInfo(errorInfo, details, options);\n}\n\n/**\n * Create a simple error message (just the header line)\n * @param errorInfo - The error info\n * @param details - Additional details\n * @returns Simple error message\n */\nexport function simpleErrorMessage(errorInfo: ErrorInfo, details?: string): string {\n  const icon = getErrorIcon();\n  const message = details\n    ? `${icon} \u9519\u8BEF [${errorInfo.code}]: ${errorInfo.title} - ${details}`\n    : `${icon} \u9519\u8BEF [${errorInfo.code}]: ${errorInfo.title}`;\n\n  const mode = getOutputMode();\n  if (mode === OutputMode.RICH) {\n    return chalk.red(message);\n  }\n  return message;\n}\n", "/**\n * Custom Error Classes for CLI\n * @module utils/errors\n *\n * Provides structured error handling with error codes,\n * causes, and solutions for user-friendly error messages.\n */\n\nimport { ErrorInfo } from '../constants/error-codes';\n\n/**\n * Base application error with structured error information\n */\nexport class AppError extends Error {\n  /** Error code (e.g., E101) */\n  public readonly code: string;\n\n  /** Error title */\n  public readonly title: string;\n\n  /** Possible causes */\n  public readonly causes: readonly string[];\n\n  /** Suggested solutions */\n  public readonly solutions: readonly string[];\n\n  /** Additional context/details */\n  public readonly details?: string;\n\n  /**\n   * Create an AppError from ErrorInfo\n   * @param errorInfo - Error definition from error-codes.ts\n   * @param details - Additional context (e.g., file path, specific value)\n   */\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    // Build the message from title and details\n    const message = details ? `${errorInfo.title}: ${details}` : errorInfo.title;\n    super(message);\n\n    this.name = 'AppError';\n    this.code = errorInfo.code;\n    this.title = errorInfo.title;\n    this.causes = errorInfo.causes;\n    this.solutions = errorInfo.solutions;\n    this.details = details;\n\n    // Maintains proper stack trace for where error was thrown (V8 engines)\n    const ErrorWithCaptureStackTrace = Error as typeof Error & {\n      captureStackTrace?: (_target: object, _constructor: Function) => void;\n    };\n    if (ErrorWithCaptureStackTrace.captureStackTrace) {\n      ErrorWithCaptureStackTrace.captureStackTrace(this, AppError);\n    }\n  }\n\n  /**\n   * Check if an error is an AppError\n   */\n  static isAppError(error: unknown): error is AppError {\n    return error instanceof AppError;\n  }\n\n  /**\n   * Convert a generic Error to AppError with a fallback error info\n   */\n  static fromError(error: Error, fallbackInfo: ErrorInfo): AppError {\n    if (AppError.isAppError(error)) {\n      return error;\n    }\n    return new AppError(fallbackInfo, error.message);\n  }\n}\n\n/**\n * Configuration-related error\n */\nexport class ConfigError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'ConfigError';\n  }\n}\n\n/**\n * User management error\n */\nexport class UserError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'UserError';\n  }\n}\n\n/**\n * Quota management error\n */\nexport class QuotaError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'QuotaError';\n  }\n}\n\n/**\n * Service management error\n */\nexport class ServiceError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'ServiceError';\n  }\n}\n\n/**\n * Network-related error\n */\nexport class NetworkError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'NetworkError';\n  }\n}\n\n/**\n * File operation error\n */\nexport class FileError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'FileError';\n  }\n}\n\n/**\n * Input validation error\n */\nexport class ValidationError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Protocol parsing error (VLESS, etc.)\n */\nexport class ProtocolError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'ProtocolError';\n  }\n}\n\n/**\n * System/permission error\n */\nexport class SystemError extends AppError {\n  constructor(errorInfo: ErrorInfo, details?: string) {\n    super(errorInfo, details);\n    this.name = 'SystemError';\n  }\n}\n", "/**\n * Unified Error Code Definitions\n * @module constants/error-codes\n *\n * Error code format: E + Category + Number\n * - E1xx: Configuration errors\n * - E2xx: User management errors\n * - E3xx: Quota management errors\n * - E4xx: Service management errors\n * - E5xx: Network errors\n * - E6xx: File operation errors\n * - E7xx: Validation errors\n * - E8xx: VLESS/Protocol parsing errors\n * - E9xx: System/Permission errors\n */\n\n/**\n * Error information details\n */\nexport interface ErrorInfo {\n  /** Error code (e.g., E101) */\n  readonly code: string;\n  /** Error title (short description) */\n  readonly title: string;\n  /** Possible causes */\n  readonly causes: readonly string[];\n  /** Solutions */\n  readonly solutions: readonly string[];\n}\n\n/**\n * Configuration Errors (E1xx)\n */\nexport const ConfigErrors = {\n  CONFIG_NOT_FOUND: {\n    code: 'E101',\n    title: '\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728',\n    causes: ['Xray \u5C1A\u672A\u5B89\u88C5', '\u914D\u7F6E\u6587\u4EF6\u88AB\u5220\u9664\u6216\u79FB\u52A8', '\u8DEF\u5F84\u914D\u7F6E\u9519\u8BEF'],\n    solutions: [\n      '\u8FD0\u884C\u5B89\u88C5\u811A\u672C\u91CD\u65B0\u5B89\u88C5 Xray',\n      '\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: /usr/local/etc/xray/config.json',\n      \"\u4F7F\u7528 'xray-manager config --restore' \u4ECE\u5907\u4EFD\u6062\u590D\",\n    ],\n  },\n  CONFIG_NO_READ_PERMISSION: {\n    code: 'E102',\n    title: '\u914D\u7F6E\u6587\u4EF6\u65E0\u8BFB\u53D6\u6743\u9650',\n    causes: ['\u5F53\u524D\u7528\u6237\u6743\u9650\u4E0D\u8DB3', '\u6587\u4EF6\u6743\u9650\u8BBE\u7F6E\u9519\u8BEF', '\u672A\u4F7F\u7528 sudo \u8FD0\u884C'],\n    solutions: [\n      \"\u4F7F\u7528 sudo \u8FD0\u884C: 'sudo xray-manager' \u6216 'sudo xm'\",\n      \"\u68C0\u67E5\u6587\u4EF6\u6743\u9650: 'ls -la /usr/local/etc/xray/config.json'\",\n      \"\u4FEE\u6539\u6743\u9650: 'sudo chmod 644 /usr/local/etc/xray/config.json'\",\n    ],\n  },\n  CONFIG_NO_WRITE_PERMISSION: {\n    code: 'E103',\n    title: '\u914D\u7F6E\u6587\u4EF6\u65E0\u5199\u5165\u6743\u9650',\n    causes: ['\u5F53\u524D\u7528\u6237\u6743\u9650\u4E0D\u8DB3', '\u6587\u4EF6\u7CFB\u7EDF\u53EA\u8BFB', '\u78C1\u76D8\u7A7A\u95F4\u4E0D\u8DB3'],\n    solutions: [\n      \"\u4F7F\u7528 sudo \u8FD0\u884C: 'sudo xray-manager' \u6216 'sudo xm'\",\n      \"\u68C0\u67E5\u78C1\u76D8\u7A7A\u95F4: 'df -h'\",\n      '\u68C0\u67E5\u6587\u4EF6\u7CFB\u7EDF\u72B6\u6001',\n    ],\n  },\n  CONFIG_INVALID_JSON: {\n    code: 'E104',\n    title: '\u914D\u7F6E\u6587\u4EF6 JSON \u683C\u5F0F\u9519\u8BEF',\n    causes: ['JSON \u8BED\u6CD5\u9519\u8BEF', '\u6587\u4EF6\u88AB\u635F\u574F', '\u7F16\u8F91\u65F6\u5F15\u5165\u9519\u8BEF'],\n    solutions: [\n      \"\u4F7F\u7528 JSON \u9A8C\u8BC1\u5DE5\u5177\u68C0\u67E5: 'cat config.json | jq .'\",\n      \"\u4ECE\u5907\u4EFD\u6062\u590D: 'xray-manager config --restore'\",\n      '\u624B\u52A8\u68C0\u67E5 JSON \u8BED\u6CD5\uFF08\u5F15\u53F7\u3001\u9017\u53F7\u3001\u62EC\u53F7\u5339\u914D\uFF09',\n    ],\n  },\n  CONFIG_INVALID_STRUCTURE: {\n    code: 'E105',\n    title: '\u914D\u7F6E\u6587\u4EF6\u7ED3\u6784\u65E0\u6548',\n    causes: ['\u7F3A\u5C11\u5FC5\u8981\u5B57\u6BB5 (inbounds/outbounds)', 'Xray \u7248\u672C\u4E0D\u517C\u5BB9', '\u914D\u7F6E\u683C\u5F0F\u8FC7\u65F6'],\n    solutions: [\n      '\u786E\u4FDD\u914D\u7F6E\u5305\u542B inbounds \u548C outbounds \u6570\u7EC4',\n      '\u53C2\u8003 Xray \u5B98\u65B9\u6587\u6863\u68C0\u67E5\u914D\u7F6E\u683C\u5F0F',\n      '\u4F7F\u7528\u6A21\u677F\u91CD\u65B0\u751F\u6210\u914D\u7F6E\u6587\u4EF6',\n    ],\n  },\n  CONFIG_BACKUP_FAILED: {\n    code: 'E106',\n    title: '\u914D\u7F6E\u5907\u4EFD\u5931\u8D25',\n    causes: ['\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728', '\u78C1\u76D8\u7A7A\u95F4\u4E0D\u8DB3', '\u6743\u9650\u4E0D\u8DB3'],\n    solutions: ['\u786E\u4FDD\u5907\u4EFD\u76EE\u5F55\u5B58\u5728', \"\u68C0\u67E5\u78C1\u76D8\u7A7A\u95F4: 'df -h'\", '\u4F7F\u7528 sudo \u8FD0\u884C\u7A0B\u5E8F'],\n  },\n  CONFIG_RESTORE_FAILED: {\n    code: 'E107',\n    title: '\u914D\u7F6E\u6062\u590D\u5931\u8D25',\n    causes: ['\u5907\u4EFD\u6587\u4EF6\u4E0D\u5B58\u5728', '\u5907\u4EFD\u6587\u4EF6\u5DF2\u635F\u574F', '\u6743\u9650\u4E0D\u8DB3'],\n    solutions: [\n      \"\u5217\u51FA\u53EF\u7528\u5907\u4EFD: 'xray-manager config --list-backups'\",\n      '\u9009\u62E9\u4E00\u4E2A\u6709\u6548\u7684\u5907\u4EFD\u6587\u4EF6',\n      '\u786E\u4FDD\u6709\u8DB3\u591F\u6743\u9650\u5199\u5165\u914D\u7F6E\u6587\u4EF6',\n    ],\n  },\n} as const;\n\n/**\n * User Management Errors (E2xx)\n */\nexport const UserErrors = {\n  INVALID_EMAIL: {\n    code: 'E201',\n    title: '\u90AE\u7BB1\u5730\u5740\u683C\u5F0F\u65E0\u6548',\n    causes: ['\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E', '\u5305\u542B\u975E\u6CD5\u5B57\u7B26', '\u7F3A\u5C11\u5FC5\u8981\u90E8\u5206 (@, \u57DF\u540D)'],\n    solutions: [\n      '\u4F7F\u7528\u6807\u51C6\u90AE\u7BB1\u683C\u5F0F: user@example.com',\n      '\u786E\u4FDD\u90AE\u7BB1\u53EA\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u5141\u8BB8\u7684\u7279\u6B8A\u5B57\u7B26',\n      '\u68C0\u67E5\u662F\u5426\u6709\u591A\u4F59\u7684\u7A7A\u683C',\n    ],\n  },\n  EMAIL_EXISTS: {\n    code: 'E202',\n    title: '\u90AE\u7BB1\u5730\u5740\u5DF2\u5B58\u5728',\n    causes: ['\u8BE5\u90AE\u7BB1\u5DF2\u88AB\u5176\u4ED6\u7528\u6237\u4F7F\u7528', '\u5C1D\u8BD5\u521B\u5EFA\u91CD\u590D\u7528\u6237'],\n    solutions: [\n      \"\u4F7F\u7528 'xray-manager user list' \u67E5\u770B\u73B0\u6709\u7528\u6237\",\n      '\u9009\u62E9\u4E00\u4E2A\u4E0D\u540C\u7684\u90AE\u7BB1\u5730\u5740',\n      \"\u5982\u9700\u66F4\u65B0\u7528\u6237\uFF0C\u4F7F\u7528 'xray-manager user update' \u547D\u4EE4\",\n    ],\n  },\n  USER_NOT_FOUND: {\n    code: 'E203',\n    title: '\u7528\u6237\u4E0D\u5B58\u5728',\n    causes: ['\u7528\u6237\u5DF2\u88AB\u5220\u9664', '\u90AE\u7BB1\u5730\u5740\u8F93\u5165\u9519\u8BEF', '\u7528\u6237\u4ECE\u672A\u521B\u5EFA'],\n    solutions: [\n      \"\u4F7F\u7528 'xray-manager user list' \u67E5\u770B\u6240\u6709\u7528\u6237\",\n      '\u68C0\u67E5\u90AE\u7BB1\u5730\u5740\u662F\u5426\u6B63\u786E\uFF08\u533A\u5206\u5927\u5C0F\u5199\uFF09',\n      \"\u4F7F\u7528 'xray-manager user add' \u521B\u5EFA\u65B0\u7528\u6237\",\n    ],\n  },\n  INVALID_UUID: {\n    code: 'E204',\n    title: 'UUID \u683C\u5F0F\u65E0\u6548',\n    causes: ['UUID \u683C\u5F0F\u4E0D\u6B63\u786E', '\u4E0D\u662F\u6709\u6548\u7684 UUID v4', '\u590D\u5236\u65F6\u4E22\u5931\u90E8\u5206\u5B57\u7B26'],\n    solutions: [\n      'UUID \u5E94\u4E3A 36 \u5B57\u7B26\u683C\u5F0F: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx',\n      '\u4F7F\u7528\u7CFB\u7EDF\u751F\u6210\u7684 UUID\uFF0C\u4E0D\u8981\u624B\u52A8\u7F16\u8F91',\n      \"\u53EF\u4F7F\u7528 'uuidgen' \u547D\u4EE4\u751F\u6210\u65B0 UUID\",\n    ],\n  },\n  KEY_GENERATION_FAILED: {\n    code: 'E205',\n    title: '\u5BC6\u94A5\u751F\u6210\u5931\u8D25',\n    causes: ['xray \u547D\u4EE4\u4E0D\u53EF\u7528', 'x25519 \u7B97\u6CD5\u4E0D\u652F\u6301', '\u7CFB\u7EDF\u968F\u673A\u6570\u751F\u6210\u5668\u95EE\u9898'],\n    solutions: [\n      \"\u786E\u4FDD Xray \u5DF2\u6B63\u786E\u5B89\u88C5: 'xray version'\",\n      '\u68C0\u67E5 Xray \u7248\u672C\u662F\u5426\u652F\u6301 x25519',\n      '\u91CD\u65B0\u5B89\u88C5 Xray',\n    ],\n  },\n} as const;\n\n/**\n * Quota Management Errors (E3xx)\n */\nexport const QuotaErrors = {\n  QUOTA_CONFIG_NOT_FOUND: {\n    code: 'E301',\n    title: '\u914D\u989D\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728',\n    causes: ['\u914D\u989D\u529F\u80FD\u672A\u521D\u59CB\u5316', '\u6587\u4EF6\u88AB\u5220\u9664', '\u8DEF\u5F84\u914D\u7F6E\u9519\u8BEF'],\n    solutions: [\n      \"\u8FD0\u884C 'xray-manager quota init' \u521D\u59CB\u5316\u914D\u989D\u7CFB\u7EDF\",\n      '\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84: /usr/local/etc/xray/quota.json',\n      '\u786E\u4FDD Xray \u914D\u7F6E\u76EE\u5F55\u5B58\u5728',\n    ],\n  },\n  INVALID_QUOTA_VALUE: {\n    code: 'E302',\n    title: '\u914D\u989D\u503C\u65E0\u6548',\n    causes: ['\u6570\u503C\u4E0D\u662F\u6709\u6548\u6570\u5B57', '\u6570\u503C\u4E3A\u8D1F\u6570\uFF08\u975E -1\uFF09', '\u8D85\u51FA\u5141\u8BB8\u8303\u56F4'],\n    solutions: [\n      '\u914D\u989D\u503C\u5FC5\u987B\u4E3A -1\uFF08\u65E0\u9650\u5236\uFF09\u6216 >= 0 \u7684\u6574\u6570',\n      '\u4F7F\u7528\u5B57\u8282\u4E3A\u5355\u4F4D\u6216\u5E26\u5355\u4F4D\u7684\u683C\u5F0F\uFF08\u5982 10GB\uFF09',\n      \"\u8BBE\u7F6E\u65E0\u9650\u5236\u914D\u989D\u4F7F\u7528 '-1'\",\n    ],\n  },\n  USER_QUOTA_NOT_FOUND: {\n    code: 'E303',\n    title: '\u7528\u6237\u914D\u989D\u4E0D\u5B58\u5728',\n    causes: ['\u7528\u6237\u672A\u8BBE\u7F6E\u914D\u989D', '\u7528\u6237\u90AE\u7BB1\u9519\u8BEF', '\u7528\u6237\u5DF2\u88AB\u5220\u9664'],\n    solutions: [\n      \"\u4F7F\u7528 'xray-manager quota list' \u67E5\u770B\u6240\u6709\u914D\u989D\",\n      \"\u4F7F\u7528 'xray-manager quota set <email> <limit>' \u8BBE\u7F6E\u914D\u989D\",\n      '\u786E\u8BA4\u7528\u6237\u90AE\u7BB1\u5730\u5740\u6B63\u786E',\n    ],\n  },\n  TRAFFIC_UPDATE_FAILED: {\n    code: 'E304',\n    title: '\u6D41\u91CF\u7EDF\u8BA1\u66F4\u65B0\u5931\u8D25',\n    causes: ['\u914D\u989D\u6587\u4EF6\u5199\u5165\u5931\u8D25', '\u5E76\u53D1\u8BBF\u95EE\u51B2\u7A81', '\u6570\u636E\u683C\u5F0F\u9519\u8BEF'],\n    solutions: ['\u68C0\u67E5\u914D\u989D\u6587\u4EF6\u5199\u5165\u6743\u9650', '\u786E\u4FDD\u6CA1\u6709\u5176\u4ED6\u8FDB\u7A0B\u6B63\u5728\u4FEE\u6539\u914D\u989D\u6587\u4EF6', '\u91CD\u65B0\u521D\u59CB\u5316\u914D\u989D\u7CFB\u7EDF'],\n  },\n  QUOTA_EXCEEDED: {\n    code: 'E305',\n    title: '\u7528\u6237\u6D41\u91CF\u914D\u989D\u5DF2\u8D85\u9650',\n    causes: ['\u7528\u6237\u6D41\u91CF\u4F7F\u7528\u8D85\u8FC7\u9650\u5236', '\u914D\u989D\u8BBE\u7F6E\u8FC7\u4F4E'],\n    solutions: [\n      \"\u4F7F\u7528 'xray-manager quota set <email> <new_limit>' \u589E\u52A0\u914D\u989D\",\n      \"\u4F7F\u7528 'xray-manager quota reset <email>' \u91CD\u7F6E\u6D41\u91CF\u7EDF\u8BA1\",\n      '\u8003\u8651\u8BBE\u7F6E\u65E0\u9650\u5236\u914D\u989D (-1)',\n    ],\n  },\n} as const;\n\n/**\n * Service Management Errors (E4xx)\n */\nexport const ServiceErrors = {\n  SERVICE_NOT_RUNNING: {\n    code: 'E401',\n    title: 'Xray \u670D\u52A1\u672A\u8FD0\u884C',\n    causes: ['\u670D\u52A1\u672A\u542F\u52A8', '\u670D\u52A1\u542F\u52A8\u540E\u5D29\u6E83', '\u914D\u7F6E\u9519\u8BEF\u5BFC\u81F4\u542F\u52A8\u5931\u8D25'],\n    solutions: [\n      \"\u542F\u52A8\u670D\u52A1: 'sudo systemctl start xray'\",\n      \"\u67E5\u770B\u670D\u52A1\u72B6\u6001: 'sudo systemctl status xray'\",\n      \"\u68C0\u67E5\u65E5\u5FD7: 'sudo journalctl -u xray -n 50'\",\n    ],\n  },\n  SERVICE_START_FAILED: {\n    code: 'E402',\n    title: '\u670D\u52A1\u542F\u52A8\u5931\u8D25',\n    causes: ['\u914D\u7F6E\u6587\u4EF6\u9519\u8BEF', '\u7AEF\u53E3\u88AB\u5360\u7528', '\u6743\u9650\u4E0D\u8DB3'],\n    solutions: [\n      \"\u9A8C\u8BC1\u914D\u7F6E: 'xray run -test -c /usr/local/etc/xray/config.json'\",\n      \"\u68C0\u67E5\u7AEF\u53E3\u5360\u7528: 'ss -tlnp | grep <port>'\",\n      \"\u67E5\u770B\u8BE6\u7EC6\u65E5\u5FD7: 'sudo journalctl -u xray -n 100'\",\n    ],\n  },\n  SERVICE_STOP_FAILED: {\n    code: 'E403',\n    title: '\u670D\u52A1\u505C\u6B62\u5931\u8D25',\n    causes: ['\u670D\u52A1\u8FDB\u7A0B\u50F5\u6B7B', '\u6743\u9650\u4E0D\u8DB3', 'systemd \u95EE\u9898'],\n    solutions: [\n      \"\u5F3A\u5236\u505C\u6B62: 'sudo systemctl kill xray'\",\n      \"\u68C0\u67E5\u8FDB\u7A0B: 'ps aux | grep xray'\",\n      \"\u624B\u52A8\u7EC8\u6B62: 'sudo kill -9 <pid>'\",\n    ],\n  },\n  INVALID_SERVICE_NAME: {\n    code: 'E404',\n    title: '\u670D\u52A1\u540D\u79F0\u65E0\u6548',\n    causes: ['\u5305\u542B\u975E\u6CD5\u5B57\u7B26', '\u8DEF\u5F84\u904D\u5386\u5C1D\u8BD5', '\u540D\u79F0\u4E3A\u7A7A'],\n    solutions: [\n      '\u670D\u52A1\u540D\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u548C @._- \u5B57\u7B26',\n      '\u9ED8\u8BA4\u670D\u52A1\u540D\u4E3A \"xray\"',\n      '\u4E0D\u8981\u5728\u670D\u52A1\u540D\u4E2D\u4F7F\u7528\u8DEF\u5F84\u5206\u9694\u7B26',\n    ],\n  },\n  SYSTEMD_NOT_AVAILABLE: {\n    code: 'E405',\n    title: 'systemd \u4E0D\u53EF\u7528',\n    causes: ['\u7CFB\u7EDF\u672A\u4F7F\u7528 systemd', '\u5728\u5BB9\u5668\u4E2D\u8FD0\u884C', 'systemd \u670D\u52A1\u672A\u542F\u52A8'],\n    solutions: [\n      '\u786E\u4FDD\u7CFB\u7EDF\u4F7F\u7528 systemd \u4F5C\u4E3A init \u7CFB\u7EDF',\n      \"\u68C0\u67E5 systemd \u72B6\u6001: 'systemctl --version'\",\n      '\u5982\u5728\u5BB9\u5668\u4E2D\uFF0C\u9700\u624B\u52A8\u7BA1\u7406\u8FDB\u7A0B',\n    ],\n  },\n} as const;\n\n/**\n * Network Errors (E5xx)\n */\nexport const NetworkErrors = {\n  CONNECTION_REFUSED: {\n    code: 'E501',\n    title: '\u8FDE\u63A5\u88AB\u62D2\u7EDD',\n    causes: ['\u76EE\u6807\u670D\u52A1\u672A\u8FD0\u884C', '\u7AEF\u53E3\u672A\u5F00\u653E', '\u9632\u706B\u5899\u963B\u6B62'],\n    solutions: [\n      '\u68C0\u67E5\u76EE\u6807\u670D\u52A1\u662F\u5426\u8FD0\u884C',\n      \"\u68C0\u67E5\u9632\u706B\u5899\u89C4\u5219: 'sudo ufw status'\",\n      \"\u5F00\u653E\u7AEF\u53E3: 'sudo ufw allow <port>'\",\n    ],\n  },\n  CONNECTION_TIMEOUT: {\n    code: 'E502',\n    title: '\u8FDE\u63A5\u8D85\u65F6',\n    causes: ['\u7F51\u7EDC\u4E0D\u7A33\u5B9A', '\u670D\u52A1\u5668\u65E0\u54CD\u5E94', '\u9632\u706B\u5899\u4E22\u5F03\u6570\u636E\u5305'],\n    solutions: ['\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5', \"\u6D4B\u8BD5\u7F51\u7EDC: 'ping <server_ip>'\", '\u68C0\u67E5\u670D\u52A1\u5668\u7AEF\u9632\u706B\u5899\u8BBE\u7F6E'],\n  },\n  PUBLIC_IP_FAILED: {\n    code: 'E503',\n    title: '\u65E0\u6CD5\u83B7\u53D6\u516C\u7F51 IP',\n    causes: ['\u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898', 'IP \u68C0\u6D4B\u670D\u52A1\u4E0D\u53EF\u7528', 'DNS \u89E3\u6790\u5931\u8D25'],\n    solutions: [\n      \"\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5: 'curl -s https://api.ipify.org'\",\n      '\u624B\u52A8\u6307\u5B9A\u670D\u52A1\u5668 IP \u5730\u5740',\n      '\u68C0\u67E5 DNS \u8BBE\u7F6E',\n    ],\n  },\n  INVALID_PORT: {\n    code: 'E504',\n    title: '\u7AEF\u53E3\u53F7\u65E0\u6548',\n    causes: ['\u7AEF\u53E3\u53F7\u8D85\u51FA\u8303\u56F4', '\u7AEF\u53E3\u53F7\u4E0D\u662F\u6570\u5B57', '\u4F7F\u7528\u4E86\u4FDD\u7559\u7AEF\u53E3'],\n    solutions: [\n      '\u7AEF\u53E3\u53F7\u5FC5\u987B\u5728 1-65535 \u4E4B\u95F4',\n      '\u5EFA\u8BAE\u4F7F\u7528 1024 \u4EE5\u4E0A\u7684\u7AEF\u53E3',\n      '\u786E\u4FDD\u7AEF\u53E3\u672A\u88AB\u5176\u4ED6\u670D\u52A1\u5360\u7528',\n    ],\n  },\n  PORT_IN_USE: {\n    code: 'E505',\n    title: '\u7AEF\u53E3\u5DF2\u88AB\u5360\u7528',\n    causes: ['\u5176\u4ED6\u7A0B\u5E8F\u6B63\u5728\u4F7F\u7528\u8BE5\u7AEF\u53E3', 'Xray \u5DF2\u5728\u8FD0\u884C', '\u7CFB\u7EDF\u670D\u52A1\u5360\u7528'],\n    solutions: [\n      \"\u67E5\u770B\u7AEF\u53E3\u5360\u7528: 'ss -tlnp | grep <port>'\",\n      '\u9009\u62E9\u5176\u4ED6\u672A\u4F7F\u7528\u7684\u7AEF\u53E3',\n      '\u505C\u6B62\u5360\u7528\u7AEF\u53E3\u7684\u670D\u52A1\u540E\u91CD\u8BD5',\n    ],\n  },\n} as const;\n\n/**\n * File Operation Errors (E6xx)\n */\nexport const FileErrors = {\n  FILE_NOT_FOUND: {\n    code: 'E601',\n    title: '\u6587\u4EF6\u4E0D\u5B58\u5728',\n    causes: ['\u6587\u4EF6\u5DF2\u88AB\u5220\u9664', '\u8DEF\u5F84\u9519\u8BEF', '\u4ECE\u672A\u521B\u5EFA'],\n    solutions: ['\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E', '\u786E\u8BA4\u6587\u4EF6\u662F\u5426\u5DF2\u521B\u5EFA', '\u68C0\u67E5\u7236\u76EE\u5F55\u662F\u5426\u5B58\u5728'],\n  },\n  DIRECTORY_NOT_FOUND: {\n    code: 'E602',\n    title: '\u76EE\u5F55\u4E0D\u5B58\u5728',\n    causes: ['\u76EE\u5F55\u5DF2\u88AB\u5220\u9664', '\u8DEF\u5F84\u9519\u8BEF', '\u7236\u76EE\u5F55\u4E0D\u5B58\u5728'],\n    solutions: [\"\u521B\u5EFA\u76EE\u5F55: 'mkdir -p <path>'\", '\u68C0\u67E5\u8DEF\u5F84\u62FC\u5199', '\u786E\u4FDD\u6709\u521B\u5EFA\u76EE\u5F55\u7684\u6743\u9650'],\n  },\n  FILE_READ_FAILED: {\n    code: 'E603',\n    title: '\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25',\n    causes: ['\u6743\u9650\u4E0D\u8DB3', '\u6587\u4EF6\u88AB\u9501\u5B9A', '\u6587\u4EF6\u5DF2\u635F\u574F'],\n    solutions: ['\u4F7F\u7528 sudo \u8FD0\u884C', '\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u88AB\u5176\u4ED6\u8FDB\u7A0B\u5360\u7528', '\u68C0\u67E5\u6587\u4EF6\u6743\u9650\u8BBE\u7F6E'],\n  },\n  FILE_WRITE_FAILED: {\n    code: 'E604',\n    title: '\u6587\u4EF6\u5199\u5165\u5931\u8D25',\n    causes: ['\u6743\u9650\u4E0D\u8DB3', '\u78C1\u76D8\u7A7A\u95F4\u4E0D\u8DB3', '\u6587\u4EF6\u7CFB\u7EDF\u53EA\u8BFB'],\n    solutions: ['\u4F7F\u7528 sudo \u8FD0\u884C', \"\u68C0\u67E5\u78C1\u76D8\u7A7A\u95F4: 'df -h'\", '\u68C0\u67E5\u6587\u4EF6\u7CFB\u7EDF\u6302\u8F7D\u72B6\u6001'],\n  },\n} as const;\n\n/**\n * Validation Errors (E7xx)\n */\nexport const ValidationErrors = {\n  REQUIRED_FIELD_EMPTY: {\n    code: 'E701',\n    title: '\u5FC5\u586B\u5B57\u6BB5\u4E0D\u80FD\u4E3A\u7A7A',\n    causes: ['\u672A\u63D0\u4F9B\u5FC5\u8981\u7684\u8F93\u5165', '\u8F93\u5165\u53EA\u5305\u542B\u7A7A\u767D\u5B57\u7B26'],\n    solutions: ['\u8BF7\u63D0\u4F9B\u6240\u6709\u5FC5\u586B\u5B57\u6BB5\u7684\u503C', '\u68C0\u67E5\u8F93\u5165\u662F\u5426\u5305\u542B\u6709\u6548\u5185\u5BB9'],\n  },\n  INVALID_FORMAT: {\n    code: 'E702',\n    title: '\u8F93\u5165\u683C\u5F0F\u4E0D\u6B63\u786E',\n    causes: ['\u8F93\u5165\u4E0D\u7B26\u5408\u9884\u671F\u683C\u5F0F', '\u5305\u542B\u975E\u6CD5\u5B57\u7B26'],\n    solutions: ['\u68C0\u67E5\u8F93\u5165\u683C\u5F0F\u8981\u6C42', '\u53C2\u8003\u793A\u4F8B\u8F93\u5165'],\n  },\n  VALUE_OUT_OF_RANGE: {\n    code: 'E703',\n    title: '\u503C\u8D85\u51FA\u6709\u6548\u8303\u56F4',\n    causes: ['\u6570\u503C\u8FC7\u5927\u6216\u8FC7\u5C0F', '\u8D85\u51FA\u5141\u8BB8\u7684\u9650\u5236'],\n    solutions: ['\u68C0\u67E5\u5141\u8BB8\u7684\u503C\u8303\u56F4', '\u4F7F\u7528\u8303\u56F4\u5185\u7684\u503C\u91CD\u8BD5'],\n  },\n} as const;\n\n/**\n * VLESS/Protocol Parsing Errors (E8xx)\n */\nexport const ProtocolErrors = {\n  INVALID_VLESS_LINK: {\n    code: 'E801',\n    title: 'VLESS \u94FE\u63A5\u683C\u5F0F\u65E0\u6548',\n    causes: ['\u94FE\u63A5\u683C\u5F0F\u4E0D\u6B63\u786E', '\u4E0D\u662F vless:// \u534F\u8BAE', '\u94FE\u63A5\u4E0D\u5B8C\u6574'],\n    solutions: ['\u786E\u4FDD\u94FE\u63A5\u4EE5 vless:// \u5F00\u5934', '\u68C0\u67E5\u94FE\u63A5\u662F\u5426\u5B8C\u6574\u590D\u5236', '\u9A8C\u8BC1\u94FE\u63A5\u6765\u6E90\u662F\u5426\u53EF\u9760'],\n  },\n  VLESS_MISSING_UUID: {\n    code: 'E802',\n    title: 'VLESS \u94FE\u63A5\u7F3A\u5C11 UUID',\n    causes: ['\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF', 'UUID \u90E8\u5206\u88AB\u622A\u65AD'],\n    solutions: ['\u68C0\u67E5\u94FE\u63A5\u662F\u5426\u5B8C\u6574', '\u91CD\u65B0\u83B7\u53D6\u6B63\u786E\u7684\u5206\u4EAB\u94FE\u63A5'],\n  },\n  VLESS_MISSING_HOST: {\n    code: 'E803',\n    title: 'VLESS \u94FE\u63A5\u7F3A\u5C11\u670D\u52A1\u5668\u5730\u5740',\n    causes: ['\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF', '\u670D\u52A1\u5668\u5730\u5740\u90E8\u5206\u7F3A\u5931'],\n    solutions: ['\u68C0\u67E5\u94FE\u63A5\u683C\u5F0F', '\u786E\u4FDD\u5305\u542B\u670D\u52A1\u5668\u5730\u5740\u548C\u7AEF\u53E3'],\n  },\n  VLESS_INVALID_PORT: {\n    code: 'E804',\n    title: 'VLESS \u94FE\u63A5\u7AEF\u53E3\u65E0\u6548',\n    causes: ['\u7AEF\u53E3\u4E0D\u662F\u6570\u5B57', '\u7AEF\u53E3\u8D85\u51FA\u8303\u56F4'],\n    solutions: ['\u7AEF\u53E3\u5FC5\u987B\u662F 1-65535 \u4E4B\u95F4\u7684\u6570\u5B57', '\u68C0\u67E5\u94FE\u63A5\u683C\u5F0F\u662F\u5426\u6B63\u786E'],\n  },\n  VLESS_MISSING_REALITY_PBK: {\n    code: 'E805',\n    title: 'Reality \u94FE\u63A5\u7F3A\u5C11\u516C\u94A5\u53C2\u6570',\n    causes: ['\u94FE\u63A5\u7F3A\u5C11 pbk \u53C2\u6570', 'Reality \u914D\u7F6E\u4E0D\u5B8C\u6574'],\n    solutions: ['Reality \u94FE\u63A5\u5FC5\u987B\u5305\u542B pbk (\u516C\u94A5) \u53C2\u6570', '\u91CD\u65B0\u751F\u6210\u5305\u542B\u5B8C\u6574\u53C2\u6570\u7684\u94FE\u63A5'],\n  },\n} as const;\n\n/**\n * System/Permission Errors (E9xx)\n */\nexport const SystemErrors = {\n  ROOT_REQUIRED: {\n    code: 'E901',\n    title: '\u9700\u8981\u7BA1\u7406\u5458\u6743\u9650',\n    causes: ['\u5F53\u524D\u7528\u6237\u4E0D\u662F root', '\u672A\u4F7F\u7528 sudo \u8FD0\u884C'],\n    solutions: [\"\u4F7F\u7528 sudo \u8FD0\u884C: 'sudo xray-vpn'\", \"\u5207\u6362\u5230 root \u7528\u6237: 'su -'\"],\n  },\n  UNSUPPORTED_OS: {\n    code: 'E902',\n    title: '\u4E0D\u652F\u6301\u7684\u64CD\u4F5C\u7CFB\u7EDF',\n    causes: ['\u64CD\u4F5C\u7CFB\u7EDF\u4E0D\u517C\u5BB9', '\u7CFB\u7EDF\u7248\u672C\u8FC7\u4F4E'],\n    solutions: [\n      '\u652F\u6301\u7684\u7CFB\u7EDF: Ubuntu 18+, Debian 10+, CentOS 7+, Fedora 30+',\n      '\u8003\u8651\u4F7F\u7528 Docker \u5BB9\u5668\u8FD0\u884C',\n    ],\n  },\n  DEPENDENCY_MISSING: {\n    code: 'E903',\n    title: '\u7F3A\u5C11\u5FC5\u8981\u7684\u4F9D\u8D56',\n    causes: ['\u7CFB\u7EDF\u5DE5\u5177\u672A\u5B89\u88C5', 'Node.js \u7248\u672C\u4E0D\u517C\u5BB9'],\n    solutions: [\n      '\u8FD0\u884C\u5B89\u88C5\u811A\u672C\u81EA\u52A8\u5B89\u88C5\u4F9D\u8D56',\n      '\u786E\u4FDD Node.js >= 18.0.0',\n      \"\u68C0\u67E5 xray \u662F\u5426\u5B89\u88C5: 'xray version'\",\n    ],\n  },\n  PREFLIGHT_FAILED: {\n    code: 'E904',\n    title: '\u542F\u52A8\u9884\u68C0\u67E5\u5931\u8D25',\n    causes: ['\u7CFB\u7EDF\u73AF\u5883\u4E0D\u6EE1\u8DB3\u8981\u6C42', '\u5FC5\u8981\u670D\u52A1\u672A\u8FD0\u884C', '\u914D\u7F6E\u5B58\u5728\u95EE\u9898'],\n    solutions: ['\u8FD0\u884C\u8BCA\u65AD\u547D\u4EE4\u68C0\u67E5\u95EE\u9898', '\u68C0\u67E5\u4E0A\u8FF0\u9519\u8BEF\u4FE1\u606F\u5E76\u9010\u4E00\u89E3\u51B3', '\u786E\u4FDD\u6240\u6709\u5FC5\u8981\u670D\u52A1\u5DF2\u542F\u52A8'],\n  },\n} as const;\n\n/**\n * Union type of all error codes\n */\nexport type ErrorCode =\n  | (typeof ConfigErrors)[keyof typeof ConfigErrors]\n  | (typeof UserErrors)[keyof typeof UserErrors]\n  | (typeof QuotaErrors)[keyof typeof QuotaErrors]\n  | (typeof ServiceErrors)[keyof typeof ServiceErrors]\n  | (typeof NetworkErrors)[keyof typeof NetworkErrors]\n  | (typeof FileErrors)[keyof typeof FileErrors]\n  | (typeof ValidationErrors)[keyof typeof ValidationErrors]\n  | (typeof ProtocolErrors)[keyof typeof ProtocolErrors]\n  | (typeof SystemErrors)[keyof typeof SystemErrors];\n\n/**\n * Find error info by error code string\n */\nexport function findErrorByCode(code: string): ErrorInfo | undefined {\n  const allErrors = {\n    ...ConfigErrors,\n    ...UserErrors,\n    ...QuotaErrors,\n    ...ServiceErrors,\n    ...NetworkErrors,\n    ...FileErrors,\n    ...ValidationErrors,\n    ...ProtocolErrors,\n    ...SystemErrors,\n  };\n\n  for (const error of Object.values(allErrors)) {\n    if (error.code === code) {\n      return error;\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Get all error codes list\n */\nexport function getAllErrorCodes(): string[] {\n  const allErrors = {\n    ...ConfigErrors,\n    ...UserErrors,\n    ...QuotaErrors,\n    ...ServiceErrors,\n    ...NetworkErrors,\n    ...FileErrors,\n    ...ValidationErrors,\n    ...ProtocolErrors,\n    ...SystemErrors,\n  };\n\n  return Object.values(allErrors).map((e) => e.code);\n}\n", "/**\n * \u6807\u51C6\u5316\u9000\u51FA\u4EE3\u7801\n * @module constants/exit-codes\n */\n\n/**\n * CLI \u5DE5\u5177\u9000\u51FA\u4EE3\u7801\u5E38\u91CF\n * \u9075\u5FAA Unix/Linux \u9000\u51FA\u4EE3\u7801\u89C4\u8303\n */\nexport const ExitCode = {\n  /** \u6210\u529F */\n  SUCCESS: 0,\n\n  /** \u901A\u7528\u9519\u8BEF */\n  GENERAL_ERROR: 1,\n\n  /** \u53C2\u6570\u9519\u8BEF - \u65E0\u6548\u7684\u547D\u4EE4\u884C\u53C2\u6570\u6216\u9009\u9879 */\n  INVALID_ARGUMENT: 2,\n\n  /** \u914D\u7F6E\u9519\u8BEF - \u914D\u7F6E\u6587\u4EF6\u9519\u8BEF\u3001\u7F3A\u5931\u6216\u65E0\u6CD5\u89E3\u6790 */\n  CONFIG_ERROR: 3,\n\n  /** \u6743\u9650\u9519\u8BEF - \u9700\u8981 root/sudo \u6743\u9650\u4F46\u672A\u63D0\u4F9B */\n  PERMISSION_ERROR: 4,\n\n  /** \u670D\u52A1\u9519\u8BEF - systemd \u670D\u52A1\u64CD\u4F5C\u5931\u8D25 */\n  SERVICE_ERROR: 5,\n\n  /** \u7F51\u7EDC\u9519\u8BEF - \u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25\u6216\u8D85\u65F6 */\n  NETWORK_ERROR: 6,\n\n  /** \u6587\u4EF6\u9519\u8BEF - \u6587\u4EF6\u8BFB\u5199\u64CD\u4F5C\u5931\u8D25 */\n  FILE_ERROR: 7,\n\n  /** \u9A8C\u8BC1\u9519\u8BEF - \u8F93\u5165\u9A8C\u8BC1\u5931\u8D25\uFF08\u90AE\u7BB1\u3001UUID \u7B49\uFF09 */\n  VALIDATION_ERROR: 8,\n\n  /** \u672A\u627E\u5230 - \u8D44\u6E90\u4E0D\u5B58\u5728\uFF08\u7528\u6237\u3001\u670D\u52A1\u7B49\uFF09 */\n  NOT_FOUND: 9,\n\n  /** \u7528\u6237\u4E2D\u65AD - Ctrl+C \u4E2D\u65AD\u7A0B\u5E8F\u6267\u884C */\n  SIGINT: 130,\n} as const;\n\n/**\n * \u9000\u51FA\u4EE3\u7801\u7C7B\u578B\n */\nexport type ExitCodeType = (typeof ExitCode)[keyof typeof ExitCode];\n\n/**\n * \u9000\u51FA\u4EE3\u7801\u5230\u63CF\u8FF0\u7684\u6620\u5C04\n */\nexport const ExitCodeDescription: Record<number, string> = {\n  [ExitCode.SUCCESS]: '\u6210\u529F',\n  [ExitCode.GENERAL_ERROR]: '\u901A\u7528\u9519\u8BEF',\n  [ExitCode.INVALID_ARGUMENT]: '\u53C2\u6570\u9519\u8BEF',\n  [ExitCode.CONFIG_ERROR]: '\u914D\u7F6E\u9519\u8BEF',\n  [ExitCode.PERMISSION_ERROR]: '\u6743\u9650\u4E0D\u8DB3',\n  [ExitCode.SERVICE_ERROR]: '\u670D\u52A1\u64CD\u4F5C\u5931\u8D25',\n  [ExitCode.NETWORK_ERROR]: '\u7F51\u7EDC\u9519\u8BEF',\n  [ExitCode.FILE_ERROR]: '\u6587\u4EF6\u9519\u8BEF',\n  [ExitCode.VALIDATION_ERROR]: '\u8F93\u5165\u9A8C\u8BC1\u5931\u8D25',\n  [ExitCode.NOT_FOUND]: '\u8D44\u6E90\u672A\u627E\u5230',\n  [ExitCode.SIGINT]: '\u7528\u6237\u4E2D\u65AD',\n};\n\n/**\n * \u6839\u636E\u9519\u8BEF\u7C7B\u578B\u83B7\u53D6\u9000\u51FA\u4EE3\u7801\n */\nexport function getExitCodeForError(error: Error): ExitCodeType {\n  const errorName = error.name.toLowerCase();\n  const errorMessage = error.message.toLowerCase();\n\n  // \u6839\u636E\u9519\u8BEF\u540D\u79F0\u6216\u6D88\u606F\u5224\u65AD\u9000\u51FA\u4EE3\u7801\n  if (errorName.includes('permission') || errorMessage.includes('eacces')) {\n    return ExitCode.PERMISSION_ERROR;\n  }\n  if (errorName.includes('validation') || errorMessage.includes('invalid')) {\n    return ExitCode.VALIDATION_ERROR;\n  }\n  if (errorName.includes('notfound') || errorMessage.includes('not found')) {\n    return ExitCode.NOT_FOUND;\n  }\n  if (errorName.includes('config') || errorMessage.includes('config')) {\n    return ExitCode.CONFIG_ERROR;\n  }\n  if (errorName.includes('service') || errorMessage.includes('systemctl')) {\n    return ExitCode.SERVICE_ERROR;\n  }\n  if (errorName.includes('file') || errorMessage.includes('enoent')) {\n    return ExitCode.FILE_ERROR;\n  }\n  if (errorName.includes('network') || errorMessage.includes('timeout')) {\n    return ExitCode.NETWORK_ERROR;\n  }\n\n  return ExitCode.GENERAL_ERROR;\n}\n\n/**\n * \u4F18\u96C5\u9000\u51FA\uFF08\u6E05\u7406\u8D44\u6E90\u540E\u9000\u51FA\uFF09\n */\nexport async function gracefulExit(\n  code: ExitCodeType,\n  cleanup?: () => Promise<void>\n): Promise<never> {\n  try {\n    if (cleanup) {\n      await cleanup();\n    }\n  } catch (error) {\n    console.error('\u6E05\u7406\u8D44\u6E90\u65F6\u51FA\u9519:', error);\n  } finally {\n    process.exit(code);\n  }\n}\n", "/**\n * Preflight Checks Utility\n *\n * Performs system checks before starting the CLI tool\n *\n * @module utils/preflight\n */\n\nimport { spawn } from 'child_process';\nimport { access, constants as fsConstants } from 'fs/promises';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport { TIMEOUTS } from '../constants/timeouts';\n\n/**\n * Preflight check options\n */\nexport interface PreflightOptions {\n  /** Check if systemd is available */\n  checkSystemd?: boolean;\n\n  /** Check if Xray binary exists */\n  checkXray?: boolean;\n\n  /** Check if config file exists and is readable */\n  checkConfig?: boolean;\n\n  /** Config file path (if checking) */\n  configPath?: string;\n\n  /** Service name (if checking) */\n  serviceName?: string;\n}\n\n/**\n * Preflight check result\n */\nexport interface PreflightResult {\n  /** Overall passed status */\n  passed: boolean;\n\n  /** Whether failures are critical (should prevent startup) */\n  critical: boolean;\n\n  /** List of errors */\n  errors: string[];\n\n  /** List of warnings */\n  warnings: string[];\n\n  /** Suggestions for fixing issues */\n  suggestions: string[];\n\n  /** Individual check results */\n  checks: {\n    systemd?: boolean;\n    xray?: boolean;\n    config?: boolean;\n    permissions?: boolean;\n  };\n}\n\n/**\n * Check if systemd is available\n */\nasync function checkSystemd(): Promise<{ passed: boolean; error?: string }> {\n  return new Promise((resolve) => {\n    const child = spawn('systemctl', ['--version'], {\n      timeout: TIMEOUTS.SYSTEMCTL_DEFAULT,\n    });\n\n    let stdout = '';\n\n    child.stdout?.on('data', (data) => {\n      stdout += data.toString();\n    });\n\n    child.on('close', (code) => {\n      if (code === 0 && stdout.includes('systemd')) {\n        resolve({ passed: true });\n      } else {\n        resolve({\n          passed: false,\n          error: 'systemd \u4E0D\u53EF\u7528 - \u6B64\u5DE5\u5177\u9700\u8981\u5728 systemd \u7CFB\u7EDF\u4E0A\u8FD0\u884C',\n        });\n      }\n    });\n\n    child.on('error', (error) => {\n      resolve({\n        passed: false,\n        error: `systemd \u68C0\u67E5\u5931\u8D25: ${error.message}`,\n      });\n    });\n  });\n}\n\n/**\n * Check if Xray binary exists and is executable\n */\nasync function checkXray(\n  path: string = DEFAULT_PATHS.XRAY_BINARY\n): Promise<{ passed: boolean; error?: string; warning?: string }> {\n  try {\n    // Check if file exists and is executable\n    await access(path, fsConstants.F_OK | fsConstants.X_OK);\n    return { passed: true };\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      return {\n        passed: false,\n        warning: `Xray \u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u5B58\u5728: ${path}`,\n      };\n    } else if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n      return {\n        passed: false,\n        error: `Xray \u4E8C\u8FDB\u5236\u6587\u4EF6\u4E0D\u53EF\u6267\u884C: ${path}`,\n      };\n    } else {\n      return {\n        passed: false,\n        warning: `Xray \u4E8C\u8FDB\u5236\u6587\u4EF6\u68C0\u67E5\u5931\u8D25: ${(error as Error).message}`,\n      };\n    }\n  }\n}\n\n/**\n * Check if config file exists and is readable\n */\nasync function checkConfig(\n  path: string = DEFAULT_PATHS.CONFIG_FILE\n): Promise<{ passed: boolean; error?: string; warning?: string }> {\n  try {\n    // Check if file exists and is readable\n    await access(path, fsConstants.F_OK | fsConstants.R_OK);\n\n    // Verify it's a JSON file\n    if (!path.endsWith('.json')) {\n      return {\n        passed: false,\n        warning: `\u914D\u7F6E\u6587\u4EF6\u5E94\u4E3A JSON \u683C\u5F0F: ${path}`,\n      };\n    }\n\n    return { passed: true };\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n      return {\n        passed: false,\n        warning: `\u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${path}`,\n      };\n    } else if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n      return {\n        passed: false,\n        error: `\u914D\u7F6E\u6587\u4EF6\u4E0D\u53EF\u8BFB: ${path}`,\n      };\n    } else {\n      return {\n        passed: false,\n        warning: `\u914D\u7F6E\u6587\u4EF6\u68C0\u67E5\u5931\u8D25: ${(error as Error).message}`,\n      };\n    }\n  }\n}\n\n/**\n * Check if current user has necessary permissions\n */\nfunction checkPermissions(): { passed: boolean; warning?: string } {\n  const isRoot = process.getuid && process.getuid() === 0;\n\n  if (isRoot) {\n    return { passed: true };\n  }\n\n  // Check if sudo is available\n  return {\n    passed: true,\n    warning: 'Not running as root - some operations may require sudo',\n  };\n}\n\n/**\n * Perform all preflight checks\n */\nexport async function preflightChecks(options: PreflightOptions = {}): Promise<PreflightResult> {\n  const result: PreflightResult = {\n    passed: true,\n    critical: false,\n    errors: [],\n    warnings: [],\n    suggestions: [],\n    checks: {},\n  };\n\n  // Check systemd\n  if (options.checkSystemd !== false) {\n    const systemdResult = await checkSystemd();\n    result.checks.systemd = systemdResult.passed;\n\n    if (!systemdResult.passed) {\n      result.passed = false;\n      result.critical = true;\n      if (systemdResult.error) {\n        result.errors.push(systemdResult.error);\n        result.suggestions.push(\n          '\u786E\u4FDD\u5728\u652F\u6301 systemd \u7684 Linux \u53D1\u884C\u7248\u4E0A\u8FD0\u884C (Debian 10+, Ubuntu 20.04+, CentOS 8+)'\n        );\n      }\n    }\n  }\n\n  // Check Xray binary\n  if (options.checkXray) {\n    const xrayResult = await checkXray();\n    result.checks.xray = xrayResult.passed;\n\n    if (!xrayResult.passed) {\n      result.passed = false;\n\n      if (xrayResult.error) {\n        result.errors.push(xrayResult.error);\n        result.suggestions.push(\n          `\u4FEE\u590D Xray \u4E8C\u8FDB\u5236\u6587\u4EF6\u6743\u9650: sudo chmod +x ${DEFAULT_PATHS.XRAY_BINARY}`\n        );\n      } else if (xrayResult.warning) {\n        result.warnings.push(xrayResult.warning);\n        result.suggestions.push(`\u5B89\u88C5 Xray: https://github.com/XTLS/Xray-install`);\n      }\n    }\n  }\n\n  // Check config file\n  if (options.checkConfig) {\n    const configPath = options.configPath || DEFAULT_PATHS.CONFIG_FILE;\n    const configResult = await checkConfig(configPath);\n    result.checks.config = configResult.passed;\n\n    if (!configResult.passed) {\n      result.passed = false;\n\n      if (configResult.error) {\n        result.errors.push(configResult.error);\n        result.suggestions.push(`\u4FEE\u590D\u914D\u7F6E\u6587\u4EF6\u6743\u9650: sudo chmod 600 ${configPath}`);\n      } else if (configResult.warning) {\n        result.warnings.push(configResult.warning);\n        result.suggestions.push(`\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: sudo touch ${configPath}`);\n      }\n    }\n  }\n\n  // Check permissions\n  const permResult = checkPermissions();\n  result.checks.permissions = permResult.passed;\n\n  if (permResult.warning) {\n    result.warnings.push(permResult.warning);\n  }\n\n  return result;\n}\n\n/**\n * Check if running as root\n */\nexport function isRoot(): boolean {\n  return !!(process.getuid && process.getuid() === 0);\n}\n\n/**\n * Check if sudo is available\n */\nexport async function canUseSudo(): Promise<boolean> {\n  return new Promise((resolve) => {\n    const child = spawn('which', ['sudo']);\n\n    child.on('close', (code) => {\n      resolve(code === 0);\n    });\n\n    child.on('error', () => {\n      resolve(false);\n    });\n  });\n}\n", "/**\n * \u8DEF\u5F84\u5E38\u91CF\u5B9A\u4E49\n * @module constants/paths\n */\n\nimport { homedir } from 'os';\nimport { join } from 'path';\n\n/**\n * \u9ED8\u8BA4\u8DEF\u5F84\u914D\u7F6E\n */\nexport const DEFAULT_PATHS = {\n  /** Xray \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84 */\n  CONFIG_FILE: '/usr/local/etc/xray/config.json',\n\n  /** Xray \u914D\u7F6E\u76EE\u5F55 */\n  CONFIG_DIR: '/usr/local/etc/xray',\n\n  /** \u914D\u7F6E\u5907\u4EFD\u76EE\u5F55 */\n  BACKUP_DIR: '/var/backups/xray',\n\n  /** systemd \u670D\u52A1\u540D\u79F0 */\n  SERVICE_NAME: 'xray',\n\n  /** systemd \u670D\u52A1\u6587\u4EF6\u8DEF\u5F84 */\n  SERVICE_FILE: '/etc/systemd/system/xray.service',\n\n  /** Xray \u53EF\u6267\u884C\u6587\u4EF6\u8DEF\u5F84 */\n  XRAY_BINARY: '/usr/local/bin/xray',\n\n  /** \u65E5\u5FD7\u76EE\u5F55\uFF08\u5982\u679C\u4F7F\u7528\u6587\u4EF6\u65E5\u5FD7\uFF09 */\n  LOG_DIR: '/var/log/xray',\n\n  /** \u8BBF\u95EE\u65E5\u5FD7\u6587\u4EF6 */\n  ACCESS_LOG: '/var/log/xray/access.log',\n\n  /** \u9519\u8BEF\u65E5\u5FD7\u6587\u4EF6 */\n  ERROR_LOG: '/var/log/xray/error.log',\n\n  /** \u4E34\u65F6\u6587\u4EF6\u76EE\u5F55 */\n  TEMP_DIR: '/tmp/xray-manager',\n\n  /** \u7528\u6237\u914D\u7F6E\u76EE\u5F55\uFF08~/.xray-manager\uFF09 */\n  USER_CONFIG_DIR: join(homedir(), '.xray-manager'),\n\n  /** \u7528\u6237\u914D\u7F6E\u6587\u4EF6 */\n  USER_CONFIG_FILE: join(homedir(), '.xray-manager', 'config.json'),\n\n  /** Clash \u914D\u7F6E\u6587\u4EF6\uFF08\u9ED8\u8BA4\u8F93\u51FA\uFF09 */\n  CLASH_CONFIG_FILE: join(homedir(), 'clash-config-v3.yaml'),\n\n  /** \u670D\u52A1\u5668\u914D\u7F6E\u6587\u4EF6\uFF08\u516C\u7F51 IP \u7B49\uFF09 */\n  SERVER_CONFIG_FILE: '/usr/local/etc/xray/server-config.json',\n\n  /** \u7528\u6237\u5143\u6570\u636E\u6587\u4EF6\uFF08\u521B\u5EFA\u65F6\u95F4\u3001\u72B6\u6001\u7B49\uFF09 */\n  USER_METADATA_FILE: '/usr/local/etc/xray/user-metadata.json',\n} as const;\n\n/**\n * \u8DEF\u5F84\u9A8C\u8BC1\u89C4\u5219\n */\nexport const PATH_VALIDATION = {\n  /** \u914D\u7F6E\u6587\u4EF6\u5FC5\u987B\u4EE5 .json \u7ED3\u5C3E */\n  CONFIG_FILE_EXTENSION: '.json',\n\n  /** \u5907\u4EFD\u6587\u4EF6\u547D\u540D\u683C\u5F0F */\n  BACKUP_FILE_PATTERN: /^config\\.\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}\\.\\d{3}Z\\.json$/,\n\n  /** \u6700\u5927\u8DEF\u5F84\u957F\u5EA6 */\n  MAX_PATH_LENGTH: 4096,\n} as const;\n\n/**\n * \u5907\u4EFD\u6587\u4EF6\u540D\u751F\u6210\n */\nexport function getBackupFileName(timestamp: Date = new Date()): string {\n  const isoString = timestamp.toISOString().replace(/:/g, '-');\n  return `config.${isoString}.json`;\n}\n\n/**\n * \u83B7\u53D6\u5B8C\u6574\u5907\u4EFD\u8DEF\u5F84\n */\nexport function getBackupFilePath(timestamp?: Date): string {\n  return join(DEFAULT_PATHS.BACKUP_DIR, getBackupFileName(timestamp));\n}\n\n/**\n * \u68C0\u67E5\u8DEF\u5F84\u662F\u5426\u4E3A\u5907\u4EFD\u6587\u4EF6\n */\nexport function isBackupFile(filename: string): boolean {\n  return PATH_VALIDATION.BACKUP_FILE_PATTERN.test(filename);\n}\n", "/**\n * Review constants and enums\n *\n * @module constants/review\n */\n\nimport type {\n  AssessmentStatus,\n  OutputFormat,\n  ReviewPriority,\n  ReviewTimeHorizon,\n} from '../types/review';\n\nexport const REVIEW_PRIORITIES: readonly ReviewPriority[] = ['high', 'medium', 'low'];\nexport const REVIEW_TIME_HORIZONS: readonly ReviewTimeHorizon[] = ['quick', 'long-term'];\nexport const REVIEW_STATUSES: readonly AssessmentStatus[] = [\n  'good',\n  'needs-improvement',\n  'missing',\n];\nexport const REVIEW_FORMATS: readonly OutputFormat[] = ['markdown', 'json'];\n\nexport const REVIEW_AREA_IDS = [\n  'documentation',\n  'license',\n  'contribution',\n  'quality',\n  'community',\n  'security',\n] as const;\nexport type ReviewAreaId = (typeof REVIEW_AREA_IDS)[number];\n\nexport const REVIEW_AREA_LABELS: Record<ReviewAreaId, string> = {\n  documentation: 'Documentation',\n  license: 'License',\n  contribution: 'Contribution',\n  quality: 'Quality',\n  community: 'Community',\n  security: 'Security',\n};\n", "/**\n * Review identifiers and timestamps\n *\n * @module utils/review-id\n */\n\nimport { randomUUID } from 'crypto';\n\nexport function createReviewId(): string {\n  return `review_${randomUUID()}`;\n}\n\nexport function getIsoTimestamp(date: Date = new Date()): string {\n  return date.toISOString();\n}\n", "/**\n * Repository scanning service\n *\n * @module services/review/repo-scanner\n */\n\nimport { access, constants as fsConstants } from 'fs/promises';\nimport { scanRepository, type RepoScanResult } from '../../utils/repo-scan';\n\nexport async function runRepoScan(repoPath: string): Promise<RepoScanResult> {\n  await access(repoPath, fsConstants.R_OK);\n  return scanRepository(repoPath);\n}\n", "/**\n * Repository scanning helpers (read-only)\n *\n * @module utils/repo-scan\n */\n\nimport { readdir, readFile, stat } from 'fs/promises';\nimport path from 'path';\n\nexport interface RepoScanResult {\n  repoPath: string;\n  files: {\n    readme?: string;\n    license?: string;\n    contributing?: string;\n    codeOfConduct?: string;\n    security?: string;\n    changelog?: string;\n    packageJson?: string;\n    pullRequestTemplate?: string;\n    maintainers?: string;\n    roadmap?: string;\n  };\n  content: {\n    readme?: string;\n    license?: string;\n    contributing?: string;\n    codeOfConduct?: string;\n    security?: string;\n    changelog?: string;\n  };\n  directories: {\n    docs?: string;\n    tests?: string;\n    examples?: string;\n    github?: string;\n    workflows?: string;\n    issueTemplates?: string;\n  };\n  signals: {\n    hasReadme: boolean;\n    hasLicense: boolean;\n    hasContributing: boolean;\n    hasCodeOfConduct: boolean;\n    hasSecurityPolicy: boolean;\n    hasChangelog: boolean;\n    hasTests: boolean;\n    hasDocs: boolean;\n    hasExamples: boolean;\n    hasGithubActions: boolean;\n    hasIssueTemplates: boolean;\n    hasPullRequestTemplate: boolean;\n    hasMaintainers: boolean;\n    hasRoadmap: boolean;\n  };\n}\n\nconst SEARCH_DIRS = ['.', '.github', 'docs'];\n\nfunction normalizeName(name: string): string {\n  return name.toLowerCase();\n}\n\nasync function safeReadDir(dirPath: string): Promise<string[]> {\n  try {\n    const entries = await readdir(dirPath, { withFileTypes: true });\n    return entries.map((entry) => entry.name);\n  } catch {\n    return [];\n  }\n}\n\nasync function safeStat(targetPath: string): Promise<ReturnType<typeof stat> | null> {\n  try {\n    return await stat(targetPath);\n  } catch {\n    return null;\n  }\n}\n\nasync function safeReadFile(targetPath: string): Promise<string | undefined> {\n  try {\n    return await readFile(targetPath, 'utf-8');\n  } catch {\n    return undefined;\n  }\n}\n\nasync function findFileInDirs(repoPath: string, names: string[]): Promise<string | undefined> {\n  const normalized = names.map(normalizeName);\n\n  for (const dir of SEARCH_DIRS) {\n    const searchDir = path.join(repoPath, dir);\n    const entries = await safeReadDir(searchDir);\n\n    for (const entry of entries) {\n      if (normalized.includes(normalizeName(entry))) {\n        return path.join(searchDir, entry);\n      }\n    }\n  }\n\n  return undefined;\n}\n\nasync function directoryExists(repoPath: string, dirName: string): Promise<string | undefined> {\n  const target = path.join(repoPath, dirName);\n  const info = await safeStat(target);\n  if (info && info.isDirectory()) {\n    return target;\n  }\n  return undefined;\n}\n\nasync function hasAnyFiles(dirPath: string, extensions: string[]): Promise<boolean> {\n  const entries = await safeReadDir(dirPath);\n  const normalized = extensions.map(normalizeName);\n  return entries.some((entry) => normalized.some((ext) => normalizeName(entry).endsWith(ext)));\n}\n\nasync function findPullRequestTemplate(repoPath: string): Promise<string | undefined> {\n  const candidates = ['PULL_REQUEST_TEMPLATE.md', 'pull_request_template.md'];\n\n  for (const dir of ['.', '.github', 'docs']) {\n    const searchDir = path.join(repoPath, dir);\n    const entries = await safeReadDir(searchDir);\n    for (const entry of entries) {\n      if (candidates.includes(entry)) {\n        return path.join(searchDir, entry);\n      }\n    }\n  }\n\n  return undefined;\n}\n\nexport async function scanRepository(repoPath: string): Promise<RepoScanResult> {\n  const resolvedRepoPath = path.resolve(repoPath);\n  const repoInfo = await safeStat(resolvedRepoPath);\n  if (!repoInfo || !repoInfo.isDirectory()) {\n    throw new Error(`Repository path is not a directory: ${resolvedRepoPath}`);\n  }\n\n  const readmePath = await findFileInDirs(resolvedRepoPath, ['README.md', 'README']);\n  const licensePath = await findFileInDirs(resolvedRepoPath, ['LICENSE', 'LICENSE.md', 'COPYING']);\n  const contributingPath = await findFileInDirs(resolvedRepoPath, [\n    'CONTRIBUTING.md',\n    'CONTRIBUTING',\n  ]);\n  const codeOfConductPath = await findFileInDirs(resolvedRepoPath, [\n    'CODE_OF_CONDUCT.md',\n    'CODE_OF_CONDUCT',\n  ]);\n  const securityPath = await findFileInDirs(resolvedRepoPath, ['SECURITY.md']);\n  const changelogPath = await findFileInDirs(resolvedRepoPath, ['CHANGELOG.md', 'CHANGELOG']);\n  const packageJsonPath = await findFileInDirs(resolvedRepoPath, ['package.json']);\n  const maintainersPath = await findFileInDirs(resolvedRepoPath, ['MAINTAINERS.md', 'MAINTAINERS']);\n  const roadmapPath = await findFileInDirs(resolvedRepoPath, ['ROADMAP.md', 'ROADMAP']);\n\n  const docsDir = await directoryExists(resolvedRepoPath, 'docs');\n  const testsDir =\n    (await directoryExists(resolvedRepoPath, 'tests')) ||\n    (await directoryExists(resolvedRepoPath, '__tests__'));\n  const examplesDir = await directoryExists(resolvedRepoPath, 'examples');\n  const githubDir = await directoryExists(resolvedRepoPath, '.github');\n  const workflowsDir = githubDir ? await directoryExists(githubDir, 'workflows') : undefined;\n  const issueTemplatesDir = githubDir\n    ? await directoryExists(githubDir, 'ISSUE_TEMPLATE')\n    : undefined;\n  const pullRequestTemplate = await findPullRequestTemplate(resolvedRepoPath);\n\n  const hasGithubActions = workflowsDir\n    ? await hasAnyFiles(workflowsDir, ['.yml', '.yaml'])\n    : false;\n\n  const content = {\n    readme: readmePath ? await safeReadFile(readmePath) : undefined,\n    license: licensePath ? await safeReadFile(licensePath) : undefined,\n    contributing: contributingPath ? await safeReadFile(contributingPath) : undefined,\n    codeOfConduct: codeOfConductPath ? await safeReadFile(codeOfConductPath) : undefined,\n    security: securityPath ? await safeReadFile(securityPath) : undefined,\n    changelog: changelogPath ? await safeReadFile(changelogPath) : undefined,\n  };\n\n  return {\n    repoPath: resolvedRepoPath,\n    files: {\n      readme: readmePath,\n      license: licensePath,\n      contributing: contributingPath,\n      codeOfConduct: codeOfConductPath,\n      security: securityPath,\n      changelog: changelogPath,\n      packageJson: packageJsonPath,\n      pullRequestTemplate,\n      maintainers: maintainersPath,\n      roadmap: roadmapPath,\n    },\n    content,\n    directories: {\n      docs: docsDir,\n      tests: testsDir,\n      examples: examplesDir,\n      github: githubDir,\n      workflows: workflowsDir,\n      issueTemplates: issueTemplatesDir,\n    },\n    signals: {\n      hasReadme: Boolean(readmePath),\n      hasLicense: Boolean(licensePath),\n      hasContributing: Boolean(contributingPath),\n      hasCodeOfConduct: Boolean(codeOfConductPath),\n      hasSecurityPolicy: Boolean(securityPath),\n      hasChangelog: Boolean(changelogPath),\n      hasTests: Boolean(testsDir),\n      hasDocs: Boolean(docsDir),\n      hasExamples: Boolean(examplesDir),\n      hasGithubActions: Boolean(hasGithubActions),\n      hasIssueTemplates: Boolean(issueTemplatesDir),\n      hasPullRequestTemplate: Boolean(pullRequestTemplate),\n      hasMaintainers: Boolean(maintainersPath),\n      hasRoadmap: Boolean(roadmapPath),\n    },\n  };\n}\n", "/**\n * Summary builder for review reports\n *\n * @module services/review/summary-builder\n */\n\nimport type { AssessmentArea, Recommendation, Summary } from '../../types/review';\n\nexport function buildSummary(areas: AssessmentArea[], recommendations: Recommendation[]): Summary {\n  const highPriority = recommendations.filter((rec) => rec.priority === 'high');\n  const quickWins = recommendations.filter((rec) => rec.timeHorizon === 'quick');\n\n  const headline =\n    highPriority.length > 0\n      ? 'High priority improvements are needed.'\n      : 'No high priority risks detected.';\n\n  const riskNotes = highPriority.slice(0, 3).map((rec) => rec.riskIfIgnored);\n  if (riskNotes.length === 0 && recommendations.length > 0) {\n    riskNotes.push(recommendations[0].riskIfIgnored);\n  }\n\n  return {\n    headline,\n    highPriorityCount: highPriority.length,\n    quickWinsCount: quickWins.length,\n    riskNotes,\n  };\n}\n", "/**\n * Evidence helpers for review reports\n *\n * @module services/review/evidence\n */\n\nimport path from 'path';\nimport type { EvidenceReference } from '../../types/review';\n\nfunction toRelativePath(repoPath: string, targetPath: string): string {\n  const relative = path.relative(repoPath, targetPath);\n  return relative.length > 0 ? relative : '.';\n}\n\nexport function fileEvidence(\n  repoPath: string,\n  targetPath: string,\n  notes?: string\n): EvidenceReference {\n  return {\n    type: 'file',\n    target: toRelativePath(repoPath, targetPath),\n    notes,\n  };\n}\n\nexport function pathEvidence(\n  repoPath: string,\n  targetPath: string,\n  notes?: string\n): EvidenceReference {\n  return {\n    type: 'path',\n    target: toRelativePath(repoPath, targetPath),\n    notes,\n  };\n}\n\nexport function missingEvidence(label: string, notes?: string): EvidenceReference {\n  return {\n    type: 'missing',\n    target: label,\n    notes,\n  };\n}\n", "/**\n * Community area evaluation\n *\n * @module services/review/areas/community\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence } from '../evidence';\n\nexport function evaluateCommunity(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.signals.hasMaintainers) {\n    recommendations.push({\n      areaId: 'community',\n      title: 'Document maintainers and support cadence',\n      details: 'Provide a MAINTAINERS file or similar guidance on support expectations.',\n      priority: 'medium',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Users may not know where to seek support or how active maintenance is.',\n      evidence: [missingEvidence('MAINTAINERS.md missing')],\n    });\n  } else if (scan.files.maintainers) {\n    findings.push({\n      areaId: 'community',\n      title: 'Maintainers guidance present',\n      details: 'Maintainers or support expectations are documented.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.maintainers)],\n    });\n  }\n\n  if (!scan.signals.hasRoadmap) {\n    recommendations.push({\n      areaId: 'community',\n      title: 'Publish a lightweight roadmap',\n      details: 'Add a ROADMAP file to communicate future direction and release cadence.',\n      priority: 'low',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Community members may not know what is planned or prioritized.',\n      evidence: [missingEvidence('ROADMAP.md missing')],\n    });\n  } else if (scan.files.roadmap) {\n    findings.push({\n      areaId: 'community',\n      title: 'Roadmap present',\n      details: 'A roadmap exists to communicate future plans.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.roadmap)],\n    });\n  }\n\n  const status = recommendations.length > 0 ? 'needs-improvement' : 'good';\n\n  return {\n    areaId: 'community',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * Contribution area evaluation\n *\n * @module services/review/areas/contribution\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence, pathEvidence } from '../evidence';\n\nexport function evaluateContribution(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.files.contributing) {\n    findings.push({\n      areaId: 'contribution',\n      title: 'CONTRIBUTING guide missing',\n      details: 'No contribution guide found for new contributors.',\n      evidence: [missingEvidence('CONTRIBUTING.md missing')],\n    });\n    recommendations.push({\n      areaId: 'contribution',\n      title: 'Add a contribution guide',\n      details: 'Document contribution workflow, coding standards, and review expectations.',\n      priority: 'high',\n      timeHorizon: 'quick',\n      riskIfIgnored: 'Contributors may abandon PRs due to unclear expectations.',\n      evidence: [missingEvidence('CONTRIBUTING.md missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'contribution',\n      title: 'Contribution guide present',\n      details: 'A CONTRIBUTING file exists for contributors.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.contributing)],\n    });\n  }\n\n  if (!scan.files.codeOfConduct) {\n    recommendations.push({\n      areaId: 'contribution',\n      title: 'Add a code of conduct',\n      details: 'Include a CODE_OF_CONDUCT file to set community expectations.',\n      priority: 'medium',\n      timeHorizon: 'quick',\n      riskIfIgnored: 'Lack of conduct guidance can hinder community trust.',\n      evidence: [missingEvidence('CODE_OF_CONDUCT.md missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'contribution',\n      title: 'Code of conduct present',\n      details: 'A code of conduct is available for community guidelines.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.codeOfConduct)],\n    });\n  }\n\n  if (!scan.directories.issueTemplates) {\n    recommendations.push({\n      areaId: 'contribution',\n      title: 'Provide issue templates',\n      details: 'Add GitHub issue templates to standardize bug reports and feature requests.',\n      priority: 'low',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Issues may lack critical details and slow triage.',\n      evidence: [missingEvidence('.github/ISSUE_TEMPLATE missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'contribution',\n      title: 'Issue templates available',\n      details: 'Issue templates are configured in the repository.',\n      evidence: [pathEvidence(scan.repoPath, scan.directories.issueTemplates)],\n    });\n  }\n\n  if (!scan.files.pullRequestTemplate) {\n    recommendations.push({\n      areaId: 'contribution',\n      title: 'Add a pull request template',\n      details: 'Provide a PR template to guide contributors through required context and testing.',\n      priority: 'low',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Pull requests may omit critical context or validation steps.',\n      evidence: [missingEvidence('Pull request template missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'contribution',\n      title: 'Pull request template present',\n      details: 'A pull request template is available for contributors.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.pullRequestTemplate)],\n    });\n  }\n\n  const status =\n    !scan.files.contributing && !scan.files.codeOfConduct\n      ? 'missing'\n      : recommendations.length > 0\n        ? 'needs-improvement'\n        : 'good';\n\n  return {\n    areaId: 'contribution',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * Documentation area evaluation\n *\n * @module services/review/areas/documentation\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence, pathEvidence } from '../evidence';\n\nfunction hasKeyword(content: string | undefined, keyword: string): boolean {\n  if (!content) {\n    return false;\n  }\n  return content.toLowerCase().includes(keyword.toLowerCase());\n}\n\nexport function evaluateDocumentation(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.files.readme) {\n    findings.push({\n      areaId: 'documentation',\n      title: 'README not found',\n      details: 'The repository does not include a README file at the root or docs directories.',\n      evidence: [missingEvidence('README.md missing')],\n    });\n    recommendations.push({\n      areaId: 'documentation',\n      title: 'Add a README with install and usage guidance',\n      details: 'Provide a primary README with installation steps, usage examples, and scope.',\n      priority: 'high',\n      timeHorizon: 'quick',\n      riskIfIgnored: 'Users and contributors will struggle to understand how to use the project.',\n      evidence: [missingEvidence('README.md missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'documentation',\n      title: 'README present',\n      details: 'A README file is present and can be used as the primary entry point.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.readme)],\n    });\n\n    const hasInstall = hasKeyword(scan.content.readme, 'install');\n    const hasUsage = hasKeyword(scan.content.readme, 'usage');\n    const hasContributing =\n      hasKeyword(scan.content.readme, 'contributing') ||\n      hasKeyword(scan.content.readme, 'contribute');\n\n    if (!hasInstall || !hasUsage) {\n      const missingParts = [!hasInstall ? 'installation' : null, !hasUsage ? 'usage' : null]\n        .filter((part): part is string => Boolean(part))\n        .join(' and ');\n      findings.push({\n        areaId: 'documentation',\n        title: 'README missing key sections',\n        details: `README lacks clear ${missingParts} guidance.`,\n        evidence: [fileEvidence(scan.repoPath, scan.files.readme)],\n      });\n      recommendations.push({\n        areaId: 'documentation',\n        title: 'Expand README with installation and usage sections',\n        details:\n          'Add concise installation steps and usage examples so new users can start quickly.',\n        priority: 'medium',\n        timeHorizon: 'quick',\n        riskIfIgnored: 'Adoption and onboarding will remain slow and support load will increase.',\n        evidence: [fileEvidence(scan.repoPath, scan.files.readme)],\n      });\n    }\n\n    if (!hasContributing) {\n      recommendations.push({\n        areaId: 'documentation',\n        title: 'Link to contribution guidance from README',\n        details:\n          'Add a brief contribution section or link to CONTRIBUTING.md for new contributors.',\n        priority: 'low',\n        timeHorizon: 'quick',\n        riskIfIgnored: 'Potential contributors may not find the right onboarding materials.',\n        evidence: [fileEvidence(scan.repoPath, scan.files.readme)],\n      });\n    }\n  }\n\n  if (!scan.directories.docs) {\n    recommendations.push({\n      areaId: 'documentation',\n      title: 'Add a dedicated docs directory',\n      details: 'Move detailed guides into a docs/ directory for discoverability and maintenance.',\n      priority: 'low',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Long-form documentation will be harder to maintain as the project grows.',\n      evidence: [missingEvidence('docs/ directory missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'documentation',\n      title: 'Docs directory present',\n      details: 'Supporting documentation exists in docs/.',\n      evidence: [pathEvidence(scan.repoPath, scan.directories.docs)],\n    });\n  }\n\n  const status = !scan.files.readme\n    ? 'missing'\n    : recommendations.length > 0\n      ? 'needs-improvement'\n      : 'good';\n\n  return {\n    areaId: 'documentation',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * License area evaluation\n *\n * @module services/review/areas/license\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence } from '../evidence';\n\nfunction detectLicenseType(content: string | undefined): string | undefined {\n  if (!content) {\n    return undefined;\n  }\n\n  const text = content.toLowerCase();\n\n  if (text.includes('mit license')) {\n    return 'MIT';\n  }\n  if (text.includes('apache license') && text.includes('version 2')) {\n    return 'Apache-2.0';\n  }\n  if (text.includes('gnu general public license') && text.includes('version 3')) {\n    return 'GPL-3.0';\n  }\n  if (text.includes('gnu general public license') && text.includes('version 2')) {\n    return 'GPL-2.0';\n  }\n  if (text.includes('mozilla public license')) {\n    return 'MPL-2.0';\n  }\n\n  return undefined;\n}\n\nexport function evaluateLicense(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.files.license) {\n    findings.push({\n      areaId: 'license',\n      title: 'License file missing',\n      details: 'A license file is required to clarify usage rights for the project.',\n      evidence: [missingEvidence('LICENSE missing')],\n    });\n    recommendations.push({\n      areaId: 'license',\n      title: 'Add an explicit license file',\n      details: 'Include a LICENSE file that matches the intended distribution terms.',\n      priority: 'high',\n      timeHorizon: 'quick',\n      riskIfIgnored: 'Users and contributors may avoid the project due to legal uncertainty.',\n      evidence: [missingEvidence('LICENSE missing')],\n    });\n  } else {\n    const licenseType = detectLicenseType(scan.content.license);\n    findings.push({\n      areaId: 'license',\n      title: 'License file present',\n      details: licenseType\n        ? `Detected license type: ${licenseType}.`\n        : 'License file present but type not detected.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.license)],\n    });\n\n    if (!licenseType) {\n      recommendations.push({\n        areaId: 'license',\n        title: 'Clarify license type',\n        details: 'Ensure the license text is complete and matches a well-known SPDX identifier.',\n        priority: 'medium',\n        timeHorizon: 'quick',\n        riskIfIgnored: 'Ambiguous licensing can slow adoption and contributions.',\n        evidence: [fileEvidence(scan.repoPath, scan.files.license)],\n      });\n    }\n  }\n\n  const status = !scan.files.license\n    ? 'missing'\n    : recommendations.length > 0\n      ? 'needs-improvement'\n      : 'good';\n\n  return {\n    areaId: 'license',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * Quality area evaluation\n *\n * @module services/review/areas/quality\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence, pathEvidence } from '../evidence';\n\nexport function evaluateQuality(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.signals.hasTests) {\n    findings.push({\n      areaId: 'quality',\n      title: 'Tests not detected',\n      details: 'No tests directory found in the repository.',\n      evidence: [missingEvidence('tests/ directory missing')],\n    });\n    recommendations.push({\n      areaId: 'quality',\n      title: 'Add automated tests',\n      details: 'Introduce unit or integration tests to validate key workflows.',\n      priority: 'high',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Regression risk increases and changes become harder to validate.',\n      evidence: [missingEvidence('tests/ directory missing')],\n    });\n  } else if (scan.directories.tests) {\n    findings.push({\n      areaId: 'quality',\n      title: 'Tests directory present',\n      details: 'Automated tests are present in the repository.',\n      evidence: [pathEvidence(scan.repoPath, scan.directories.tests)],\n    });\n  }\n\n  if (!scan.signals.hasGithubActions) {\n    recommendations.push({\n      areaId: 'quality',\n      title: 'Add CI workflows',\n      details: 'Set up continuous integration to run tests and lint checks.',\n      priority: 'medium',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Quality checks will be inconsistent across contributions.',\n      evidence: [missingEvidence('.github/workflows missing')],\n    });\n  } else if (scan.directories.workflows) {\n    findings.push({\n      areaId: 'quality',\n      title: 'CI workflows detected',\n      details: 'GitHub Actions workflows are configured.',\n      evidence: [pathEvidence(scan.repoPath, scan.directories.workflows)],\n    });\n  }\n\n  if (!scan.files.changelog) {\n    recommendations.push({\n      areaId: 'quality',\n      title: 'Maintain a changelog',\n      details: 'Add a CHANGELOG file to track releases and major changes.',\n      priority: 'low',\n      timeHorizon: 'long-term',\n      riskIfIgnored: 'Users will struggle to track changes between releases.',\n      evidence: [missingEvidence('CHANGELOG.md missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'quality',\n      title: 'Changelog present',\n      details: 'Changelog exists for release tracking.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.changelog)],\n    });\n  }\n\n  const status = recommendations.length > 0 ? 'needs-improvement' : 'good';\n\n  return {\n    areaId: 'quality',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * Security area evaluation\n *\n * @module services/review/areas/security\n */\n\nimport { type AreaEvaluation } from '../review-engine';\nimport type { RepoScanResult } from '../../../utils/repo-scan';\nimport { fileEvidence, missingEvidence } from '../evidence';\n\nexport function evaluateSecurity(scan: RepoScanResult): AreaEvaluation {\n  const findings: AreaEvaluation['findings'] = [];\n  const recommendations: AreaEvaluation['recommendations'] = [];\n\n  if (!scan.files.security) {\n    findings.push({\n      areaId: 'security',\n      title: 'Security policy missing',\n      details: 'No SECURITY.md file was found for reporting vulnerabilities.',\n      evidence: [missingEvidence('SECURITY.md missing')],\n    });\n    recommendations.push({\n      areaId: 'security',\n      title: 'Add a security policy',\n      details: 'Document how to report vulnerabilities and response expectations.',\n      priority: 'high',\n      timeHorizon: 'quick',\n      riskIfIgnored: 'Security issues may be reported publicly without guidance.',\n      evidence: [missingEvidence('SECURITY.md missing')],\n    });\n  } else {\n    findings.push({\n      areaId: 'security',\n      title: 'Security policy present',\n      details: 'A SECURITY.md file exists for vulnerability reporting.',\n      evidence: [fileEvidence(scan.repoPath, scan.files.security)],\n    });\n\n    const securityText = scan.content.security?.toLowerCase() ?? '';\n    const hasContact = securityText.includes('email') || securityText.includes('contact');\n    const hasReport = securityText.includes('report') || securityText.includes('vulnerability');\n\n    if (!hasContact || !hasReport) {\n      recommendations.push({\n        areaId: 'security',\n        title: 'Clarify disclosure instructions',\n        details: 'Add contact details and reporting steps to the security policy.',\n        priority: 'medium',\n        timeHorizon: 'quick',\n        riskIfIgnored: 'Reporters may not know how to disclose issues safely.',\n        evidence: [fileEvidence(scan.repoPath, scan.files.security)],\n      });\n    }\n  }\n\n  const status = !scan.files.security\n    ? 'missing'\n    : recommendations.length > 0\n      ? 'needs-improvement'\n      : 'good';\n\n  return {\n    areaId: 'security',\n    status,\n    findings,\n    recommendations,\n  };\n}\n", "/**\n * Review engine orchestration\n *\n * @module services/review/review-engine\n */\n\nimport { REVIEW_AREA_LABELS, type ReviewAreaId } from '../../constants/review';\nimport type {\n  AssessmentArea,\n  Finding,\n  Recommendation,\n  ReviewReport,\n  Summary,\n} from '../../types/review';\nimport { createReviewId, getIsoTimestamp } from '../../utils/review-id';\nimport type { RepoScanResult } from '../../utils/repo-scan';\nimport { runRepoScan } from './repo-scanner';\nimport { buildSummary } from './summary-builder';\nimport { evaluateCommunity } from './areas/community';\nimport { evaluateContribution } from './areas/contribution';\nimport { evaluateDocumentation } from './areas/documentation';\nimport { evaluateLicense } from './areas/license';\nimport { evaluateQuality } from './areas/quality';\nimport { evaluateSecurity } from './areas/security';\n\nexport interface AreaEvaluation {\n  areaId: ReviewAreaId;\n  status: AssessmentArea['status'];\n  findings: Array<Omit<Finding, 'id'>>;\n  recommendations: Array<Omit<Recommendation, 'id'>>;\n}\n\nfunction attachIds(areas: AreaEvaluation[]): AssessmentArea[] {\n  let findingIndex = 0;\n  let recommendationIndex = 0;\n\n  return areas.map((area) => ({\n    id: area.areaId,\n    name: REVIEW_AREA_LABELS[area.areaId],\n    status: area.status,\n    findings: area.findings.map((finding) => ({\n      ...finding,\n      id: `finding_${++findingIndex}`,\n    })),\n    recommendations: area.recommendations.map((rec) => ({\n      ...rec,\n      id: `rec_${++recommendationIndex}`,\n    })),\n  }));\n}\n\nfunction evaluateAreas(scan: RepoScanResult): AreaEvaluation[] {\n  return [\n    evaluateDocumentation(scan),\n    evaluateLicense(scan),\n    evaluateContribution(scan),\n    evaluateQuality(scan),\n    evaluateCommunity(scan),\n    evaluateSecurity(scan),\n  ];\n}\n\nexport async function generateReviewReport(repoPath: string): Promise<ReviewReport> {\n  const scan = await runRepoScan(repoPath);\n  const evaluated = evaluateAreas(scan);\n  const areas = attachIds(evaluated);\n  const recommendations = areas.flatMap((area) => area.recommendations);\n  const summary: Summary = buildSummary(areas, recommendations);\n\n  return {\n    id: createReviewId(),\n    repoPath: scan.repoPath,\n    generatedAt: getIsoTimestamp(),\n    summary,\n    areas,\n    recommendations,\n  };\n}\n", "/**\n * Report renderer for review outputs\n *\n * @module services/review/report-renderer\n */\n\nimport type { AssessmentArea, Recommendation, ReviewReport } from '../../types/review';\n\nexport interface RenderOptions {\n  summaryOnly?: boolean;\n  recommendationsOnly?: boolean;\n}\n\nfunction renderEvidence(evidence: { type: string; target: string; notes?: string }[]): string {\n  if (!evidence.length) {\n    return '';\n  }\n  const items = evidence\n    .map((item) => `- ${item.type}: ${item.target}${item.notes ? ` (${item.notes})` : ''}`)\n    .join('\\n');\n  return `\\n\\nEvidence:\\n${items}`;\n}\n\nfunction renderRecommendationsList(recommendations: Recommendation[]): string {\n  if (recommendations.length === 0) {\n    return 'No recommendations found.';\n  }\n\n  const priorityOrder: Record<string, number> = { high: 0, medium: 1, low: 2 };\n  const sorted = [...recommendations].sort((a, b) => {\n    const left = priorityOrder[a.priority] ?? 99;\n    const right = priorityOrder[b.priority] ?? 99;\n    return left - right;\n  });\n\n  return sorted\n    .map((rec) => {\n      const header = `- [${rec.priority.toUpperCase()} | ${rec.timeHorizon}] ${rec.title}`;\n      const details = `  ${rec.details}`;\n      const risk = `  Risk if ignored: ${rec.riskIfIgnored}`;\n      const evidence = renderEvidence(rec.evidence)\n        .split('\\n')\n        .map((line) => `  ${line}`)\n        .join('\\n');\n      return [header, details, risk, evidence].filter(Boolean).join('\\n');\n    })\n    .join('\\n');\n}\n\nfunction renderArea(area: AssessmentArea): string {\n  const findings = area.findings.length\n    ? area.findings\n        .map((finding) => {\n          const header = `- ${finding.title}`;\n          const details = `  ${finding.details}`;\n          const evidence = renderEvidence(finding.evidence)\n            .split('\\n')\n            .map((line) => `  ${line}`)\n            .join('\\n');\n          return [header, details, evidence].filter(Boolean).join('\\n');\n        })\n        .join('\\n')\n    : 'No findings.';\n\n  const recommendations = renderRecommendationsList(area.recommendations);\n\n  return [\n    `### ${area.name}`,\n    `Status: ${area.status}`,\n    '',\n    'Findings:',\n    findings,\n    '',\n    'Recommendations:',\n    recommendations,\n  ].join('\\n');\n}\n\nexport function renderReportMarkdown(report: ReviewReport, options: RenderOptions = {}): string {\n  if (options.summaryOnly) {\n    return renderSummaryMarkdown(report);\n  }\n\n  if (options.recommendationsOnly) {\n    return renderRecommendationsMarkdown(report.recommendations);\n  }\n\n  const header = [\n    '# Open Source Review Report',\n    '',\n    `Repository: ${report.repoPath}`,\n    `Generated: ${report.generatedAt}`,\n    '',\n  ].join('\\n');\n\n  const summary = renderSummaryMarkdown(report);\n  const contributorRecommendations = report.recommendations.filter(\n    (rec) => rec.areaId === 'contribution'\n  );\n  const contributorSection = contributorRecommendations.length\n    ? ['## Contributor Guidance', renderRecommendationsList(contributorRecommendations)].join('\\n')\n    : '';\n  const recommendations = renderRecommendationsMarkdown(report.recommendations);\n  const areas = report.areas.map(renderArea).join('\\n\\n');\n\n  return [header, summary, '', contributorSection, '', recommendations, '', '## Areas', areas]\n    .filter((section) => section.trim().length > 0)\n    .join('\\n');\n}\n\nexport function renderSummaryMarkdown(report: ReviewReport): string {\n  const risks = report.summary.riskNotes.length\n    ? report.summary.riskNotes.map((note) => `- ${note}`).join('\\n')\n    : 'No critical risks noted.';\n\n  return [\n    '## Summary',\n    `Headline: ${report.summary.headline}`,\n    `High priority recommendations: ${report.summary.highPriorityCount}`,\n    `Quick wins: ${report.summary.quickWinsCount}`,\n    'Risk notes:',\n    risks,\n  ].join('\\n');\n}\n\nexport function renderRecommendationsMarkdown(recommendations: Recommendation[]): string {\n  return ['## Recommendations', renderRecommendationsList(recommendations)].join('\\n');\n}\n\nexport function renderReportJson(report: ReviewReport, options: RenderOptions = {}): string {\n  if (options.summaryOnly) {\n    return JSON.stringify(report.summary, null, 2);\n  }\n\n  if (options.recommendationsOnly) {\n    return JSON.stringify(report.recommendations, null, 2);\n  }\n\n  return JSON.stringify(report, null, 2);\n}\n", "/**\n * Report output writer\n *\n * @module utils/report-output\n */\n\nimport { writeFile } from 'fs/promises';\n\nexport interface ReportOutputPayload {\n  markdown?: string;\n  json?: string;\n  markdownPath?: string;\n  jsonPath?: string;\n}\n\nexport async function writeReportOutputs(payload: ReportOutputPayload): Promise<void> {\n  const stdoutChunks: string[] = [];\n\n  if (payload.markdown) {\n    if (payload.markdownPath) {\n      await writeFile(payload.markdownPath, payload.markdown, 'utf-8');\n    } else {\n      stdoutChunks.push(payload.markdown);\n    }\n  }\n\n  if (payload.json) {\n    if (payload.jsonPath) {\n      await writeFile(payload.jsonPath, payload.json, 'utf-8');\n    } else {\n      stdoutChunks.push(payload.json);\n    }\n  }\n\n  if (stdoutChunks.length > 0) {\n    process.stdout.write(stdoutChunks.join('\\n\\n'));\n    process.stdout.write('\\n');\n  }\n}\n", "/**\n * Repository review command\n *\n * @module commands/review\n */\n\nimport type { Command } from 'commander';\nimport logger from '../utils/logger';\nimport { ExitCode, getExitCodeForError, gracefulExit } from '../constants/exit-codes';\nimport { REVIEW_FORMATS } from '../constants/review';\nimport type { OutputFormat } from '../types/review';\nimport { generateReviewReport } from '../services/review/review-engine';\nimport { renderReportJson, renderReportMarkdown } from '../services/review/report-renderer';\nimport { writeReportOutputs } from '../utils/report-output';\n\ninterface ReviewCommandOptions {\n  repo: string;\n  format?: string;\n  out?: string;\n  jsonOut?: string;\n  summary?: boolean;\n  recommendations?: boolean;\n}\n\nfunction parseFormats(value?: string): OutputFormat[] {\n  if (!value) {\n    return [...REVIEW_FORMATS];\n  }\n\n  const normalized = value\n    .split(',')\n    .map((item) => item.trim())\n    .filter(Boolean) as OutputFormat[];\n\n  const unique = Array.from(new Set(normalized));\n  const invalid = unique.filter((format) => !REVIEW_FORMATS.includes(format));\n\n  if (invalid.length > 0) {\n    throw new Error(`Invalid format(s): ${invalid.join(', ')}`);\n  }\n\n  return unique;\n}\n\nexport function registerReviewCommand(program: Command): void {\n  program\n    .command('review')\n    .description('Generate an open-source review report for a local repository')\n    .requiredOption('--repo <path>', 'Repository path to review')\n    .option('--format <formats>', 'Output formats (markdown,json)', 'markdown,json')\n    .option('--out <path>', 'Markdown output path')\n    .option('--json-out <path>', 'JSON output path')\n    .option('--summary', 'Render summary only')\n    .option('--recommendations', 'Render recommendations only')\n    .action(async (options: ReviewCommandOptions) => {\n      try {\n        if (options.summary && options.recommendations) {\n          throw new Error('Only one of --summary or --recommendations can be used.');\n        }\n\n        let formats = parseFormats(options.format);\n\n        if (options.out && !formats.includes('markdown')) {\n          formats = [...formats, 'markdown'];\n        }\n        if (options.jsonOut && !formats.includes('json')) {\n          formats = [...formats, 'json'];\n        }\n\n        const report = await generateReviewReport(options.repo);\n        const renderOptions = {\n          summaryOnly: Boolean(options.summary),\n          recommendationsOnly: Boolean(options.recommendations),\n        };\n\n        const markdown = formats.includes('markdown')\n          ? renderReportMarkdown(report, renderOptions)\n          : undefined;\n        const json = formats.includes('json') ? renderReportJson(report, renderOptions) : undefined;\n\n        await writeReportOutputs({\n          markdown,\n          json,\n          markdownPath: options.out,\n          jsonPath: options.jsonOut,\n        });\n\n        logger.success('Review report generated successfully.');\n      } catch (error) {\n        const err = error as Error;\n        logger.error(`Review failed: ${err.message}`);\n        await gracefulExit(getExitCodeForError(err) || ExitCode.GENERAL_ERROR);\n      }\n    });\n}\n", "/**\n * Clash config export command\n *\n * @module commands/clash\n */\n\nimport type { Command } from 'commander';\nimport { input, confirm } from '@inquirer/prompts';\nimport { promises as fs } from 'fs';\nimport { dirname, join } from 'path';\nimport { homedir } from 'os';\nimport chalk from 'chalk';\nimport logger from '../utils/logger';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport { parseVlessLink } from '../utils/vless-link';\nimport { buildClashConfigYaml } from '../services/clash-config';\n\ninterface ClashExportResult {\n  outputPath: string;\n  proxyName: string;\n  proxyGroupName: string;\n}\n\ninterface ClashExportOptions {\n  link?: string;\n  outputPath?: string;\n  proxyName?: string;\n  json?: boolean;\n  force?: boolean;\n  promptLink?: boolean;\n  promptOutputPath?: boolean;\n  promptOverwrite?: boolean;\n}\n\ninterface ClashCommandOptions {\n  link?: string;\n  out?: string;\n  name?: string;\n  json?: boolean;\n  force?: boolean;\n}\n\nfunction normalizeOutputPath(value: string): string {\n  const trimmed = value.trim();\n  let path = trimmed;\n\n  // \u5904\u7406 ~ \u5F00\u5934\u7684\u8DEF\u5F84\n  if (path.startsWith('~/')) {\n    path = join(homedir(), path.slice(2));\n  }\n\n  // \u5982\u679C\u4E3A\u7A7A\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u8DEF\u5F84\n  if (!path) {\n    return DEFAULT_PATHS.CLASH_CONFIG_FILE;\n  }\n\n  return path;\n}\n\nasync function isDirectory(path: string): Promise<boolean> {\n  try {\n    const stat = await fs.stat(path);\n    return stat.isDirectory();\n  } catch {\n    return false;\n  }\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n  try {\n    await fs.access(path);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nasync function writeClashConfigFile(\n  options: ClashExportOptions\n): Promise<ClashExportResult | null> {\n  const rawLink = options.link || '';\n  const link = rawLink.trim();\n  if (!link) {\n    throw new Error('\u672A\u63D0\u4F9B VLESS \u94FE\u63A5');\n  }\n\n  let outputPath = normalizeOutputPath(options.outputPath || DEFAULT_PATHS.CLASH_CONFIG_FILE);\n\n  // \u5982\u679C\u662F\u76EE\u5F55\uFF0C\u5219\u8FFD\u52A0\u9ED8\u8BA4\u6587\u4EF6\u540D\n  if (await isDirectory(outputPath)) {\n    outputPath = join(outputPath, 'clash-config.yaml');\n  }\n\n  const info = parseVlessLink(link);\n  const { yaml, proxyName, proxyGroupName } = buildClashConfigYaml(info, {\n    proxyName: options.proxyName,\n  });\n\n  const exists = await fileExists(outputPath);\n  if (exists && !options.force) {\n    if (options.promptOverwrite) {\n      const overwrite = await confirm({\n        message: chalk.yellow(`\u8F93\u51FA\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u662F\u5426\u8986\u76D6\uFF1F\\n${outputPath}`),\n        default: false,\n      });\n      if (!overwrite) {\n        logger.info('\u5DF2\u53D6\u6D88\u751F\u6210 Clash \u914D\u7F6E');\n        return null;\n      }\n    } else {\n      throw new Error(`\u8F93\u51FA\u6587\u4EF6\u5DF2\u5B58\u5728: ${outputPath}`);\n    }\n  }\n\n  await fs.mkdir(dirname(outputPath), { recursive: true });\n  await fs.writeFile(outputPath, yaml, 'utf8');\n\n  return {\n    outputPath,\n    proxyName,\n    proxyGroupName,\n  };\n}\n\nexport async function exportClashConfigFromLink(options: ClashExportOptions = {}): Promise<void> {\n  try {\n    let link = options.link;\n    if (!link && options.promptLink) {\n      link = await input({\n        message: '\u8BF7\u8F93\u5165 VLESS \u94FE\u63A5:',\n      });\n    }\n\n    let outputPath = options.outputPath;\n    if (options.promptOutputPath) {\n      const outputInput = await input({\n        message: '\u8BF7\u8F93\u5165 Clash \u914D\u7F6E\u8F93\u51FA\u8DEF\u5F84:',\n        default: options.outputPath || DEFAULT_PATHS.CLASH_CONFIG_FILE,\n      });\n      outputPath = outputInput;\n    }\n\n    const result = await writeClashConfigFile({\n      ...options,\n      link,\n      outputPath,\n    });\n\n    if (!result) {\n      return;\n    }\n\n    if (options.json) {\n      console.log(JSON.stringify(result, null, 2));\n      return;\n    }\n\n    logger.newline();\n    logger.separator();\n    console.log(chalk.bold.cyan('\uD83D\uDCC4 Clash \u914D\u7F6E\u5DF2\u751F\u6210'));\n    logger.separator();\n    logger.newline();\n    console.log(chalk.cyan('  \u8F93\u51FA\u8DEF\u5F84: ') + chalk.white(result.outputPath));\n    console.log(chalk.cyan('  \u8282\u70B9\u540D\u79F0: ') + chalk.white(result.proxyName));\n    logger.newline();\n  } catch (error) {\n    logger.error((error as Error).message);\n    process.exit(1);\n  }\n}\n\nexport function registerClashCommand(program: Command): void {\n  program\n    .command('clash')\n    .description('\u4ECE VLESS \u5206\u4EAB\u94FE\u63A5\u751F\u6210 Clash \u914D\u7F6E\u6587\u4EF6')\n    .option('--link <vless>', 'VLESS \u5206\u4EAB\u94FE\u63A5')\n    .option('--out <path>', 'Clash \u914D\u7F6E\u8F93\u51FA\u8DEF\u5F84', DEFAULT_PATHS.CLASH_CONFIG_FILE)\n    .option('--name <name>', '\u8282\u70B9\u540D\u79F0\uFF08\u8986\u76D6\u94FE\u63A5\u5185\u540D\u79F0\uFF09')\n    .option('--json', '\u4EE5 JSON \u683C\u5F0F\u8F93\u51FA\u7ED3\u679C')\n    .option('-f, --force', '\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u8F93\u51FA\u6587\u4EF6')\n    .action(async (options: ClashCommandOptions) => {\n      await exportClashConfigFromLink({\n        link: options.link,\n        outputPath: options.out,\n        proxyName: options.name,\n        json: options.json,\n        force: options.force,\n        promptLink: !options.link,\n        promptOutputPath: false,\n        promptOverwrite: true,\n      });\n    });\n}\n", "/**\n * \u8F93\u5165\u9A8C\u8BC1\u5DE5\u5177\u51FD\u6570\n * @module utils/validator\n */\n\n/**\n * \u90AE\u7BB1\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\n */\nconst EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/;\n\n/**\n * UUID v4 \u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\n */\nconst UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/**\n * \u7AEF\u53E3\u53F7\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\uFF081-65535\uFF09\n */\nconst _PORT_REGEX =\n  /^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;\n\n/**\n * \u57DF\u540D\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\n */\nconst DOMAIN_REGEX = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$/;\n\n/**\n * \u670D\u52A1\u540D\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\uFF08\u4EC5\u5B57\u6BCD\u6570\u5B57\u3001@\u3001._-\uFF09\n */\nconst SERVICE_NAME_REGEX = /^[a-zA-Z0-9@._-]+$/;\n\n/**\n * IPv4 \u5730\u5740\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\n */\nconst IPV4_REGEX =\n  /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n\n/**\n * \u8DEF\u5F84\u9A8C\u8BC1\u6B63\u5219\u8868\u8FBE\u5F0F\uFF08Unix \u8DEF\u5F84\uFF09\n */\nconst PATH_REGEX = /^\\/(?:[^/\\0]+\\/)*[^/\\0]*$/;\n\n/**\n * \u9A8C\u8BC1\u90AE\u7BB1\u5730\u5740\n * @param email \u90AE\u7BB1\u5730\u5740\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidEmail(email: string): boolean {\n  if (!email || typeof email !== 'string') {\n    return false;\n  }\n  return EMAIL_REGEX.test(email);\n}\n\n/**\n * \u9A8C\u8BC1 UUID v4 \u683C\u5F0F\n * @param uuid UUID \u5B57\u7B26\u4E32\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidUuid(uuid: string): boolean {\n  if (!uuid || typeof uuid !== 'string') {\n    return false;\n  }\n  return UUID_V4_REGEX.test(uuid);\n}\n\n/**\n * \u9A8C\u8BC1\u7AEF\u53E3\u53F7\uFF081-65535\uFF09\n * @param port \u7AEF\u53E3\u53F7\uFF08\u6570\u5B57\u6216\u5B57\u7B26\u4E32\uFF09\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidPort(port: number | string): boolean {\n  const num = typeof port === 'string' ? parseInt(port, 10) : port;\n\n  if (isNaN(num) || !Number.isInteger(num)) {\n    return false;\n  }\n\n  return num >= 1 && num <= 65535;\n}\n\n/**\n * \u9A8C\u8BC1\u57DF\u540D\n * @param domain \u57DF\u540D\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidDomain(domain: string): boolean {\n  if (!domain || typeof domain !== 'string') {\n    return false;\n  }\n  return DOMAIN_REGEX.test(domain);\n}\n\n/**\n * \u9A8C\u8BC1\u670D\u52A1\u540D\u79F0\n * @param serviceName \u670D\u52A1\u540D\u79F0\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidServiceName(serviceName: string): boolean {\n  if (!serviceName || typeof serviceName !== 'string') {\n    return false;\n  }\n  return SERVICE_NAME_REGEX.test(serviceName);\n}\n\n/**\n * \u9A8C\u8BC1 IPv4 \u5730\u5740\n * @param ip IP \u5730\u5740\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidIPv4(ip: string): boolean {\n  if (!ip || typeof ip !== 'string') {\n    return false;\n  }\n  return IPV4_REGEX.test(ip);\n}\n\n/**\n * \u9A8C\u8BC1 Unix \u8DEF\u5F84\n * @param path \u8DEF\u5F84\u5B57\u7B26\u4E32\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidPath(path: string): boolean {\n  if (!path || typeof path !== 'string') {\n    return false;\n  }\n  return PATH_REGEX.test(path);\n}\n\n/**\n * \u9A8C\u8BC1 URL\n * @param url URL \u5B57\u7B26\u4E32\n * @returns \u662F\u5426\u6709\u6548\n */\nexport function isValidUrl(url: string): boolean {\n  try {\n    new URL(url);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * \u9A8C\u8BC1\u5668\u63A5\u53E3\n */\nexport interface Validator {\n  validate(_value: string): boolean;\n  errorMessage: string;\n}\n\n/**\n * \u9A8C\u8BC1\u5668\u6620\u5C04\n */\nexport const validators: Record<string, Validator> = {\n  email: {\n    validate: isValidEmail,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740\uFF08\u5982 user@example.com\uFF09',\n  },\n\n  uuid: {\n    validate: isValidUuid,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684 UUID v4 \u683C\u5F0F',\n  },\n\n  port: {\n    validate: (value) => {\n      const num = parseInt(value, 10);\n      return !isNaN(num) && isValidPort(num);\n    },\n    errorMessage: '\u7AEF\u53E3\u53F7\u5FC5\u987B\u5728 1-65535 \u4E4B\u95F4',\n  },\n\n  domain: {\n    validate: isValidDomain,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684\u57DF\u540D\uFF08\u5982 example.com\uFF09',\n  },\n\n  serviceName: {\n    validate: isValidServiceName,\n    errorMessage: '\u670D\u52A1\u540D\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u3001\u6570\u5B57\u548C @._- \u5B57\u7B26',\n  },\n\n  ipv4: {\n    validate: isValidIPv4,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684 IPv4 \u5730\u5740',\n  },\n\n  path: {\n    validate: isValidPath,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684 Unix \u8DEF\u5F84\uFF08\u4EE5 / \u5F00\u5934\uFF09',\n  },\n\n  url: {\n    validate: isValidUrl,\n    errorMessage: '\u8BF7\u8F93\u5165\u6709\u6548\u7684 URL',\n  },\n};\n\n/**\n * \u9A8C\u8BC1\u7ED3\u679C\n */\nexport interface ValidationResult {\n  /** \u662F\u5426\u6709\u6548 */\n  valid: boolean;\n\n  /** \u9519\u8BEF\u6D88\u606F */\n  error?: string;\n\n  /** \u5B57\u6BB5\u540D\u79F0 */\n  field?: string;\n}\n\n/**\n * \u901A\u7528\u9A8C\u8BC1\u51FD\u6570\n * @param value \u5F85\u9A8C\u8BC1\u7684\u503C\n * @param validatorName \u9A8C\u8BC1\u5668\u540D\u79F0\n * @param fieldName \u5B57\u6BB5\u540D\u79F0\uFF08\u7528\u4E8E\u9519\u8BEF\u6D88\u606F\uFF09\n * @returns \u9A8C\u8BC1\u7ED3\u679C\n */\nexport function validate(\n  value: string,\n  validatorName: keyof typeof validators,\n  fieldName?: string\n): ValidationResult {\n  const validator = validators[validatorName];\n\n  if (!validator) {\n    return {\n      valid: false,\n      error: `\u672A\u77E5\u7684\u9A8C\u8BC1\u5668: ${validatorName}`,\n      field: fieldName,\n    };\n  }\n\n  const valid = validator.validate(value);\n\n  if (!valid) {\n    return {\n      valid: false,\n      error: validator.errorMessage,\n      field: fieldName,\n    };\n  }\n\n  return { valid: true };\n}\n\n/**\n * \u6279\u91CF\u9A8C\u8BC1\n * @param values \u5B57\u6BB5\u548C\u503C\u7684\u6620\u5C04\n * @param validatorMap \u5B57\u6BB5\u548C\u9A8C\u8BC1\u5668\u7684\u6620\u5C04\n * @returns \u9A8C\u8BC1\u7ED3\u679C\u5217\u8868\n */\nexport function validateMultiple(\n  values: Record<string, string>,\n  validatorMap: Record<string, keyof typeof validators>\n): ValidationResult[] {\n  const results: ValidationResult[] = [];\n\n  for (const [field, value] of Object.entries(values)) {\n    const validatorName = validatorMap[field];\n    if (validatorName) {\n      results.push(validate(value, validatorName, field));\n    }\n  }\n\n  return results;\n}\n\n/**\n * \u68C0\u67E5\u6240\u6709\u9A8C\u8BC1\u662F\u5426\u901A\u8FC7\n * @param results \u9A8C\u8BC1\u7ED3\u679C\u5217\u8868\n * @returns \u662F\u5426\u5168\u90E8\u901A\u8FC7\n */\nexport function allValid(results: ValidationResult[]): boolean {\n  return results.every((result) => result.valid);\n}\n\n/**\n * \u83B7\u53D6\u6240\u6709\u9519\u8BEF\u6D88\u606F\n * @param results \u9A8C\u8BC1\u7ED3\u679C\u5217\u8868\n * @returns \u9519\u8BEF\u6D88\u606F\u5217\u8868\n */\nexport function getErrors(results: ValidationResult[]): string[] {\n  return results.filter((result) => !result.valid).map((result) => result.error || '\u672A\u77E5\u9519\u8BEF');\n}\n", "/**\n * VLESS link parser and generator utilities\n * @module utils/vless-link\n */\n\nimport { isValidPort, isValidUuid } from './validator';\nimport { ProtocolError } from './errors';\nimport { ProtocolErrors } from '../constants/error-codes';\n\n/**\n * Parameters for generating VLESS REALITY link\n */\nexport interface VlessRealityParams {\n  uuid: string;\n  server: string;\n  port: number;\n  publicKey: string;\n  shortId: string;\n  sni?: string;\n  flow?: string;\n  fingerprint?: string;\n  remark?: string;\n}\n\n/**\n * Parameters for generating VLESS WebSocket (CDN) link\n */\nexport interface VlessWebSocketParams {\n  uuid: string;\n  server: string;\n  port: number;\n  path: string;\n  host?: string;\n  sni?: string;\n  tls?: boolean;\n  remark?: string;\n}\n\n/**\n * Generate VLESS REALITY share link\n *\n * @param params - REALITY link parameters\n * @returns VLESS share link string\n */\nexport function generateVlessRealityLink(params: VlessRealityParams): string {\n  const {\n    uuid,\n    server,\n    port,\n    publicKey,\n    shortId,\n    sni = 'www.microsoft.com',\n    flow = 'xtls-rprx-vision',\n    fingerprint = 'chrome',\n    remark = 'Xray-Reality',\n  } = params;\n\n  const searchParams = new URLSearchParams({\n    encryption: 'none',\n    flow,\n    security: 'reality',\n    sni,\n    fp: fingerprint,\n    pbk: publicKey,\n    sid: shortId,\n    type: 'tcp',\n    headerType: 'none',\n  });\n\n  return `vless://${uuid}@${server}:${port}?${searchParams.toString()}#${encodeURIComponent(remark)}`;\n}\n\n/**\n * Generate VLESS WebSocket (CDN) share link\n *\n * @param params - WebSocket link parameters\n * @returns VLESS share link string\n */\nexport function generateVlessWebSocketLink(params: VlessWebSocketParams): string {\n  const { uuid, server, port, path, host, sni, tls = true, remark = 'Xray-CDN' } = params;\n\n  const searchParams = new URLSearchParams({\n    encryption: 'none',\n    security: tls ? 'tls' : 'none',\n    type: 'ws',\n    host: host || server,\n    path,\n  });\n\n  if (tls && sni) {\n    searchParams.set('sni', sni);\n  }\n\n  return `vless://${uuid}@${server}:${port}?${searchParams.toString()}#${encodeURIComponent(remark)}`;\n}\n\nexport interface VlessLinkInfo {\n  uuid: string;\n  server: string;\n  port: number;\n  name: string;\n  encryption?: string;\n  security?: string;\n  type?: string;\n  flow?: string;\n  sni?: string;\n  fp?: string;\n  pbk?: string;\n  sid?: string;\n  spx?: string;\n  host?: string;\n  path?: string;\n  serviceName?: string;\n  alpn?: string;\n  headerType?: string;\n}\n\nexport function normalizeVlessLink(raw: string): string {\n  return raw.trim().replace(/\\s+/g, '');\n}\n\nexport function parseVlessLink(raw: string): VlessLinkInfo {\n  const normalized = normalizeVlessLink(raw);\n  let url: URL;\n\n  try {\n    url = new URL(normalized);\n  } catch {\n    throw new ProtocolError(ProtocolErrors.INVALID_VLESS_LINK);\n  }\n\n  if (url.protocol !== 'vless:') {\n    throw new ProtocolError(ProtocolErrors.INVALID_VLESS_LINK, url.protocol);\n  }\n\n  const uuid = url.username;\n  if (!uuid) {\n    throw new ProtocolError(ProtocolErrors.VLESS_MISSING_UUID);\n  }\n  if (!isValidUuid(uuid)) {\n    throw new ProtocolError(ProtocolErrors.VLESS_MISSING_UUID, uuid);\n  }\n\n  const server = url.hostname;\n  if (!server) {\n    throw new ProtocolError(ProtocolErrors.VLESS_MISSING_HOST);\n  }\n\n  const port = url.port ? parseInt(url.port, 10) : 443;\n  if (!isValidPort(port)) {\n    throw new ProtocolError(ProtocolErrors.VLESS_INVALID_PORT, String(port));\n  }\n\n  const name = url.hash ? decodeURIComponent(url.hash.slice(1)) : '';\n  const params = url.searchParams;\n  const getParam = (key: string): string | undefined => {\n    const value = params.get(key);\n    return value === null ? undefined : value;\n  };\n\n  return {\n    uuid,\n    server,\n    port,\n    name: name || `${server}:${port}`,\n    encryption: getParam('encryption'),\n    security: getParam('security'),\n    type: getParam('type'),\n    flow: getParam('flow'),\n    sni: getParam('sni'),\n    fp: getParam('fp'),\n    pbk: getParam('pbk'),\n    sid: getParam('sid'),\n    spx: getParam('spx'),\n    host: getParam('host'),\n    path: getParam('path'),\n    serviceName: getParam('serviceName'),\n    alpn: getParam('alpn'),\n    headerType: getParam('headerType'),\n  };\n}\n", "/**\n * Clash config generator for VLESS links\n * @module services/clash-config\n */\n\nimport { VlessLinkInfo } from '../utils/vless-link';\n\nexport interface ClashConfigOptions {\n  proxyName?: string;\n  proxyGroupName?: string;\n}\n\nexport interface ClashConfigResult {\n  yaml: string;\n  proxyName: string;\n  proxyGroupName: string;\n}\n\nfunction yamlQuote(value: string): string {\n  const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n  return `\"${escaped}\"`;\n}\n\nfunction renderStringList(lines: string[], indent: number, values: string[]): void {\n  const prefix = ' '.repeat(indent);\n  values.forEach((value) => {\n    lines.push(`${prefix}- ${yamlQuote(value)}`);\n  });\n}\n\nexport function buildClashConfigYaml(\n  info: VlessLinkInfo,\n  options: ClashConfigOptions = {}\n): ClashConfigResult {\n  const proxyName = options.proxyName || info.name || `${info.server}:${info.port}`;\n  const proxyGroupName = options.proxyGroupName || 'PROXY';\n\n  const network = (info.type || 'tcp').toLowerCase();\n  const security = (info.security || '').toLowerCase();\n\n  const lines: string[] = [];\n\n  lines.push('port: 7890');\n  lines.push('socks-port: 7891');\n  lines.push('allow-lan: true');\n  lines.push('mode: rule');\n  lines.push('log-level: info');\n  lines.push('');\n  lines.push('proxies:');\n  lines.push(`  - name: ${yamlQuote(proxyName)}`);\n  lines.push('    type: vless');\n  lines.push(`    server: ${yamlQuote(info.server)}`);\n  lines.push(`    port: ${info.port}`);\n  lines.push(`    uuid: ${yamlQuote(info.uuid)}`);\n  lines.push('    udp: true');\n  lines.push(`    network: ${yamlQuote(network)}`);\n\n  if (info.flow) {\n    lines.push(`    flow: ${yamlQuote(info.flow)}`);\n  }\n\n  if (security === 'reality' || security === 'tls') {\n    lines.push('    tls: true');\n    if (info.sni) {\n      lines.push(`    servername: ${yamlQuote(info.sni)}`);\n    }\n  }\n\n  if (security === 'reality') {\n    if (!info.pbk) {\n      throw new Error('Reality \u94FE\u63A5\u7F3A\u5C11 pbk \u53C2\u6570');\n    }\n    lines.push('    reality-opts:');\n    lines.push(`      public-key: ${yamlQuote(info.pbk)}`);\n    if (info.sid) {\n      lines.push(`      short-id: ${yamlQuote(info.sid)}`);\n    }\n    if (info.spx) {\n      lines.push(`      spider-x: ${yamlQuote(info.spx)}`);\n    }\n  }\n\n  if (info.fp) {\n    lines.push(`    client-fingerprint: ${yamlQuote(info.fp)}`);\n  }\n\n  if (info.alpn) {\n    const list = info.alpn\n      .split(',')\n      .map((value) => value.trim())\n      .filter(Boolean);\n    if (list.length > 0) {\n      lines.push('    alpn:');\n      renderStringList(lines, 6, list);\n    }\n  }\n\n  if (network === 'ws') {\n    lines.push('    ws-opts:');\n    if (info.path) {\n      lines.push(`      path: ${yamlQuote(info.path)}`);\n    }\n    if (info.host) {\n      lines.push('      headers:');\n      lines.push(`        Host: ${yamlQuote(info.host)}`);\n    }\n  }\n\n  if (network === 'grpc') {\n    lines.push('    grpc-opts:');\n    const serviceName = info.serviceName || info.path;\n    if (serviceName) {\n      lines.push(`      grpc-service-name: ${yamlQuote(serviceName)}`);\n    }\n  }\n\n  lines.push('');\n  lines.push('proxy-groups:');\n  lines.push(`  - name: ${yamlQuote(proxyGroupName)}`);\n  lines.push('    type: select');\n  lines.push('    proxies:');\n  lines.push(`      - ${yamlQuote(proxyName)}`);\n  lines.push('      - DIRECT');\n  lines.push('');\n  lines.push('rules:');\n  lines.push(`  - MATCH,${proxyGroupName}`);\n  lines.push('');\n\n  return {\n    yaml: `${lines.join('\\n')}\\n`,\n    proxyName,\n    proxyGroupName,\n  };\n}\n", "import React, { createContext, useContext, useState, useCallback } from 'react';\nimport { type ThemeName, type Theme, getTheme } from './theme.js';\n\ninterface ThemeContextValue {\n  themeName: ThemeName;\n  theme: Theme;\n  setTheme: (name: ThemeName) => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue>({\n  themeName: 'dark',\n  theme: getTheme('dark'),\n  setTheme: () => {},\n});\n\nexport function ThemeProvider({\n  children,\n  defaultTheme = 'dark',\n}: {\n  children: React.ReactNode;\n  defaultTheme?: ThemeName;\n}) {\n  const [themeName, setThemeName] = useState<ThemeName>(defaultTheme);\n\n  const setTheme = useCallback((name: ThemeName) => {\n    setThemeName(name);\n  }, []);\n\n  const value: ThemeContextValue = {\n    themeName,\n    theme: getTheme(themeName),\n    setTheme,\n  };\n\n  return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n  return useContext(ThemeContext);\n}\n", "export interface Theme {\n  // Brand\n  primary: string;\n  primaryShimmer: string;\n\n  // Semantic\n  success: string;\n  error: string;\n  warning: string;\n  info: string;\n\n  // Text\n  text: string;\n  inverseText: string;\n  inactive: string;\n  subtle: string;\n\n  // UI Chrome\n  border: string;\n  borderAccent: string;\n  highlight: string;\n\n  // Service status\n  serviceRunning: string;\n  serviceStopped: string;\n\n  // Quota\n  quotaNormal: string;\n  quotaWarning: string;\n  quotaExceeded: string;\n  quotaUnlimited: string;\n\n  // Progress\n  progressFill: string;\n  progressEmpty: string;\n}\n\nexport type ThemeName = 'dark' | 'light';\n\nexport const darkTheme: Theme = {\n  primary: '#00c8c8',\n  primaryShimmer: '#32e6e6',\n\n  success: '#48c757',\n  error: '#f04747',\n  warning: '#fac83c',\n  info: '#5789f7',\n\n  text: '#e6e6e6',\n  inverseText: '#141414',\n  inactive: '#808080',\n  subtle: '#5a5a5a',\n\n  border: '#3c3c3c',\n  borderAccent: '#00c8c8',\n  highlight: '#283c3c',\n\n  serviceRunning: '#48c757',\n  serviceStopped: '#f04747',\n\n  quotaNormal: '#48c757',\n  quotaWarning: '#fac83c',\n  quotaExceeded: '#f04747',\n  quotaUnlimited: '#5789f7',\n\n  progressFill: '#00c8c8',\n  progressEmpty: '#323232',\n};\n\nexport const lightTheme: Theme = {\n  primary: '#009999',\n  primaryShimmer: '#00b7b7',\n\n  success: '#2c7a39',\n  error: '#ab2b3f',\n  warning: '#966c1e',\n  info: '#5769f7',\n\n  text: '#141414',\n  inverseText: '#f5f5f5',\n  inactive: '#787878',\n  subtle: '#afafaf',\n\n  border: '#c8c8c8',\n  borderAccent: '#009999',\n  highlight: '#dcf0f0',\n\n  serviceRunning: '#2c7a39',\n  serviceStopped: '#ab2b3f',\n\n  quotaNormal: '#2c7a39',\n  quotaWarning: '#966c1e',\n  quotaExceeded: '#ab2b3f',\n  quotaUnlimited: '#5769f7',\n\n  progressFill: '#009999',\n  progressEmpty: '#dcdcdc',\n};\n\nconst themes: Record<ThemeName, Theme> = { dark: darkTheme, light: lightTheme };\n\nexport function getTheme(name: ThemeName): Theme {\n  return themes[name];\n}\n\nexport function resolveColor(color: string | undefined, theme: Theme): string | undefined {\n  if (!color) return undefined;\n  if (color.startsWith('#') || color.startsWith('rgb(') || color.startsWith('ansi')) {\n    return color;\n  }\n  return (theme as unknown as Record<string, string>)[color] ?? color;\n}\n", "import React, { createContext, useContext, useState, useCallback } from 'react';\nimport {\n  type Language,\n  type Translations,\n  t as getTranslations,\n  setLanguage as setLangPersist,\n  getCurrentLanguage,\n  loadLanguagePreference,\n} from '../config/i18n.js';\n\ninterface I18nContextValue {\n  language: Language;\n  t: Translations;\n  setLanguage: (lang: Language) => void;\n  toggleLanguage: () => void;\n}\n\nconst I18nContext = createContext<I18nContextValue>({\n  language: 'en',\n  t: getTranslations(),\n  setLanguage: () => {},\n  toggleLanguage: () => {},\n});\n\nexport function I18nProvider({\n  children,\n  defaultLanguage = 'en',\n}: {\n  children: React.ReactNode;\n  defaultLanguage?: Language;\n}) {\n  // Load from preference file, fallback to default\n  const initial = loadLanguagePreference() || defaultLanguage;\n  const [language, setLanguageState] = useState<Language>(initial);\n\n  const setLanguage = useCallback((lang: Language) => {\n    setLangPersist(lang);\n    setLanguageState(lang);\n  }, []);\n\n  const toggleLanguage = useCallback(() => {\n    const newLang = language === 'zh' ? 'en' : 'zh';\n    setLanguage(newLang);\n  }, [language, setLanguage]);\n\n  // Update module-level language so t() returns correct translations\n  if (getCurrentLanguage() !== language) {\n    setLangPersist(language);\n  }\n\n  return (\n    <I18nContext.Provider value={{ language, t: getTranslations(), setLanguage, toggleLanguage }}>\n      {children}\n    </I18nContext.Provider>\n  );\n}\n\nexport function useI18n(): I18nContextValue {\n  return useContext(I18nContext);\n}\n", "/**\n * Internationalization (i18n) Configuration\n *\n * Provides language support for Chinese and English\n *\n * @module config/i18n\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\n/** Supported languages */\nexport type Language = 'zh' | 'en';\n\n/** Language preference storage path */\nconst LANG_FILE = path.join(os.homedir(), '.xray-manager-lang');\n\n/** Translation interface */\nexport interface Translations {\n  // Menu items\n  menu: {\n    viewStatus: string;\n    startService: string;\n    stopService: string;\n    restartService: string;\n    userManagement: string;\n    quotaManagement: string;\n    configManagement: string;\n    viewLogs: string;\n    switchLanguage: string;\n    exit: string;\n    onlineUsers: string;\n    subscriptions: string;\n  };\n\n  // Menu hints (shown next to menu items)\n  hints: {\n    viewDetails: string;\n    liveConnections: string;\n    addDeleteShare: string;\n    limitsUsage: string;\n    subLinkServer: string;\n    backupRestore: string;\n    accessError: string;\n  };\n\n  // Status labels\n  status: {\n    serviceStatus: string;\n    userCount: string;\n    active: string;\n    inactive: string;\n    unknown: string;\n    running: string;\n    stopped: string;\n    loading: string;\n    error: string;\n  };\n\n  // UI common\n  ui: {\n    navigate: string;\n    select: string;\n    search: string;\n    quit: string;\n    back: string;\n    add: string;\n    delete_: string;\n    share: string;\n    details: string;\n    refresh: string;\n    follow: string;\n    scroll: string;\n    switchLog: string;\n    setQuota: string;\n    resetUsage: string;\n    reenable: string;\n    start: string;\n    stop: string;\n    entries: string;\n    users: string;\n    noData: string;\n    processing: string;\n    autoRefresh: string;\n    never: string;\n    expired: string;\n    daysLeft: string;\n    unlimited: string;\n    createBackup: string;\n    existing: string;\n    custom: string;\n    confirmStop: string;\n    confirmRestart: string;\n    userCreated: string;\n    email: string;\n    uuid: string;\n    expiry: string;\n    expiryDaysPrompt: string;\n    emailPrompt: string;\n    selectUser: string;\n    selectQuota: string;\n    noUsers: string;\n    noConnections: string;\n    noEntries: string;\n    noQuotas: string;\n    pressEscBack: string;\n  };\n\n  // Quota labels\n  quota: {\n    title: string;\n    list: string;\n    set: string;\n    show: string;\n    reset: string;\n    reenable: string;\n    unlimited: string;\n    used: string;\n    remaining: string;\n    exceeded: string;\n    warning: string;\n    normal: string;\n    noQuota: string;\n    selectUser: string;\n    selectPreset: string;\n    enterCustom: string;\n    confirmReset: string;\n    confirmReenable: string;\n    executeCheck: string;\n    checkComplete: string;\n    normalUsers: string;\n    warningUsers: string;\n    exceededUsers: string;\n    disabledUsers: string;\n  };\n\n  // Logs labels\n  logs: {\n    title: string;\n    accessLog: string;\n    errorLog: string;\n    noLogs: string;\n    logFileNotFound: string;\n    logFileEmpty: string;\n    showingLines: string;\n  };\n\n  // Config labels\n  config: {\n    title: string;\n    viewConfig: string;\n    backupConfig: string;\n    restoreConfig: string;\n    backupSuccess: string;\n    restoreSuccess: string;\n    noBackups: string;\n    selectBackup: string;\n    confirmRestore: string;\n    restoreWarning: string;\n  };\n\n  // Public IP labels\n  publicIp: {\n    detecting: string;\n    detected: string;\n    detectionFailed: string;\n    enterManually: string;\n    invalidIp: string;\n    saved: string;\n    natDetected: string;\n  };\n\n  // Common actions\n  actions: {\n    selectAction: string;\n    confirm: string;\n    cancel: string;\n    back: string;\n  };\n\n  // Messages\n  messages: {\n    languageSwitched: string;\n    operationSuccess: string;\n    operationFailed: string;\n    thankYou: string;\n    terminalTooNarrow: string;\n    terminalTooShort: string;\n    terminalResizeSuggestion: string;\n    quotaSet: string;\n    quotaReset: string;\n    userReenabled: string;\n    noUsersWithQuota: string;\n    noDisabledUsers: string;\n  };\n}\n\n/** Chinese translations */\nconst zhTranslations: Translations = {\n  menu: {\n    viewStatus: '\u670D\u52A1\u72B6\u6001',\n    startService: '\u542F\u52A8\u670D\u52A1',\n    stopService: '\u505C\u6B62\u670D\u52A1',\n    restartService: '\u91CD\u542F\u670D\u52A1',\n    userManagement: '\u7528\u6237\u7BA1\u7406',\n    quotaManagement: '\u6D41\u91CF\u914D\u989D',\n    configManagement: '\u914D\u7F6E\u7BA1\u7406',\n    viewLogs: '\u67E5\u770B\u65E5\u5FD7',\n    switchLanguage: '\u5207\u6362\u8BED\u8A00',\n    exit: '\u9000\u51FA',\n    onlineUsers: '\u5728\u7EBF\u7528\u6237',\n    subscriptions: '\u8BA2\u9605\u94FE\u63A5',\n  },\n  hints: {\n    viewDetails: '\u67E5\u770B\u8BE6\u60C5',\n    liveConnections: '\u5B9E\u65F6\u8FDE\u63A5',\n    addDeleteShare: '\u589E / \u5220 / \u5206\u4EAB',\n    limitsUsage: '\u9650\u989D\u4E0E\u7528\u91CF',\n    subLinkServer: '\u8BA2\u9605\u670D\u52A1',\n    backupRestore: '\u5907\u4EFD / \u6062\u590D',\n    accessError: '\u8BBF\u95EE\u4E0E\u9519\u8BEF',\n  },\n  status: {\n    serviceStatus: '\u670D\u52A1\u72B6\u6001',\n    userCount: '\u7528\u6237\u6570',\n    active: '\u8FD0\u884C\u4E2D',\n    inactive: '\u5DF2\u505C\u6B62',\n    unknown: '\u672A\u77E5',\n    running: '\u8FD0\u884C\u4E2D',\n    stopped: '\u5DF2\u505C\u6B62',\n    loading: '\u52A0\u8F7D\u4E2D',\n    error: '\u9519\u8BEF',\n  },\n  ui: {\n    navigate: '\u5BFC\u822A',\n    select: '\u9009\u62E9',\n    search: '\u641C\u7D22',\n    quit: '\u9000\u51FA',\n    back: '\u8FD4\u56DE',\n    add: '\u6DFB\u52A0',\n    delete_: '\u5220\u9664',\n    share: '\u5206\u4EAB',\n    details: '\u8BE6\u60C5',\n    refresh: '\u5237\u65B0',\n    follow: '\u8DDF\u968F',\n    scroll: '\u6EDA\u52A8',\n    switchLog: '\u5207\u6362\u65E5\u5FD7',\n    setQuota: '\u8BBE\u7F6E\u914D\u989D',\n    resetUsage: '\u91CD\u7F6E\u7528\u91CF',\n    reenable: '\u91CD\u65B0\u542F\u7528',\n    start: '\u542F\u52A8',\n    stop: '\u505C\u6B62',\n    entries: '\u6761\u8BB0\u5F55',\n    users: '\u7528\u6237',\n    noData: '\u6682\u65E0\u6570\u636E',\n    processing: '\u5904\u7406\u4E2D...',\n    autoRefresh: '\u81EA\u52A8\u5237\u65B0',\n    never: '\u6C38\u4E0D',\n    expired: '\u5DF2\u8FC7\u671F',\n    daysLeft: '\u5929\u540E\u5230\u671F',\n    unlimited: '\u65E0\u9650\u5236',\n    createBackup: '\u521B\u5EFA\u5907\u4EFD',\n    existing: '\u4E2A\u5DF2\u6709',\n    custom: '\u81EA\u5B9A\u4E49...',\n    confirmStop: '\u505C\u6B62\u670D\u52A1\uFF1F\u6D3B\u8DC3\u8FDE\u63A5\u5C06\u65AD\u5F00\u3002',\n    confirmRestart: '\u91CD\u542F\u670D\u52A1\uFF1F\u6D3B\u8DC3\u8FDE\u63A5\u5C06\u65AD\u5F00\u3002',\n    userCreated: '\u7528\u6237\u5DF2\u521B\u5EFA',\n    email: '\u90AE\u7BB1',\n    uuid: 'UUID',\n    expiry: '\u5230\u671F',\n    expiryDaysPrompt: '\u5230\u671F\u5929\u6570 (\u7559\u7A7A=\u6C38\u4E0D):',\n    emailPrompt: '\u90AE\u7BB1:',\n    selectUser: '\u9009\u62E9\u7528\u6237:',\n    selectQuota: '\u9009\u62E9\u914D\u989D:',\n    noUsers: '\u6682\u65E0\u7528\u6237',\n    noConnections: '\u65E0\u6D3B\u8DC3\u8FDE\u63A5',\n    noEntries: '\u6682\u65E0\u8BB0\u5F55',\n    noQuotas: '\u6682\u65E0\u914D\u989D\u914D\u7F6E',\n    pressEscBack: '\u6309 esc \u8FD4\u56DE',\n  },\n  quota: {\n    title: '\u6D41\u91CF\u914D\u989D\u7BA1\u7406',\n    list: '\u67E5\u770B\u914D\u989D\u5217\u8868',\n    set: '\u8BBE\u7F6E\u7528\u6237\u914D\u989D',\n    show: '\u67E5\u770B\u914D\u989D\u8BE6\u60C5',\n    reset: '\u91CD\u7F6E\u5DF2\u7528\u6D41\u91CF',\n    reenable: '\u91CD\u65B0\u542F\u7528\u7528\u6237',\n    unlimited: '\u65E0\u9650\u5236',\n    used: '\u5DF2\u4F7F\u7528',\n    remaining: '\u5269\u4F59',\n    exceeded: '\u5DF2\u8D85\u989D',\n    warning: '\u63A5\u8FD1\u9650\u989D',\n    normal: '\u6B63\u5E38',\n    noQuota: '\u672A\u8BBE\u7F6E\u914D\u989D',\n    selectUser: '\u8BF7\u9009\u62E9\u7528\u6237',\n    selectPreset: '\u8BF7\u9009\u62E9\u9884\u8BBE\u914D\u989D',\n    enterCustom: '\u8BF7\u8F93\u5165\u81EA\u5B9A\u4E49\u914D\u989D',\n    confirmReset: '\u786E\u5B9A\u8981\u91CD\u7F6E\u8BE5\u7528\u6237\u7684\u5DF2\u7528\u6D41\u91CF\u5417\uFF1F',\n    confirmReenable: '\u786E\u5B9A\u8981\u91CD\u65B0\u542F\u7528\u8BE5\u7528\u6237\u5417\uFF1F',\n    executeCheck: '\u6267\u884C\u914D\u989D\u68C0\u67E5',\n    checkComplete: '\u914D\u989D\u68C0\u67E5\u5B8C\u6210',\n    normalUsers: '\u6B63\u5E38\u7528\u6237',\n    warningUsers: '\u8B66\u544A\u7528\u6237',\n    exceededUsers: '\u8D85\u9650\u7528\u6237',\n    disabledUsers: '\u5DF2\u7981\u7528',\n  },\n  logs: {\n    title: '\u65E5\u5FD7\u67E5\u770B',\n    accessLog: '\u8BBF\u95EE\u65E5\u5FD7',\n    errorLog: '\u9519\u8BEF\u65E5\u5FD7',\n    noLogs: '\u6682\u65E0\u65E5\u5FD7',\n    logFileNotFound: '\u65E5\u5FD7\u6587\u4EF6\u4E0D\u5B58\u5728',\n    logFileEmpty: '\u65E5\u5FD7\u6587\u4EF6\u4E3A\u7A7A',\n    showingLines: '\u663E\u793A\u6700\u8FD1 {lines} \u884C',\n  },\n  config: {\n    title: '\u914D\u7F6E\u7BA1\u7406',\n    viewConfig: '\u67E5\u770B\u5F53\u524D\u914D\u7F6E',\n    backupConfig: '\u5907\u4EFD\u914D\u7F6E',\n    restoreConfig: '\u6062\u590D\u914D\u7F6E',\n    backupSuccess: '\u914D\u7F6E\u5DF2\u5907\u4EFD\u5230: {path}',\n    restoreSuccess: '\u914D\u7F6E\u5DF2\u6062\u590D',\n    noBackups: '\u6682\u65E0\u5907\u4EFD\u6587\u4EF6',\n    selectBackup: '\u8BF7\u9009\u62E9\u8981\u6062\u590D\u7684\u5907\u4EFD',\n    confirmRestore: '\u786E\u5B9A\u8981\u6062\u590D\u6B64\u5907\u4EFD\u5417\uFF1F',\n    restoreWarning: '\u6062\u590D\u914D\u7F6E\u5C06\u8986\u76D6\u5F53\u524D\u914D\u7F6E\u5E76\u91CD\u542F\u670D\u52A1',\n  },\n  publicIp: {\n    detecting: '\u6B63\u5728\u68C0\u6D4B\u516C\u7F51 IP...',\n    detected: '\u68C0\u6D4B\u5230\u516C\u7F51 IP: {ip}',\n    detectionFailed: '\u65E0\u6CD5\u81EA\u52A8\u68C0\u6D4B\u516C\u7F51 IP',\n    enterManually: '\u8BF7\u624B\u52A8\u8F93\u5165\u516C\u7F51 IP \u5730\u5740',\n    invalidIp: '\u65E0\u6548\u7684 IP \u5730\u5740\u683C\u5F0F',\n    saved: '\u516C\u7F51 IP \u5DF2\u4FDD\u5B58',\n    natDetected: '\u68C0\u6D4B\u5230 NAT \u73AF\u5883 (\u79C1\u6709 IP: {ip})',\n  },\n  actions: {\n    selectAction: '\u8BF7\u9009\u62E9\u64CD\u4F5C',\n    confirm: '\u786E\u8BA4',\n    cancel: '\u53D6\u6D88',\n    back: '\u8FD4\u56DE',\n  },\n  messages: {\n    languageSwitched: '\u8BED\u8A00\u5DF2\u5207\u6362\u4E3A\u4E2D\u6587',\n    operationSuccess: '\u64CD\u4F5C\u6210\u529F',\n    operationFailed: '\u64CD\u4F5C\u5931\u8D25',\n    thankYou: '\u611F\u8C22\u4F7F\u7528 Xray Manager!',\n    terminalTooNarrow: '\u7EC8\u7AEF\u5BBD\u5EA6\u8FC7\u7A84',\n    terminalTooShort: '\u7EC8\u7AEF\u9AD8\u5EA6\u8FC7\u4F4E',\n    terminalResizeSuggestion: '\u8BF7\u8C03\u6574\u7EC8\u7AEF\u5927\u5C0F\u4EE5\u83B7\u5F97\u6700\u4F73\u663E\u793A\u6548\u679C',\n    quotaSet: '\u914D\u989D\u8BBE\u7F6E\u6210\u529F',\n    quotaReset: '\u5DF2\u7528\u6D41\u91CF\u5DF2\u91CD\u7F6E',\n    userReenabled: '\u7528\u6237\u5DF2\u91CD\u65B0\u542F\u7528',\n    noUsersWithQuota: '\u6682\u65E0\u8BBE\u7F6E\u914D\u989D\u7684\u7528\u6237',\n    noDisabledUsers: '\u6682\u65E0\u88AB\u7981\u7528\u7684\u7528\u6237',\n  },\n};\n\n/** English translations */\nconst enTranslations: Translations = {\n  menu: {\n    viewStatus: 'Service Status',\n    startService: 'Start Service',\n    stopService: 'Stop Service',\n    restartService: 'Restart Service',\n    userManagement: 'User Management',\n    quotaManagement: 'Traffic & Quotas',\n    configManagement: 'Configuration',\n    viewLogs: 'View Logs',\n    switchLanguage: 'Switch Language',\n    exit: 'Exit',\n    onlineUsers: 'Online Users',\n    subscriptions: 'Subscriptions',\n  },\n  hints: {\n    viewDetails: 'view details',\n    liveConnections: 'live connections',\n    addDeleteShare: 'add / delete / share',\n    limitsUsage: 'limits & usage',\n    subLinkServer: 'sub link server',\n    backupRestore: 'backup / restore',\n    accessError: 'access & error',\n  },\n  status: {\n    serviceStatus: 'Service Status',\n    userCount: 'User Count',\n    active: 'Active',\n    inactive: 'Inactive',\n    unknown: 'Unknown',\n    running: 'Running',\n    stopped: 'Stopped',\n    loading: 'Loading',\n    error: 'Error',\n  },\n  ui: {\n    navigate: 'navigate',\n    select: 'select',\n    search: 'search',\n    quit: 'quit',\n    back: 'back',\n    add: 'add',\n    delete_: 'delete',\n    share: 'share',\n    details: 'details',\n    refresh: 'refresh',\n    follow: 'follow',\n    scroll: 'scroll',\n    switchLog: 'switch log',\n    setQuota: 'set quota',\n    resetUsage: 'reset usage',\n    reenable: 're-enable',\n    start: 'start',\n    stop: 'stop',\n    entries: 'entries',\n    users: 'users',\n    noData: 'No data',\n    processing: 'Processing...',\n    autoRefresh: 'Auto-refresh',\n    never: 'Never',\n    expired: 'Expired',\n    daysLeft: 'd left',\n    unlimited: 'Unlimited',\n    createBackup: 'Create Backup',\n    existing: 'existing',\n    custom: 'Custom...',\n    confirmStop: 'Stop service? Active connections will be dropped.',\n    confirmRestart: 'Restart service? Active connections will be dropped.',\n    userCreated: 'User created',\n    email: 'Email',\n    uuid: 'UUID',\n    expiry: 'Expiry',\n    expiryDaysPrompt: 'Expiry (days, empty=never):',\n    emailPrompt: 'Email:',\n    selectUser: 'Select user:',\n    selectQuota: 'Select quota:',\n    noUsers: 'No users configured',\n    noConnections: 'No active connections',\n    noEntries: 'No entries',\n    noQuotas: 'No quotas configured',\n    pressEscBack: 'press esc to go back',\n  },\n  quota: {\n    title: 'Traffic Quota Management',\n    list: 'View Quota List',\n    set: 'Set User Quota',\n    show: 'View Quota Details',\n    reset: 'Reset Used Traffic',\n    reenable: 'Re-enable User',\n    unlimited: 'Unlimited',\n    used: 'Used',\n    remaining: 'Remaining',\n    exceeded: 'Exceeded',\n    warning: 'Warning',\n    normal: 'Normal',\n    noQuota: 'No quota set',\n    selectUser: 'Select a user',\n    selectPreset: 'Select a preset quota',\n    enterCustom: 'Enter custom quota',\n    confirmReset: \"Are you sure you want to reset this user's traffic?\",\n    confirmReenable: 'Are you sure you want to re-enable this user?',\n    executeCheck: 'Execute Quota Check',\n    checkComplete: 'Quota check complete',\n    normalUsers: 'Normal users',\n    warningUsers: 'Warning users',\n    exceededUsers: 'Exceeded users',\n    disabledUsers: 'Disabled',\n  },\n  logs: {\n    title: 'Log Viewer',\n    accessLog: 'Access Log',\n    errorLog: 'Error Log',\n    noLogs: 'No logs available',\n    logFileNotFound: 'Log file not found',\n    logFileEmpty: 'Log file is empty',\n    showingLines: 'Showing last {lines} lines',\n  },\n  config: {\n    title: 'Config Management',\n    viewConfig: 'View Current Config',\n    backupConfig: 'Backup Config',\n    restoreConfig: 'Restore Config',\n    backupSuccess: 'Config backed up to: {path}',\n    restoreSuccess: 'Config restored successfully',\n    noBackups: 'No backup files available',\n    selectBackup: 'Select a backup to restore',\n    confirmRestore: 'Are you sure you want to restore this backup?',\n    restoreWarning: 'Restoring will overwrite current config and restart service',\n  },\n  publicIp: {\n    detecting: 'Detecting public IP...',\n    detected: 'Detected public IP: {ip}',\n    detectionFailed: 'Failed to detect public IP automatically',\n    enterManually: 'Please enter public IP address manually',\n    invalidIp: 'Invalid IP address format',\n    saved: 'Public IP saved',\n    natDetected: 'NAT environment detected (private IP: {ip})',\n  },\n  actions: {\n    selectAction: 'Please select an action',\n    confirm: 'Confirm',\n    cancel: 'Cancel',\n    back: 'Back',\n  },\n  messages: {\n    languageSwitched: 'Language switched to English',\n    operationSuccess: 'Operation successful',\n    operationFailed: 'Operation failed',\n    thankYou: 'Thank you for using Xray Manager!',\n    terminalTooNarrow: 'Terminal width is too narrow',\n    terminalTooShort: 'Terminal height is too short',\n    terminalResizeSuggestion: 'Please resize your terminal for optimal display',\n    quotaSet: 'Quota set successfully',\n    quotaReset: 'Used traffic has been reset',\n    userReenabled: 'User has been re-enabled',\n    noUsersWithQuota: 'No users with quota configured',\n    noDisabledUsers: 'No disabled users',\n  },\n};\n\n/** All translations */\nconst translations: Record<Language, Translations> = {\n  zh: zhTranslations,\n  en: enTranslations,\n};\n\n/** Current language (default: English) */\nlet currentLanguage: Language = 'en';\n\n/**\n * Load language preference from file\n */\nexport function loadLanguagePreference(): Language {\n  try {\n    if (fs.existsSync(LANG_FILE)) {\n      const lang = fs.readFileSync(LANG_FILE, 'utf-8').trim();\n      if (lang === 'zh' || lang === 'en') {\n        currentLanguage = lang;\n        return lang;\n      }\n    }\n  } catch {\n    // Ignore errors, use default\n  }\n  return 'en'; // Default to English\n}\n\n/**\n * Save language preference to file\n */\nexport function saveLanguagePreference(lang: Language): void {\n  try {\n    fs.writeFileSync(LANG_FILE, lang, 'utf-8');\n    currentLanguage = lang;\n  } catch {\n    // Ignore errors\n  }\n}\n\n/**\n * Get current language\n */\nexport function getCurrentLanguage(): Language {\n  return currentLanguage;\n}\n\n/**\n * Set current language\n */\nexport function setLanguage(lang: Language): void {\n  currentLanguage = lang;\n  saveLanguagePreference(lang);\n}\n\n/**\n * Toggle language (switch between zh and en)\n */\nexport function toggleLanguage(): Language {\n  const newLang = currentLanguage === 'zh' ? 'en' : 'zh';\n  setLanguage(newLang);\n  return newLang;\n}\n\n/**\n * Get translations for current language\n */\nexport function t(): Translations {\n  return translations[currentLanguage];\n}\n\n/**\n * Get translation for specific language\n */\nexport function getTranslations(lang: Language): Translations {\n  return translations[lang];\n}\n\n// Load language preference on module initialization\nloadLanguagePreference();\n", "import React, { createContext, useContext, useMemo } from 'react';\nimport { ConfigManager } from '../services/config-manager.js';\nimport { UserManager } from '../services/user-manager.js';\nimport { SystemdManager } from '../services/systemd-manager.js';\nimport { QuotaManager } from '../services/quota-manager.js';\nimport { TrafficManager } from '../services/traffic-manager.js';\nimport { LogManager } from '../services/log-manager.js';\nimport { StatsConfigManager } from '../services/stats-config-manager.js';\n\nexport interface ServiceInstances {\n  configManager: ConfigManager;\n  userManager: UserManager;\n  systemdManager: SystemdManager;\n  quotaManager: QuotaManager;\n  trafficManager: TrafficManager;\n  logManager: LogManager;\n  statsConfigManager: StatsConfigManager;\n}\n\nexport interface ServiceOptions {\n  configPath?: string;\n  serviceName?: string;\n}\n\nconst ServiceContext = createContext<ServiceInstances | null>(null);\n\nexport function ServiceProvider({\n  children,\n  options,\n}: {\n  children: React.ReactNode;\n  options: ServiceOptions;\n}) {\n  const services = useMemo(() => {\n    const serviceName = options.serviceName ?? 'xray';\n    return {\n      configManager: new ConfigManager(options.configPath),\n      userManager: new UserManager(options.configPath, serviceName),\n      systemdManager: new SystemdManager(serviceName),\n      quotaManager: new QuotaManager(),\n      trafficManager: new TrafficManager(),\n      logManager: new LogManager(serviceName),\n      statsConfigManager: new StatsConfigManager(options.configPath, serviceName),\n    };\n  }, [options.configPath, options.serviceName]);\n\n  return <ServiceContext.Provider value={services}>{children}</ServiceContext.Provider>;\n}\n\nexport function useServices(): ServiceInstances {\n  const ctx = useContext(ServiceContext);\n  if (!ctx) throw new Error('useServices must be used within ServiceProvider');\n  return ctx;\n}\n", "/**\n * ConfigManager - Xray Configuration File Management\n *\n * Provides safe interface to read, write, validate, and backup Xray config\n *\n * @module services/config-manager\n */\n\nimport { readFile, writeFile, mkdir, chmod, access, readdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname, join } from 'path';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport type { XrayConfig } from '../types/config';\nimport { ConfigError } from '../utils/errors';\nimport { ConfigErrors } from '../constants/error-codes';\n\n/**\n * ConfigManager - Safe configuration file operations\n */\nexport class ConfigManager {\n  private configPath: string;\n  private backupDir: string;\n\n  /**\n   * Create a new ConfigManager\n   *\n   * @param configPath - Path to config file (default: /usr/local/etc/xray/config.json)\n   */\n  constructor(configPath?: string) {\n    this.configPath = configPath || DEFAULT_PATHS.CONFIG_FILE;\n    this.backupDir = DEFAULT_PATHS.BACKUP_DIR || '/var/backups/xray';\n  }\n\n  /**\n   * Read and parse config file\n   *\n   * @returns Parsed configuration object\n   */\n  async readConfig(): Promise<XrayConfig> {\n    try {\n      const content = await readFile(this.configPath, 'utf-8');\n      const config = JSON.parse(content) as XrayConfig;\n      return config;\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n        throw new ConfigError(ConfigErrors.CONFIG_NOT_FOUND, this.configPath);\n      } else if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n        throw new ConfigError(ConfigErrors.CONFIG_NO_READ_PERMISSION, this.configPath);\n      } else if (error instanceof SyntaxError) {\n        throw new ConfigError(ConfigErrors.CONFIG_INVALID_JSON, (error as Error).message);\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Write config to file with secure permissions\n   *\n   * @param config - Configuration object to write\n   */\n  async writeConfig(config: XrayConfig): Promise<void> {\n    try {\n      // Validate config before writing\n      this.validateConfig(config);\n\n      // Ensure directory exists\n      const dir = dirname(this.configPath);\n      if (!existsSync(dir)) {\n        await mkdir(dir, { recursive: true });\n      }\n\n      // Write with pretty formatting\n      const content = JSON.stringify(config, null, 2);\n      await writeFile(this.configPath, content, 'utf-8');\n\n      // Set secure permissions (600 = rw-------)\n      await chmod(this.configPath, 0o600);\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n        throw new ConfigError(ConfigErrors.CONFIG_NO_WRITE_PERMISSION, this.configPath);\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Validate configuration structure\n   *\n   * @param config - Configuration to validate\n   * @throws Error if validation fails\n   */\n  validateConfig(config: XrayConfig): void {\n    if (!config || typeof config !== 'object') {\n      throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, '\u914D\u7F6E\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61');\n    }\n\n    // Check for required top-level fields\n    if (!config.inbounds || !Array.isArray(config.inbounds)) {\n      throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, '\u7F3A\u5C11 inbounds \u6570\u7EC4');\n    }\n\n    if (!config.outbounds || !Array.isArray(config.outbounds)) {\n      throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, '\u7F3A\u5C11 outbounds \u6570\u7EC4');\n    }\n\n    // Validate inbounds\n    for (const inbound of config.inbounds) {\n      if (!inbound.protocol) {\n        throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, 'inbound \u7F3A\u5C11 protocol');\n      }\n      if (typeof inbound.port !== 'number') {\n        throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, 'inbound \u7F3A\u5C11\u6709\u6548 port');\n      }\n    }\n\n    // Validate outbounds\n    for (const outbound of config.outbounds) {\n      if (!outbound.protocol) {\n        throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, 'outbound \u7F3A\u5C11 protocol');\n      }\n    }\n  }\n\n  /**\n   * Backup configuration file\n   *\n   * @returns Path to backup file\n   */\n  async backupConfig(): Promise<string> {\n    try {\n      // Ensure backup directory exists\n      if (!existsSync(this.backupDir)) {\n        await mkdir(this.backupDir, { recursive: true, mode: 0o700 });\n      }\n\n      // Generate timestamp-based backup filename\n      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n      const backupPath = join(this.backupDir, `config.${timestamp}.json`);\n\n      // Read current config\n      const config = await this.readConfig();\n\n      // Write backup\n      const content = JSON.stringify(config, null, 2);\n      await writeFile(backupPath, content, 'utf-8');\n      await chmod(backupPath, 0o600);\n\n      return backupPath;\n    } catch (error) {\n      throw new ConfigError(ConfigErrors.CONFIG_BACKUP_FAILED, (error as Error).message);\n    }\n  }\n\n  /**\n   * List available backups\n   *\n   * @returns Array of backup file paths\n   */\n  async listBackups(): Promise<string[]> {\n    try {\n      if (!existsSync(this.backupDir)) {\n        return [];\n      }\n\n      const files = await readdir(this.backupDir);\n      const backups = files\n        .filter((file) => file.startsWith('config.') && file.endsWith('.json'))\n        .map((file) => join(this.backupDir, file))\n        .sort()\n        .reverse(); // Most recent first\n\n      return backups;\n    } catch (error) {\n      throw new ConfigError(ConfigErrors.CONFIG_BACKUP_FAILED, (error as Error).message);\n    }\n  }\n\n  /**\n   * Restore configuration from backup\n   *\n   * @param backupPath - Path to backup file\n   */\n  async restoreConfig(backupPath: string): Promise<void> {\n    try {\n      // Verify backup file exists\n      await access(backupPath);\n\n      // Backup current config first (pre-restore backup)\n      await this.backupConfig();\n\n      // Read backup content\n      const content = await readFile(backupPath, 'utf-8');\n      const config = JSON.parse(content) as XrayConfig;\n\n      // Validate and write\n      await this.writeConfig(config);\n    } catch (error) {\n      throw new ConfigError(ConfigErrors.CONFIG_RESTORE_FAILED, (error as Error).message);\n    }\n  }\n\n  /**\n   * Modify a configuration item\n   *\n   * @param path - Dot-separated path to config item (e.g., \"log.loglevel\")\n   * @param value - New value\n   */\n  async modifyConfigItem(path: string, value: unknown): Promise<void> {\n    const config = await this.readConfig();\n\n    // Split path and navigate to parent object\n    const parts = path.split('.');\n    let current: Record<string, unknown> = config as unknown as Record<string, unknown>;\n\n    for (let i = 0; i < parts.length - 1; i++) {\n      if (!current[parts[i]]) {\n        current[parts[i]] = {};\n      }\n      current = current[parts[i]] as Record<string, unknown>;\n    }\n\n    // Set value\n    const lastPart = parts[parts.length - 1];\n    current[lastPart] = value;\n\n    // Validate and write\n    await this.writeConfig(config);\n  }\n\n  /**\n   * Get formatted configuration for display\n   *\n   * @returns Pretty-printed JSON string\n   */\n  async getFormattedConfig(): Promise<string> {\n    const config = await this.readConfig();\n    return JSON.stringify(config, null, 2);\n  }\n\n  /**\n   * List available backups with metadata\n   *\n   * @returns Array of backup info objects\n   */\n  async listBackupsWithInfo(): Promise<\n    Array<{ path: string; filename: string; createdAt: Date; size: number }>\n  > {\n    const backupPaths = await this.listBackups();\n    const backupsWithInfo = [];\n\n    for (const backupPath of backupPaths) {\n      try {\n        const stats = await import('fs/promises').then((fs) => fs.stat(backupPath));\n        const filename = backupPath.split('/').pop() || '';\n\n        // Extract timestamp from filename: config.2024-01-15T10-30-00-000Z.json\n        let createdAt = stats.mtime;\n        const timestampMatch = filename.match(/config\\.(\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2})/);\n        if (timestampMatch) {\n          const isoString = timestampMatch[1].replace(/-/g, (match, offset) => {\n            // Replace dashes in time portion with colons\n            return offset > 10 ? ':' : '-';\n          });\n          try {\n            createdAt = new Date(isoString);\n          } catch {\n            // Use file mtime as fallback\n          }\n        }\n\n        backupsWithInfo.push({\n          path: backupPath,\n          filename,\n          createdAt,\n          size: stats.size,\n        });\n      } catch {\n        // Skip files we can't stat\n        continue;\n      }\n    }\n\n    return backupsWithInfo;\n  }\n\n  /**\n   * Restore configuration from backup with optional service restart\n   *\n   * @param backupPath - Path to backup file\n   * @param restartService - Whether to restart service after restore (default: true)\n   */\n  async restoreFromBackup(backupPath: string, restartService: boolean = true): Promise<void> {\n    // First restore the config\n    await this.restoreConfig(backupPath);\n\n    // Optionally restart service\n    if (restartService) {\n      const { SystemdManager } = await import('./systemd-manager');\n      const systemd = new SystemdManager(DEFAULT_PATHS.SERVICE_NAME);\n      await systemd.restart();\n    }\n  }\n}\n", "/**\n * UserManager - User Management with Auto UUID Generation\n *\n * Provides safe user management with automatic service restart\n *\n * @module services/user-manager\n */\n\nimport { randomUUID, createPrivateKey, createPublicKey } from 'crypto';\nimport { URLSearchParams } from 'url';\nimport { ConfigManager } from './config-manager';\nimport { SystemdManager } from './systemd-manager';\nimport { PublicIpManager } from './public-ip-manager';\nimport { UserMetadataManager } from './user-metadata-manager';\nimport type { User, CreateUserParams, UserShareInfo } from '../types/user';\nimport { isValidEmail } from '../utils/validator';\nimport { UserError, NetworkError } from '../utils/errors';\nimport { UserErrors, NetworkErrors, ConfigErrors } from '../constants/error-codes';\nimport { ConfigError } from '../utils/errors';\n\n/**\n * Generate X25519 public key from private key\n *\n * @param privateKeyBase64 - Base64URL encoded private key (32 bytes)\n * @returns Base64URL encoded public key\n */\nfunction generatePublicKeyFromPrivate(privateKeyBase64: string): string {\n  try {\n    // Decode the raw private key (32 bytes)\n    const privateKeyBuffer = Buffer.from(privateKeyBase64, 'base64url');\n\n    // X25519 PKCS#8 DER header (for 32-byte raw key)\n    const pkcs8Header = Buffer.from([\n      0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04,\n      0x20,\n    ]);\n\n    const privateKeyDer = Buffer.concat([pkcs8Header, privateKeyBuffer]);\n\n    const privateKey = createPrivateKey({\n      key: privateKeyDer,\n      format: 'der',\n      type: 'pkcs8',\n    });\n\n    const publicKey = createPublicKey(privateKey);\n    const publicKeySpki = publicKey.export({ type: 'spki', format: 'der' });\n\n    // Extract the raw public key (last 32 bytes of SPKI)\n    const publicKeyRaw = publicKeySpki.slice(-32);\n    return publicKeyRaw.toString('base64url');\n  } catch {\n    throw new UserError(UserErrors.KEY_GENERATION_FAILED);\n  }\n}\n\n/**\n * UserManager - Manage Xray users\n */\nexport class UserManager {\n  private configManager: ConfigManager;\n  private systemdManager: SystemdManager;\n  private publicIpManager: PublicIpManager;\n  private metadataManager: UserMetadataManager;\n  private serviceName: string;\n\n  /**\n   * Create a new UserManager\n   *\n   * @param configPath - Optional config file path\n   * @param serviceName - Service name (default: xray)\n   */\n  constructor(configPath?: string, serviceName: string = 'xray') {\n    this.configManager = new ConfigManager(configPath);\n    this.systemdManager = new SystemdManager(serviceName);\n    this.publicIpManager = new PublicIpManager();\n    this.metadataManager = new UserMetadataManager();\n    this.serviceName = serviceName;\n  }\n\n  /**\n   * Generate a new UUID v4 using crypto.randomUUID()\n   *\n   * @returns UUID string\n   */\n  generateUuid(): string {\n    return randomUUID();\n  }\n\n  /**\n   * Validate email address\n   *\n   * @param email - Email to validate\n   * @throws Error if email is invalid\n   */\n  validateEmail(email: string): void {\n    if (!isValidEmail(email)) {\n      throw new UserError(UserErrors.INVALID_EMAIL, email);\n    }\n  }\n\n  /**\n   * List all users from config\n   *\n   * @returns Array of users\n   */\n  async listUsers(): Promise<User[]> {\n    const config = await this.configManager.readConfig();\n    const allMetadata = await this.metadataManager.getAllMetadata();\n    const users: User[] = [];\n\n    // Extract users from all inbounds\n    for (const inbound of config.inbounds || []) {\n      if (inbound.settings?.clients) {\n        for (const client of inbound.settings.clients) {\n          const metadata = allMetadata[client.id];\n          users.push({\n            id: client.id,\n            email: client.email || '',\n            level: client.level || 0,\n            flow: client.flow,\n            createdAt: metadata?.createdAt || new Date().toISOString(),\n            status: metadata?.status || 'active',\n            expiryDate: metadata?.expiryDate,\n            dataLimit: metadata?.dataLimit,\n            maxConnections: metadata?.maxConnections,\n            subscriptionToken: metadata?.subscriptionToken,\n          });\n        }\n      }\n    }\n\n    return users;\n  }\n\n  /**\n   * Add a new user with auto-generated UUID\n   *\n   * @param params - User creation parameters\n   * @returns Created user\n   */\n  async addUser(params: CreateUserParams): Promise<User> {\n    // Validate email\n    this.validateEmail(params.email);\n\n    // Check for duplicate email\n    const existingUsers = await this.listUsers();\n    const duplicate = existingUsers.find((u) => u.email === params.email);\n    if (duplicate) {\n      throw new UserError(UserErrors.EMAIL_EXISTS, params.email);\n    }\n\n    // Backup config before modification\n    await this.configManager.backupConfig();\n\n    // Generate UUID\n    const id = this.generateUuid();\n    const now = new Date().toISOString();\n\n    // Calculate expiry date\n    let expiryDate: string | undefined;\n    if (params.expiryDate) {\n      expiryDate = params.expiryDate;\n    } else if (params.expiryDays && params.expiryDays > 0) {\n      const expiry = new Date();\n      expiry.setDate(expiry.getDate() + params.expiryDays);\n      expiryDate = expiry.toISOString();\n    }\n\n    // Create user object\n    const newUser: User = {\n      id,\n      email: params.email,\n      level: params.level ?? 0,\n      flow: params.flow,\n      createdAt: now,\n      status: 'active',\n      expiryDate,\n      dataLimit: params.dataLimit,\n      maxConnections: params.maxConnections,\n    };\n\n    // Read config\n    const config = await this.configManager.readConfig();\n\n    // Find first VLESS or VMess inbound and add user\n    let added = false;\n    for (const inbound of config.inbounds || []) {\n      if (inbound.protocol === 'vless' || inbound.protocol === 'vmess') {\n        if (!inbound.settings) {\n          inbound.settings = { clients: [] };\n        }\n        if (!inbound.settings.clients) {\n          inbound.settings.clients = [];\n        }\n\n        // Determine flow value: use provided, or default for VLESS + REALITY\n        let flowValue = params.flow;\n        if (!flowValue && inbound.protocol === 'vless') {\n          // For VLESS with REALITY or TLS, default to xtls-rprx-vision\n          const security = inbound.streamSettings?.security;\n          if (security === 'reality' || security === 'tls') {\n            flowValue = 'xtls-rprx-vision';\n          }\n        }\n\n        inbound.settings.clients.push({\n          id,\n          email: params.email,\n          level: params.level,\n          flow: flowValue,\n        });\n\n        added = true;\n        break;\n      }\n    }\n\n    if (!added) {\n      throw new ConfigError(ConfigErrors.CONFIG_INVALID_STRUCTURE, '\u672A\u627E\u5230 VLESS/VMess inbound');\n    }\n\n    // Write config\n    await this.configManager.writeConfig(config);\n\n    // Create user metadata with expiry and limits\n    await this.metadataManager.createUser(id);\n    if (expiryDate || params.dataLimit || params.maxConnections) {\n      await this.metadataManager.setMetadata(id, {\n        ...(expiryDate ? { expiryDate } : {}),\n        ...(params.dataLimit ? { dataLimit: params.dataLimit } : {}),\n        ...(params.maxConnections ? { maxConnections: params.maxConnections } : {}),\n      });\n    }\n\n    // Restart service\n    await this.systemdManager.restart();\n\n    return newUser;\n  }\n\n  /**\n   * Delete user by ID\n   *\n   * @param userId - User ID (UUID) to delete\n   */\n  async deleteUser(userId: string): Promise<void> {\n    // Backup config before modification\n    await this.configManager.backupConfig();\n\n    // Read config\n    const config = await this.configManager.readConfig();\n\n    // Find and remove user\n    let found = false;\n    for (const inbound of config.inbounds || []) {\n      if (inbound.settings?.clients) {\n        const index = inbound.settings.clients.findIndex((c) => c.id === userId);\n        if (index !== -1) {\n          inbound.settings.clients.splice(index, 1);\n          found = true;\n          break;\n        }\n      }\n    }\n\n    if (!found) {\n      throw new UserError(UserErrors.USER_NOT_FOUND, userId);\n    }\n\n    // Write config\n    await this.configManager.writeConfig(config);\n\n    // Delete user metadata\n    await this.metadataManager.deleteMetadata(userId);\n\n    // Restart service\n    await this.systemdManager.restart();\n  }\n\n  /**\n   * Get share information for a user\n   *\n   * @param userId - User ID (UUID)\n   * @returns Share information including VLESS link\n   */\n  async getShareInfo(userId: string): Promise<UserShareInfo> {\n    const config = await this.configManager.readConfig();\n    const metadata = await this.metadataManager.getMetadata(userId);\n\n    // Find user in all inbounds and collect inbound info\n    let user: User | undefined;\n    let primaryInbound:\n      | {\n          port: number;\n          protocol: string;\n          streamSettings?: {\n            network?: string;\n            security?: string;\n            realitySettings?: {\n              privateKey: string;\n              serverNames: string[];\n              shortIds: string[];\n            };\n            wsSettings?: {\n              path: string;\n              headers?: Record<string, string>;\n            };\n          };\n        }\n      | undefined;\n    let wsInbound:\n      | {\n          port: number;\n          protocol: string;\n          streamSettings?: {\n            network?: string;\n            security?: string;\n            wsSettings?: {\n              path: string;\n              headers?: Record<string, string>;\n            };\n          };\n        }\n      | undefined;\n\n    // Search through all inbounds\n    for (const inbound of config.inbounds || []) {\n      if (inbound.settings?.clients) {\n        const client = inbound.settings.clients.find((c) => c.id === userId);\n        if (client) {\n          if (!user) {\n            user = {\n              id: client.id,\n              email: client.email || '',\n              level: client.level || 0,\n              flow: client.flow,\n              createdAt: metadata?.createdAt || new Date().toISOString(),\n              status: metadata?.status || 'active',\n            };\n          }\n\n          const network = inbound.streamSettings?.network || 'tcp';\n          const security = inbound.streamSettings?.security || 'none';\n\n          // Categorize inbound: WebSocket vs Primary (REALITY/TLS)\n          if (network === 'ws') {\n            wsInbound = {\n              port: inbound.port,\n              protocol: inbound.protocol,\n              streamSettings: inbound.streamSettings,\n            };\n          } else if (security === 'reality' || security === 'tls') {\n            primaryInbound = {\n              port: inbound.port,\n              protocol: inbound.protocol,\n              streamSettings: inbound.streamSettings,\n            };\n          } else if (!primaryInbound) {\n            // Fallback to first found inbound\n            primaryInbound = {\n              port: inbound.port,\n              protocol: inbound.protocol,\n              streamSettings: inbound.streamSettings,\n            };\n          }\n        }\n      }\n    }\n\n    if (!user) {\n      throw new UserError(UserErrors.USER_NOT_FOUND, userId);\n    }\n\n    // Get public IP (from cache or detect)\n    let serverAddress: string;\n    try {\n      serverAddress = await this.publicIpManager.getPublicIp();\n    } catch {\n      throw new NetworkError(NetworkErrors.PUBLIC_IP_FAILED);\n    }\n\n    // Use primary inbound for main link, fallback to ws if no primary\n    const mainInbound = primaryInbound || wsInbound;\n    if (!mainInbound) {\n      throw new UserError(UserErrors.USER_NOT_FOUND, userId);\n    }\n\n    const port = mainInbound.port || 443;\n    const security = mainInbound.streamSettings?.security || 'tls';\n    const network = mainInbound.streamSettings?.network || 'tcp';\n    const flow = user.flow || 'xtls-rprx-vision';\n    const name = encodeURIComponent(user.email);\n\n    let vlessLink: string;\n    let publicKey: string | undefined;\n    let shortId: string | undefined;\n    let serverName: string | undefined;\n\n    if (security === 'reality' && primaryInbound?.streamSettings?.realitySettings) {\n      const reality = primaryInbound.streamSettings.realitySettings;\n\n      // Generate public key from private key\n      publicKey = generatePublicKeyFromPrivate(reality.privateKey);\n      serverName = reality.serverNames[0] || 'www.microsoft.com';\n      shortId = reality.shortIds[0] || '';\n\n      const params = new URLSearchParams();\n      params.set('encryption', 'none');\n      params.set('security', 'reality');\n      params.set('type', network);\n      params.set('flow', flow);\n      params.set('pbk', publicKey);\n      params.set('fp', 'chrome');\n      params.set('sni', serverName);\n      params.set('sid', shortId);\n      params.set('spx', '/');\n\n      vlessLink = `vless://${user.id}@${serverAddress}:${port}?${params.toString()}#${name}`;\n    } else {\n      vlessLink = `vless://${user.id}@${serverAddress}:${port}?encryption=none&security=${security}&type=${network}&flow=${flow}#${name}`;\n    }\n\n    // Build CDN (WebSocket) link if ws inbound exists\n    let cdnShareLink: string | undefined;\n    let wsPath: string | undefined;\n\n    if (wsInbound?.streamSettings?.wsSettings) {\n      wsPath = wsInbound.streamSettings.wsSettings.path;\n      const wsHost = wsInbound.streamSettings.wsSettings.headers?.Host || serverAddress;\n      const wsSecurity = wsInbound.streamSettings.security || 'none';\n      const wsPort = wsInbound.port || 443;\n\n      const wsParams = new URLSearchParams({\n        encryption: 'none',\n        security: wsSecurity === 'tls' ? 'tls' : 'tls', // CDN always uses TLS on client side\n        type: 'ws',\n        host: wsHost,\n        path: wsPath,\n        sni: wsHost,\n      });\n\n      // CDN link uses domain as server address (user should replace with their CDN domain)\n      cdnShareLink = `vless://${user.id}@${wsHost}:${wsPort}?${wsParams.toString()}#${encodeURIComponent(user.email + '-CDN')}`;\n    }\n\n    return {\n      user,\n      shareLink: vlessLink,\n      cdnShareLink,\n      serverAddress,\n      serverPort: port,\n      protocol: mainInbound.protocol || 'vless',\n      security,\n      network,\n      serverName,\n      publicKey,\n      shortId,\n      wsPath,\n      qrCode: vlessLink,\n    };\n  }\n\n  /**\n   * Get CDN share link for a user with custom domain\n   *\n   * @param userId - User ID (UUID)\n   * @param cdnDomain - CDN domain (e.g., \"example.com\")\n   * @param cdnPort - CDN port (default: 443)\n   * @returns CDN share link string or null if no WebSocket inbound\n   */\n  async getCdnShareLink(\n    userId: string,\n    cdnDomain: string,\n    cdnPort: number = 443\n  ): Promise<string | null> {\n    const config = await this.configManager.readConfig();\n\n    // Find WebSocket inbound with this user\n    for (const inbound of config.inbounds || []) {\n      if (inbound.settings?.clients) {\n        const client = inbound.settings.clients.find((c) => c.id === userId);\n        if (client && inbound.streamSettings?.network === 'ws') {\n          const wsPath = inbound.streamSettings.wsSettings?.path || '/ws';\n\n          const params = new URLSearchParams({\n            encryption: 'none',\n            security: 'tls',\n            type: 'ws',\n            host: cdnDomain,\n            path: wsPath,\n            sni: cdnDomain,\n          });\n\n          const name = encodeURIComponent((client.email || 'user') + '-CDN');\n          return `vless://${client.id}@${cdnDomain}:${cdnPort}?${params.toString()}#${name}`;\n        }\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Check if public IP needs manual input\n   *\n   * @returns true if manual input is needed\n   */\n  async needsPublicIpInput(): Promise<boolean> {\n    return this.publicIpManager.needsManualInput();\n  }\n\n  /**\n   * Set public IP manually\n   *\n   * @param ip - Public IP address\n   */\n  async setPublicIp(ip: string): Promise<void> {\n    await this.publicIpManager.setPublicIp(ip);\n  }\n\n  /**\n   * Get current public IP (from cache)\n   *\n   * @returns Public IP or null if not set\n   */\n  async getPublicIp(): Promise<string | null> {\n    const config = await this.publicIpManager.getConfig();\n    return config?.publicIp || null;\n  }\n\n  /**\n   * Get metadata manager for external access\n   *\n   * @returns UserMetadataManager instance\n   */\n  getMetadataManager(): UserMetadataManager {\n    return this.metadataManager;\n  }\n}\n", "/**\n * PublicIpManager - Public IP Detection and Caching Service\n *\n * Provides automatic public IP detection with fallback to manual input\n *\n * @module services/public-ip-manager\n */\n\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname } from 'path';\nimport * as https from 'https';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport { isPrivateIp } from '../utils/network';\nimport type {\n  ServerConfig,\n  IpSource,\n  IpDetectionResult,\n  IpDetectionService,\n} from '../types/server-config';\n\n/**\n * Default IP detection services (in priority order)\n */\nconst IP_SERVICES: IpDetectionService[] = [\n  { name: 'ipify', url: 'https://api.ipify.org', timeout: 3000 },\n  { name: 'ifconfig.me', url: 'https://ifconfig.me/ip', timeout: 3000 },\n  { name: 'ip.sb', url: 'https://api.ip.sb/ip', timeout: 3000 },\n];\n\n/**\n * Validate IPv4 address format\n */\nfunction isValidIpv4(ip: string): boolean {\n  const ipv4Regex = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n  if (!ipv4Regex.test(ip)) return false;\n\n  const parts = ip.split('.');\n  return parts.every((part) => {\n    const num = parseInt(part, 10);\n    return num >= 0 && num <= 255;\n  });\n}\n\n/**\n * Validate IPv6 address format (simplified)\n */\nfunction isValidIpv6(ip: string): boolean {\n  const ipv6Regex =\n    /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::$|^([0-9a-fA-F]{1,4}:)*:([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4}$/;\n  return ipv6Regex.test(ip);\n}\n\n/**\n * Validate IP address (IPv4 or IPv6)\n */\nexport function isValidIp(ip: string): boolean {\n  return isValidIpv4(ip) || isValidIpv6(ip);\n}\n\n/**\n * Fetch IP from a single service with timeout\n */\nfunction fetchIpFromService(service: IpDetectionService): Promise<IpDetectionResult> {\n  return new Promise((resolve) => {\n    const timeoutId = setTimeout(() => {\n      resolve({\n        ip: '',\n        success: false,\n        error: `Timeout after ${service.timeout}ms`,\n        provider: service.name,\n      });\n    }, service.timeout);\n\n    const req = https.get(service.url, (res) => {\n      let data = '';\n\n      res.on('data', (chunk) => {\n        data += chunk;\n      });\n\n      res.on('end', () => {\n        clearTimeout(timeoutId);\n        const ip = data.trim();\n\n        if (isValidIp(ip)) {\n          resolve({\n            ip,\n            success: true,\n            provider: service.name,\n          });\n        } else {\n          resolve({\n            ip: '',\n            success: false,\n            error: `Invalid IP response: ${ip.substring(0, 50)}`,\n            provider: service.name,\n          });\n        }\n      });\n    });\n\n    req.on('error', (error) => {\n      clearTimeout(timeoutId);\n      resolve({\n        ip: '',\n        success: false,\n        error: error.message,\n        provider: service.name,\n      });\n    });\n  });\n}\n\n/**\n * PublicIpManager - Manage public IP detection and caching\n */\nexport class PublicIpManager {\n  private configPath: string;\n  private maxRetries: number;\n\n  /**\n   * Create a new PublicIpManager\n   *\n   * @param configPath - Path to server config file\n   * @param maxRetries - Maximum retry attempts (default: 1)\n   */\n  constructor(configPath?: string, maxRetries: number = 1) {\n    this.configPath = configPath || DEFAULT_PATHS.SERVER_CONFIG_FILE;\n    this.maxRetries = maxRetries;\n  }\n\n  /**\n   * Read server config from file\n   *\n   * @returns ServerConfig or null if not found\n   */\n  async getConfig(): Promise<ServerConfig | null> {\n    try {\n      if (!existsSync(this.configPath)) {\n        return null;\n      }\n      const content = await readFile(this.configPath, 'utf-8');\n      return JSON.parse(content) as ServerConfig;\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Save server config to file\n   *\n   * @param config - ServerConfig to save\n   */\n  private async saveConfig(config: ServerConfig): Promise<void> {\n    const dir = dirname(this.configPath);\n    if (!existsSync(dir)) {\n      await mkdir(dir, { recursive: true });\n    }\n    await writeFile(this.configPath, JSON.stringify(config, null, 2), 'utf-8');\n  }\n\n  /**\n   * Detect public IP from external services\n   *\n   * @returns Detection result\n   */\n  private async detectPublicIp(): Promise<IpDetectionResult> {\n    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n      for (const service of IP_SERVICES) {\n        const result = await fetchIpFromService(service);\n        if (result.success) {\n          return result;\n        }\n      }\n    }\n\n    return {\n      ip: '',\n      success: false,\n      error: 'All IP detection services failed after retries',\n    };\n  }\n\n  /**\n   * Get public IP (from cache or detect)\n   *\n   * @returns Public IP address\n   * @throws Error if unable to get IP and no cache exists\n   */\n  async getPublicIp(): Promise<string> {\n    // Try to get from cache first\n    const config = await this.getConfig();\n    if (config?.publicIp) {\n      return config.publicIp;\n    }\n\n    // Try to detect\n    const result = await this.detectPublicIp();\n    if (result.success) {\n      // Cache the result\n      await this.saveConfig({\n        publicIp: result.ip,\n        lastUpdated: new Date().toISOString(),\n        source: 'auto',\n      });\n      return result.ip;\n    }\n\n    throw new Error(result.error || 'Failed to detect public IP');\n  }\n\n  /**\n   * Force refresh public IP (ignore cache)\n   *\n   * @returns New public IP address\n   * @throws Error if detection fails\n   */\n  async refreshPublicIp(): Promise<string> {\n    const result = await this.detectPublicIp();\n    if (result.success) {\n      await this.saveConfig({\n        publicIp: result.ip,\n        lastUpdated: new Date().toISOString(),\n        source: 'auto',\n      });\n      return result.ip;\n    }\n\n    throw new Error(result.error || 'Failed to detect public IP');\n  }\n\n  /**\n   * Manually set public IP\n   *\n   * @param ip - IP address to set\n   * @throws Error if IP format is invalid\n   */\n  async setPublicIp(ip: string): Promise<void> {\n    const trimmedIp = ip.trim();\n    if (!isValidIp(trimmedIp)) {\n      throw new Error(`Invalid IP address format: ${ip}`);\n    }\n\n    await this.saveConfig({\n      publicIp: trimmedIp,\n      lastUpdated: new Date().toISOString(),\n      source: 'manual',\n    });\n  }\n\n  /**\n   * Check if manual IP input is needed\n   *\n   * @returns true if NAT environment detected or detection fails\n   */\n  async needsManualInput(): Promise<boolean> {\n    // Check if we already have a cached IP\n    const config = await this.getConfig();\n    if (config?.publicIp) {\n      return false;\n    }\n\n    // Try to detect\n    const result = await this.detectPublicIp();\n    if (!result.success) {\n      return true;\n    }\n\n    // Check if detected IP is private (NAT)\n    if (isPrivateIp(result.ip)) {\n      return true;\n    }\n\n    // Cache the detected IP\n    await this.saveConfig({\n      publicIp: result.ip,\n      lastUpdated: new Date().toISOString(),\n      source: 'auto',\n    });\n\n    return false;\n  }\n\n  /**\n   * Get IP source (auto or manual)\n   *\n   * @returns IP source or null if no config\n   */\n  async getIpSource(): Promise<IpSource | null> {\n    const config = await this.getConfig();\n    return config?.source || null;\n  }\n}\n", "/**\n * Supported Linux distributions configuration\n * Feature: 009-cross-platform-support\n */\n\nimport { OsFamily, PackageManager } from '../types/platform.js';\n\nexport interface DistroConfig {\n  family: OsFamily;\n  minVersion: string;\n  packageManager: PackageManager;\n  displayName: string;\n}\n\nexport const SUPPORTED_DISTROS: Record<string, DistroConfig> = {\n  ubuntu: {\n    family: OsFamily.DEBIAN,\n    minVersion: '22.04',\n    packageManager: PackageManager.APT,\n    displayName: 'Ubuntu',\n  },\n  debian: {\n    family: OsFamily.DEBIAN,\n    minVersion: '11',\n    packageManager: PackageManager.APT,\n    displayName: 'Debian',\n  },\n  kali: {\n    family: OsFamily.DEBIAN,\n    minVersion: '2023',\n    packageManager: PackageManager.APT,\n    displayName: 'Kali Linux',\n  },\n  centos: {\n    family: OsFamily.RHEL,\n    minVersion: '9',\n    packageManager: PackageManager.DNF,\n    displayName: 'CentOS Stream',\n  },\n  almalinux: {\n    family: OsFamily.RHEL,\n    minVersion: '9',\n    packageManager: PackageManager.DNF,\n    displayName: 'AlmaLinux',\n  },\n  rocky: {\n    family: OsFamily.RHEL,\n    minVersion: '9',\n    packageManager: PackageManager.DNF,\n    displayName: 'Rocky Linux',\n  },\n  fedora: {\n    family: OsFamily.RHEL,\n    minVersion: '39',\n    packageManager: PackageManager.DNF,\n    displayName: 'Fedora',\n  },\n};\n\nexport const PRIVATE_IP_RANGES = [\n  /^10\\./,\n  /^172\\.(1[6-9]|2[0-9]|3[01])\\./,\n  /^192\\.168\\./,\n  /^127\\./, // Loopback\n];\n\nexport const SUPPORTED_DISTRO_IDS = Object.keys(SUPPORTED_DISTROS);\n\nexport function isDistroSupported(distroId: string): boolean {\n  return distroId.toLowerCase() in SUPPORTED_DISTROS;\n}\n\nexport function getDistroConfig(distroId: string): DistroConfig | undefined {\n  return SUPPORTED_DISTROS[distroId.toLowerCase()];\n}\n", "/**\n * Network detection utilities\n * Feature: 009-cross-platform-support\n */\n\nimport { execSync } from 'child_process';\nimport * as https from 'https';\nimport { NetworkConfig, NetworkInterface } from '../types/platform.js';\nimport { PRIVATE_IP_RANGES } from '../constants/supported-distros.js';\n\n/**\n * Public IP detection result\n */\nexport interface PublicIpResult {\n  ip: string;\n  success: boolean;\n  error?: string;\n  provider?: string;\n}\n\n/**\n * Default timeout for IP detection (3 seconds)\n */\nconst DEFAULT_TIMEOUT = 3000;\n\n/**\n * IP detection services in priority order\n */\nconst IP_DETECTION_SERVICES = [\n  { name: 'ipify', url: 'https://api.ipify.org' },\n  { name: 'ifconfig.me', url: 'https://ifconfig.me/ip' },\n  { name: 'ip.sb', url: 'https://api.ip.sb/ip' },\n];\n\n/**\n * Validate IPv4 address format\n */\nfunction isValidIpv4(ip: string): boolean {\n  const ipv4Regex = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n  if (!ipv4Regex.test(ip)) return false;\n\n  const parts = ip.split('.');\n  return parts.every((part) => {\n    const num = parseInt(part, 10);\n    return num >= 0 && num <= 255;\n  });\n}\n\n/**\n * Validate IPv6 address format (simplified)\n */\nfunction isValidIpv6(ip: string): boolean {\n  // Handle special cases\n  if (ip === '::') return true;\n  if (ip === '::1') return true;\n\n  // Full IPv6 address: 8 groups of 4 hex digits\n  const fullIpv6 = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;\n  if (fullIpv6.test(ip)) return true;\n\n  // IPv6 with :: compression (can appear anywhere)\n  // Must have :: and valid hex groups before/after\n  if (ip.includes('::')) {\n    const parts = ip.split('::');\n    if (parts.length !== 2) return false;\n\n    const validatePart = (part: string): boolean => {\n      if (part === '') return true;\n      const groups = part.split(':');\n      return groups.every((g) => /^[0-9a-fA-F]{1,4}$/.test(g));\n    };\n\n    return validatePart(parts[0]) && validatePart(parts[1]);\n  }\n\n  return false;\n}\n\n/**\n * Validate IP address (IPv4 or IPv6)\n */\nexport function isValidIp(ip: string): boolean {\n  return isValidIpv4(ip) || isValidIpv6(ip);\n}\n\n/**\n * Fetch public IP from a single service with timeout\n *\n * @param url - Service URL\n * @param timeout - Timeout in milliseconds\n * @returns Promise resolving to IP string or rejecting on error\n */\nfunction fetchFromService(url: string, timeout: number): Promise<string> {\n  return new Promise((resolve, reject) => {\n    const timeoutId = setTimeout(() => {\n      reject(new Error(`Timeout after ${timeout}ms`));\n    }, timeout);\n\n    const req = https.get(url, (res) => {\n      let data = '';\n\n      res.on('data', (chunk) => {\n        data += chunk;\n      });\n\n      res.on('end', () => {\n        clearTimeout(timeoutId);\n        const ip = data.trim();\n\n        if (isValidIp(ip)) {\n          resolve(ip);\n        } else {\n          reject(new Error(`Invalid IP response: ${ip.substring(0, 50)}`));\n        }\n      });\n    });\n\n    req.on('error', (error) => {\n      clearTimeout(timeoutId);\n      reject(error);\n    });\n  });\n}\n\n/**\n * Fetch public IP address with timeout and retry\n *\n * @param timeout - Timeout per request in milliseconds (default: 3000)\n * @param maxRetries - Maximum retry attempts (default: 1)\n * @returns Public IP detection result\n */\nexport async function fetchPublicIp(\n  timeout: number = DEFAULT_TIMEOUT,\n  maxRetries: number = 1\n): Promise<PublicIpResult> {\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    for (const service of IP_DETECTION_SERVICES) {\n      try {\n        const ip = await fetchFromService(service.url, timeout);\n        return {\n          ip,\n          success: true,\n          provider: service.name,\n        };\n      } catch {\n        // Try next service\n        continue;\n      }\n    }\n  }\n\n  return {\n    ip: '',\n    success: false,\n    error: 'All IP detection services failed after retries',\n  };\n}\n\n/**\n * Check if an IP address is private (NAT)\n */\nexport function isPrivateIp(ip: string): boolean {\n  return PRIVATE_IP_RANGES.some((regex) => regex.test(ip));\n}\n\n/**\n * Get all network interfaces with IPv4 addresses\n */\nexport function getNetworkInterfaces(): NetworkInterface[] {\n  const interfaces: NetworkInterface[] = [];\n\n  try {\n    const output = execSync('ip -4 addr show', { encoding: 'utf-8' });\n    const lines = output.split('\\n');\n\n    let currentInterface: Partial<NetworkInterface> = {};\n\n    for (const line of lines) {\n      // Match interface line: \"2: eth0: <BROADCAST...\"\n      const ifaceMatch = line.match(/^\\d+:\\s+(\\S+):/);\n      if (ifaceMatch) {\n        if (currentInterface.name) {\n          interfaces.push(currentInterface as NetworkInterface);\n        }\n        currentInterface = {\n          name: ifaceMatch[1],\n          isLoopback: ifaceMatch[1] === 'lo',\n        };\n      }\n\n      // Match inet line: \"    inet 192.168.1.100/24...\"\n      const inetMatch = line.match(/^\\s+inet\\s+(\\d+\\.\\d+\\.\\d+\\.\\d+)/);\n      if (inetMatch && currentInterface.name) {\n        currentInterface.ipv4 = inetMatch[1];\n      }\n    }\n\n    // Add last interface\n    if (currentInterface.name) {\n      interfaces.push(currentInterface as NetworkInterface);\n    }\n  } catch {\n    // Failed to get interfaces\n  }\n\n  return interfaces.filter((iface) => !iface.isLoopback && iface.ipv4);\n}\n\n/**\n * Detect network configuration\n */\nexport function detectNetwork(): NetworkConfig {\n  const interfaces = getNetworkInterfaces();\n  const firstIp = interfaces[0]?.ipv4 || '';\n\n  return {\n    interfaces,\n    selectedIp: firstIp,\n    isNat: isPrivateIp(firstIp),\n  };\n}\n", "/**\n * UserMetadataManager - User Metadata Persistence Service\n *\n * Manages user creation time, status, and other metadata\n *\n * @module services/user-metadata-manager\n */\n\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname } from 'path';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport type { UserMeta, UserMetadataStore, UserStatus } from '../types/user-metadata';\n\n/**\n * Validate UUID v4 format\n */\nfunction isValidUuid(uuid: string): boolean {\n  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n  return uuidRegex.test(uuid);\n}\n\n/**\n * UserMetadataManager - Manage user metadata persistence\n */\nexport class UserMetadataManager {\n  private metadataPath: string;\n  private cache: UserMetadataStore | null = null;\n\n  /**\n   * Create a new UserMetadataManager\n   *\n   * @param metadataPath - Path to metadata file\n   */\n  constructor(metadataPath?: string) {\n    this.metadataPath = metadataPath || DEFAULT_PATHS.USER_METADATA_FILE;\n  }\n\n  /**\n   * Load metadata from file\n   *\n   * @returns UserMetadataStore\n   */\n  private async loadMetadata(): Promise<UserMetadataStore> {\n    if (this.cache) {\n      return this.cache;\n    }\n\n    try {\n      if (!existsSync(this.metadataPath)) {\n        this.cache = { users: {} };\n        return this.cache;\n      }\n      const content = await readFile(this.metadataPath, 'utf-8');\n      this.cache = JSON.parse(content) as UserMetadataStore;\n      return this.cache;\n    } catch {\n      this.cache = { users: {} };\n      return this.cache;\n    }\n  }\n\n  /**\n   * Save metadata to file\n   *\n   * @param store - UserMetadataStore to save\n   */\n  private async saveMetadata(store: UserMetadataStore): Promise<void> {\n    const dir = dirname(this.metadataPath);\n    if (!existsSync(dir)) {\n      await mkdir(dir, { recursive: true });\n    }\n    await writeFile(this.metadataPath, JSON.stringify(store, null, 2), 'utf-8');\n    this.cache = store;\n  }\n\n  /**\n   * Get metadata for a specific user\n   *\n   * @param userId - User UUID\n   * @returns UserMeta or null if not found\n   */\n  async getMetadata(userId: string): Promise<UserMeta | null> {\n    const store = await this.loadMetadata();\n    return store.users[userId] || null;\n  }\n\n  /**\n   * Set metadata for a user (create or update)\n   *\n   * @param userId - User UUID\n   * @param metadata - Partial metadata to set/update\n   */\n  async setMetadata(userId: string, metadata: Partial<UserMeta>): Promise<void> {\n    if (!isValidUuid(userId)) {\n      throw new Error(`Invalid UUID format: ${userId}`);\n    }\n\n    const store = await this.loadMetadata();\n    const existing = store.users[userId] || {\n      createdAt: new Date().toISOString(),\n      status: 'active' as UserStatus,\n    };\n\n    store.users[userId] = {\n      ...existing,\n      ...metadata,\n    };\n\n    await this.saveMetadata(store);\n  }\n\n  /**\n   * Create metadata for a new user\n   *\n   * @param userId - User UUID\n   * @returns Created UserMeta\n   */\n  async createUser(userId: string): Promise<UserMeta> {\n    if (!isValidUuid(userId)) {\n      throw new Error(`Invalid UUID format: ${userId}`);\n    }\n\n    const store = await this.loadMetadata();\n\n    // Don't overwrite existing metadata\n    if (store.users[userId]) {\n      return store.users[userId];\n    }\n\n    const now = new Date().toISOString();\n    const metadata: UserMeta = {\n      createdAt: now,\n      status: 'active',\n      statusChangedAt: now,\n    };\n\n    store.users[userId] = metadata;\n    await this.saveMetadata(store);\n\n    return metadata;\n  }\n\n  /**\n   * Update user status\n   *\n   * @param userId - User UUID\n   * @param status - New status\n   */\n  async updateStatus(userId: string, status: UserStatus): Promise<void> {\n    const store = await this.loadMetadata();\n\n    if (!store.users[userId]) {\n      throw new Error(`User metadata not found: ${userId}`);\n    }\n\n    store.users[userId].status = status;\n    store.users[userId].statusChangedAt = new Date().toISOString();\n\n    await this.saveMetadata(store);\n  }\n\n  /**\n   * Delete user metadata\n   *\n   * @param userId - User UUID\n   */\n  async deleteMetadata(userId: string): Promise<void> {\n    const store = await this.loadMetadata();\n\n    if (store.users[userId]) {\n      delete store.users[userId];\n      await this.saveMetadata(store);\n    }\n  }\n\n  /**\n   * Get all user metadata\n   *\n   * @returns Record of userId to UserMeta\n   */\n  async getAllMetadata(): Promise<Record<string, UserMeta>> {\n    const store = await this.loadMetadata();\n    return { ...store.users };\n  }\n\n  /**\n   * Get users by status\n   *\n   * @param status - Status to filter by\n   * @returns Array of [userId, metadata] pairs\n   */\n  async getUsersByStatus(status: UserStatus): Promise<Array<[string, UserMeta]>> {\n    const store = await this.loadMetadata();\n    return Object.entries(store.users).filter(([_, meta]) => meta.status === status);\n  }\n\n  /**\n   * Clear cache (force reload from file on next access)\n   */\n  clearCache(): void {\n    this.cache = null;\n  }\n}\n", "/**\n * QuotaManager - \u914D\u989D\u914D\u7F6E\u7BA1\u7406\u670D\u52A1\n *\n * \u7BA1\u7406\u7528\u6237\u6D41\u91CF\u914D\u989D\u7684\u914D\u7F6E\u548C\u6301\u4E45\u5316\n *\n * @module services/quota-manager\n */\n\nimport { readFile, writeFile, mkdir, chmod } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname } from 'path';\nimport type { TrafficQuota, QuotaConfig, SetQuotaParams, AlertLevel } from '../types/quota';\nimport { DEFAULT_QUOTA, DEFAULT_QUOTA_CONFIG } from '../types/quota';\nimport { QUOTA_CONFIG_PATH, WARNING_THRESHOLD, EXCEEDED_THRESHOLD } from '../constants/quota';\nimport { QuotaError, ValidationError, NetworkError } from '../utils/errors';\nimport { QuotaErrors, ValidationErrors, NetworkErrors } from '../constants/error-codes';\n\n/**\n * \u9A8C\u8BC1\u90AE\u7BB1\u683C\u5F0F\n */\nfunction isValidEmail(email: string): boolean {\n  return email.length > 0 && email.includes('@') && email.length <= 254;\n}\n\n/**\n * \u9A8C\u8BC1\u914D\u989D\u503C\n * @param bytes - \u914D\u989D\u5B57\u8282\u6570\n * @returns true \u5982\u679C\u6709\u6548\uFF08-1 \u8868\u793A\u65E0\u9650\u5236\uFF0C\u6216\u8005 >= 0\uFF09\n */\nfunction isValidQuotaBytes(bytes: number): boolean {\n  return bytes === -1 || (Number.isFinite(bytes) && bytes >= 0);\n}\n\n/**\n * \u9A8C\u8BC1\u7AEF\u53E3\u53F7\n */\nfunction isValidPort(port: number): boolean {\n  return Number.isInteger(port) && port >= 1 && port <= 65535;\n}\n\n/**\n * QuotaManager - \u7BA1\u7406\u7528\u6237\u6D41\u91CF\u914D\u989D\n */\nexport class QuotaManager {\n  private configPath: string;\n\n  /**\n   * \u521B\u5EFA QuotaManager \u5B9E\u4F8B\n   *\n   * @param configPath - \u914D\u989D\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4 /usr/local/etc/xray/quota.json\uFF09\n   */\n  constructor(configPath: string = QUOTA_CONFIG_PATH) {\n    this.configPath = configPath;\n  }\n\n  /**\n   * \u8BFB\u53D6\u914D\u989D\u914D\u7F6E\u6587\u4EF6\n   *\n   * @returns \u914D\u989D\u914D\u7F6E\n   */\n  async readConfig(): Promise<QuotaConfig> {\n    try {\n      if (!existsSync(this.configPath)) {\n        return { ...DEFAULT_QUOTA_CONFIG };\n      }\n\n      const content = await readFile(this.configPath, 'utf-8');\n      const config = JSON.parse(content) as QuotaConfig;\n\n      // \u786E\u4FDD\u914D\u7F6E\u7ED3\u6784\u5B8C\u6574\n      return {\n        ...DEFAULT_QUOTA_CONFIG,\n        ...config,\n        users: config.users || {},\n      };\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n        throw new QuotaError(QuotaErrors.QUOTA_CONFIG_NOT_FOUND, this.configPath);\n      } else if (error instanceof SyntaxError) {\n        throw new QuotaError(QuotaErrors.QUOTA_CONFIG_NOT_FOUND, (error as Error).message);\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * \u5199\u5165\u914D\u989D\u914D\u7F6E\u6587\u4EF6\n   *\n   * @param config - \u914D\u989D\u914D\u7F6E\n   */\n  async writeConfig(config: QuotaConfig): Promise<void> {\n    try {\n      // \u786E\u4FDD\u76EE\u5F55\u5B58\u5728\n      const dir = dirname(this.configPath);\n      if (!existsSync(dir)) {\n        await mkdir(dir, { recursive: true });\n      }\n\n      // \u5199\u5165\u914D\u7F6E\n      const content = JSON.stringify(config, null, 2);\n      await writeFile(this.configPath, content, 'utf-8');\n\n      // \u8BBE\u7F6E\u5B89\u5168\u6743\u9650\n      await chmod(this.configPath, 0o600);\n    } catch (error) {\n      if ((error as NodeJS.ErrnoException).code === 'EACCES') {\n        throw new QuotaError(QuotaErrors.TRAFFIC_UPDATE_FAILED, this.configPath);\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * \u83B7\u53D6\u7528\u6237\u914D\u989D\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   * @returns \u914D\u989D\u914D\u7F6E\uFF0C\u4E0D\u5B58\u5728\u65F6\u8FD4\u56DE\u9ED8\u8BA4\u503C\n   */\n  async getQuota(email: string): Promise<TrafficQuota> {\n    const config = await this.readConfig();\n    return config.users[email] || { ...DEFAULT_QUOTA };\n  }\n\n  /**\n   * \u8BBE\u7F6E\u7528\u6237\u914D\u989D\n   *\n   * @param params - \u914D\u989D\u8BBE\u7F6E\u53C2\u6570\n   * @throws Error \u5982\u679C\u53C2\u6570\u65E0\u6548\n   */\n  async setQuota(params: SetQuotaParams): Promise<void> {\n    // \u9A8C\u8BC1\u90AE\u7BB1\n    if (!isValidEmail(params.email)) {\n      throw new ValidationError(ValidationErrors.INVALID_FORMAT, params.email);\n    }\n\n    // \u9A8C\u8BC1\u914D\u989D\u503C\n    if (!isValidQuotaBytes(params.quotaBytes)) {\n      throw new QuotaError(QuotaErrors.INVALID_QUOTA_VALUE, String(params.quotaBytes));\n    }\n\n    const config = await this.readConfig();\n\n    const existingQuota = config.users[params.email];\n    const now = new Date().toISOString();\n\n    config.users[params.email] = {\n      quotaBytes: params.quotaBytes,\n      quotaType: params.quotaType,\n      usedBytes: existingQuota?.usedBytes || 0,\n      lastReset: existingQuota?.lastReset || now,\n      status: existingQuota?.status || 'active',\n    };\n\n    await this.writeConfig(config);\n  }\n\n  /**\n   * \u91CD\u7F6E\u7528\u6237\u5DF2\u7528\u6D41\u91CF\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   */\n  async resetUsage(email: string): Promise<void> {\n    const config = await this.readConfig();\n\n    if (!config.users[email]) {\n      throw new QuotaError(QuotaErrors.USER_QUOTA_NOT_FOUND, email);\n    }\n\n    config.users[email].usedBytes = 0;\n    config.users[email].lastReset = new Date().toISOString();\n    config.users[email].status = 'active';\n\n    await this.writeConfig(config);\n  }\n\n  /**\n   * \u66F4\u65B0\u7528\u6237\u5DF2\u7528\u6D41\u91CF\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   * @param usedBytes - \u5DF2\u7528\u5B57\u8282\u6570\n   * @throws Error \u5982\u679C\u53C2\u6570\u65E0\u6548\n   */\n  async updateUsage(email: string, usedBytes: number): Promise<void> {\n    // \u9A8C\u8BC1\u5DF2\u7528\u5B57\u8282\u6570\n    if (!Number.isFinite(usedBytes) || usedBytes < 0) {\n      throw new ValidationError(ValidationErrors.VALUE_OUT_OF_RANGE, String(usedBytes));\n    }\n\n    const config = await this.readConfig();\n\n    if (!config.users[email]) {\n      // \u5982\u679C\u7528\u6237\u6CA1\u6709\u914D\u989D\u8BB0\u5F55\uFF0C\u521B\u5EFA\u9ED8\u8BA4\u8BB0\u5F55\n      config.users[email] = { ...DEFAULT_QUOTA };\n    }\n\n    config.users[email].usedBytes = usedBytes;\n\n    await this.writeConfig(config);\n  }\n\n  /**\n   * \u83B7\u53D6\u6240\u6709\u7528\u6237\u914D\u989D\n   *\n   * @returns \u7528\u6237\u914D\u989D\u6620\u5C04\n   */\n  async getAllQuotas(): Promise<Record<string, TrafficQuota>> {\n    const config = await this.readConfig();\n    return config.users;\n  }\n\n  /**\n   * \u5220\u9664\u7528\u6237\u914D\u989D\u8BB0\u5F55\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   */\n  async deleteQuota(email: string): Promise<void> {\n    const config = await this.readConfig();\n\n    if (!config.users[email]) {\n      return; // \u4E0D\u5B58\u5728\u5219\u9759\u9ED8\u8FD4\u56DE\n    }\n\n    delete config.users[email];\n    await this.writeConfig(config);\n  }\n\n  /**\n   * \u8BBE\u7F6E\u7528\u6237\u72B6\u6001\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   * @param status - \u65B0\u72B6\u6001\n   */\n  async setStatus(email: string, status: TrafficQuota['status']): Promise<void> {\n    const config = await this.readConfig();\n\n    if (!config.users[email]) {\n      throw new QuotaError(QuotaErrors.USER_QUOTA_NOT_FOUND, email);\n    }\n\n    config.users[email].status = status;\n    await this.writeConfig(config);\n  }\n\n  /**\n   * \u8BA1\u7B97\u8B66\u544A\u7EA7\u522B\n   *\n   * @param usedBytes - \u5DF2\u7528\u5B57\u8282\u6570\n   * @param quotaBytes - \u914D\u989D\u5B57\u8282\u6570\uFF08-1 \u8868\u793A\u65E0\u9650\u5236\uFF09\n   * @returns \u8B66\u544A\u7EA7\u522B\n   */\n  calculateAlertLevel(usedBytes: number, quotaBytes: number): AlertLevel {\n    if (quotaBytes < 0) {\n      return 'normal'; // \u65E0\u9650\u5236\n    }\n\n    const percent = (usedBytes / quotaBytes) * 100;\n\n    if (percent >= EXCEEDED_THRESHOLD) {\n      return 'exceeded';\n    }\n    if (percent >= WARNING_THRESHOLD) {\n      return 'warning';\n    }\n    return 'normal';\n  }\n\n  /**\n   * \u83B7\u53D6 API \u7AEF\u53E3\n   *\n   * @returns API \u7AEF\u53E3\u53F7\n   */\n  async getApiPort(): Promise<number> {\n    const config = await this.readConfig();\n    return config.apiPort;\n  }\n\n  /**\n   * \u8BBE\u7F6E API \u7AEF\u53E3\n   *\n   * @param port - API \u7AEF\u53E3\u53F7\n   * @throws Error \u5982\u679C\u7AEF\u53E3\u53F7\u65E0\u6548\n   */\n  async setApiPort(port: number): Promise<void> {\n    if (!isValidPort(port)) {\n      throw new NetworkError(NetworkErrors.INVALID_PORT, String(port));\n    }\n\n    const config = await this.readConfig();\n    config.apiPort = port;\n    await this.writeConfig(config);\n  }\n}\n", "/**\n * \u6D41\u91CF\u914D\u989D\u76F8\u5173\u7C7B\u578B\u5B9A\u4E49\n * @module types/quota\n */\n\n/**\n * \u6D41\u91CF\u914D\u989D\u7C7B\u578B\n */\nexport type QuotaType = 'limited' | 'unlimited';\n\n/**\n * \u914D\u989D\u72B6\u6001\n */\nexport type QuotaStatus = 'active' | 'disabled' | 'exceeded';\n\n/**\n * \u8B66\u544A\u7EA7\u522B\n */\nexport type AlertLevel = 'normal' | 'warning' | 'exceeded';\n\n/**\n * \u6D41\u91CF\u5355\u4F4D\n */\nexport type TrafficUnit = 'B' | 'KB' | 'MB' | 'GB' | 'TB';\n\n/**\n * \u6D41\u91CF\u914D\u989D\n */\nexport interface TrafficQuota {\n  /** \u914D\u989D\u603B\u91CF\uFF08\u5B57\u8282\uFF09\uFF0C-1 \u8868\u793A\u65E0\u9650\u5236 */\n  quotaBytes: number;\n  /** \u914D\u989D\u7C7B\u578B */\n  quotaType: QuotaType;\n  /** \u5DF2\u4F7F\u7528\u6D41\u91CF\uFF08\u5B57\u8282\uFF09 */\n  usedBytes: number;\n  /** \u4E0A\u6B21\u91CD\u7F6E\u65F6\u95F4\uFF08ISO 8601\uFF09 */\n  lastReset: string;\n  /** \u72B6\u6001 */\n  status: QuotaStatus;\n}\n\n/**\n * \u6D41\u91CF\u4F7F\u7528\u60C5\u51B5\n */\nexport interface TrafficUsage {\n  /** \u7528\u6237\u90AE\u7BB1\u6807\u8BC6 */\n  email: string;\n  /** \u4E0A\u884C\u6D41\u91CF\uFF08\u5B57\u8282\uFF09 */\n  uplink: number;\n  /** \u4E0B\u884C\u6D41\u91CF\uFF08\u5B57\u8282\uFF09 */\n  downlink: number;\n  /** \u603B\u6D41\u91CF\uFF08\u5B57\u8282\uFF09 */\n  total: number;\n  /** \u67E5\u8BE2\u65F6\u95F4\uFF08ISO 8601\uFF09 */\n  queriedAt: string;\n}\n\n/**\n * \u5E26\u914D\u989D\u7684\u7528\u6237\n */\nexport interface UserWithQuota {\n  /** \u7528\u6237 UUID */\n  id: string;\n  /** \u7528\u6237\u90AE\u7BB1\u6807\u8BC6 */\n  email: string;\n  /** \u6D41\u91CF\u914D\u989D\u914D\u7F6E */\n  quota: TrafficQuota;\n  /** \u5F53\u524D\u6D41\u91CF\u4F7F\u7528\uFF08\u53EF\u80FD\u4E0D\u53EF\u7528\uFF09 */\n  usage?: TrafficUsage;\n  /** \u4F7F\u7528\u767E\u5206\u6BD4\uFF080-100\uFF0C\u65E0\u9650\u5236\u65F6\u4E3A 0\uFF09 */\n  usagePercent?: number;\n  /** \u8B66\u544A\u7EA7\u522B */\n  alertLevel?: AlertLevel;\n}\n\n/**\n * \u914D\u989D\u914D\u7F6E\u6587\u4EF6\n */\nexport interface QuotaConfig {\n  /** \u914D\u7F6E\u7248\u672C\u53F7 */\n  version: string;\n  /** Xray Stats API \u7AEF\u53E3 */\n  apiPort: number;\n  /** \u7528\u6237\u914D\u989D\u6620\u5C04\uFF08key \u4E3A email\uFF09 */\n  users: Record<string, TrafficQuota>;\n}\n\n/**\n * \u914D\u989D\u8BBE\u7F6E\u53C2\u6570\n */\nexport interface SetQuotaParams {\n  /** \u7528\u6237\u90AE\u7BB1 */\n  email: string;\n  /** \u914D\u989D\u5B57\u8282\u6570\uFF08-1 \u8868\u793A\u65E0\u9650\u5236\uFF09 */\n  quotaBytes: number;\n  /** \u914D\u989D\u7C7B\u578B */\n  quotaType: QuotaType;\n}\n\n/**\n * \u683C\u5F0F\u5316\u7684\u6D41\u91CF\u503C\n */\nexport interface FormattedTraffic {\n  /** \u6570\u503C */\n  value: number;\n  /** \u5355\u4F4D */\n  unit: TrafficUnit;\n  /** \u663E\u793A\u5B57\u7B26\u4E32 */\n  display: string;\n}\n\n/**\n * Xray Stats API \u54CD\u5E94\n */\nexport interface XrayStatsResponse {\n  stat: Array<{\n    name: string;\n    value: number;\n  }>;\n}\n\n/**\n * \u9ED8\u8BA4\u914D\u989D\u503C\n */\nexport const DEFAULT_QUOTA: TrafficQuota = {\n  quotaBytes: -1,\n  quotaType: 'unlimited',\n  usedBytes: 0,\n  lastReset: new Date().toISOString(),\n  status: 'active',\n};\n\n/**\n * \u9ED8\u8BA4\u914D\u989D\u914D\u7F6E\n */\nexport const DEFAULT_QUOTA_CONFIG: QuotaConfig = {\n  version: '1.0',\n  apiPort: 10085,\n  users: {},\n};\n\n/**\n * Stats API \u7F3A\u5931\u7EC4\u4EF6\u7C7B\u578B\n */\nexport type MissingComponent =\n  | 'stats'\n  | 'policy'\n  | 'api'\n  | 'api-inbound'\n  | 'api-routing'\n  | 'api-outbound';\n\n/**\n * Stats API \u68C0\u6D4B\u7ED3\u679C\n */\nexport interface StatsDetectionResult {\n  /** API \u662F\u5426\u53EF\u7528\uFF08\u53EF\u8FDE\u63A5\uFF09 */\n  available: boolean;\n  /** \u914D\u7F6E\u6587\u4EF6\u4E2D\u662F\u5426\u68C0\u6D4B\u5230 stats \u914D\u7F6E */\n  configDetected: boolean;\n  /** \u68C0\u6D4B\u5230\u7684 API \u7AEF\u53E3 */\n  detectedPort?: number;\n  /** Xray \u670D\u52A1\u662F\u5426\u8FD0\u884C */\n  serviceRunning: boolean;\n  /** \u72B6\u6001\u63CF\u8FF0\u6D88\u606F */\n  message: string;\n  /** \u5EFA\u8BAE\u64CD\u4F5C */\n  suggestion?: string;\n  /** \u7F3A\u5931\u7684\u914D\u7F6E\u7EC4\u4EF6\u5217\u8868 */\n  missingComponents: MissingComponent[];\n}\n\n/**\n * Stats API \u914D\u7F6E\u7ED3\u679C\n */\nexport interface StatsConfigResult {\n  /** \u914D\u7F6E\u662F\u5426\u6210\u529F */\n  success: boolean;\n  /** \u5907\u4EFD\u6587\u4EF6\u8DEF\u5F84 */\n  backupPath?: string;\n  /** \u914D\u7F6E\u7684 API \u7AEF\u53E3 */\n  apiPort: number;\n  /** \u7ED3\u679C\u6D88\u606F */\n  message: string;\n  /** \u9519\u8BEF\u4FE1\u606F\uFF08\u5982\u679C\u5931\u8D25\uFF09 */\n  error?: string;\n  /** \u662F\u5426\u5DF2\u56DE\u6EDA */\n  rolledBack: boolean;\n}\n", "/**\n * \u6D41\u91CF\u914D\u989D\u76F8\u5173\u5E38\u91CF\n * @module constants/quota\n */\n\n/**\n * \u914D\u989D\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\n */\nexport const QUOTA_CONFIG_PATH = '/usr/local/etc/xray/quota.json';\n\n/**\n * \u9ED8\u8BA4 Xray Stats API \u7AEF\u53E3\n */\nexport const DEFAULT_API_PORT = 10085;\n\n/**\n * \u9ED8\u8BA4 API \u670D\u52A1\u5668\u5730\u5740\n */\nexport const DEFAULT_API_SERVER = '127.0.0.1';\n\n/**\n * \u8B66\u544A\u9608\u503C\uFF08\u767E\u5206\u6BD4\uFF09\n */\nexport const WARNING_THRESHOLD = 80;\n\n/**\n * \u8D85\u989D\u9608\u503C\uFF08\u767E\u5206\u6BD4\uFF09\n */\nexport const EXCEEDED_THRESHOLD = 100;\n\n/**\n * Xray Stats \u547D\u4EE4\n */\nexport const XRAY_STATS_COMMAND = 'xray';\n\n/**\n * Stats API \u5B50\u547D\u4EE4\n */\nexport const STATS_SUBCOMMAND = 'api';\n\n/**\n * \u6D41\u91CF\u7EDF\u8BA1\u540D\u79F0\u6A21\u5F0F\n */\nexport const STATS_PATTERNS = {\n  /** \u7528\u6237\u4E0A\u884C\u6D41\u91CF */\n  USER_UPLINK: (email: string) => `user>>>${email}>>>traffic>>>uplink`,\n  /** \u7528\u6237\u4E0B\u884C\u6D41\u91CF */\n  USER_DOWNLINK: (email: string) => `user>>>${email}>>>traffic>>>downlink`,\n};\n\n/**\n * \u914D\u989D\u914D\u7F6E\u7248\u672C\n */\nexport const QUOTA_CONFIG_VERSION = '1.0';\n\n/**\n * \u5355\u4F4D\u5B57\u8282\u6570\u6620\u5C04\n */\nexport const UNIT_BYTES = {\n  B: 1,\n  KB: 1024,\n  MB: 1024 ** 2,\n  GB: 1024 ** 3,\n  TB: 1024 ** 4,\n} as const;\n\n/**\n * \u9884\u8BBE\u914D\u989D\u9009\u9879\uFF08\u7528\u4E8E UI\uFF09\n */\nexport const PRESET_QUOTAS = [\n  { label: '1 GB', bytes: 1 * UNIT_BYTES.GB },\n  { label: '5 GB', bytes: 5 * UNIT_BYTES.GB },\n  { label: '10 GB', bytes: 10 * UNIT_BYTES.GB },\n  { label: '50 GB', bytes: 50 * UNIT_BYTES.GB },\n  { label: '100 GB', bytes: 100 * UNIT_BYTES.GB },\n  { label: '500 GB', bytes: 500 * UNIT_BYTES.GB },\n  { label: '1 TB', bytes: 1 * UNIT_BYTES.TB },\n  { label: '\u65E0\u9650\u5236', bytes: -1 },\n];\n\n/**\n * \u9ED8\u8BA4 Stats API \u914D\u7F6E\n */\nexport const DEFAULT_STATS_CONFIG = {\n  /** Stats \u914D\u7F6E\u5757\uFF08\u7A7A\u5BF9\u8C61\u542F\u7528\u7EDF\u8BA1\uFF09 */\n  stats: {},\n\n  /** Policy \u914D\u7F6E\uFF08\u542F\u7528\u7528\u6237\u548C\u5165\u7AD9\u6D41\u91CF\u7EDF\u8BA1\uFF09 */\n  policy: {\n    levels: {\n      '0': {\n        statsUserUplink: true,\n        statsUserDownlink: true,\n      },\n    },\n    system: {\n      statsInboundUplink: true,\n      statsInboundDownlink: true,\n    },\n  },\n\n  /** API \u914D\u7F6E */\n  api: {\n    tag: 'api',\n    services: ['StatsService'] as const,\n  },\n\n  /** API \u5165\u7AD9\u914D\u7F6E */\n  apiInbound: {\n    tag: 'api',\n    port: DEFAULT_API_PORT,\n    listen: DEFAULT_API_SERVER,\n    protocol: 'dokodemo-door' as const,\n    settings: {\n      address: DEFAULT_API_SERVER,\n    },\n  },\n\n  /** API \u8DEF\u7531\u89C4\u5219 */\n  apiRoutingRule: {\n    type: 'field' as const,\n    inboundTag: ['api'],\n    outboundTag: 'api',\n  },\n\n  /** API \u51FA\u7AD9\u914D\u7F6E */\n  apiOutbound: {\n    protocol: 'freedom' as const,\n    tag: 'api',\n  },\n} as const;\n\n/**\n * Stats API \u7AEF\u53E3\u8303\u56F4\n */\nexport const STATS_PORT_RANGE = {\n  /** \u8D77\u59CB\u7AEF\u53E3 */\n  START: 10085,\n  /** \u7ED3\u675F\u7AEF\u53E3 */\n  END: 10099,\n} as const;\n\n/**\n * Stats API \u8FDE\u63A5\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09\n */\nexport const STATS_API_TIMEOUT = 5000;\n\n/**\n * \u670D\u52A1\u91CD\u542F\u7B49\u5F85\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\n */\nexport const SERVICE_RESTART_WAIT = 2000;\n", "/**\n * TrafficManager - \u6D41\u91CF\u7EDF\u8BA1\u670D\u52A1\n *\n * \u901A\u8FC7 Xray Stats API \u83B7\u53D6\u7528\u6237\u6D41\u91CF\u4F7F\u7528\u60C5\u51B5\n *\n * @module services/traffic-manager\n */\n\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync } from 'fs';\nimport { readFile } from 'fs/promises';\nimport type { TrafficUsage, XrayStatsResponse } from '../types/quota';\nimport { QuotaManager } from './quota-manager';\nimport {\n  DEFAULT_API_PORT,\n  DEFAULT_API_SERVER,\n  STATS_PATTERNS,\n  XRAY_STATS_COMMAND,\n} from '../constants/quota';\n\nconst execAsync = promisify(exec);\n\n/**\n * Stats API \u68C0\u6D4B\u7ED3\u679C\n */\nexport interface StatsDetectionResult {\n  /** API \u662F\u5426\u53EF\u7528 */\n  available: boolean;\n\n  /** \u662F\u5426\u68C0\u6D4B\u5230 stats \u914D\u7F6E */\n  configDetected: boolean;\n\n  /** \u68C0\u6D4B\u5230\u7684 API \u7AEF\u53E3 */\n  detectedPort?: number;\n\n  /** \u670D\u52A1\u662F\u5426\u8FD0\u884C */\n  serviceRunning: boolean;\n\n  /** \u63D0\u793A\u6D88\u606F */\n  message: string;\n\n  /** \u5EFA\u8BAE\u64CD\u4F5C */\n  suggestion?: string;\n}\n\n/**\n * \u9ED8\u8BA4 Xray \u914D\u7F6E\u8DEF\u5F84\n */\nconst DEFAULT_XRAY_CONFIG_PATH = '/usr/local/etc/xray/config.json';\n\n/**\n * TrafficManager - \u7BA1\u7406 Xray \u6D41\u91CF\u7EDF\u8BA1\n */\nexport class TrafficManager {\n  private apiServer: string;\n  private apiPort: number;\n\n  /**\n   * \u521B\u5EFA TrafficManager \u5B9E\u4F8B\n   *\n   * @param apiServer - API \u670D\u52A1\u5668\u5730\u5740\uFF08\u9ED8\u8BA4 127.0.0.1\uFF09\n   * @param apiPort - API \u7AEF\u53E3\uFF08\u9ED8\u8BA4 10085\uFF09\n   */\n  constructor(apiServer: string = DEFAULT_API_SERVER, apiPort: number = DEFAULT_API_PORT) {\n    this.apiServer = apiServer;\n    this.apiPort = apiPort;\n  }\n\n  /**\n   * \u4ECE Xray \u914D\u7F6E\u4E2D\u8BFB\u53D6 API \u7AEF\u53E3\n   */\n  private async detectApiPortFromConfig(\n    configPath: string = DEFAULT_XRAY_CONFIG_PATH\n  ): Promise<number | null> {\n    try {\n      const content = await readFile(configPath, 'utf-8');\n      const config = JSON.parse(content);\n      const apiTag = config.api?.tag || 'api';\n      const apiInbound = config.inbounds?.find(\n        (inbound: { tag?: string }) => inbound.tag === apiTag\n      );\n      const port = Number(apiInbound?.port);\n      if (Number.isInteger(port) && port >= 1 && port <= 65535) {\n        return port;\n      }\n      return null;\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * \u4ECE\u914D\u989D\u914D\u7F6E\u4E2D\u540C\u6B65 API \u7AEF\u53E3\n   */\n  private async syncApiPort(): Promise<void> {\n    let quotaPort: number | null = null;\n    try {\n      const quotaManager = new QuotaManager();\n      quotaPort = await quotaManager.getApiPort();\n    } catch {\n      quotaPort = null;\n    }\n\n    const configPort = await this.detectApiPortFromConfig();\n    const resolvedPort = configPort ?? quotaPort;\n\n    if (\n      typeof resolvedPort === 'number' &&\n      Number.isInteger(resolvedPort) &&\n      resolvedPort >= 1 &&\n      resolvedPort <= 65535\n    ) {\n      this.apiPort = resolvedPort;\n    }\n  }\n\n  /**\n   * \u83B7\u53D6 API \u670D\u52A1\u5668\u5730\u5740\n   */\n  getServerAddress(): string {\n    return `${this.apiServer}:${this.apiPort}`;\n  }\n\n  /**\n   * \u68C0\u67E5 Xray Stats API \u662F\u5426\u53EF\u7528\n   *\n   * @returns \u662F\u5426\u53EF\u7528\n   */\n  async isStatsAvailable(): Promise<boolean> {\n    try {\n      await this.syncApiPort();\n      const { stdout } = await execAsync(\n        `${XRAY_STATS_COMMAND} api statsquery --server=${this.getServerAddress()} 2>/dev/null`\n      );\n      // \u5982\u679C\u547D\u4EE4\u6210\u529F\u6267\u884C\u5E76\u8FD4\u56DE JSON\uFF0C\u5219 API \u53EF\u7528\n      JSON.parse(stdout || '{}');\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * \u5224\u65AD\u6D41\u91CF\u7EDF\u8BA1\u662F\u5426\u53EF\u7528\uFF08\u542B policy \u68C0\u67E5\uFF09\n   */\n  async isUsageAvailable(): Promise<boolean> {\n    const [available, policyEnabled] = await Promise.all([\n      this.isStatsAvailable(),\n      this.hasUserStatsPolicy(),\n    ]);\n\n    return available && policyEnabled;\n  }\n\n  /**\n   * \u6267\u884C Xray stats \u547D\u4EE4\n   *\n   * @param name - \u7EDF\u8BA1\u540D\u79F0\n   * @returns \u7EDF\u8BA1\u503C\uFF08\u5B57\u8282\u6570\uFF09\n   */\n  private async queryStats(name: string): Promise<number> {\n    try {\n      const { stdout } = await execAsync(\n        `${XRAY_STATS_COMMAND} api stats --server=${this.getServerAddress()} -name \"${name}\" 2>/dev/null`\n      );\n      const result = JSON.parse(stdout || '{}');\n      return Number(result.stat?.value) || 0;\n    } catch {\n      return 0;\n    }\n  }\n\n  /**\n   * \u68C0\u67E5\u7528\u6237\u6D41\u91CF\u7EDF\u8BA1\u7B56\u7565\u662F\u5426\u542F\u7528\n   */\n  private async hasUserStatsPolicy(\n    configPath: string = DEFAULT_XRAY_CONFIG_PATH\n  ): Promise<boolean> {\n    try {\n      const content = await readFile(configPath, 'utf-8');\n      const config = JSON.parse(content);\n      const levels = config.policy?.levels;\n      if (!levels) {\n        return false;\n      }\n      const levelValues = Object.values(\n        levels as Record<string, { statsUserUplink?: boolean; statsUserDownlink?: boolean }>\n      );\n      return levelValues.some(\n        (level) => level?.statsUserUplink === true && level?.statsUserDownlink === true\n      );\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * \u83B7\u53D6\u7528\u6237\u6D41\u91CF\u4F7F\u7528\u60C5\u51B5\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   * @returns \u6D41\u91CF\u4F7F\u7528\u6570\u636E\uFF0C\u670D\u52A1\u672A\u8FD0\u884C\u65F6\u8FD4\u56DE null\n   */\n  async getUsage(email: string): Promise<TrafficUsage | null> {\n    const available = await this.isStatsAvailable();\n    if (!available) {\n      return null;\n    }\n\n    const policyEnabled = await this.hasUserStatsPolicy();\n    if (!policyEnabled) {\n      return null;\n    }\n\n    const uplinkName = STATS_PATTERNS.USER_UPLINK(email);\n    const downlinkName = STATS_PATTERNS.USER_DOWNLINK(email);\n\n    const [uplink, downlink] = await Promise.all([\n      this.queryStats(uplinkName),\n      this.queryStats(downlinkName),\n    ]);\n\n    return {\n      email,\n      uplink,\n      downlink,\n      total: uplink + downlink,\n      queriedAt: new Date().toISOString(),\n    };\n  }\n\n  /**\n   * \u83B7\u53D6\u6240\u6709\u7528\u6237\u6D41\u91CF\u4F7F\u7528\u60C5\u51B5\n   *\n   * @returns \u6240\u6709\u7528\u6237\u7684\u6D41\u91CF\u6570\u636E\n   */\n  async getAllUsage(): Promise<TrafficUsage[]> {\n    const available = await this.isStatsAvailable();\n    if (!available) {\n      return [];\n    }\n\n    const policyEnabled = await this.hasUserStatsPolicy();\n    if (!policyEnabled) {\n      return [];\n    }\n\n    try {\n      const { stdout } = await execAsync(\n        `${XRAY_STATS_COMMAND} api statsquery --server=${this.getServerAddress()} 2>/dev/null`\n      );\n      const response: XrayStatsResponse = JSON.parse(stdout || '{\"stat\":[]}');\n\n      // \u89E3\u6790\u6240\u6709\u7528\u6237\u6D41\u91CF\n      const userStats = new Map<string, { uplink: number; downlink: number }>();\n\n      for (const stat of response.stat || []) {\n        const match = stat.name.match(/^user>>>(.+?)>>>traffic>>>(uplink|downlink)$/);\n        if (match) {\n          const email = match[1];\n          const direction = match[2] as 'uplink' | 'downlink';\n\n          if (!userStats.has(email)) {\n            userStats.set(email, { uplink: 0, downlink: 0 });\n          }\n\n          const stats = userStats.get(email)!;\n          stats[direction] = Number(stat.value) || 0;\n        }\n      }\n\n      // \u8F6C\u6362\u4E3A TrafficUsage \u6570\u7EC4\n      const now = new Date().toISOString();\n      const usages: TrafficUsage[] = [];\n\n      for (const [email, stats] of userStats) {\n        usages.push({\n          email,\n          uplink: stats.uplink,\n          downlink: stats.downlink,\n          total: stats.uplink + stats.downlink,\n          queriedAt: now,\n        });\n      }\n\n      return usages;\n    } catch {\n      return [];\n    }\n  }\n\n  /**\n   * \u91CD\u7F6E\u7528\u6237\u6D41\u91CF\u7EDF\u8BA1\uFF08\u67E5\u8BE2\u5E76\u91CD\u7F6E\uFF09\n   *\n   * @param email - \u7528\u6237\u90AE\u7BB1\n   * @returns \u91CD\u7F6E\u524D\u7684\u6D41\u91CF\u6570\u636E\n   */\n  async resetUserStats(email: string): Promise<TrafficUsage | null> {\n    const available = await this.isStatsAvailable();\n    if (!available) {\n      return null;\n    }\n\n    const uplinkName = STATS_PATTERNS.USER_UPLINK(email);\n    const downlinkName = STATS_PATTERNS.USER_DOWNLINK(email);\n\n    // \u4F7F\u7528 -reset \u53C2\u6570\u67E5\u8BE2\u5E76\u91CD\u7F6E\n    const queryAndReset = async (name: string): Promise<number> => {\n      try {\n        const { stdout } = await execAsync(\n          `${XRAY_STATS_COMMAND} api stats --server=${this.getServerAddress()} -name \"${name}\" -reset 2>/dev/null`\n        );\n        const result = JSON.parse(stdout || '{}');\n        return Number(result.stat?.value) || 0;\n      } catch {\n        return 0;\n      }\n    };\n\n    const [uplink, downlink] = await Promise.all([\n      queryAndReset(uplinkName),\n      queryAndReset(downlinkName),\n    ]);\n\n    return {\n      email,\n      uplink,\n      downlink,\n      total: uplink + downlink,\n      queriedAt: new Date().toISOString(),\n    };\n  }\n\n  /**\n   * \u68C0\u6D4B Xray Stats API \u914D\u7F6E\u72B6\u6001\n   *\n   * @param configPath - Xray \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\n   * @returns \u68C0\u6D4B\u7ED3\u679C\n   */\n  async detectStatsConfig(\n    configPath: string = DEFAULT_XRAY_CONFIG_PATH\n  ): Promise<StatsDetectionResult> {\n    const result: StatsDetectionResult = {\n      available: false,\n      configDetected: false,\n      serviceRunning: false,\n      message: '',\n    };\n\n    // 1. \u68C0\u67E5\u670D\u52A1\u662F\u5426\u8FD0\u884C\n    try {\n      await execAsync('systemctl is-active xray');\n      result.serviceRunning = true;\n    } catch {\n      result.serviceRunning = false;\n      result.message = 'Xray \u670D\u52A1\u672A\u8FD0\u884C';\n      result.suggestion = '\u8BF7\u5148\u542F\u52A8 Xray \u670D\u52A1: systemctl start xray';\n      return result;\n    }\n\n    // 2. \u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u662F\u5426\u5B58\u5728\n    if (!existsSync(configPath)) {\n      result.message = `\u672A\u627E\u5230 Xray \u914D\u7F6E\u6587\u4EF6: ${configPath}`;\n      result.suggestion = '\u8BF7\u786E\u8BA4 Xray \u5DF2\u6B63\u786E\u5B89\u88C5';\n      return result;\n    }\n\n    // 3. \u89E3\u6790\u914D\u7F6E\u6587\u4EF6\u67E5\u627E stats \u548C api \u914D\u7F6E\n    try {\n      const content = await readFile(configPath, 'utf-8');\n      const config = JSON.parse(content);\n\n      // \u68C0\u67E5 stats \u914D\u7F6E\n      if (!config.stats) {\n        result.message = 'Xray \u914D\u7F6E\u4E2D\u672A\u542F\u7528 stats \u7EDF\u8BA1\u529F\u80FD';\n        result.suggestion = '\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u6DFB\u52A0 \"stats\": {} \u6765\u542F\u7528\u6D41\u91CF\u7EDF\u8BA1';\n        return result;\n      }\n\n      // \u68C0\u67E5 policy \u914D\u7F6E\n      const levels = config.policy?.levels;\n      const hasUserStatsPolicy = levels\n        ? Object.values(\n            levels as Record<string, { statsUserUplink?: boolean; statsUserDownlink?: boolean }>\n          ).some((level) => level?.statsUserUplink === true && level?.statsUserDownlink === true)\n        : false;\n      if (!hasUserStatsPolicy) {\n        result.message = 'Xray \u914D\u7F6E\u4E2D\u672A\u542F\u7528 policy \u6D41\u91CF\u7EDF\u8BA1';\n        result.suggestion = '\u8BF7\u5728 policy.levels \u4E2D\u542F\u7528 statsUserUplink/statsUserDownlink';\n        return result;\n      }\n\n      result.configDetected = true;\n\n      // \u68C0\u67E5 api \u914D\u7F6E\n      if (!config.api) {\n        result.message = 'Xray \u914D\u7F6E\u4E2D\u672A\u542F\u7528 API \u63A5\u53E3';\n        result.suggestion = '\u8BF7\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u6DFB\u52A0 api \u914D\u7F6E\u6765\u542F\u7528 Stats API';\n        return result;\n      }\n\n      // \u67E5\u627E api inbound \u7AEF\u53E3\n      const apiTag = config.api.tag || 'api';\n      const apiInbound = config.inbounds?.find(\n        (inbound: { tag?: string }) => inbound.tag === apiTag\n      );\n\n      if (apiInbound?.port) {\n        result.detectedPort = apiInbound.port;\n      }\n\n      // 4. \u6D4B\u8BD5 API \u8FDE\u63A5\n      result.available = await this.isStatsAvailable();\n\n      if (result.available) {\n        result.message = 'Stats API \u5DF2\u5C31\u7EEA';\n      } else {\n        result.message = 'Stats API \u914D\u7F6E\u5DF2\u68C0\u6D4B\u5230\uFF0C\u4F46\u65E0\u6CD5\u8FDE\u63A5';\n        result.suggestion = `\u8BF7\u68C0\u67E5 API \u7AEF\u53E3 ${this.apiPort} \u662F\u5426\u6B63\u786E\uFF0C\u6216\u91CD\u542F Xray \u670D\u52A1`;\n      }\n    } catch (error) {\n      if (error instanceof SyntaxError) {\n        result.message = 'Xray \u914D\u7F6E\u6587\u4EF6 JSON \u683C\u5F0F\u9519\u8BEF';\n        result.suggestion = '\u8BF7\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F';\n      } else {\n        result.message = `\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${(error as Error).message}`;\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * \u83B7\u53D6 Stats API \u72B6\u6001\u7684\u53CB\u597D\u63D0\u793A\u4FE1\u606F\n   *\n   * @returns \u72B6\u6001\u63D0\u793A\n   */\n  async getStatusMessage(): Promise<string> {\n    const [available, policyEnabled] = await Promise.all([\n      this.isStatsAvailable(),\n      this.hasUserStatsPolicy(),\n    ]);\n\n    if (available && policyEnabled) {\n      return '\u6D41\u91CF\u7EDF\u8BA1\u529F\u80FD\u6B63\u5E38';\n    }\n\n    if (available && !policyEnabled) {\n      return '\u6D41\u91CF\u7EDF\u8BA1\u4E0D\u53EF\u7528 (\u9700\u8981\u5728 Xray \u914D\u7F6E\u4E2D\u542F\u7528 policy \u7EDF\u8BA1)';\n    }\n\n    const detection = await this.detectStatsConfig();\n\n    if (!detection.serviceRunning) {\n      return '\u6D41\u91CF\u7EDF\u8BA1\u4E0D\u53EF\u7528 (Xray \u670D\u52A1\u672A\u8FD0\u884C)';\n    }\n\n    if (!detection.configDetected) {\n      return '\u6D41\u91CF\u7EDF\u8BA1\u4E0D\u53EF\u7528 (\u9700\u8981\u5728 Xray \u914D\u7F6E\u4E2D\u542F\u7528 stats)';\n    }\n\n    return '\u6D41\u91CF\u7EDF\u8BA1\u4E0D\u53EF\u7528 (Stats API \u8FDE\u63A5\u5931\u8D25)';\n  }\n}\n", "/**\n * LogManager - System Log Management via journalctl\n *\n * Provides safe interface to query and follow systemd journal logs\n *\n * @module services/log-manager\n */\n\nimport { spawn, ChildProcess } from 'child_process';\nimport { existsSync } from 'fs';\nimport { readFile, stat } from 'fs/promises';\nimport { which } from '../utils/which';\nimport { DEFAULT_PATHS } from '../constants/paths';\n\nconst DEFAULT_LOG_LINES = 200;\nconst DEFAULT_FILE_LOG_LINES = 50;\n\n/**\n * Log entry structure\n */\nexport interface LogEntry {\n  /** Log timestamp */\n  timestamp: Date;\n\n  /** Log message */\n  message: string;\n\n  /** Log level */\n  level: string;\n\n  /** Process ID */\n  pid?: string;\n\n  /** Hostname */\n  hostname?: string;\n\n  /** Systemd unit */\n  unit?: string;\n\n  /** Raw log data */\n  raw?: string;\n}\n\n/**\n * Log query options\n */\nexport interface LogQueryOptions {\n  /** Filter by log level (error, warning, info, debug) */\n  level?: string;\n\n  /** Time range start (e.g., \"1 hour ago\", \"today\", \"2024-01-01\") */\n  since?: string;\n\n  /** Time range end */\n  until?: string;\n\n  /** Number of lines to retrieve */\n  lines?: number;\n\n  /** Follow mode (real-time) */\n  follow?: boolean;\n}\n\n/**\n * Log follow process\n */\nexport interface LogFollowProcess {\n  /** Kill the follow process */\n  kill: () => void;\n\n  /** Child process */\n  process: ChildProcess;\n}\n\n/**\n * LogManager - Query and follow systemd journal logs\n */\nexport class LogManager {\n  private serviceName: string;\n\n  /**\n   * Create a new LogManager\n   *\n   * @param serviceName - Service name to query logs for\n   */\n  constructor(serviceName: string) {\n    this.validateServiceName(serviceName);\n    this.serviceName = serviceName;\n  }\n\n  /**\n   * Validate service name to prevent command injection\n   *\n   * @param name - Service name to validate\n   * @throws Error if invalid\n   */\n  private validateServiceName(name: string): void {\n    if (!name || name.trim().length === 0) {\n      throw new Error('Service name cannot be empty');\n    }\n\n    // Prevent path traversal\n    if (name.includes('/') || name.includes('\\\\') || name.includes('..')) {\n      throw new Error(`Invalid service name: ${name} (path traversal detected)`);\n    }\n\n    // Prevent command injection\n    const dangerousChars = /[;&|`$()]/;\n    if (dangerousChars.test(name)) {\n      throw new Error(`Invalid service name: ${name} (potentially dangerous characters detected)`);\n    }\n\n    // Only allow alphanumeric, dash, underscore, and dot\n    const validPattern = /^[a-zA-Z0-9_.-]+$/;\n    if (!validPattern.test(name)) {\n      throw new Error(`Invalid service name: ${name}`);\n    }\n  }\n\n  /**\n   * Check if journalctl is available\n   *\n   * @returns True if journalctl is available\n   */\n  isJournalctlAvailable(): boolean {\n    try {\n      const journalctlPath = which('journalctl');\n      return journalctlPath !== null && existsSync(journalctlPath);\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * Map log level to journalctl priority\n   *\n   * @param level - Log level (error, warning, info, debug)\n   * @returns journalctl priority string\n   */\n  private mapLevelToPriority(level: string): string {\n    const mapping: Record<string, string> = {\n      emergency: 'emerg',\n      alert: 'alert',\n      critical: 'crit',\n      error: 'err',\n      warning: 'warning',\n      notice: 'notice',\n      info: 'info',\n      debug: 'debug',\n    };\n\n    return mapping[level.toLowerCase()] || level;\n  }\n\n  /**\n   * Map journalctl priority to readable level\n   *\n   * @param priority - Journalctl priority (0-7)\n   * @returns Readable log level\n   */\n  private mapPriorityToLevel(priority: string): string {\n    const mapping: Record<string, string> = {\n      '0': 'emergency',\n      '1': 'alert',\n      '2': 'critical',\n      '3': 'error',\n      '4': 'warning',\n      '5': 'notice',\n      '6': 'info',\n      '7': 'debug',\n    };\n\n    return mapping[priority] || 'unknown';\n  }\n\n  /**\n   * Parse a JSON log entry from journalctl\n   *\n   * @param jsonLine - JSON string from journalctl -o json\n   * @returns Parsed log entry\n   */\n  parseLogEntry(jsonLine: string): LogEntry {\n    try {\n      const data = JSON.parse(jsonLine);\n\n      // Extract timestamp (microseconds since epoch)\n      const timestampMicros = parseInt(data.__REALTIME_TIMESTAMP || '0', 10);\n      const timestamp = new Date(timestampMicros / 1000);\n\n      // Extract message\n      const message = data.MESSAGE || '';\n\n      // Extract and map priority\n      const priority = data.PRIORITY || '6';\n      const level = this.mapPriorityToLevel(priority);\n\n      // Extract metadata\n      const pid = data._PID;\n      const hostname = data._HOSTNAME;\n      const unit = data._SYSTEMD_UNIT;\n\n      return {\n        timestamp,\n        message,\n        level,\n        pid,\n        hostname,\n        unit,\n        raw: jsonLine,\n      };\n    } catch (error) {\n      throw new Error(`Failed to parse log entry: ${(error as Error).message}`);\n    }\n  }\n\n  /**\n   * Query logs with filters\n   *\n   * @param options - Query options\n   * @returns Array of log entries\n   */\n  async queryLogs(options: LogQueryOptions = {}): Promise<LogEntry[]> {\n    if (!this.isJournalctlAvailable()) {\n      throw new Error(\n        'journalctl is not available on this system. Please ensure systemd is installed.'\n      );\n    }\n\n    const lineLimit = options.lines ?? DEFAULT_LOG_LINES;\n\n    // Build journalctl arguments\n    const args: string[] = [\n      '-u',\n      this.serviceName, // Unit filter\n      '-o',\n      'json', // JSON output\n      '--no-pager', // Disable pager\n    ];\n\n    // Add level filter\n    if (options.level) {\n      const priority = this.mapLevelToPriority(options.level);\n      args.push('-p', priority);\n    }\n\n    // Add time range filters\n    if (options.since) {\n      args.push('--since', options.since);\n    }\n\n    if (options.until) {\n      args.push('--until', options.until);\n    }\n\n    // Add line limit\n    if (Number.isFinite(lineLimit) && lineLimit > 0) {\n      args.push('-n', String(lineLimit));\n    }\n\n    return new Promise((resolve, reject) => {\n      const child = spawn('journalctl', args, {\n        stdio: ['ignore', 'pipe', 'pipe'],\n      });\n\n      let stdout = '';\n      let stderr = '';\n\n      child.stdout.on('data', (data: Buffer) => {\n        stdout += data.toString();\n      });\n\n      child.stderr.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      child.on('close', (code: number) => {\n        if (code !== 0) {\n          const errorMsg = stderr.trim() || `journalctl exited with code ${code}`;\n\n          // Provide helpful error messages\n          if (errorMsg.includes('permission') || errorMsg.includes('access')) {\n            reject(\n              new Error(`\u65E0\u6743\u8BBF\u95EE\u65E5\u5FD7\u3002\u8BF7\u4F7F\u7528 sudo \u6216\u4EE5 root \u7528\u6237\u8FD0\u884C\u3002\\n\u8BE6\u7EC6\u9519\u8BEF: ${errorMsg}`)\n            );\n          } else {\n            reject(new Error(`\u67E5\u8BE2\u65E5\u5FD7\u5931\u8D25: ${errorMsg}`));\n          }\n          return;\n        }\n\n        // Parse log entries\n        const logs: LogEntry[] = [];\n        const lines = stdout.trim().split('\\n');\n\n        for (const line of lines) {\n          if (!line.trim()) continue;\n\n          try {\n            const entry = this.parseLogEntry(line);\n            logs.push(entry);\n          } catch (error) {\n            // Skip malformed entries\n            console.warn(`Skipped malformed log entry: ${(error as Error).message}`);\n          }\n        }\n\n        resolve(logs);\n      });\n\n      child.on('error', (error: Error) => {\n        reject(new Error(`Failed to execute journalctl: ${error.message}`));\n      });\n    });\n  }\n\n  /**\n   * Follow logs in real-time\n   *\n   * @param options - Query options\n   * @param onLog - Callback for each log entry\n   * @returns Follow process controller\n   */\n  async followLogs(\n    options: LogQueryOptions = {},\n    onLog?: (_entry: LogEntry) => void\n  ): Promise<LogFollowProcess> {\n    if (!this.isJournalctlAvailable()) {\n      throw new Error(\n        'journalctl is not available on this system. Please ensure systemd is installed.'\n      );\n    }\n\n    // Build journalctl arguments\n    const args: string[] = [\n      '-u',\n      this.serviceName,\n      '-o',\n      'json',\n      '--no-pager',\n      '-f', // Follow mode\n    ];\n\n    // Add level filter\n    if (options.level) {\n      const priority = this.mapLevelToPriority(options.level);\n      args.push('-p', priority);\n    }\n\n    // Add line limit for initial output\n    if (options.lines) {\n      args.push('-n', String(options.lines));\n    }\n\n    const child = spawn('journalctl', args, {\n      stdio: ['ignore', 'pipe', 'pipe'],\n    });\n\n    // Handle stdout\n    if (onLog) {\n      let buffer = '';\n\n      child.stdout.on('data', (data: Buffer) => {\n        buffer += data.toString();\n        const lines = buffer.split('\\n');\n\n        // Process complete lines\n        for (let i = 0; i < lines.length - 1; i++) {\n          const line = lines[i].trim();\n          if (!line) continue;\n\n          try {\n            const entry = this.parseLogEntry(line);\n            onLog(entry);\n          } catch (error) {\n            console.warn(`Skipped malformed log entry: ${(error as Error).message}`);\n          }\n        }\n\n        // Keep incomplete line in buffer\n        buffer = lines[lines.length - 1];\n      });\n    }\n\n    // Handle stderr\n    child.stderr.on('data', (data: Buffer) => {\n      const errorMsg = data.toString();\n      console.error(`journalctl error: ${errorMsg}`);\n    });\n\n    return {\n      process: child,\n      kill: () => {\n        child.kill('SIGINT');\n      },\n    };\n  }\n\n  /**\n   * Read last N lines from access log file\n   *\n   * @param lines - Number of lines to read (default: 50)\n   * @returns Array of log entry objects\n   */\n  async readAccessLog(lines: number = DEFAULT_FILE_LOG_LINES): Promise<LogEntry[]> {\n    return this.readLogFile(DEFAULT_PATHS.ACCESS_LOG, lines);\n  }\n\n  /**\n   * Read last N lines from error log file\n   *\n   * @param lines - Number of lines to read (default: 50)\n   * @returns Array of log entry objects\n   */\n  async readErrorLog(lines: number = DEFAULT_FILE_LOG_LINES): Promise<LogEntry[]> {\n    return this.readLogFile(DEFAULT_PATHS.ERROR_LOG, lines);\n  }\n\n  /**\n   * Check if a log file exists\n   *\n   * @param type - Log type ('access' or 'error')\n   * @returns true if file exists\n   */\n  async logExists(type: 'access' | 'error'): Promise<boolean> {\n    const logPath = type === 'access' ? DEFAULT_PATHS.ACCESS_LOG : DEFAULT_PATHS.ERROR_LOG;\n    return existsSync(logPath);\n  }\n\n  /**\n   * Get log file size\n   *\n   * @param type - Log type ('access' or 'error')\n   * @returns File size in bytes, or 0 if file doesn't exist\n   */\n  async getLogSize(type: 'access' | 'error'): Promise<number> {\n    const logPath = type === 'access' ? DEFAULT_PATHS.ACCESS_LOG : DEFAULT_PATHS.ERROR_LOG;\n    try {\n      const stats = await stat(logPath);\n      return stats.size;\n    } catch {\n      return 0;\n    }\n  }\n\n  /**\n   * Read last N lines from a log file\n   *\n   * @param logPath - Path to log file\n   * @param lines - Number of lines to read\n   * @returns Array of log entry objects\n   */\n  private async readLogFile(logPath: string, lines: number): Promise<LogEntry[]> {\n    if (!existsSync(logPath)) {\n      return [];\n    }\n\n    try {\n      const content = await readFile(logPath, 'utf-8');\n      const allLines = content.split('\\n').filter((line) => line.trim());\n\n      // Get last N lines\n      const lastLines = allLines.slice(-lines);\n\n      return lastLines.map((line, index) =>\n        this.parseFileLogEntry(line, allLines.length - lines + index + 1)\n      );\n    } catch (error) {\n      throw new Error(`\u8BFB\u53D6\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25: ${(error as Error).message}`);\n    }\n  }\n\n  /**\n   * Parse a log line from file into LogEntry\n   *\n   * @param line - Raw log line\n   * @param lineNumber - Line number in file\n   * @returns LogEntry object\n   */\n  private parseFileLogEntry(line: string, _lineNumber: number): LogEntry {\n    // Try to parse timestamp from common log formats\n    // Format 1: 2024/01/15 10:30:00 [Info] message\n    // Format 2: 2024-01-15T10:30:00.000Z message\n    let timestamp = new Date();\n    let level = 'info';\n    let message = line;\n\n    // Try to extract timestamp\n    const timestampMatch = line.match(/^(\\d{4}[/-]\\d{2}[/-]\\d{2}[T\\s]\\d{2}:\\d{2}:\\d{2})/);\n    if (timestampMatch) {\n      try {\n        timestamp = new Date(timestampMatch[1].replace(' ', 'T'));\n        message = line.substring(timestampMatch[0].length).trim();\n      } catch {\n        // Keep default timestamp\n      }\n    }\n\n    // Try to extract log level\n    const levelMatch = message.match(/^\\[?(Info|Warning|Error|Debug)\\]?:?\\s*/i);\n    if (levelMatch) {\n      level = levelMatch[1].toLowerCase();\n      message = message.substring(levelMatch[0].length);\n    }\n\n    return {\n      timestamp,\n      message,\n      level,\n      raw: line,\n    };\n  }\n}\n", "/**\n * Which utility - Find executable in PATH\n *\n * @module utils/which\n */\n\nimport { execSync } from 'child_process';\n\n/**\n * Find executable in PATH\n *\n * @param command - Command name to find\n * @returns Path to executable or null if not found\n */\nexport function which(command: string): string | null {\n  try {\n    const result = execSync(`which ${command}`, {\n      encoding: 'utf-8',\n      stdio: ['ignore', 'pipe', 'ignore'],\n    });\n\n    return result.trim() || null;\n  } catch {\n    return null;\n  }\n}\n", "/**\n * StatsConfigManager - Xray Stats API \u914D\u7F6E\u7BA1\u7406\n *\n * \u63D0\u4F9B\u81EA\u52A8\u68C0\u6D4B\u3001\u914D\u7F6E\u3001\u5907\u4EFD\u548C\u56DE\u6EDA Stats API \u7684\u529F\u80FD\n *\n * @module services/stats-config-manager\n */\n\nimport { createServer } from 'net';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport { ConfigManager } from './config-manager';\nimport { SystemdManager } from './systemd-manager';\nimport { DEFAULT_PATHS } from '../constants/paths';\nimport {\n  DEFAULT_API_PORT,\n  DEFAULT_API_SERVER,\n  DEFAULT_STATS_CONFIG,\n  STATS_PORT_RANGE,\n  STATS_API_TIMEOUT,\n  SERVICE_RESTART_WAIT,\n  XRAY_STATS_COMMAND,\n} from '../constants/quota';\nimport type {\n  XrayConfigWithStats,\n  ApiInbound,\n  RoutingRule,\n  ApiServiceType,\n  PolicyLevelConfig,\n  PolicySystemConfig,\n  Outbound,\n} from '../types/config';\nimport type { StatsDetectionResult, StatsConfigResult, MissingComponent } from '../types/quota';\n\nconst execAsync = promisify(exec);\n\n/**\n * StatsConfigManager - Stats API \u914D\u7F6E\u7BA1\u7406\u670D\u52A1\n */\nexport class StatsConfigManager {\n  private configManager: ConfigManager;\n  private systemdManager: SystemdManager;\n  private configPath: string;\n\n  /**\n   * \u521B\u5EFA StatsConfigManager \u5B9E\u4F8B\n   *\n   * @param configPath - Xray \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\n   * @param serviceName - systemd \u670D\u52A1\u540D\u79F0\n   */\n  constructor(configPath?: string, serviceName?: string) {\n    this.configPath = configPath || DEFAULT_PATHS.CONFIG_FILE;\n    this.configManager = new ConfigManager(this.configPath);\n    this.systemdManager = new SystemdManager(serviceName || DEFAULT_PATHS.SERVICE_NAME);\n  }\n\n  /**\n   * \u68C0\u6D4B\u7F3A\u5931\u7684 Stats API \u914D\u7F6E\u7EC4\u4EF6\n   *\n   * @returns \u7F3A\u5931\u7EC4\u4EF6\u5217\u8868\n   */\n  async detectMissingComponents(): Promise<MissingComponent[]> {\n    const missing: MissingComponent[] = [];\n\n    try {\n      const config = (await this.configManager.readConfig()) as XrayConfigWithStats;\n\n      // \u68C0\u67E5 stats \u914D\u7F6E\n      if (!config.stats) {\n        missing.push('stats');\n      }\n\n      // \u68C0\u67E5 policy \u914D\u7F6E\uFF08\u7528\u6237\u6D41\u91CF\u7EDF\u8BA1\uFF09\n      const levels = config.policy?.levels;\n      const hasUserStatsPolicy = levels\n        ? Object.values(levels).some(\n            (level) => level?.statsUserUplink === true && level?.statsUserDownlink === true\n          )\n        : false;\n      if (!hasUserStatsPolicy) {\n        missing.push('policy');\n      }\n\n      // \u68C0\u67E5 api \u914D\u7F6E\n      if (!config.api || !config.api.services?.includes('StatsService')) {\n        missing.push('api');\n      }\n\n      // \u68C0\u67E5 api inbound\n      const hasApiInbound = config.inbounds?.some(\n        (inbound) => inbound.tag === 'api' && inbound.protocol === 'dokodemo-door'\n      );\n      if (!hasApiInbound) {\n        missing.push('api-inbound');\n      }\n\n      // \u68C0\u67E5 api outbound\n      const hasApiOutbound = config.outbounds?.some((outbound) => outbound.tag === 'api');\n      if (!hasApiOutbound) {\n        missing.push('api-outbound');\n      }\n\n      // \u68C0\u67E5 api \u8DEF\u7531\u89C4\u5219\n      const hasApiRouting = config.routing?.rules?.some(\n        (rule) => rule.inboundTag?.includes('api') && rule.outboundTag === 'api'\n      );\n      if (!hasApiRouting) {\n        missing.push('api-routing');\n      }\n    } catch {\n      // \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u6240\u6709\u7EC4\u4EF6\u90FD\u7F3A\u5931\n      return ['stats', 'policy', 'api', 'api-inbound', 'api-outbound', 'api-routing'];\n    }\n\n    return missing;\n  }\n\n  /**\n   * \u68C0\u6D4B\u7AEF\u53E3\u662F\u5426\u53EF\u7528\n   *\n   * @param port - \u8981\u68C0\u6D4B\u7684\u7AEF\u53E3\n   * @returns \u7AEF\u53E3\u662F\u5426\u53EF\u7528\n   */\n  async isPortAvailable(port: number): Promise<boolean> {\n    return new Promise((resolve) => {\n      const server = createServer();\n\n      server.once('error', () => {\n        resolve(false);\n      });\n\n      server.once('listening', () => {\n        server.close();\n        resolve(true);\n      });\n\n      server.listen(port, DEFAULT_API_SERVER);\n    });\n  }\n\n  /**\n   * \u67E5\u627E\u53EF\u7528\u7AEF\u53E3\n   *\n   * @param startPort - \u8D77\u59CB\u7AEF\u53E3\n   * @returns \u53EF\u7528\u7AEF\u53E3\uFF0C\u5982\u679C\u6CA1\u6709\u53EF\u7528\u7AEF\u53E3\u5219\u8FD4\u56DE null\n   */\n  async findAvailablePort(startPort: number = DEFAULT_API_PORT): Promise<number | null> {\n    for (let port = startPort; port <= STATS_PORT_RANGE.END; port++) {\n      // \u68C0\u67E5\u7AEF\u53E3\u662F\u5426\u88AB\u7CFB\u7EDF\u5360\u7528\n      const available = await this.isPortAvailable(port);\n      if (!available) {\n        continue;\n      }\n\n      // \u68C0\u67E5\u7AEF\u53E3\u662F\u5426\u5DF2\u88AB Xray \u914D\u7F6E\u4F7F\u7528\n      try {\n        const config = (await this.configManager.readConfig()) as XrayConfigWithStats;\n        const portInUse = config.inbounds?.some((inbound) => inbound.port === port);\n        if (portInUse) {\n          continue;\n        }\n      } catch {\n        // \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u7AEF\u53E3\u53EF\u7528\n      }\n\n      return port;\n    }\n\n    return null;\n  }\n\n  /**\n   * \u751F\u6210 Stats API \u914D\u7F6E\u5BF9\u8C61\n   *\n   * @param port - API \u7AEF\u53E3\n   * @returns Stats API \u914D\u7F6E\u5BF9\u8C61\n   */\n  generateStatsConfig(port: number = DEFAULT_API_PORT): {\n    stats: Record<string, never>;\n    policy: {\n      levels: Record<string, PolicyLevelConfig>;\n      system: PolicySystemConfig;\n    };\n    api: { tag: string; services: ApiServiceType[] };\n    apiInbound: ApiInbound;\n    apiOutbound: Outbound;\n    apiRoutingRule: RoutingRule;\n  } {\n    return {\n      stats: {},\n      policy: {\n        levels: {\n          ...DEFAULT_STATS_CONFIG.policy.levels,\n        },\n        system: {\n          ...DEFAULT_STATS_CONFIG.policy.system,\n        },\n      },\n      api: {\n        tag: DEFAULT_STATS_CONFIG.api.tag,\n        services: [...DEFAULT_STATS_CONFIG.api.services] as ApiServiceType[],\n      },\n      apiInbound: {\n        tag: DEFAULT_STATS_CONFIG.apiInbound.tag,\n        port,\n        listen: DEFAULT_STATS_CONFIG.apiInbound.listen,\n        protocol: DEFAULT_STATS_CONFIG.apiInbound.protocol,\n        settings: {\n          address: DEFAULT_STATS_CONFIG.apiInbound.settings.address,\n        },\n      },\n      apiOutbound: {\n        protocol: DEFAULT_STATS_CONFIG.apiOutbound.protocol,\n        tag: DEFAULT_STATS_CONFIG.apiOutbound.tag,\n      },\n      apiRoutingRule: {\n        type: DEFAULT_STATS_CONFIG.apiRoutingRule.type,\n        inboundTag: [...DEFAULT_STATS_CONFIG.apiRoutingRule.inboundTag],\n        outboundTag: DEFAULT_STATS_CONFIG.apiRoutingRule.outboundTag,\n      },\n    };\n  }\n\n  /**\n   * \u667A\u80FD\u5408\u5E76 Stats \u914D\u7F6E\u5230\u73B0\u6709\u914D\u7F6E\n   *\n   * @param config - \u73B0\u6709\u914D\u7F6E\n   * @param statsConfig - Stats \u914D\u7F6E\n   * @returns \u5408\u5E76\u540E\u7684\u914D\u7F6E\n   */\n  mergeStatsConfig(\n    config: XrayConfigWithStats,\n    statsConfig: ReturnType<typeof this.generateStatsConfig>\n  ): XrayConfigWithStats {\n    const merged = { ...config };\n\n    // \u6DFB\u52A0 stats \u914D\u7F6E\uFF08\u5982\u679C\u4E0D\u5B58\u5728\uFF09\n    if (!merged.stats) {\n      merged.stats = statsConfig.stats;\n    }\n\n    // \u6DFB\u52A0\u6216\u66F4\u65B0 policy \u914D\u7F6E\uFF08\u7528\u6237\u6D41\u91CF\u7EDF\u8BA1\uFF09\n    if (!merged.policy) {\n      merged.policy = statsConfig.policy;\n    } else {\n      const hasLevels = !!merged.policy.levels && Object.keys(merged.policy.levels).length > 0;\n      const levels = hasLevels ? { ...merged.policy.levels } : { ...statsConfig.policy.levels };\n\n      for (const levelKey of Object.keys(levels)) {\n        levels[levelKey] = {\n          ...levels[levelKey],\n          statsUserUplink: true,\n          statsUserDownlink: true,\n        };\n      }\n\n      merged.policy.levels = levels;\n      merged.policy.system = {\n        ...(merged.policy.system || {}),\n        statsInboundUplink: true,\n        statsInboundDownlink: true,\n      };\n    }\n\n    // \u6DFB\u52A0\u6216\u66F4\u65B0 api \u914D\u7F6E\n    if (!merged.api) {\n      merged.api = statsConfig.api;\n    } else if (!merged.api.services.includes('StatsService')) {\n      merged.api.services = [...merged.api.services, 'StatsService'];\n    }\n\n    // \u6DFB\u52A0 api inbound\uFF08\u5982\u679C\u4E0D\u5B58\u5728\uFF09\n    const hasApiInbound = merged.inbounds?.some(\n      (inbound) => inbound.tag === 'api' && inbound.protocol === 'dokodemo-door'\n    );\n    if (!hasApiInbound) {\n      merged.inbounds = [...(merged.inbounds || []), statsConfig.apiInbound];\n    }\n\n    // \u6DFB\u52A0 api outbound\uFF08\u5982\u679C\u4E0D\u5B58\u5728\uFF09\n    const hasApiOutbound = merged.outbounds?.some((outbound) => outbound.tag === 'api');\n    if (!hasApiOutbound) {\n      merged.outbounds = [...(merged.outbounds || []), statsConfig.apiOutbound];\n    }\n\n    // \u6DFB\u52A0 api \u8DEF\u7531\u89C4\u5219\uFF08\u5982\u679C\u4E0D\u5B58\u5728\uFF09\n    if (!merged.routing) {\n      merged.routing = { rules: [] };\n    }\n    if (!merged.routing.rules) {\n      merged.routing.rules = [];\n    }\n\n    const hasApiRouting = merged.routing.rules.some(\n      (rule) => rule.inboundTag?.includes('api') && rule.outboundTag === 'api'\n    );\n    if (!hasApiRouting) {\n      merged.routing.rules = [statsConfig.apiRoutingRule, ...merged.routing.rules];\n    }\n\n    return merged;\n  }\n\n  /**\n   * \u9A8C\u8BC1 Stats API \u8FDE\u63A5\n   *\n   * @param port - API \u7AEF\u53E3\n   * @returns \u662F\u5426\u53EF\u8FDE\u63A5\n   */\n  async verifyStatsApiConnection(port: number = DEFAULT_API_PORT): Promise<boolean> {\n    try {\n      const { stdout } = await execAsync(\n        `${XRAY_STATS_COMMAND} api statsquery --server=${DEFAULT_API_SERVER}:${port} 2>/dev/null`,\n        { timeout: STATS_API_TIMEOUT }\n      );\n      // \u5982\u679C\u547D\u4EE4\u6210\u529F\u6267\u884C\u5E76\u8FD4\u56DE JSON\uFF0C\u5219 API \u53EF\u7528\n      JSON.parse(stdout || '{}');\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * \u5907\u4EFD\u914D\u7F6E\u6587\u4EF6\n   *\n   * @returns \u5907\u4EFD\u6587\u4EF6\u8DEF\u5F84\n   */\n  async backupBeforeModify(): Promise<string> {\n    return await this.configManager.backupConfig();\n  }\n\n  /**\n   * \u56DE\u6EDA\u914D\u7F6E\u5E76\u91CD\u542F\u670D\u52A1\n   *\n   * @param backupPath - \u5907\u4EFD\u6587\u4EF6\u8DEF\u5F84\n   */\n  async rollbackOnFailure(backupPath: string): Promise<void> {\n    await this.configManager.restoreConfig(backupPath);\n    await this.systemdManager.restart();\n  }\n\n  /**\n   * \u91CD\u542F\u670D\u52A1\u5E76\u9A8C\u8BC1\u72B6\u6001\n   *\n   * @returns \u670D\u52A1\u662F\u5426\u6B63\u5E38\u8FD0\u884C\n   */\n  async restartAndVerify(): Promise<boolean> {\n    try {\n      await this.systemdManager.restart();\n\n      // \u7B49\u5F85\u670D\u52A1\u542F\u52A8\n      await new Promise((resolve) => setTimeout(resolve, SERVICE_RESTART_WAIT));\n\n      // \u68C0\u67E5\u670D\u52A1\u72B6\u6001\n      const status = await this.systemdManager.getStatus();\n      return status.active;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * \u68C0\u6D4B Stats API \u72B6\u6001\n   *\n   * @returns \u68C0\u6D4B\u7ED3\u679C\n   */\n  async detectStatsConfig(): Promise<StatsDetectionResult> {\n    const missingComponents = await this.detectMissingComponents();\n    let serviceRunning = false;\n    try {\n      const status = await this.systemdManager.getStatus();\n      serviceRunning = status.active;\n    } catch {\n      serviceRunning = false;\n    }\n\n    // \u5982\u679C\u6240\u6709\u7EC4\u4EF6\u90FD\u5B58\u5728\uFF0C\u5C1D\u8BD5\u8FDE\u63A5 API\n    if (missingComponents.length === 0 && serviceRunning) {\n      // \u83B7\u53D6\u914D\u7F6E\u7684\u7AEF\u53E3\n      let detectedPort = DEFAULT_API_PORT;\n      try {\n        const config = (await this.configManager.readConfig()) as XrayConfigWithStats;\n        const apiInbound = config.inbounds?.find(\n          (inbound) => inbound.tag === 'api' && inbound.protocol === 'dokodemo-door'\n        );\n        if (apiInbound) {\n          detectedPort = apiInbound.port;\n        }\n      } catch {\n        // \u4F7F\u7528\u9ED8\u8BA4\u7AEF\u53E3\n      }\n\n      const available = await this.verifyStatsApiConnection(detectedPort);\n\n      return {\n        available,\n        configDetected: true,\n        detectedPort,\n        serviceRunning,\n        message: available ? 'Stats API \u5DF2\u914D\u7F6E\u4E14\u53EF\u7528' : 'Stats API \u5DF2\u914D\u7F6E\u4F46\u65E0\u6CD5\u8FDE\u63A5',\n        suggestion: available ? undefined : '\u8BF7\u68C0\u67E5 Xray \u670D\u52A1\u72B6\u6001\u548C\u9632\u706B\u5899\u8BBE\u7F6E',\n        missingComponents: [],\n      };\n    }\n\n    // \u6709\u7F3A\u5931\u7EC4\u4EF6\n    const componentNames: Record<MissingComponent, string> = {\n      stats: 'stats \u914D\u7F6E\u5757',\n      policy: 'policy \u914D\u7F6E',\n      api: 'API \u914D\u7F6E',\n      'api-inbound': 'API \u5165\u7AD9\u914D\u7F6E',\n      'api-outbound': 'API \u51FA\u7AD9\u914D\u7F6E',\n      'api-routing': 'API \u8DEF\u7531\u89C4\u5219',\n    };\n\n    const missingNames = missingComponents.map((c) => componentNames[c]).join('\u3001');\n\n    return {\n      available: false,\n      configDetected: missingComponents.length < 6,\n      serviceRunning,\n      message: `Stats API \u672A\u5B8C\u5168\u914D\u7F6E\uFF0C\u7F3A\u5C11: ${missingNames}`,\n      suggestion: '\u662F\u5426\u81EA\u52A8\u914D\u7F6E Stats API\uFF1F',\n      missingComponents,\n    };\n  }\n\n  /**\n   * \u542F\u7528 Stats API\uFF08\u4E3B\u65B9\u6CD5\uFF09\n   *\n   * @returns \u914D\u7F6E\u7ED3\u679C\n   */\n  async enableStatsApi(): Promise<StatsConfigResult> {\n    let backupPath: string | undefined;\n\n    try {\n      // 1. \u67E5\u627E\u53EF\u7528\u7AEF\u53E3\n      const port = await this.findAvailablePort();\n      if (!port) {\n        return {\n          success: false,\n          apiPort: DEFAULT_API_PORT,\n          message: '\u65E0\u6CD5\u627E\u5230\u53EF\u7528\u7AEF\u53E3',\n          error: `\u7AEF\u53E3\u8303\u56F4 ${STATS_PORT_RANGE.START}-${STATS_PORT_RANGE.END} \u5747\u88AB\u5360\u7528`,\n          rolledBack: false,\n        };\n      }\n\n      // 2. \u5907\u4EFD\u914D\u7F6E\n      backupPath = await this.backupBeforeModify();\n\n      // 3. \u8BFB\u53D6\u73B0\u6709\u914D\u7F6E\n      const config = (await this.configManager.readConfig()) as XrayConfigWithStats;\n\n      // 4. \u751F\u6210\u5E76\u5408\u5E76 Stats \u914D\u7F6E\n      const statsConfig = this.generateStatsConfig(port);\n      const mergedConfig = this.mergeStatsConfig(config, statsConfig);\n\n      // 5. \u5199\u5165\u914D\u7F6E (cast to unknown first to bypass strict type checking)\n      await this.configManager.writeConfig(\n        mergedConfig as unknown as Parameters<typeof this.configManager.writeConfig>[0]\n      );\n\n      // 6. \u91CD\u542F\u670D\u52A1\n      const serviceOk = await this.restartAndVerify();\n      if (!serviceOk) {\n        // \u670D\u52A1\u91CD\u542F\u5931\u8D25\uFF0C\u56DE\u6EDA\n        await this.rollbackOnFailure(backupPath);\n        return {\n          success: false,\n          backupPath,\n          apiPort: port,\n          message: '\u670D\u52A1\u91CD\u542F\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u539F\u914D\u7F6E',\n          error: 'Xray \u670D\u52A1\u542F\u52A8\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u914D\u7F6E\u6587\u4EF6',\n          rolledBack: true,\n        };\n      }\n\n      // 7. \u9A8C\u8BC1 API \u8FDE\u63A5\n      const apiOk = await this.verifyStatsApiConnection(port);\n      if (!apiOk) {\n        // API \u65E0\u6CD5\u8FDE\u63A5\uFF0C\u4F46\u670D\u52A1\u8FD0\u884C\u6B63\u5E38\uFF0C\u4E0D\u56DE\u6EDA\n        return {\n          success: true,\n          backupPath,\n          apiPort: port,\n          message: 'Stats API \u914D\u7F6E\u6210\u529F\uFF0C\u4F46\u8FDE\u63A5\u9A8C\u8BC1\u5931\u8D25',\n          error: 'API \u53EF\u80FD\u9700\u8981\u51E0\u79D2\u949F\u624D\u80FD\u5C31\u7EEA\uFF0C\u6216\u68C0\u67E5\u9632\u706B\u5899\u8BBE\u7F6E',\n          rolledBack: false,\n        };\n      }\n\n      return {\n        success: true,\n        backupPath,\n        apiPort: port,\n        message: 'Stats API \u914D\u7F6E\u6210\u529F\uFF01',\n        rolledBack: false,\n      };\n    } catch (error) {\n      // \u53D1\u751F\u9519\u8BEF\uFF0C\u5C1D\u8BD5\u56DE\u6EDA\n      if (backupPath) {\n        try {\n          await this.rollbackOnFailure(backupPath);\n          return {\n            success: false,\n            backupPath,\n            apiPort: DEFAULT_API_PORT,\n            message: '\u914D\u7F6E\u5931\u8D25\uFF0C\u5DF2\u6062\u590D\u539F\u914D\u7F6E',\n            error: (error as Error).message,\n            rolledBack: true,\n          };\n        } catch (rollbackError) {\n          return {\n            success: false,\n            backupPath,\n            apiPort: DEFAULT_API_PORT,\n            message: '\u914D\u7F6E\u5931\u8D25\uFF0C\u56DE\u6EDA\u4E5F\u5931\u8D25',\n            error: `\u539F\u9519\u8BEF: ${(error as Error).message}; \u56DE\u6EDA\u9519\u8BEF: ${(rollbackError as Error).message}`,\n            rolledBack: false,\n          };\n        }\n      }\n\n      return {\n        success: false,\n        apiPort: DEFAULT_API_PORT,\n        message: '\u914D\u7F6E\u5931\u8D25',\n        error: (error as Error).message,\n        rolledBack: false,\n      };\n    }\n  }\n}\n", "import React, { createContext, useContext, useReducer, useCallback } from 'react';\nimport { type Route, SCREEN_TITLES } from '../app/routes.js';\n\ninterface NavigationState {\n  stack: Route[];\n}\n\ntype NavigationAction =\n  | { type: 'NAVIGATE'; route: Route }\n  | { type: 'GO_BACK' }\n  | { type: 'RESET' };\n\nfunction reducer(state: NavigationState, action: NavigationAction): NavigationState {\n  switch (action.type) {\n    case 'NAVIGATE':\n      return { stack: [...state.stack, action.route] };\n    case 'GO_BACK':\n      if (state.stack.length <= 1) return state;\n      return { stack: state.stack.slice(0, -1) };\n    case 'RESET':\n      return { stack: [{ screen: 'main-menu' }] };\n    default:\n      return state;\n  }\n}\n\ninterface NavigationContextValue {\n  currentRoute: Route;\n  breadcrumb: string[];\n  canGoBack: boolean;\n  navigate: (route: Route) => void;\n  goBack: () => void;\n  reset: () => void;\n}\n\nconst NavigationContext = createContext<NavigationContextValue>({\n  currentRoute: { screen: 'main-menu' },\n  breadcrumb: ['Home'],\n  canGoBack: false,\n  navigate: () => {},\n  goBack: () => {},\n  reset: () => {},\n});\n\nexport function NavigationProvider({ children }: { children: React.ReactNode }) {\n  const [state, dispatch] = useReducer(reducer, {\n    stack: [{ screen: 'main-menu' }],\n  });\n\n  const navigate = useCallback((route: Route) => {\n    dispatch({ type: 'NAVIGATE', route });\n  }, []);\n\n  const goBack = useCallback(() => {\n    dispatch({ type: 'GO_BACK' });\n  }, []);\n\n  const reset = useCallback(() => {\n    dispatch({ type: 'RESET' });\n  }, []);\n\n  const currentRoute = state.stack[state.stack.length - 1] ?? { screen: 'main-menu' as const };\n  const breadcrumb = state.stack.map((r) => SCREEN_TITLES[r.screen]);\n  const canGoBack = state.stack.length > 1;\n\n  return (\n    <NavigationContext.Provider\n      value={{ currentRoute, breadcrumb, canGoBack, navigate, goBack, reset }}\n    >\n      {children}\n    </NavigationContext.Provider>\n  );\n}\n\nexport function useNavigation(): NavigationContextValue {\n  return useContext(NavigationContext);\n}\n", "export type Route =\n  | { screen: 'main-menu' }\n  | { screen: 'service-status' }\n  | { screen: 'user-management' }\n  | { screen: 'user-add' }\n  | { screen: 'user-delete' }\n  | { screen: 'user-share'; userId?: string }\n  | { screen: 'quota-management' }\n  | { screen: 'quota-set' }\n  | { screen: 'quota-details'; email?: string }\n  | { screen: 'config-management' }\n  | { screen: 'log-viewer' }\n  | { screen: 'online-users' }\n  | { screen: 'subscriptions' }\n  | { screen: 'command-palette' };\n\nexport const SCREEN_TITLES: Record<Route['screen'], string> = {\n  'main-menu': 'Home',\n  'service-status': 'Service Status',\n  'user-management': 'User Management',\n  'user-add': 'Add User',\n  'user-delete': 'Delete User',\n  'user-share': 'Share Link',\n  'quota-management': 'Quota Management',\n  'quota-set': 'Set Quota',\n  'quota-details': 'Quota Details',\n  'config-management': 'Configuration',\n  'log-viewer': 'Log Viewer',\n  'online-users': 'Online Users',\n  subscriptions: 'Subscriptions',\n  'command-palette': 'Command Palette',\n};\n", "import React, { createContext, useContext, useState, useCallback } from 'react';\n\nexport interface Notification {\n  id: number;\n  type: 'success' | 'error' | 'warning' | 'info';\n  message: string;\n}\n\ninterface NotificationContextValue {\n  notifications: Notification[];\n  notify: (type: Notification['type'], message: string) => void;\n  dismiss: (id: number) => void;\n}\n\nlet nextId = 0;\n\nconst NotificationContext = createContext<NotificationContextValue>({\n  notifications: [],\n  notify: () => {},\n  dismiss: () => {},\n});\n\nexport function NotificationProvider({ children }: { children: React.ReactNode }) {\n  const [notifications, setNotifications] = useState<Notification[]>([]);\n\n  const dismiss = useCallback((id: number) => {\n    setNotifications((prev) => prev.filter((n) => n.id !== id));\n  }, []);\n\n  const notify = useCallback(\n    (type: Notification['type'], message: string) => {\n      const id = nextId++;\n      setNotifications((prev) => [...prev, { id, type, message }]);\n      // Auto-dismiss after 3 seconds\n      setTimeout(() => dismiss(id), 3000);\n    },\n    [dismiss]\n  );\n\n  return (\n    <NotificationContext.Provider value={{ notifications, notify, dismiss }}>\n      {children}\n    </NotificationContext.Provider>\n  );\n}\n\nexport function useNotification(): NotificationContextValue {\n  return useContext(NotificationContext);\n}\n", "import React, { useState } from 'react';\nimport { Box, useInput, useApp } from 'ink';\nimport { Header } from '../components/design-system/Header.js';\nimport { StatusBar } from '../components/design-system/StatusBar.js';\nimport { Divider } from '../components/design-system/Divider.js';\nimport { Breadcrumb } from '../components/Breadcrumb.js';\nimport { Dashboard } from '../components/Dashboard.js';\nimport { Toast } from '../components/Toast.js';\nimport { CommandPalette, type CommandItem } from '../components/CommandPalette.js';\nimport { Router } from './Router.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useDashboardData } from '../hooks/useDashboardData.js';\n\ninterface AppShellProps {\n  version: string;\n}\n\nexport function AppShell({ version }: AppShellProps) {\n  const { exit } = useApp();\n  const { currentRoute, goBack, canGoBack, navigate, reset } = useNavigation();\n  const { notifications, dismiss } = useNotification();\n  const { data: dashboardData, loading: dashboardLoading } = useDashboardData();\n  const [showPalette, setShowPalette] = useState(false);\n\n  const commandItems: CommandItem[] = [\n    { label: 'Service Status', value: 'service-status', category: 'Service' },\n    { label: 'Online Users', value: 'online-users', category: 'Monitor' },\n    { label: 'User Management', value: 'user-management', category: 'Users' },\n    { label: 'Add User', value: 'user-add', category: 'Users' },\n    { label: 'Traffic & Quotas', value: 'quota-management', category: 'Quotas' },\n    { label: 'Set Quota', value: 'quota-set', category: 'Quotas' },\n    { label: 'Subscriptions', value: 'subscriptions', category: 'Service' },\n    { label: 'Configuration', value: 'config-management', category: 'System' },\n    { label: 'View Logs', value: 'log-viewer', category: 'System' },\n  ];\n\n  useInput((input, key) => {\n    if (showPalette) return;\n    if (input === '/' && currentRoute.screen !== 'command-palette') {\n      setShowPalette(true);\n    } else if (key.escape) {\n      if (canGoBack) goBack();\n    } else if (input === 'q') {\n      if (currentRoute.screen === 'main-menu') exit();\n      else reset();\n    }\n  });\n\n  const handlePaletteSelect = (value: string) => {\n    setShowPalette(false);\n    navigate({ screen: value } as { screen: 'service-status' });\n  };\n\n  const serviceStatus = dashboardData?.serviceActive\n    ? ('running' as const)\n    : dashboardData\n      ? ('stopped' as const)\n      : ('loading' as const);\n\n  const isHome = currentRoute.screen === 'main-menu';\n\n  return (\n    <Box flexDirection=\"column\">\n      {/* Header: title + service status */}\n      <Header version={version} serviceStatus={serviceStatus} uptime={dashboardData?.uptime} />\n\n      {/* Dashboard: only on home screen */}\n      {isHome && (\n        <>\n          <Dashboard data={dashboardData} loading={dashboardLoading} />\n          <Divider />\n        </>\n      )}\n\n      {/* Breadcrumb: only when navigated away from home */}\n      {!isHome && (\n        <Box paddingX={2} paddingBottom={1}>\n          <Breadcrumb />\n        </Box>\n      )}\n\n      {/* Command Palette overlay */}\n      {showPalette && (\n        <Box paddingX={2}>\n          <CommandPalette\n            items={commandItems}\n            onSelect={handlePaletteSelect}\n            onCancel={() => setShowPalette(false)}\n          />\n        </Box>\n      )}\n\n      {/* Main content */}\n      {!showPalette && <Router />}\n\n      {/* Notifications */}\n      {notifications.length > 0 && (\n        <Box flexDirection=\"column\" paddingX={2} paddingTop={1}>\n          {notifications.map((n) => (\n            <Toast key={n.id} type={n.type} message={n.message} onDismiss={() => dismiss(n.id)} />\n          ))}\n        </Box>\n      )}\n\n      {/* Status bar */}\n      <Divider />\n      <StatusBar />\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from './ThemeProvider.js';\nimport { useI18n } from '../../contexts/I18nContext.js';\n\ninterface HeaderProps {\n  version: string;\n  serviceStatus?: 'running' | 'stopped' | 'error' | 'loading';\n  uptime?: string;\n}\n\nexport function Header({ version, serviceStatus = 'loading', uptime }: HeaderProps) {\n  const { theme } = useTheme();\n  const { t } = useI18n();\n\n  const statusColor =\n    serviceStatus === 'running'\n      ? theme.serviceRunning\n      : serviceStatus === 'stopped'\n        ? theme.serviceStopped\n        : serviceStatus === 'error'\n          ? theme.error\n          : theme.inactive;\n\n  const statusLabel = t.status[serviceStatus] ?? serviceStatus;\n\n  return (\n    <Box paddingX={2} paddingY={1} justifyContent=\"space-between\">\n      <Box gap={1}>\n        <Text color={theme.primary} bold>\n          Xray Manager\n        </Text>\n        <Text dimColor>v{version}</Text>\n      </Box>\n      <Box gap={1}>\n        <Text color={statusColor} bold>\n          {'\\u25cf'} {statusLabel}\n        </Text>\n        {uptime && <Text dimColor>{uptime}</Text>}\n      </Box>\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useNavigation } from '../../contexts/NavigationContext.js';\nimport { useI18n } from '../../contexts/I18nContext.js';\n\nexport interface ShortcutHint {\n  key: string;\n  action: string;\n}\n\ninterface StatusBarProps {\n  hints?: ShortcutHint[];\n}\n\nexport function StatusBar({ hints }: StatusBarProps) {\n  const { canGoBack } = useNavigation();\n  const { t } = useI18n();\n\n  const effectiveHints = hints ?? [\n    ...(canGoBack ? [{ key: 'esc', action: t.ui.back }] : []),\n    { key: '\\u2191\\u2193', action: t.ui.navigate },\n    { key: 'enter', action: t.ui.select },\n    { key: '/', action: t.ui.search },\n    { key: 'q', action: t.ui.quit },\n  ];\n\n  return (\n    <Box paddingX={2}>\n      {effectiveHints.map((hint, i) => (\n        <Text key={i} dimColor>\n          {i > 0 ? '  ' : ''}\n          <Text bold>{hint.key}</Text> {hint.action}\n        </Text>\n      ))}\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from './ThemeProvider.js';\nimport { resolveColor } from './theme.js';\n\ninterface DividerProps {\n  color?: string;\n  title?: string;\n  padding?: number;\n}\n\nexport function Divider({ color, title, padding = 2 }: DividerProps) {\n  const { theme } = useTheme();\n  const w = Math.max(10, (process.stdout.columns || 80) - padding * 2);\n  const dimmed = !color;\n  const lineColor = resolveColor(color, theme) ?? theme.border;\n\n  if (title) {\n    const titleStr = ` ${title} `;\n    const remaining = Math.max(0, w - titleStr.length);\n    const left = Math.min(3, remaining);\n    const right = remaining - left;\n    return (\n      <Box paddingX={padding}>\n        <Text dimColor={dimmed} color={dimmed ? undefined : lineColor}>\n          {'\\u2500'.repeat(left)}\n        </Text>\n        <Text dimColor>{titleStr}</Text>\n        <Text dimColor={dimmed} color={dimmed ? undefined : lineColor}>\n          {'\\u2500'.repeat(Math.max(0, right))}\n        </Text>\n      </Box>\n    );\n  }\n\n  return (\n    <Box paddingX={padding}>\n      <Text dimColor={dimmed} color={dimmed ? undefined : lineColor}>\n        {'\\u2500'.repeat(w)}\n      </Text>\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useNavigation } from '../contexts/NavigationContext.js';\n\nexport function Breadcrumb() {\n  const { breadcrumb } = useNavigation();\n\n  if (breadcrumb.length <= 1) return null;\n\n  return (\n    <Box>\n      {breadcrumb.map((segment, i) => {\n        const isLast = i === breadcrumb.length - 1;\n        return (\n          <Text key={i}>\n            {i > 0 && <Text dimColor> {'>'} </Text>}\n            <Text dimColor={!isLast} bold={isLast}>\n              {segment}\n            </Text>\n          </Text>\n        );\n      })}\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\nimport { formatBytes } from '../utils/format.js';\n\nexport interface DashboardData {\n  serviceActive: boolean;\n  uptime?: string;\n  userCount: number;\n  onlineCount?: number;\n  totalTraffic: number;\n  uploadTraffic: number;\n  downloadTraffic: number;\n  quotaSummary: { ok: number; warning: number; exceeded: number };\n  cpuPercent?: number;\n  memPercent?: number;\n  diskPercent?: number;\n}\n\ninterface DashboardProps {\n  data: DashboardData | null;\n  loading?: boolean;\n}\n\nfunction MiniBar({\n  value,\n  max = 100,\n  width = 8,\n  theme,\n}: {\n  value: number;\n  max?: number;\n  theme: Record<string, string>;\n  width?: number;\n}) {\n  const ratio = Math.min(value / max, 1);\n  const filled = Math.round(ratio * width);\n  const empty = width - filled;\n  const color = value > 90 ? theme.error : value > 70 ? theme.warning : theme.success;\n  return (\n    <Text>\n      <Text color={color}>{'\\u2588'.repeat(filled)}</Text>\n      <Text dimColor>{'\\u2591'.repeat(empty)}</Text>\n    </Text>\n  );\n}\n\nexport function Dashboard({ data, loading }: DashboardProps) {\n  const { theme } = useTheme();\n  const t = theme as unknown as Record<string, string>;\n\n  if (loading || !data) {\n    return (\n      <Box paddingX={2}>\n        <Text dimColor italic>\n          Loading...\n        </Text>\n      </Box>\n    );\n  }\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2}>\n      {/* Row 1: Traffic + Users */}\n      <Box gap={2}>\n        <Box gap={1}>\n          <Text dimColor>Traffic</Text>\n          <Text bold>{formatBytes(data.totalTraffic)}</Text>\n          <Text dimColor>\n            {'\\u2191'}\n            {formatBytes(data.uploadTraffic)} {'\\u2193'}\n            {formatBytes(data.downloadTraffic)}\n          </Text>\n        </Box>\n\n        <Text dimColor>|</Text>\n\n        <Box gap={1}>\n          <Text dimColor>Users</Text>\n          {data.onlineCount !== undefined && (\n            <Text color={theme.success} bold>\n              {data.onlineCount}\n            </Text>\n          )}\n          {data.onlineCount !== undefined && <Text dimColor>/</Text>}\n          <Text bold>{data.userCount}</Text>\n          {data.quotaSummary.exceeded > 0 && (\n            <Text color={theme.error}>({data.quotaSummary.exceeded} over)</Text>\n          )}\n        </Box>\n      </Box>\n\n      {/* Row 2: System resources \u2014 compact bar style */}\n      {data.cpuPercent !== undefined && (\n        <Box gap={2}>\n          <Box gap={1}>\n            <Text dimColor>cpu</Text>\n            <MiniBar value={data.cpuPercent ?? 0} theme={t} />\n            <Text dimColor>{data.cpuPercent}%</Text>\n          </Box>\n          <Box gap={1}>\n            <Text dimColor>mem</Text>\n            <MiniBar value={data.memPercent ?? 0} theme={t} />\n            <Text dimColor>{data.memPercent}%</Text>\n          </Box>\n          {data.diskPercent !== undefined && (\n            <Box gap={1}>\n              <Text dimColor>disk</Text>\n              <MiniBar value={data.diskPercent} theme={t} />\n              <Text dimColor>{data.diskPercent}%</Text>\n            </Box>\n          )}\n        </Box>\n      )}\n    </Box>\n  );\n}\n", "/**\n * \u683C\u5F0F\u5316\u5DE5\u5177\u51FD\u6570\n * @module utils/format\n */\n\n/**\n * \u8131\u654F\u9009\u9879\n */\nexport interface MaskOptions {\n  /** \u524D\u7F00\u957F\u5EA6\uFF08\u9ED8\u8BA4 4\uFF09 */\n  prefixLength?: number;\n\n  /** \u540E\u7F00\u957F\u5EA6\uFF08\u9ED8\u8BA4 4\uFF09 */\n  suffixLength?: number;\n\n  /** \u63A9\u7801\u5B57\u7B26\uFF08\u9ED8\u8BA4 *\uFF09 */\n  maskChar?: string;\n}\n\n/**\n * \u8131\u654F\u663E\u793A\u654F\u611F\u4FE1\u606F\uFF08\u524D4\u540E4\uFF09\n * @param value \u539F\u59CB\u503C\n * @param options \u8131\u654F\u9009\u9879\n * @returns \u8131\u654F\u540E\u7684\u503C\n */\nexport function maskSensitiveValue(value: string, options: MaskOptions = {}): string {\n  const { prefixLength = 4, suffixLength = 4, maskChar = '*' } = options;\n\n  // Handle empty or very short strings\n  if (!value) {\n    return maskChar.repeat(3);\n  }\n\n  if (value.length <= prefixLength + suffixLength) {\n    // For short strings, show first char only\n    if (value.length <= 3) {\n      return value[0] + maskChar.repeat(value.length - 1 || 2);\n    }\n    return maskChar.repeat(value.length);\n  }\n\n  // Special handling for email addresses\n  if (value.includes('@')) {\n    const [localPart, domain] = value.split('@');\n    const maskedLocal =\n      localPart.slice(0, Math.min(4, localPart.length)) +\n      maskChar.repeat(Math.max(0, localPart.length - 4));\n    return `${maskedLocal}@${domain}`;\n  }\n\n  // Default masking: show first 4 and last 4\n  const prefix = value.slice(0, prefixLength);\n  const suffix = value.slice(-suffixLength);\n  const maskLength = value.length - prefixLength - suffixLength;\n\n  return `${prefix}${maskChar.repeat(maskLength)}${suffix}`;\n}\n\n/**\n * \u683C\u5F0F\u5316\u8FD0\u884C\u65F6\u957F\uFF08\u6BEB\u79D2\u8F6C\u4E3A\u53EF\u8BFB\u683C\u5F0F\uFF09\n * @param milliseconds \u6BEB\u79D2\u6570\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u65F6\u957F\u5B57\u7B26\u4E32\n */\nexport function formatUptime(milliseconds: number): string {\n  if (!milliseconds || milliseconds < 0) {\n    return '0\u79D2';\n  }\n\n  const seconds = Math.floor(milliseconds / 1000);\n  const minutes = Math.floor(seconds / 60);\n  const hours = Math.floor(minutes / 60);\n  const days = Math.floor(hours / 24);\n\n  if (days > 0) {\n    return `${days}\u5929 ${hours % 24}\u5C0F\u65F6 ${minutes % 60}\u5206\u949F`;\n  } else if (hours > 0) {\n    return `${hours}\u5C0F\u65F6 ${minutes % 60}\u5206\u949F`;\n  } else if (minutes > 0) {\n    return `${minutes}\u5206\u949F ${seconds % 60}\u79D2`;\n  } else {\n    return `${seconds}\u79D2`;\n  }\n}\n\n/**\n * \u683C\u5F0F\u5316\u5B57\u8282\u5927\u5C0F\n * @param bytes \u5B57\u8282\u6570\n * @param decimals \u5C0F\u6570\u4F4D\u6570\uFF08\u9ED8\u8BA4 2\uFF09\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u5927\u5C0F\u5B57\u7B26\u4E32\n */\nexport function formatBytes(bytes: number, decimals: number = 2): string {\n  if (bytes === 0) return '0 B';\n  if (!bytes || bytes < 0) return 'N/A';\n\n  const k = 1024;\n  const dm = decimals < 0 ? 0 : decimals;\n  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];\n\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n}\n\n/**\n * \u683C\u5F0F\u5316\u65F6\u95F4\u6233\u4E3A\u53EF\u8BFB\u65E5\u671F\n * @param timestamp ISO 8601 \u5B57\u7B26\u4E32\u6216 Unix \u65F6\u95F4\u6233\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u65E5\u671F\u5B57\u7B26\u4E32\n */\nexport function formatDate(timestamp: string | number): string {\n  const date = typeof timestamp === 'string' ? new Date(timestamp) : new Date(timestamp);\n\n  if (isNaN(date.getTime())) {\n    return 'Invalid Date';\n  }\n\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const day = String(date.getDate()).padStart(2, '0');\n  const hours = String(date.getHours()).padStart(2, '0');\n  const minutes = String(date.getMinutes()).padStart(2, '0');\n\n  return `${year}-${month}-${day} ${hours}:${minutes}`;\n}\n\n/**\n * \u683C\u5F0F\u5316\u76F8\u5BF9\u65F6\u95F4\uFF08\u5982 \"2 \u5C0F\u65F6\u524D\"\uFF09\n * @param timestamp ISO 8601 \u5B57\u7B26\u4E32\u6216 Unix \u65F6\u95F4\u6233\n * @returns \u76F8\u5BF9\u65F6\u95F4\u5B57\u7B26\u4E32\n */\nexport function formatRelativeTime(timestamp: string | number): string {\n  const date = typeof timestamp === 'string' ? new Date(timestamp) : new Date(timestamp);\n  const now = new Date();\n  const diffMs = now.getTime() - date.getTime();\n\n  if (diffMs < 0) {\n    return '\u672A\u6765';\n  }\n\n  const diffSeconds = Math.floor(diffMs / 1000);\n  const diffMinutes = Math.floor(diffSeconds / 60);\n  const diffHours = Math.floor(diffMinutes / 60);\n  const diffDays = Math.floor(diffHours / 24);\n\n  if (diffDays > 0) {\n    return `${diffDays}\u5929\u524D`;\n  } else if (diffHours > 0) {\n    return `${diffHours}\u5C0F\u65F6\u524D`;\n  } else if (diffMinutes > 0) {\n    return `${diffMinutes}\u5206\u949F\u524D`;\n  } else {\n    return `${diffSeconds}\u79D2\u524D`;\n  }\n}\n\n/**\n * \u683C\u5F0F\u5316\u6301\u7EED\u65F6\u95F4\uFF08\u6BEB\u79D2\u8F6C\u4E3A\u7B80\u6D01\u683C\u5F0F\uFF09\n * @param ms \u6BEB\u79D2\u6570\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u6301\u7EED\u65F6\u95F4\u5B57\u7B26\u4E32\n */\nexport function formatDuration(ms: number): string {\n  if (ms < 1000) {\n    return `${ms}ms`;\n  } else if (ms < 60000) {\n    return `${(ms / 1000).toFixed(1)}s`;\n  } else if (ms < 3600000) {\n    return `${(ms / 60000).toFixed(1)}m`;\n  } else {\n    return `${(ms / 3600000).toFixed(1)}h`;\n  }\n}\n\n/**\n * \u683C\u5F0F\u5316 JSON\uFF08\u7F8E\u5316\u8F93\u51FA\uFF09\n * @param obj \u5BF9\u8C61\n * @param spaces \u7F29\u8FDB\u7A7A\u683C\u6570\uFF08\u9ED8\u8BA4 2\uFF09\n * @returns \u683C\u5F0F\u5316\u540E\u7684 JSON \u5B57\u7B26\u4E32\n */\nexport function formatJSON(obj: unknown, spaces: number = 2): string {\n  try {\n    return JSON.stringify(obj, null, spaces);\n  } catch {\n    return String(obj);\n  }\n}\n\n/**\n * \u622A\u65AD\u5B57\u7B26\u4E32\uFF08\u6DFB\u52A0\u7701\u7565\u53F7\uFF09\n * @param str \u539F\u59CB\u5B57\u7B26\u4E32\n * @param maxLength \u6700\u5927\u957F\u5EA6\n * @param ellipsis \u7701\u7565\u53F7\uFF08\u9ED8\u8BA4 ...\uFF09\n * @returns \u622A\u65AD\u540E\u7684\u5B57\u7B26\u4E32\n */\nexport function truncate(str: string, maxLength: number, ellipsis: string = '...'): string {\n  if (!str || str.length <= maxLength) {\n    return str;\n  }\n\n  return str.slice(0, maxLength - ellipsis.length) + ellipsis;\n}\n\n/**\n * \u586B\u5145\u5B57\u7B26\u4E32\uFF08\u5BF9\u9F50\uFF09\n * @param str \u539F\u59CB\u5B57\u7B26\u4E32\n * @param length \u76EE\u6807\u957F\u5EA6\n * @param padChar \u586B\u5145\u5B57\u7B26\uFF08\u9ED8\u8BA4\u7A7A\u683C\uFF09\n * @param align \u5BF9\u9F50\u65B9\u5F0F\uFF08\u9ED8\u8BA4 left\uFF09\n * @returns \u586B\u5145\u540E\u7684\u5B57\u7B26\u4E32\n */\nexport function pad(\n  str: string,\n  length: number,\n  padChar: string = ' ',\n  align: 'left' | 'right' | 'center' = 'left'\n): string {\n  if (str.length >= length) {\n    return str;\n  }\n\n  const padLength = length - str.length;\n\n  switch (align) {\n    case 'right':\n      return padChar.repeat(padLength) + str;\n    case 'center': {\n      const leftPad = Math.floor(padLength / 2);\n      const rightPad = padLength - leftPad;\n      return padChar.repeat(leftPad) + str + padChar.repeat(rightPad);\n    }\n    case 'left':\n    default:\n      return str + padChar.repeat(padLength);\n  }\n}\n\n/**\n * \u683C\u5F0F\u5316\u8868\u683C\u884C\uFF08\u7528\u4E8E\u63A7\u5236\u53F0\u8F93\u51FA\uFF09\n * @param columns \u5217\u6570\u636E\n * @param widths \u5217\u5BBD\u5EA6\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u884C\u5B57\u7B26\u4E32\n */\nexport function formatTableRow(columns: string[], widths: number[]): string {\n  return columns.map((col, i) => pad(truncate(col, widths[i]), widths[i])).join(' \u2502 ');\n}\n\n/**\n * \u683C\u5F0F\u5316\u767E\u5206\u6BD4\n * @param value \u6570\u503C\uFF080-1 \u6216 0-100\uFF09\n * @param total \u603B\u6570\uFF08\u53EF\u9009\uFF09\n * @param decimals \u5C0F\u6570\u4F4D\u6570\uFF08\u9ED8\u8BA4 1\uFF09\n * @returns \u683C\u5F0F\u5316\u540E\u7684\u767E\u5206\u6BD4\u5B57\u7B26\u4E32\n */\nexport function formatPercentage(value: number, total?: number, decimals: number = 1): string {\n  let percent: number;\n\n  if (total !== undefined && total > 0) {\n    percent = (value / total) * 100;\n  } else if (value > 0 && value <= 1) {\n    percent = value * 100;\n  } else {\n    percent = value;\n  }\n\n  return `${percent.toFixed(decimals)}%`;\n}\n", "import React, { useEffect } from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\ntype ToastType = 'success' | 'error' | 'warning' | 'info';\n\nconst TOAST_ICONS: Record<ToastType, string> = {\n  success: '\\u2713',\n  error: '\\u2717',\n  warning: '!',\n  info: '\\u2139',\n};\n\nconst TOAST_COLORS: Record<ToastType, string> = {\n  success: 'success',\n  error: 'error',\n  warning: 'warning',\n  info: 'info',\n};\n\ninterface ToastProps {\n  type: ToastType;\n  message: string;\n  duration?: number;\n  onDismiss?: () => void;\n}\n\nexport function Toast({ type, message, duration = 3000, onDismiss }: ToastProps) {\n  const { theme } = useTheme();\n\n  useEffect(() => {\n    if (onDismiss && duration > 0) {\n      const timer = setTimeout(onDismiss, duration);\n      return () => clearTimeout(timer);\n    }\n  }, [duration, onDismiss]);\n\n  const color = (theme as unknown as Record<string, string>)[TOAST_COLORS[type]] ?? theme.text;\n\n  return (\n    <Box>\n      <Text color={color} bold>\n        {TOAST_ICONS[type]}\n      </Text>\n      <Text color={color}> {message}</Text>\n    </Box>\n  );\n}\n", "import React, { useState, useMemo } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport Fuse from 'fuse.js';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\nexport interface CommandItem {\n  label: string;\n  value: string;\n  icon?: string;\n  category?: string;\n}\n\ninterface CommandPaletteProps {\n  items: CommandItem[];\n  onSelect: (value: string) => void;\n  onCancel: () => void;\n}\n\nexport function CommandPalette({ items, onSelect, onCancel }: CommandPaletteProps) {\n  const { theme } = useTheme();\n  const [query, setQuery] = useState('');\n  const [selectedIdx, setSelectedIdx] = useState(0);\n\n  const fuse = useMemo(\n    () => new Fuse(items, { keys: ['label', 'category'], threshold: 0.4 }),\n    [items]\n  );\n\n  const results = useMemo(() => {\n    if (!query) return items;\n    return fuse.search(query).map((r) => r.item);\n  }, [query, fuse, items]);\n\n  const visibleCount = Math.min(8, results.length);\n\n  useInput((input, key) => {\n    if (key.escape) {\n      onCancel();\n    } else if (key.return) {\n      const item = results[selectedIdx];\n      if (item) onSelect(item.value);\n    } else if (key.upArrow || (key.ctrl && input === 'p')) {\n      setSelectedIdx((prev) => (prev > 0 ? prev - 1 : results.length - 1));\n    } else if (key.downArrow || (key.ctrl && input === 'n')) {\n      setSelectedIdx((prev) => (prev < results.length - 1 ? prev + 1 : 0));\n    } else if (key.backspace || key.delete) {\n      setQuery((prev) => prev.slice(0, -1));\n      setSelectedIdx(0);\n    } else if (input && !key.ctrl && !key.meta) {\n      setQuery((prev) => prev + input);\n      setSelectedIdx(0);\n    }\n  });\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      borderStyle=\"round\"\n      borderColor={theme.primary}\n      paddingX={1}\n      paddingY={0}\n    >\n      {/* Search input */}\n      <Box>\n        <Text color={theme.primary} bold>\n          {'/ '}\n        </Text>\n        <Text color={theme.text}>{query}</Text>\n        <Text color={theme.primary}>{'\\u2588'}</Text>\n      </Box>\n\n      {/* Results */}\n      {results.slice(0, visibleCount).map((item, i) => {\n        const isSelected = i === selectedIdx;\n        return (\n          <Box key={item.value}>\n            <Text color={isSelected ? theme.primary : theme.subtle}>\n              {isSelected ? '\\u276f ' : '  '}\n            </Text>\n            {item.icon && <Text>{item.icon} </Text>}\n            <Text color={isSelected ? theme.primary : theme.text} bold={isSelected}>\n              {item.label}\n            </Text>\n            {item.category && <Text color={theme.subtle}> [{item.category}]</Text>}\n          </Box>\n        );\n      })}\n\n      {results.length === 0 && <Text color={theme.inactive}>No matches</Text>}\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box } from 'ink';\nimport { Select, type SelectOption } from '../components/Select.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { Confirm } from '../components/Confirm.js';\n\ntype MenuAction = string;\n\nexport function MainMenu() {\n  const { navigate } = useNavigation();\n  const { t, toggleLanguage, language } = useI18n();\n  const { notify } = useNotification();\n  const { systemdManager } = useServices();\n  const [operating, setOperating] = React.useState(false);\n  const [confirmAction, setConfirmAction] = React.useState<'stop' | 'restart' | null>(null);\n\n  const langHint = language === 'en' ? 'EN / \\u4e2d\\u6587' : '\\u4e2d\\u6587 / EN';\n\n  const items: SelectOption<MenuAction>[] = [\n    { label: t.menu.viewStatus, value: 'service-status', hint: t.hints.viewDetails },\n    { label: t.menu.startService, value: 'service-start' },\n    { label: t.menu.stopService, value: 'service-stop' },\n    { label: t.menu.restartService, value: 'service-restart' },\n    { separator: true },\n    { label: t.menu.onlineUsers, value: 'online-users', hint: t.hints.liveConnections },\n    { label: t.menu.userManagement, value: 'user-management', hint: t.hints.addDeleteShare },\n    { label: t.menu.quotaManagement, value: 'quota-management', hint: t.hints.limitsUsage },\n    { label: t.menu.subscriptions, value: 'subscriptions', hint: t.hints.subLinkServer },\n    { separator: true },\n    { label: t.menu.configManagement, value: 'config-management', hint: t.hints.backupRestore },\n    { label: t.menu.viewLogs, value: 'log-viewer', hint: t.hints.accessError },\n    { separator: true },\n    { label: t.menu.switchLanguage, value: 'switch-language', hint: langHint },\n    { label: t.menu.exit, value: 'exit', hint: 'q' },\n  ];\n\n  const executeAction = async (action: 'start' | 'stop' | 'restart') => {\n    setConfirmAction(null);\n    setOperating(true);\n    try {\n      if (action === 'start') await systemdManager.start();\n      else if (action === 'stop') await systemdManager.stop();\n      else await systemdManager.restart();\n      notify('success', `Service ${action}ed`);\n    } catch (e) {\n      notify('error', `${(e as Error).message}`);\n    }\n    setOperating(false);\n  };\n\n  const handleSelect = async (value: MenuAction) => {\n    switch (value) {\n      case 'service-status':\n        navigate({ screen: 'service-status' });\n        break;\n      case 'service-start':\n        executeAction('start');\n        break;\n      case 'service-stop':\n        setConfirmAction('stop');\n        break;\n      case 'service-restart':\n        setConfirmAction('restart');\n        break;\n      case 'online-users':\n        navigate({ screen: 'online-users' });\n        break;\n      case 'user-management':\n        navigate({ screen: 'user-management' });\n        break;\n      case 'quota-management':\n        navigate({ screen: 'quota-management' });\n        break;\n      case 'subscriptions':\n        navigate({ screen: 'subscriptions' });\n        break;\n      case 'config-management':\n        navigate({ screen: 'config-management' });\n        break;\n      case 'log-viewer':\n        navigate({ screen: 'log-viewer' });\n        break;\n      case 'switch-language':\n        toggleLanguage();\n        break;\n      case 'exit':\n        process.exit(0);\n    }\n  };\n\n  if (confirmAction) {\n    return (\n      <Box paddingX={2}>\n        <Confirm\n          message={confirmAction === 'stop' ? t.ui.confirmStop : t.ui.confirmRestart}\n          onConfirm={() => executeAction(confirmAction)}\n          onCancel={() => setConfirmAction(null)}\n          destructive\n        />\n      </Box>\n    );\n  }\n\n  if (operating) {\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n  }\n\n  return <Select items={items} onSelect={handleSelect} visibleCount={20} />;\n}\n", "import React, { useState, useCallback } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\nexport interface SelectItem<T = string> {\n  label: string;\n  value: T;\n  description?: string;\n  hint?: string;\n  disabled?: boolean;\n}\n\nexport interface SelectSeparator {\n  separator: true;\n  label?: string;\n}\n\nexport type SelectOption<T = string> = SelectItem<T> | SelectSeparator;\n\nfunction isSeparator<T>(opt: SelectOption<T>): opt is SelectSeparator {\n  return 'separator' in opt && opt.separator === true;\n}\n\ninterface SelectProps<T = string> {\n  items: SelectOption<T>[];\n  onSelect: (value: T) => void;\n  onCancel?: () => void;\n  title?: string;\n  visibleCount?: number;\n  isFocused?: boolean;\n}\n\nexport function Select<T = string>({\n  items,\n  onSelect,\n  onCancel,\n  title,\n  visibleCount = 14,\n  isFocused = true,\n}: SelectProps<T>) {\n  const { theme } = useTheme();\n  const selectableIndices = items\n    .map((item, i) => ({ item, i }))\n    .filter(({ item }) => !isSeparator(item) && !(item as SelectItem<T>).disabled)\n    .map(({ i }) => i);\n\n  const [focusedIdx, setFocusedIdx] = useState(0);\n  const [scrollOffset, setScrollOffset] = useState(0);\n\n  const currentIndex = selectableIndices[focusedIdx] ?? 0;\n\n  const navigate = useCallback(\n    (direction: 1 | -1) => {\n      setFocusedIdx((prev) => {\n        const next = prev + direction;\n        if (next < 0) return selectableIndices.length - 1;\n        if (next >= selectableIndices.length) return 0;\n        return next;\n      });\n    },\n    [selectableIndices.length]\n  );\n\n  useInput(\n    (input, key) => {\n      if (key.upArrow || input === 'k') navigate(-1);\n      else if (key.downArrow || input === 'j') navigate(1);\n      else if (key.return) {\n        const item = items[currentIndex];\n        if (item && !isSeparator(item) && !item.disabled) onSelect(item.value);\n      } else if (key.escape && onCancel) onCancel();\n    },\n    { isActive: isFocused }\n  );\n\n  // Scroll tracking\n  const effectiveOffset = (() => {\n    let off = scrollOffset;\n    if (currentIndex < off) off = currentIndex;\n    if (currentIndex >= off + visibleCount) off = currentIndex - visibleCount + 1;\n    if (off !== scrollOffset) setScrollOffset(off);\n    return off;\n  })();\n\n  const visibleItems = items.slice(effectiveOffset, effectiveOffset + visibleCount);\n  const hasMore = effectiveOffset + visibleCount < items.length;\n  const hasLess = effectiveOffset > 0;\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2}>\n      {title && (\n        <Box marginBottom={1}>\n          <Text dimColor>{title}</Text>\n        </Box>\n      )}\n\n      {hasLess && <Text dimColor> {'...'}</Text>}\n\n      {visibleItems.map((item, vi) => {\n        const realIdx = vi + effectiveOffset;\n\n        if (isSeparator(item)) {\n          return (\n            <Box key={`sep-${realIdx}`} marginY={0}>\n              <Text dimColor> {'\u2500'.repeat(30)}</Text>\n            </Box>\n          );\n        }\n\n        const isActive = realIdx === currentIndex;\n        const si = item as SelectItem<T>;\n\n        return (\n          <Box key={`i-${realIdx}`}>\n            <Text color={isActive ? theme.primary : undefined}>\n              {isActive ? ' \\u276f ' : '   '}\n            </Text>\n            <Text\n              color={si.disabled ? theme.inactive : isActive ? theme.primary : undefined}\n              bold={isActive}\n              dimColor={si.disabled}\n            >\n              {si.label}\n            </Text>\n            {si.hint && <Text dimColor> {si.hint}</Text>}\n          </Box>\n        );\n      })}\n\n      {hasMore && <Text dimColor> {'...'}</Text>}\n    </Box>\n  );\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\nimport { resolveColor } from './design-system/theme.js';\n\nconst FRAMES = [\n  '\\u280b',\n  '\\u2819',\n  '\\u2839',\n  '\\u2838',\n  '\\u283c',\n  '\\u2834',\n  '\\u2826',\n  '\\u2827',\n  '\\u2807',\n  '\\u280f',\n];\n\ninterface SpinnerProps {\n  message?: string;\n  color?: string;\n}\n\nexport function Spinner({ message, color = 'primary' }: SpinnerProps) {\n  const { theme } = useTheme();\n  const [frame, setFrame] = useState(0);\n\n  useEffect(() => {\n    const timer = setInterval(() => {\n      setFrame((prev) => (prev + 1) % FRAMES.length);\n    }, 80);\n    return () => clearInterval(timer);\n  }, []);\n\n  const resolvedColor = resolveColor(color, theme)!;\n\n  return (\n    <Text>\n      <Text color={resolvedColor}>{FRAMES[frame]}</Text>\n      {message && <Text color={theme.text}> {message}</Text>}\n    </Text>\n  );\n}\n", "import React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\ninterface ConfirmProps {\n  message: string;\n  onConfirm: () => void;\n  onCancel: () => void;\n  defaultValue?: boolean;\n  destructive?: boolean;\n  isFocused?: boolean;\n}\n\nexport function Confirm({\n  message,\n  onConfirm,\n  onCancel,\n  defaultValue = false,\n  destructive = false,\n  isFocused = true,\n}: ConfirmProps) {\n  const { theme } = useTheme();\n  const color = destructive ? theme.error : theme.warning;\n  const hint = defaultValue ? '[Y/n]' : '[y/N]';\n\n  useInput(\n    (input, key) => {\n      if (input === 'y' || input === 'Y') {\n        onConfirm();\n      } else if (input === 'n' || input === 'N' || key.escape) {\n        onCancel();\n      } else if (key.return) {\n        if (defaultValue) onConfirm();\n        else onCancel();\n      }\n    },\n    { isActive: isFocused }\n  );\n\n  return (\n    <Box>\n      <Text color={color} bold>\n        {'? '}\n      </Text>\n      <Text color={theme.text}>{message} </Text>\n      <Text color={theme.inactive}>{hint}</Text>\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useServiceStatus } from '../hooks/useServiceStatus.js';\nimport { StatusBadge } from '../components/StatusBadge.js';\nimport { KeyValue } from '../components/KeyValue.js';\nimport { Spinner } from '../components/Spinner.js';\n\nexport function ServiceStatus() {\n  const { status, loading } = useServiceStatus(2000);\n\n  if (loading) {\n    return (\n      <Box paddingX={2}>\n        <Spinner message=\"Fetching service status...\" />\n      </Box>\n    );\n  }\n\n  if (!status) {\n    return (\n      <Box paddingX={2}>\n        <Text color=\"red\">Failed to retrieve service status</Text>\n      </Box>\n    );\n  }\n\n  const labelW = 14;\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Box flexDirection=\"column\">\n        <KeyValue\n          label=\"Status\"\n          labelWidth={labelW}\n          value={\n            <StatusBadge\n              status={status.healthy ? 'running' : status.active ? 'warning' : 'stopped'}\n              label={status.healthy ? 'Running' : status.active ? status.subState : 'Stopped'}\n            />\n          }\n        />\n        <KeyValue label=\"Active State\" labelWidth={labelW} value={status.activeState} />\n        <KeyValue label=\"Sub State\" labelWidth={labelW} value={status.subState} />\n        <KeyValue label=\"Loaded\" labelWidth={labelW} value={status.loaded ? 'Yes' : 'No'} />\n        {status.pid && <KeyValue label=\"PID\" labelWidth={labelW} value={String(status.pid)} />}\n        {status.uptime && <KeyValue label=\"Uptime\" labelWidth={labelW} value={status.uptime} />}\n        {status.memory && <KeyValue label=\"Memory\" labelWidth={labelW} value={status.memory} />}\n      </Box>\n\n      <Text dimColor italic>\n        Auto-refreshing every 2s\n      </Text>\n    </Box>\n  );\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useServices } from '../contexts/ServiceContext.js';\n\ninterface ServiceStatusData {\n  active: boolean;\n  activeState: string;\n  subState: string;\n  loaded: boolean;\n  healthy: boolean;\n  pid?: number;\n  uptime?: string;\n  memory?: string;\n}\n\nexport function useServiceStatus(pollInterval = 5000) {\n  const { systemdManager } = useServices();\n  const [status, setStatus] = useState<ServiceStatusData | null>(null);\n  const [loading, setLoading] = useState(true);\n\n  const refresh = useCallback(async () => {\n    try {\n      const s = await systemdManager.getStatus();\n      setStatus({\n        active: s.active,\n        activeState: s.activeState,\n        subState: s.subState,\n        loaded: s.loaded,\n        healthy: s.healthy,\n        pid: s.pid ?? undefined,\n        uptime: s.uptime,\n        memory: s.memory,\n      });\n    } catch {\n      setStatus(null);\n    } finally {\n      setLoading(false);\n    }\n  }, [systemdManager]);\n\n  useEffect(() => {\n    refresh();\n    const timer = setInterval(refresh, pollInterval);\n    return () => clearInterval(timer);\n  }, [refresh, pollInterval]);\n\n  return { status, loading, refresh };\n}\n", "import React from 'react';\nimport { Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\nimport { resolveColor } from './design-system/theme.js';\n\ntype BadgeStatus =\n  | 'running'\n  | 'stopped'\n  | 'error'\n  | 'warning'\n  | 'loading'\n  | 'disabled'\n  | 'ok'\n  | 'exceeded';\n\nconst STATUS_CONFIG: Record<BadgeStatus, { icon: string; themeKey: string; label: string }> = {\n  running: { icon: '\\u25cf', themeKey: 'serviceRunning', label: 'Running' },\n  stopped: { icon: '\\u25cf', themeKey: 'serviceStopped', label: 'Stopped' },\n  error: { icon: '\\u25cf', themeKey: 'error', label: 'Error' },\n  warning: { icon: '\\u25cf', themeKey: 'warning', label: 'Warning' },\n  loading: { icon: '\\u25cb', themeKey: 'inactive', label: 'Loading' },\n  disabled: { icon: '\\u25cf', themeKey: 'inactive', label: 'Disabled' },\n  ok: { icon: '\\u25cf', themeKey: 'success', label: 'OK' },\n  exceeded: { icon: '\\u25cf', themeKey: 'quotaExceeded', label: 'Exceeded' },\n};\n\ninterface StatusBadgeProps {\n  status: BadgeStatus;\n  label?: string;\n}\n\nexport function StatusBadge({ status, label }: StatusBadgeProps) {\n  const { theme } = useTheme();\n  const config = STATUS_CONFIG[status];\n  const color = resolveColor(config.themeKey, theme);\n\n  return (\n    <Text>\n      <Text color={color}>{config.icon}</Text>\n      <Text> </Text>\n      <Text color={color}>{label ?? config.label}</Text>\n    </Text>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\ninterface KeyValueProps {\n  label: string;\n  value: React.ReactNode;\n  labelWidth?: number;\n}\n\nexport function KeyValue({ label, value, labelWidth }: KeyValueProps) {\n  const { theme } = useTheme();\n\n  return (\n    <Box>\n      <Box width={labelWidth}>\n        <Text color={theme.inactive}>{label}:</Text>\n      </Box>\n      <Text> </Text>\n      {typeof value === 'string' ? <Text color={theme.text}>{value}</Text> : value}\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { useUsers } from '../hooks/useUsers.js';\nimport { Table, type Column } from '../components/Table.js';\nimport { StatusBadge } from '../components/StatusBadge.js';\nimport { Spinner } from '../components/Spinner.js';\n\nexport function UserManagement() {\n  const { theme } = useTheme();\n  const { navigate } = useNavigation();\n  const { t } = useI18n();\n  const { users, loading } = useUsers();\n\n  useInput((input) => {\n    if (input === 'a') navigate({ screen: 'user-add' });\n    else if (input === 'd') navigate({ screen: 'user-delete' });\n    else if (input === 's') navigate({ screen: 'user-share' });\n  });\n\n  const columns: Column<Record<string, unknown>>[] = [\n    { key: 'email', header: t.ui.email, width: 20 },\n    {\n      key: 'id',\n      header: t.ui.uuid,\n      width: 14,\n      render: (row) => <Text dimColor>{String(row.id ?? '').slice(0, 8)}...</Text>,\n    },\n    {\n      key: 'expiry',\n      header: t.ui.expiry,\n      width: 12,\n      render: (row) => {\n        const expiry = row.expiryDate as string | undefined;\n        if (!expiry) return <Text dimColor>-</Text>;\n        const days = Math.ceil((new Date(expiry).getTime() - Date.now()) / 86400000);\n        if (days <= 0)\n          return (\n            <Text color={theme.error} bold>\n              {t.ui.expired}\n            </Text>\n          );\n        if (days <= 3)\n          return (\n            <Text color={theme.warning}>\n              {days}\n              {t.ui.daysLeft}\n            </Text>\n          );\n        return (\n          <Text>\n            {days}\n            {t.ui.daysLeft}\n          </Text>\n        );\n      },\n    },\n    {\n      key: 'status',\n      header: t.status.serviceStatus.split(' ')[0] ?? 'Status',\n      width: 10,\n      render: (row) => {\n        const s = (row.status as string) ?? 'active';\n        return (\n          <StatusBadge\n            status={s === 'exceeded' ? 'exceeded' : s === 'disabled' ? 'disabled' : 'ok'}\n          />\n        );\n      },\n    },\n  ];\n\n  const tableData = users.map((u) => ({\n    email: u.email ?? u.id?.slice(0, 8) ?? '?',\n    id: u.id ?? '',\n    status: u.status ?? 'active',\n    expiryDate: u.expiryDate,\n  }));\n\n  if (loading) {\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n  }\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Table\n        columns={columns}\n        data={tableData}\n        onSelect={(row) => navigate({ screen: 'user-share', userId: row.id as string })}\n        emptyMessage={t.ui.noUsers}\n      />\n\n      <Text dimColor>\n        {users.length} {t.ui.users} <Text bold>a</Text> {t.ui.add} <Text bold>d</Text>{' '}\n        {t.ui.delete_} <Text bold>s</Text> {t.ui.share} <Text bold>enter</Text> {t.ui.details}\n      </Text>\n    </Box>\n  );\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { type User } from '../types/user.js';\n\nexport function useUsers() {\n  const { userManager } = useServices();\n  const [users, setUsers] = useState<User[]>([]);\n  const [loading, setLoading] = useState(true);\n\n  const refresh = useCallback(async () => {\n    try {\n      setLoading(true);\n      const list = await userManager.listUsers();\n      setUsers(list);\n    } catch {\n      setUsers([]);\n    } finally {\n      setLoading(false);\n    }\n  }, [userManager]);\n\n  useEffect(() => {\n    refresh();\n  }, [refresh]);\n\n  return { users, loading, refresh };\n}\n", "import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\nexport interface Column<T> {\n  key: string;\n  header: string;\n  width?: number;\n  align?: 'left' | 'right' | 'center';\n  render?: (row: T) => React.ReactNode;\n}\n\ninterface TableProps<T> {\n  columns: Column<T>[];\n  data: T[];\n  maxRows?: number;\n  onSelect?: (row: T, index: number) => void;\n  emptyMessage?: string;\n  isFocused?: boolean;\n}\n\nfunction padStr(str: string, width: number, align: 'left' | 'right' | 'center' = 'left'): string {\n  const len = str.length;\n  if (len >= width) return str.slice(0, width);\n  const diff = width - len;\n  if (align === 'right') return ' '.repeat(diff) + str;\n  if (align === 'center') {\n    const left = Math.floor(diff / 2);\n    return ' '.repeat(left) + str + ' '.repeat(diff - left);\n  }\n  return str + ' '.repeat(diff);\n}\n\nexport function Table<T extends Record<string, unknown>>({\n  columns,\n  data,\n  maxRows = 15,\n  onSelect,\n  emptyMessage = 'No data',\n  isFocused = true,\n}: TableProps<T>) {\n  const { theme } = useTheme();\n  const [selectedIdx, setSelectedIdx] = useState(0);\n  const [scrollOffset, setScrollOffset] = useState(0);\n\n  const termWidth = process.stdout.columns || 80;\n  const defaultColWidth = Math.max(\n    8,\n    Math.floor((termWidth - columns.length * 3) / columns.length)\n  );\n\n  useInput(\n    (input, key) => {\n      if (key.upArrow || input === 'k') {\n        setSelectedIdx((prev) => {\n          const next = Math.max(0, prev - 1);\n          if (next < scrollOffset) setScrollOffset(next);\n          return next;\n        });\n      } else if (key.downArrow || input === 'j') {\n        setSelectedIdx((prev) => {\n          const next = Math.min(data.length - 1, prev + 1);\n          if (next >= scrollOffset + maxRows) setScrollOffset(next - maxRows + 1);\n          return next;\n        });\n      } else if (key.return && onSelect && data[selectedIdx]) {\n        onSelect(data[selectedIdx]!, selectedIdx);\n      }\n    },\n    { isActive: isFocused && data.length > 0 }\n  );\n\n  if (data.length === 0) {\n    return (\n      <Box>\n        <Text color={theme.inactive}>{emptyMessage}</Text>\n      </Box>\n    );\n  }\n\n  const visibleData = data.slice(scrollOffset, scrollOffset + maxRows);\n\n  return (\n    <Box flexDirection=\"column\">\n      {/* Header */}\n      <Box>\n        <Text color={theme.subtle}>{'  '}</Text>\n        {columns.map((col, ci) => (\n          <Box key={col.key} width={col.width ?? defaultColWidth}>\n            <Text color={theme.inactive} bold>\n              {padStr(col.header, (col.width ?? defaultColWidth) - 2, col.align)}\n            </Text>\n            {ci < columns.length - 1 && <Text color={theme.border}>{' \\u2502 '}</Text>}\n          </Box>\n        ))}\n      </Box>\n\n      {/* Separator */}\n      <Box>\n        <Text color={theme.border}>\n          {'  '}\n          {columns\n            .map((col) => '\\u2500'.repeat((col.width ?? defaultColWidth) - 1))\n            .join('\\u2500\\u253c\\u2500')}\n        </Text>\n      </Box>\n\n      {/* Rows */}\n      {visibleData.map((row, vi) => {\n        const realIdx = vi + scrollOffset;\n        const isSelected = realIdx === selectedIdx;\n\n        return (\n          <Box key={vi}>\n            <Text color={isSelected ? theme.primary : theme.subtle}>\n              {isSelected ? '\\u276f ' : '  '}\n            </Text>\n            {columns.map((col, ci) => {\n              const cellContent = col.render ? col.render(row) : String(row[col.key] ?? '');\n              const w = col.width ?? defaultColWidth;\n\n              return (\n                <Box key={col.key} width={w}>\n                  {typeof cellContent === 'string' ? (\n                    <Text color={isSelected ? theme.text : theme.text}>\n                      {padStr(cellContent, w - 2, col.align)}\n                    </Text>\n                  ) : (\n                    cellContent\n                  )}\n                  {ci < columns.length - 1 && <Text color={theme.border}>{' \\u2502 '}</Text>}\n                </Box>\n              );\n            })}\n          </Box>\n        );\n      })}\n\n      {/* Footer info */}\n      {data.length > maxRows && (\n        <Box marginTop={1}>\n          <Text color={theme.subtle}>\n            Showing {scrollOffset + 1}-{Math.min(scrollOffset + maxRows, data.length)} of{' '}\n            {data.length}\n          </Text>\n        </Box>\n      )}\n    </Box>\n  );\n}\n", "import React, { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { TextInput } from '../components/TextInput.js';\nimport { Spinner } from '../components/Spinner.js';\n\nexport function UserAdd() {\n  const { theme } = useTheme();\n  const { userManager } = useServices();\n  const { goBack } = useNavigation();\n  const { notify } = useNotification();\n  const { t } = useI18n();\n  const [phase, setPhase] = useState<'email' | 'expiry' | 'adding'>('email');\n  const [email, setEmail] = useState('');\n  const [result, setResult] = useState<{ email: string; id: string; expiryDate?: string } | null>(\n    null\n  );\n\n  const handleEmailSubmit = (value: string) => {\n    if (!value.trim()) return;\n    setEmail(value.trim());\n    setPhase('expiry');\n  };\n\n  const handleExpirySubmit = async (daysStr: string) => {\n    setPhase('adding');\n    const days = daysStr.trim() ? parseInt(daysStr.trim(), 10) : undefined;\n    try {\n      const user = await userManager.addUser({\n        email,\n        expiryDays: days && days > 0 ? days : undefined,\n      });\n      setResult({ email: user.email ?? email, id: user.id, expiryDate: user.expiryDate });\n      notify('success', t.ui.userCreated);\n    } catch (e) {\n      notify('error', (e as Error).message);\n      setPhase('email');\n    }\n  };\n\n  if (result) {\n    return (\n      <Box flexDirection=\"column\" paddingX={2} gap={1}>\n        <Text color={theme.success} bold>\n          {'\\u2713'} {t.ui.userCreated}\n        </Text>\n        <Box flexDirection=\"column\">\n          <Text dimColor>\n            {t.ui.email}: <Text color={theme.text}>{result.email}</Text>\n          </Text>\n          <Text dimColor>\n            {t.ui.uuid}: <Text color={theme.text}>{result.id}</Text>\n          </Text>\n          <Text dimColor>\n            {t.ui.expiry}:{' '}\n            <Text color={theme.text}>\n              {result.expiryDate ? new Date(result.expiryDate).toLocaleDateString() : t.ui.never}\n            </Text>\n          </Text>\n        </Box>\n        <Text dimColor italic>\n          {t.ui.pressEscBack}\n        </Text>\n      </Box>\n    );\n  }\n\n  if (phase === 'adding') {\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n  }\n\n  if (phase === 'expiry') {\n    return (\n      <Box flexDirection=\"column\" paddingX={2} gap={1}>\n        <Text dimColor>\n          {t.ui.email}: {email}\n        </Text>\n        <TextInput\n          label={t.ui.expiryDaysPrompt}\n          placeholder=\"30\"\n          onSubmit={handleExpirySubmit}\n          onCancel={() => setPhase('email')}\n          validator={(v) => {\n            if (v.trim() && (isNaN(Number(v)) || Number(v) < 0)) return 'Invalid number';\n            return null;\n          }}\n        />\n      </Box>\n    );\n  }\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2}>\n      <TextInput\n        label={t.ui.emailPrompt}\n        placeholder=\"user@example.com\"\n        onSubmit={handleEmailSubmit}\n        onCancel={goBack}\n        validator={(v) => {\n          if (!v.includes('@')) return 'Invalid email';\n          return null;\n        }}\n      />\n    </Box>\n  );\n}\n", "import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\n\ninterface TextInputProps {\n  label?: string;\n  placeholder?: string;\n  value?: string;\n  onChange?: (value: string) => void;\n  onSubmit: (value: string) => void;\n  onCancel?: () => void;\n  mask?: string;\n  validator?: (value: string) => string | null;\n  isFocused?: boolean;\n}\n\nexport function TextInput({\n  label,\n  placeholder,\n  value: controlledValue,\n  onChange,\n  onSubmit,\n  onCancel,\n  mask,\n  validator,\n  isFocused = true,\n}: TextInputProps) {\n  const { theme } = useTheme();\n  const [internalValue, setInternalValue] = useState('');\n  const [error, setError] = useState<string | null>(null);\n  const [cursorVisible, setCursorVisible] = useState(true);\n\n  const value = controlledValue ?? internalValue;\n  const setValue = (v: string) => {\n    if (onChange) onChange(v);\n    else setInternalValue(v);\n    if (error) setError(null);\n  };\n\n  // Cursor blink\n  React.useEffect(() => {\n    const timer = setInterval(() => setCursorVisible((v) => !v), 530);\n    return () => clearInterval(timer);\n  }, []);\n\n  useInput(\n    (input, key) => {\n      if (key.return) {\n        if (validator) {\n          const err = validator(value);\n          if (err) {\n            setError(err);\n            return;\n          }\n        }\n        onSubmit(value);\n      } else if (key.escape && onCancel) {\n        onCancel();\n      } else if (key.backspace || key.delete) {\n        setValue(value.slice(0, -1));\n      } else if (input && !key.ctrl && !key.meta) {\n        setValue(value + input);\n      }\n    },\n    { isActive: isFocused }\n  );\n\n  const displayValue = mask ? mask.repeat(value.length) : value;\n  const cursor = cursorVisible ? '\\u2588' : ' ';\n\n  return (\n    <Box flexDirection=\"column\">\n      <Box>\n        {label && (\n          <Text color={theme.primary} bold>\n            {label}{' '}\n          </Text>\n        )}\n        <Text color={theme.text}>\n          {displayValue}\n          <Text color={theme.primary}>{cursor}</Text>\n        </Text>\n        {!value && placeholder && <Text color={theme.subtle}>{placeholder}</Text>}\n      </Box>\n      {error && <Text color={theme.error}> {error}</Text>}\n    </Box>\n  );\n}\n", "import React, { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { useUsers } from '../hooks/useUsers.js';\nimport { Select, type SelectItem } from '../components/Select.js';\nimport { Confirm } from '../components/Confirm.js';\nimport { Spinner } from '../components/Spinner.js';\n\ntype Phase = 'select' | 'confirm' | 'deleting';\n\nexport function UserDelete() {\n  const { userManager } = useServices();\n  const { goBack } = useNavigation();\n  const { notify } = useNotification();\n  const { t } = useI18n();\n  const { users, loading } = useUsers();\n  const [phase, setPhase] = useState<Phase>('select');\n  const [selectedUser, setSelectedUser] = useState<{ id: string; email: string } | null>(null);\n\n  const handleUserSelect = (userId: string) => {\n    const user = users.find((u) => u.id === userId);\n    if (user) {\n      setSelectedUser({ id: user.id, email: user.email ?? user.id.slice(0, 8) });\n      setPhase('confirm');\n    }\n  };\n\n  const handleConfirm = async () => {\n    if (!selectedUser) return;\n    setPhase('deleting');\n    try {\n      await userManager.deleteUser(selectedUser.id);\n      notify('success', `${selectedUser.email} deleted`);\n      goBack();\n    } catch (e) {\n      notify('error', (e as Error).message);\n      setPhase('select');\n    }\n  };\n\n  if (loading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n  if (users.length === 0)\n    return (\n      <Box paddingX={2}>\n        <Text dimColor>{t.ui.noUsers}</Text>\n      </Box>\n    );\n  if (phase === 'deleting')\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n\n  if (phase === 'confirm' && selectedUser) {\n    return (\n      <Box paddingX={2}>\n        <Confirm\n          message={`${t.ui.delete_} ${selectedUser.email}?`}\n          onConfirm={handleConfirm}\n          onCancel={() => setPhase('select')}\n          destructive\n        />\n      </Box>\n    );\n  }\n\n  const items: SelectItem<string>[] = users.map((u) => ({\n    label: u.email ?? u.id.slice(0, 8),\n    value: u.id,\n    hint: u.id.slice(0, 8),\n  }));\n\n  return (\n    <Select items={items} onSelect={handleUserSelect} onCancel={goBack} title={t.ui.selectUser} />\n  );\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useUsers } from '../hooks/useUsers.js';\nimport { Select, type SelectItem } from '../components/Select.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { type Route } from '../app/routes.js';\n\nexport function UserShare() {\n  const { theme } = useTheme();\n  const { userManager } = useServices();\n  const { goBack, currentRoute } = useNavigation();\n  const { notify } = useNotification();\n  const { users, loading: usersLoading } = useUsers();\n  const [selectedUserId, setSelectedUserId] = useState<string | null>(\n    (currentRoute as Extract<Route, { screen: 'user-share' }>).userId ?? null\n  );\n  const [shareInfo, setShareInfo] = useState<{ link: string; email: string } | null>(null);\n  const [loadingShare, setLoadingShare] = useState(false);\n\n  useEffect(() => {\n    if (selectedUserId) {\n      setLoadingShare(true);\n      userManager\n        .getShareInfo(selectedUserId)\n        .then((info) => {\n          setShareInfo({\n            link: info.shareLink ?? 'No share link available',\n            email: info.user?.email ?? selectedUserId.slice(0, 8),\n          });\n        })\n        .catch((e) => {\n          notify('error', `Failed: ${(e as Error).message}`);\n          setShareInfo(null);\n        })\n        .finally(() => setLoadingShare(false));\n    }\n  }, [selectedUserId, userManager, notify]);\n\n  if (usersLoading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message=\"Loading users...\" />\n      </Box>\n    );\n\n  if (!selectedUserId) {\n    const items: SelectItem<string>[] = users.map((u) => ({\n      label: u.email ?? u.id.slice(0, 8),\n      value: u.id,\n    }));\n    return (\n      <Select items={items} onSelect={setSelectedUserId} onCancel={goBack} title=\"Select user:\" />\n    );\n  }\n\n  if (loadingShare)\n    return (\n      <Box paddingX={2}>\n        <Spinner message=\"Generating link...\" />\n      </Box>\n    );\n\n  if (!shareInfo) {\n    return (\n      <Box paddingX={2}>\n        <Text color={theme.error}>Failed to generate share link</Text>\n      </Box>\n    );\n  }\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Text dimColor>\n        User: <Text bold>{shareInfo.email}</Text>\n      </Text>\n      <Box borderStyle=\"single\" borderColor={theme.border} paddingX={1}>\n        <Text wrap=\"wrap\">{shareInfo.link}</Text>\n      </Box>\n      <Text dimColor italic>\n        Press esc to go back\n      </Text>\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { useQuotas } from '../hooks/useQuotas.js';\nimport { Table, type Column } from '../components/Table.js';\nimport { ProgressBar } from '../components/ProgressBar.js';\nimport { StatusBadge } from '../components/StatusBadge.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { formatBytes } from '../utils/format.js';\n\nexport function QuotaManagement() {\n  const { theme } = useTheme();\n  const { navigate } = useNavigation();\n  const { t } = useI18n();\n  const { quotas, loading } = useQuotas();\n\n  useInput((input) => {\n    if (input === 's') navigate({ screen: 'quota-set' });\n  });\n\n  const quotaEntries = Object.entries(quotas).map(([email, q]) => ({\n    email,\n    quota: q.quotaBytes > 0 ? formatBytes(q.quotaBytes) : t.ui.unlimited,\n    used: formatBytes(q.usedBytes),\n    ratio: q.quotaBytes > 0 ? q.usedBytes / q.quotaBytes : 0,\n    status: q.status ?? 'active',\n    quotaBytes: q.quotaBytes,\n  }));\n\n  const columns: Column<Record<string, unknown>>[] = [\n    { key: 'email', header: t.ui.email, width: 18 },\n    { key: 'quota', header: t.quota.title.split(' ')[0] ?? 'Quota', width: 12 },\n    { key: 'used', header: t.quota.used, width: 12 },\n    {\n      key: 'progress',\n      header: '',\n      width: 20,\n      render: (row) => {\n        if ((row.quotaBytes as number) <= 0) return <Text dimColor>{'\\u2500'}</Text>;\n        return <ProgressBar ratio={row.ratio as number} width={12} />;\n      },\n    },\n    {\n      key: 'status',\n      header: '',\n      width: 10,\n      render: (row) => {\n        const s = row.status as string;\n        if (s === 'exceeded') return <StatusBadge status=\"exceeded\" />;\n        if (s === 'disabled') return <StatusBadge status=\"disabled\" />;\n        return <StatusBadge status=\"ok\" />;\n      },\n    },\n  ];\n\n  if (loading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Table\n        columns={columns}\n        data={quotaEntries}\n        onSelect={(row) => navigate({ screen: 'quota-details', email: row.email as string })}\n        emptyMessage={t.ui.noQuotas}\n      />\n      <Text dimColor>\n        {quotaEntries.length} {t.ui.entries} <Text bold>s</Text> {t.ui.setQuota}{' '}\n        <Text bold>enter</Text> {t.ui.details}\n      </Text>\n    </Box>\n  );\n}\n", "import { useState, useEffect, useCallback } from 'react';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { type TrafficQuota } from '../types/quota.js';\nimport { DEFAULT_QUOTA } from '../types/quota.js';\n\nexport function useQuotas() {\n  const { quotaManager, trafficManager } = useServices();\n  const [quotas, setQuotas] = useState<Record<string, TrafficQuota>>({});\n  const [loading, setLoading] = useState(true);\n\n  const refresh = useCallback(async () => {\n    try {\n      setLoading(true);\n      const [stored, usages] = await Promise.all([\n        quotaManager.getAllQuotas(),\n        trafficManager.getAllUsage().catch(() => []),\n      ]);\n\n      const merged: Record<string, TrafficQuota> = { ...stored };\n      for (const usage of usages) {\n        const existing = merged[usage.email] ?? { ...DEFAULT_QUOTA };\n        merged[usage.email] = {\n          ...existing,\n          usedBytes: usage.total,\n        };\n      }\n      setQuotas(merged);\n    } catch {\n      setQuotas({});\n    } finally {\n      setLoading(false);\n    }\n  }, [quotaManager, trafficManager]);\n\n  useEffect(() => {\n    refresh();\n  }, [refresh]);\n\n  return { quotas, loading, refresh };\n}\n", "import React from 'react';\nimport { Text } from 'ink';\nimport { useTheme } from './design-system/ThemeProvider.js';\nimport { resolveColor } from './design-system/theme.js';\n\ninterface ProgressBarProps {\n  ratio: number;\n  width?: number;\n  showPercent?: boolean;\n  thresholds?: { warning: number; error: number };\n}\n\nconst BLOCKS = [' ', '\\u2588'];\n\nexport function ProgressBar({\n  ratio,\n  width = 20,\n  showPercent = true,\n  thresholds = { warning: 0.8, error: 1.0 },\n}: ProgressBarProps) {\n  const { theme } = useTheme();\n  const clamped = Math.max(0, Math.min(ratio, 1.5));\n  const filled = Math.round(Math.min(clamped, 1) * width);\n  const empty = width - filled;\n  const pct = Math.round(clamped * 100);\n\n  let fillColorKey: string;\n  if (clamped >= thresholds.error) {\n    fillColorKey = 'quotaExceeded';\n  } else if (clamped >= thresholds.warning) {\n    fillColorKey = 'quotaWarning';\n  } else {\n    fillColorKey = 'quotaNormal';\n  }\n\n  const fillColor = resolveColor(fillColorKey, theme)!;\n  const emptyColor = resolveColor('progressEmpty', theme)!;\n\n  return (\n    <Text>\n      <Text color={fillColor}>{BLOCKS[1].repeat(filled)}</Text>\n      <Text color={emptyColor}>{'\\u2591'.repeat(empty)}</Text>\n      {showPercent && <Text color={fillColor}> {pct}%</Text>}\n    </Text>\n  );\n}\n", "import React, { useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useUsers } from '../hooks/useUsers.js';\nimport { Select, type SelectItem } from '../components/Select.js';\nimport { TextInput } from '../components/TextInput.js';\nimport { Spinner } from '../components/Spinner.js';\n\ntype Phase = 'select-user' | 'enter-quota' | 'setting';\n\nconst PRESETS: SelectItem<string>[] = [\n  { label: '1 GB', value: '1073741824' },\n  { label: '5 GB', value: '5368709120' },\n  { label: '10 GB', value: '10737418240' },\n  { label: '50 GB', value: '53687091200' },\n  { label: '100 GB', value: '107374182400' },\n  { label: 'Unlimited', value: '0' },\n  { label: 'Custom...', value: 'custom' },\n];\n\nfunction parseQuota(input: string): number | null {\n  const m = input.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*(gb|mb|tb)?$/i);\n  if (!m) return null;\n  const n = parseFloat(m[1]!);\n  const u = (m[2] ?? 'gb').toLowerCase();\n  if (u === 'tb') return n * 1099511627776;\n  if (u === 'gb') return n * 1073741824;\n  if (u === 'mb') return n * 1048576;\n  return n;\n}\n\nexport function QuotaSet() {\n  const { quotaManager } = useServices();\n  const { goBack } = useNavigation();\n  const { notify } = useNotification();\n  const { users, loading: usersLoading } = useUsers();\n  const [phase, setPhase] = useState<Phase>('select-user');\n  const [selectedEmail, setSelectedEmail] = useState('');\n  const [customMode, setCustomMode] = useState(false);\n\n  const applyQuota = async (bytes: number) => {\n    setPhase('setting');\n    try {\n      await quotaManager.setQuota({\n        email: selectedEmail,\n        quotaBytes: bytes,\n        quotaType: bytes > 0 ? 'limited' : 'unlimited',\n      });\n      notify('success', `Quota set for ${selectedEmail}`);\n      goBack();\n    } catch (e) {\n      notify('error', `Failed: ${(e as Error).message}`);\n      setPhase('enter-quota');\n    }\n  };\n\n  if (usersLoading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message=\"Loading...\" />\n      </Box>\n    );\n  if (phase === 'setting')\n    return (\n      <Box paddingX={2}>\n        <Spinner message=\"Setting quota...\" />\n      </Box>\n    );\n\n  if (phase === 'select-user') {\n    const items: SelectItem<string>[] = users.map((u) => ({\n      label: u.email ?? u.id.slice(0, 8),\n      value: u.email ?? u.id,\n    }));\n    return (\n      <Select\n        items={items}\n        onSelect={(e) => {\n          setSelectedEmail(e);\n          setPhase('enter-quota');\n        }}\n        onCancel={goBack}\n        title=\"Select user:\"\n      />\n    );\n  }\n\n  if (customMode) {\n    return (\n      <Box flexDirection=\"column\" paddingX={2} gap={1}>\n        <Text dimColor>\n          User: <Text bold>{selectedEmail}</Text>\n        </Text>\n        <TextInput\n          label=\"Quota (e.g. 10GB, 500MB):\"\n          onSubmit={(val) => {\n            const bytes = parseQuota(val);\n            if (bytes !== null) applyQuota(bytes);\n          }}\n          onCancel={() => setCustomMode(false)}\n          validator={(v) => (parseQuota(v) === null ? 'e.g. 10GB, 500MB, 1TB' : null)}\n        />\n      </Box>\n    );\n  }\n\n  return (\n    <Box flexDirection=\"column\" gap={1}>\n      <Box paddingX={2}>\n        <Text dimColor>\n          User: <Text bold>{selectedEmail}</Text>\n        </Text>\n      </Box>\n      <Select\n        items={PRESETS}\n        onSelect={(v) => (v === 'custom' ? setCustomMode(true) : applyQuota(parseInt(v, 10)))}\n        onCancel={goBack}\n        title=\"Select quota:\"\n      />\n    </Box>\n  );\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { KeyValue } from '../components/KeyValue.js';\nimport { ProgressBar } from '../components/ProgressBar.js';\nimport { StatusBadge } from '../components/StatusBadge.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { Confirm } from '../components/Confirm.js';\nimport { formatBytes } from '../utils/format.js';\nimport { type Route } from '../app/routes.js';\nimport { type TrafficQuota } from '../types/quota.js';\n\nexport function QuotaDetails() {\n  const { theme } = useTheme();\n  const { quotaManager } = useServices();\n  const { currentRoute } = useNavigation();\n  const { notify } = useNotification();\n  const { t } = useI18n();\n  const email = (currentRoute as Extract<Route, { screen: 'quota-details' }>).email ?? '';\n  const [quota, setQuota] = useState<TrafficQuota | null>(null);\n  const [loading, setLoading] = useState(true);\n  const [confirmAction, setConfirmAction] = useState<'reset' | 'reenable' | null>(null);\n\n  const fetchQuota = async () => {\n    try {\n      setQuota(await quotaManager.getQuota(email));\n    } catch {\n      setQuota(null);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    fetchQuota();\n  }, [email]);\n\n  useInput((input) => {\n    if (input === 'r') setConfirmAction('reset');\n    else if (input === 'e') setConfirmAction('reenable');\n  });\n\n  const handleReset = async () => {\n    try {\n      await quotaManager.resetUsage(email);\n      notify('success', t.messages.quotaReset);\n      fetchQuota();\n    } catch (e) {\n      notify('error', (e as Error).message);\n    }\n    setConfirmAction(null);\n  };\n\n  const handleReenable = async () => {\n    try {\n      await quotaManager.setStatus(email, 'active');\n      notify('success', t.messages.userReenabled);\n      fetchQuota();\n    } catch (e) {\n      notify('error', (e as Error).message);\n    }\n    setConfirmAction(null);\n  };\n\n  if (loading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n\n  if (confirmAction === 'reset') {\n    return (\n      <Box paddingX={2}>\n        <Confirm\n          message={t.quota.confirmReset}\n          onConfirm={handleReset}\n          onCancel={() => setConfirmAction(null)}\n        />\n      </Box>\n    );\n  }\n  if (confirmAction === 'reenable') {\n    return (\n      <Box paddingX={2}>\n        <Confirm\n          message={t.quota.confirmReenable}\n          onConfirm={handleReenable}\n          onCancel={() => setConfirmAction(null)}\n        />\n      </Box>\n    );\n  }\n\n  if (!quota)\n    return (\n      <Box paddingX={2}>\n        <Text dimColor>\n          {t.quota.noQuota} ({email})\n        </Text>\n      </Box>\n    );\n\n  const ratio = quota.quotaBytes > 0 ? quota.usedBytes / quota.quotaBytes : 0;\n  const remaining = quota.quotaBytes > 0 ? Math.max(0, quota.quotaBytes - quota.usedBytes) : -1;\n  const labelW = 12;\n  const badgeStatus =\n    quota.status === 'exceeded'\n      ? ('exceeded' as const)\n      : quota.status === 'disabled'\n        ? ('disabled' as const)\n        : quota.quotaBytes > 0 && ratio >= 0.8\n          ? ('warning' as const)\n          : ('ok' as const);\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Text bold>{email}</Text>\n      <Box flexDirection=\"column\">\n        <KeyValue label=\"Status\" labelWidth={labelW} value={<StatusBadge status={badgeStatus} />} />\n        <KeyValue\n          label={t.quota.title.split(' ')[0] ?? 'Quota'}\n          labelWidth={labelW}\n          value={quota.quotaBytes > 0 ? formatBytes(quota.quotaBytes) : t.ui.unlimited}\n        />\n        <KeyValue label={t.quota.used} labelWidth={labelW} value={formatBytes(quota.usedBytes)} />\n        {remaining >= 0 && (\n          <KeyValue label={t.quota.remaining} labelWidth={labelW} value={formatBytes(remaining)} />\n        )}\n      </Box>\n      {quota.quotaBytes > 0 && <ProgressBar ratio={ratio} width={30} />}\n      <Text dimColor>\n        <Text bold>r</Text> {t.ui.resetUsage} <Text bold>e</Text> {t.ui.reenable}{' '}\n        <Text bold>esc</Text> {t.ui.back}\n      </Text>\n    </Box>\n  );\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { Select, type SelectItem } from '../components/Select.js';\nimport { Confirm } from '../components/Confirm.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { KeyValue } from '../components/KeyValue.js';\n\ntype Phase = 'menu' | 'confirm-restore' | 'operating';\n\nexport function ConfigManagement() {\n  const { theme } = useTheme();\n  const { configManager } = useServices();\n  const { goBack } = useNavigation();\n  const { notify } = useNotification();\n  const [phase, setPhase] = useState<Phase>('menu');\n  const [configSummary, setConfigSummary] = useState<Record<string, string> | null>(null);\n  const [backups, setBackups] = useState<string[]>([]);\n  const [loading, setLoading] = useState(true);\n  const [restorePath, setRestorePath] = useState<string | null>(null);\n\n  useEffect(() => {\n    (async () => {\n      try {\n        const config = await configManager.readConfig();\n        const inbound = config.inbounds?.[0];\n        setConfigSummary({\n          Protocol: inbound?.protocol ?? 'unknown',\n          Port: String(inbound?.port ?? '-'),\n          Network: (inbound?.streamSettings?.network as string) ?? '-',\n          Security: (inbound?.streamSettings?.security as string) ?? '-',\n        });\n        setBackups(await configManager.listBackups());\n      } catch {\n        /* config may not exist */\n      }\n      setLoading(false);\n    })();\n  }, [configManager]);\n\n  const handleBackup = async () => {\n    setPhase('operating');\n    try {\n      const path = await configManager.backupConfig();\n      notify('success', `Backed up to ${path}`);\n      setBackups(await configManager.listBackups());\n    } catch (e) {\n      notify('error', `Backup failed: ${(e as Error).message}`);\n    }\n    setPhase('menu');\n  };\n\n  const handleRestore = async () => {\n    if (!restorePath) return;\n    setPhase('operating');\n    try {\n      await configManager.restoreConfig(restorePath);\n      notify('success', 'Config restored');\n    } catch (e) {\n      notify('error', `Restore failed: ${(e as Error).message}`);\n    }\n    setRestorePath(null);\n    setPhase('menu');\n  };\n\n  if (loading || phase === 'operating') {\n    return (\n      <Box paddingX={2}>\n        <Spinner message={phase === 'operating' ? 'Processing...' : 'Loading config...'} />\n      </Box>\n    );\n  }\n\n  if (phase === 'confirm-restore' && restorePath) {\n    return (\n      <Box paddingX={2}>\n        <Confirm\n          message=\"Restore this backup? Current config will be overwritten.\"\n          onConfirm={handleRestore}\n          onCancel={() => {\n            setRestorePath(null);\n            setPhase('menu');\n          }}\n          destructive\n        />\n      </Box>\n    );\n  }\n\n  const menuItems: SelectItem<string>[] = [\n    { label: 'Create Backup', value: 'backup', hint: `${backups.length} existing` },\n    ...(backups.length > 0\n      ? backups.slice(0, 5).map((b) => ({\n          label: `Restore: ${b.split('/').pop() ?? b}`,\n          value: `restore:${b}`,\n        }))\n      : []),\n  ];\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      {/* Current config summary */}\n      {configSummary && (\n        <Box flexDirection=\"column\">\n          {Object.entries(configSummary).map(([k, v]) => (\n            <KeyValue key={k} label={k} value={v} labelWidth={10} />\n          ))}\n        </Box>\n      )}\n\n      <Select\n        items={menuItems}\n        onSelect={(v) => {\n          if (v === 'backup') handleBackup();\n          else if (v.startsWith('restore:')) {\n            setRestorePath(v.slice(8));\n            setPhase('confirm-restore');\n          }\n        }}\n        onCancel={goBack}\n      />\n    </Box>\n  );\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { Spinner } from '../components/Spinner.js';\n\ninterface LogLine {\n  timestamp?: string;\n  level?: string;\n  message: string;\n}\n\nexport function LogViewer() {\n  const { theme } = useTheme();\n  const { logManager } = useServices();\n  const { t } = useI18n();\n  const [logType, setLogType] = useState<'access' | 'error'>('access');\n  const [logs, setLogs] = useState<LogLine[]>([]);\n  const [loading, setLoading] = useState(true);\n  const [follow, setFollow] = useState(false);\n  const [scrollOffset, setScrollOffset] = useState(0);\n\n  const maxVisible = Math.max(5, (process.stdout.rows || 24) - 10);\n\n  const fetchLogs = async () => {\n    try {\n      setLoading(true);\n      const entries =\n        logType === 'access'\n          ? await logManager.readAccessLog(200)\n          : await logManager.readErrorLog(200);\n      setLogs(\n        entries.map((e) => ({\n          timestamp:\n            e.timestamp instanceof Date\n              ? e.timestamp.toISOString().slice(11, 19)\n              : String(e.timestamp ?? ''),\n          level: e.level,\n          message: e.message,\n        }))\n      );\n      if (follow) setScrollOffset(Math.max(0, entries.length - maxVisible));\n    } catch {\n      setLogs([]);\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  useEffect(() => {\n    fetchLogs();\n  }, [logType]);\n  useEffect(() => {\n    if (!follow) return;\n    const timer = setInterval(fetchLogs, 3000);\n    return () => clearInterval(timer);\n  }, [follow, logType]);\n\n  useInput((input, key) => {\n    if (input === 'f') setFollow((p) => !p);\n    else if (input === 't') setLogType((p) => (p === 'access' ? 'error' : 'access'));\n    else if (key.upArrow || input === 'k') {\n      setScrollOffset((p) => Math.max(0, p - 1));\n      setFollow(false);\n    } else if (key.downArrow || input === 'j')\n      setScrollOffset((p) => Math.min(Math.max(0, logs.length - maxVisible), p + 1));\n    else if (key.pageUp) {\n      setScrollOffset((p) => Math.max(0, p - maxVisible));\n      setFollow(false);\n    } else if (key.pageDown)\n      setScrollOffset((p) => Math.min(Math.max(0, logs.length - maxVisible), p + maxVisible));\n  });\n\n  const visibleLogs = logs.slice(scrollOffset, scrollOffset + maxVisible);\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      <Box gap={2}>\n        <Text\n          bold={logType === 'access'}\n          dimColor={logType !== 'access'}\n          underline={logType === 'access'}\n        >\n          {t.logs.accessLog}\n        </Text>\n        <Text\n          bold={logType === 'error'}\n          dimColor={logType !== 'error'}\n          underline={logType === 'error'}\n        >\n          {t.logs.errorLog}\n        </Text>\n        {follow && (\n          <Text color={theme.success} bold>\n            FOLLOW\n          </Text>\n        )}\n      </Box>\n\n      {loading ? (\n        <Spinner message={t.ui.processing} />\n      ) : logs.length === 0 ? (\n        <Text dimColor>{t.ui.noEntries}</Text>\n      ) : (\n        <Box flexDirection=\"column\">\n          {visibleLogs.map((line, i) => (\n            <Box key={i + scrollOffset}>\n              {line.timestamp && <Text dimColor>{line.timestamp} </Text>}\n              {line.level && (\n                <Text\n                  color={\n                    line.level.toLowerCase().includes('err')\n                      ? theme.error\n                      : line.level.toLowerCase().includes('warn')\n                        ? theme.warning\n                        : undefined\n                  }\n                  bold={line.level.toLowerCase().includes('err')}\n                >\n                  {line.level.toUpperCase().padEnd(5)}{' '}\n                </Text>\n              )}\n              <Text wrap=\"truncate-end\">{line.message}</Text>\n            </Box>\n          ))}\n        </Box>\n      )}\n\n      <Text dimColor>\n        {logs.length} {t.ui.entries} <Text bold>t</Text> {t.ui.switchLog} <Text bold>f</Text>{' '}\n        {t.ui.follow}\n        {follow ? ' (on)' : ''} <Text bold>{'\\u2191\\u2193'}</Text> {t.ui.scroll}\n      </Text>\n    </Box>\n  );\n}\n", "import React from 'react';\nimport { Box, Text } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { useOnlineUsers } from '../hooks/useOnlineUsers.js';\nimport { Spinner } from '../components/Spinner.js';\nimport { formatBytes } from '../utils/format.js';\n\nexport function OnlineUsers() {\n  const { theme } = useTheme();\n  const { t } = useI18n();\n  const { summary, loading } = useOnlineUsers(5000);\n\n  if (loading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n\n  if (!summary) {\n    return (\n      <Box paddingX={2}>\n        <Text dimColor>{t.ui.noConnections}</Text>\n      </Box>\n    );\n  }\n\n  const activeList = summary.activeUsers.filter((u) => u.activeNow);\n  const allUsers = summary.activeUsers;\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      {/* Summary line */}\n      <Box gap={2}>\n        <Text>\n          <Text color={theme.success} bold>\n            {summary.activeCount}\n          </Text>\n          <Text dimColor> active</Text>\n        </Text>\n        <Text dimColor>|</Text>\n        <Text>\n          <Text bold>{allUsers.length}</Text>\n          <Text dimColor> {t.ui.users} total</Text>\n        </Text>\n        {summary.uniqueIps > 0 && (\n          <>\n            <Text dimColor>|</Text>\n            <Text>\n              <Text bold>{summary.uniqueIps}</Text>\n              <Text dimColor> IPs</Text>\n            </Text>\n          </>\n        )}\n        {!summary.statsAvailable && <Text color={theme.warning}>Stats API unavailable</Text>}\n      </Box>\n\n      {/* User traffic table */}\n      {allUsers.length > 0 ? (\n        <Box flexDirection=\"column\">\n          {/* Header */}\n          <Box>\n            <Box width={24}>\n              <Text dimColor bold>\n                User\n              </Text>\n            </Box>\n            <Box width={14}>\n              <Text dimColor bold>\n                {'\\u2191'} Upload\n              </Text>\n            </Box>\n            <Box width={14}>\n              <Text dimColor bold>\n                {'\\u2193'} Download\n              </Text>\n            </Box>\n            <Box width={10}>\n              <Text dimColor bold>\n                Status\n              </Text>\n            </Box>\n          </Box>\n\n          {/* Rows */}\n          {allUsers.map((user) => (\n            <Box key={user.email}>\n              <Box width={24}>\n                <Text color={user.activeNow ? theme.text : theme.inactive}>{user.email}</Text>\n              </Box>\n              <Box width={14}>\n                <Text dimColor={!user.activeNow}>{formatBytes(user.upload)}</Text>\n              </Box>\n              <Box width={14}>\n                <Text dimColor={!user.activeNow}>{formatBytes(user.download)}</Text>\n              </Box>\n              <Box width={10}>\n                {user.activeNow ? (\n                  <Text color={theme.success} bold>\n                    {'\\u25cf'} active\n                  </Text>\n                ) : (\n                  <Text dimColor>{'\\u25cb'} idle</Text>\n                )}\n              </Box>\n            </Box>\n          ))}\n        </Box>\n      ) : (\n        <Text dimColor>{t.ui.noConnections}</Text>\n      )}\n\n      {/* TCP connections section */}\n      {summary.tcpConnections.length > 0 && (\n        <Box flexDirection=\"column\">\n          <Text dimColor>TCP connections:</Text>\n          {summary.tcpConnections.slice(0, 10).map((c, i) => (\n            <Text key={i} dimColor>\n              {' '}\n              {c.remoteIp}:{c.remotePort} {'\\u2192'} :{c.localPort}\n            </Text>\n          ))}\n          {summary.tcpConnections.length > 10 && (\n            <Text dimColor> ...and {summary.tcpConnections.length - 10} more</Text>\n          )}\n        </Box>\n      )}\n\n      <Text dimColor italic>\n        {t.ui.autoRefresh}: 5s\n      </Text>\n    </Box>\n  );\n}\n", "import { useState, useEffect, useCallback, useRef } from 'react';\nimport { OnlineManager, type OnlineUserSummary } from '../services/online-manager';\n\nexport function useOnlineUsers(pollInterval = 5000) {\n  const [summary, setSummary] = useState<OnlineUserSummary | null>(null);\n  const [loading, setLoading] = useState(true);\n  const managerRef = useRef(new OnlineManager());\n\n  const refresh = useCallback(async () => {\n    try {\n      const data = await managerRef.current.getOnlineConnections();\n      setSummary(data);\n    } catch {\n      // Keep existing data\n    } finally {\n      setLoading(false);\n    }\n  }, []);\n\n  useEffect(() => {\n    refresh();\n    const timer = setInterval(refresh, pollInterval);\n    return () => clearInterval(timer);\n  }, [refresh, pollInterval]);\n\n  return { summary, loading, refresh };\n}\n", "/**\n * Online User Manager\n *\n * Detects currently active users using two methods:\n * 1. Xray Stats API: compare traffic snapshots to detect active users\n * 2. TCP connections: parse `ss` output for connections to Xray ports\n *\n * @module services/online-manager\n */\n\nimport { execSync } from 'child_process';\nimport { ConfigManager } from './config-manager';\n\nexport interface OnlineUser {\n  email: string;\n  upload: number;\n  download: number;\n  activeNow: boolean;\n}\n\nexport interface TcpConnection {\n  remoteIp: string;\n  remotePort: number;\n  localPort: number;\n}\n\nexport interface OnlineUserSummary {\n  /** Users with traffic activity in the last interval */\n  activeUsers: OnlineUser[];\n  /** Number of active users */\n  activeCount: number;\n  /** TCP connections to Xray ports */\n  tcpConnections: TcpConnection[];\n  /** Unique remote IPs */\n  uniqueIps: number;\n  /** Xray listening ports */\n  listeningPorts: number[];\n  /** Xray stats API available */\n  statsAvailable: boolean;\n}\n\ninterface TrafficSnapshot {\n  email: string;\n  uplink: number;\n  downlink: number;\n}\n\n/**\n * Parse ss address like \"172.31.44.89:443\" or \"[::ffff:1.2.3.4]:443\"\n */\nfunction parseAddr(addr: string): { ip: string; port: number } | null {\n  const v6 = addr.match(/^\\[(.+)\\]:(\\d+)$/);\n  if (v6) {\n    let ip = v6[1]!;\n    const mapped = ip.match(/^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/i);\n    if (mapped) ip = mapped[1]!;\n    return { ip, port: parseInt(v6[2]!, 10) };\n  }\n  const v4 = addr.match(/^(.+):(\\d+)$/);\n  if (v4) return { ip: v4[1]!, port: parseInt(v4[2]!, 10) };\n  return null;\n}\n\nexport class OnlineManager {\n  private configManager: ConfigManager;\n  private previousSnapshot: Map<string, { up: number; down: number }> = new Map();\n  private apiPort: number = 10085;\n\n  constructor(configPath?: string) {\n    this.configManager = new ConfigManager(configPath);\n  }\n\n  /**\n   * Get Xray listening ports and API port from config\n   */\n  private async loadPorts(): Promise<{ listen: number[]; api: number }> {\n    try {\n      const config = await this.configManager.readConfig();\n      const listen: number[] = [];\n      let api = 10085;\n      for (const inbound of config.inbounds ?? []) {\n        if (inbound.tag === 'api' && inbound.port) {\n          api = inbound.port;\n        } else if (inbound.port) {\n          listen.push(inbound.port);\n        }\n      }\n      this.apiPort = api;\n      return { listen, api };\n    } catch {\n      return { listen: [], api: 10085 };\n    }\n  }\n\n  /**\n   * Query Xray Stats API via the xray binary\n   */\n  private queryStats(): TrafficSnapshot[] {\n    try {\n      const output = execSync(\n        `/usr/local/bin/xray api statsquery --server=127.0.0.1:${this.apiPort} 2>/dev/null`,\n        { encoding: 'utf-8', timeout: 5000 }\n      );\n      const data = JSON.parse(output);\n      const userMap = new Map<string, { uplink: number; downlink: number }>();\n\n      for (const stat of data.stat ?? []) {\n        const match = (stat.name as string).match(/^user>>>(.+?)>>>traffic>>>(uplink|downlink)$/);\n        if (!match) continue;\n        const email = match[1]!;\n        const direction = match[2]!;\n        if (!userMap.has(email)) userMap.set(email, { uplink: 0, downlink: 0 });\n        const entry = userMap.get(email)!;\n        if (direction === 'uplink') entry.uplink = Number(stat.value ?? 0);\n        else entry.downlink = Number(stat.value ?? 0);\n      }\n\n      return Array.from(userMap.entries()).map(([email, v]) => ({\n        email,\n        uplink: v.uplink,\n        downlink: v.downlink,\n      }));\n    } catch {\n      return [];\n    }\n  }\n\n  /**\n   * Get TCP connections to Xray ports via ss\n   */\n  private getTcpConnections(ports: number[]): TcpConnection[] {\n    if (ports.length === 0) return [];\n    const connections: TcpConnection[] = [];\n\n    try {\n      const output = execSync('ss -tnH state established 2>/dev/null || true', {\n        encoding: 'utf-8',\n        timeout: 5000,\n      });\n\n      for (const line of output.split('\\n')) {\n        const parts = line.trim().split(/\\s+/);\n        if (parts.length < 4) continue;\n\n        const local = parseAddr(parts[2]!);\n        const peer = parseAddr(parts[3]!);\n        if (!local || !peer) continue;\n        if (!ports.includes(local.port)) continue;\n        if (peer.ip === '127.0.0.1' || peer.ip === '::1' || peer.ip === '0.0.0.0') continue;\n\n        connections.push({\n          remoteIp: peer.ip,\n          remotePort: peer.port,\n          localPort: local.port,\n        });\n      }\n    } catch {\n      // ss failed\n    }\n\n    return connections;\n  }\n\n  /**\n   * Detect online users by comparing traffic snapshots\n   */\n  async getOnlineConnections(): Promise<OnlineUserSummary> {\n    const { listen } = await this.loadPorts();\n\n    // Method 1: Stats API \u2014 compare with previous snapshot\n    const currentStats = this.queryStats();\n    const statsAvailable = currentStats.length > 0;\n    const activeUsers: OnlineUser[] = [];\n\n    for (const user of currentStats) {\n      const prev = this.previousSnapshot.get(user.email);\n      const activeNow = prev ? user.uplink > prev.up || user.downlink > prev.down : false; // First run, can't determine\n\n      activeUsers.push({\n        email: user.email,\n        upload: user.uplink,\n        download: user.downlink,\n        activeNow,\n      });\n    }\n\n    // Save current snapshot for next comparison\n    this.previousSnapshot.clear();\n    for (const user of currentStats) {\n      this.previousSnapshot.set(user.email, { up: user.uplink, down: user.downlink });\n    }\n\n    const activeCount = activeUsers.filter((u) => u.activeNow).length;\n\n    // Method 2: TCP connections\n    const tcpConnections = this.getTcpConnections(listen);\n    const uniqueIps = new Set(tcpConnections.map((c) => c.remoteIp)).size;\n\n    return {\n      activeUsers,\n      activeCount,\n      tcpConnections,\n      uniqueIps,\n      listeningPorts: listen,\n      statsAvailable,\n    };\n  }\n\n  /**\n   * Get connection count per IP\n   */\n  async getConnectionCounts(): Promise<Map<string, number>> {\n    const summary = await this.getOnlineConnections();\n    const counts = new Map<string, number>();\n    for (const conn of summary.tcpConnections) {\n      counts.set(conn.remoteIp, (counts.get(conn.remoteIp) ?? 0) + 1);\n    }\n    return counts;\n  }\n}\n", "import React, { useState, useEffect } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { useTheme } from '../components/design-system/ThemeProvider.js';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { useNotification } from '../contexts/NotificationContext.js';\nimport { useI18n } from '../contexts/I18nContext.js';\nimport { SubscriptionServer } from '../services/subscription-server.js';\nimport { PublicIpManager } from '../services/public-ip-manager.js';\nimport { StatusBadge } from '../components/StatusBadge.js';\nimport { Spinner } from '../components/Spinner.js';\n\ninterface SubInfo {\n  email: string;\n  token: string;\n  fullUrl: string;\n}\n\nexport function SubscriptionManagement() {\n  const { theme } = useTheme();\n  const { userManager } = useServices();\n  const { notify } = useNotification();\n  const { t } = useI18n();\n  const [subServer] = useState(() => new SubscriptionServer(userManager));\n  const [running, setRunning] = useState(false);\n  const [port, setPort] = useState(2096);\n  const [subs, setSubs] = useState<SubInfo[]>([]);\n  const [loading, setLoading] = useState(true);\n\n  const refresh = async () => {\n    try {\n      const config = await subServer.loadConfig();\n      setPort(config.port);\n      setRunning(subServer.isRunning());\n\n      let serverIp = 'localhost';\n      try {\n        serverIp = await new PublicIpManager().getPublicIp();\n      } catch {\n        /* fallback */\n      }\n\n      const allSubs = await subServer.getAllSubscriptions();\n      setSubs(\n        allSubs.map((s) => ({\n          email: s.email,\n          token: s.token,\n          fullUrl: `http://${serverIp}:${config.port}${s.url}`,\n        }))\n      );\n    } catch {\n      /* ignore */\n    }\n    setLoading(false);\n  };\n\n  useEffect(() => {\n    refresh();\n  }, []);\n\n  useInput((input) => {\n    if (input === 's') {\n      if (running) {\n        subServer.stop().then(() => {\n          setRunning(false);\n          notify('info', 'Server stopped');\n        });\n      } else {\n        subServer\n          .start()\n          .then((p) => {\n            setRunning(true);\n            setPort(p);\n            notify('success', `Server started on :${p}`);\n          })\n          .catch((e) => notify('error', (e as Error).message));\n      }\n    } else if (input === 'r') {\n      refresh();\n    }\n  });\n\n  if (loading)\n    return (\n      <Box paddingX={2}>\n        <Spinner message={t.ui.processing} />\n      </Box>\n    );\n\n  return (\n    <Box flexDirection=\"column\" paddingX={2} gap={1}>\n      {/* Server status */}\n      <Box gap={2}>\n        <Text dimColor>Server:</Text>\n        <StatusBadge status={running ? 'running' : 'stopped'} />\n        <Text dimColor>\n          Port: <Text bold>{port}</Text>\n        </Text>\n      </Box>\n\n      {/* User subscription list \u2014 each user gets full-width URL display */}\n      {subs.length > 0 ? (\n        <Box flexDirection=\"column\">\n          {subs.map((sub) => (\n            <Box key={sub.email} flexDirection=\"column\" marginBottom={1}>\n              <Text bold>{sub.email}</Text>\n              <Text color={theme.primary} wrap=\"wrap\">\n                {' '}\n                {sub.fullUrl}\n              </Text>\n            </Box>\n          ))}\n        </Box>\n      ) : (\n        <Text dimColor>{t.ui.noUsers}</Text>\n      )}\n\n      {/* Hints */}\n      <Text dimColor>\n        <Text bold>s</Text> {running ? t.ui.stop : t.ui.start} <Text bold>r</Text> {t.ui.refresh}\n      </Text>\n    </Box>\n  );\n}\n", "/**\n * Subscription Server\n *\n * Lightweight HTTP server that serves user subscription links.\n * Each user gets a unique token-based URL that returns their\n * current config in V2RayN-compatible format (base64 encoded VLESS links).\n *\n * @module services/subscription-server\n */\n\nimport http from 'http';\nimport { randomBytes } from 'crypto';\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { UserManager } from './user-manager';\nimport { UserMetadataManager } from './user-metadata-manager';\n\nconst SUB_CONFIG_PATH = join(homedir(), '.xray-manager', 'subscriptions.json');\n\ninterface SubConfig {\n  port: number;\n  enabled: boolean;\n  tokens: Record<string, string>; // token -> userId\n}\n\nconst DEFAULT_CONFIG: SubConfig = {\n  port: 2096,\n  enabled: false,\n  tokens: {},\n};\n\nexport class SubscriptionServer {\n  private server: http.Server | null = null;\n  private userManager: UserManager;\n  private metadataManager: UserMetadataManager;\n  private config: SubConfig = DEFAULT_CONFIG;\n\n  constructor(userManager: UserManager) {\n    this.userManager = userManager;\n    this.metadataManager = new UserMetadataManager();\n  }\n\n  /**\n   * Load subscription config\n   */\n  async loadConfig(): Promise<SubConfig> {\n    try {\n      if (existsSync(SUB_CONFIG_PATH)) {\n        const content = await readFile(SUB_CONFIG_PATH, 'utf-8');\n        this.config = { ...DEFAULT_CONFIG, ...JSON.parse(content) };\n      }\n    } catch {\n      this.config = { ...DEFAULT_CONFIG };\n    }\n    return this.config;\n  }\n\n  /**\n   * Save subscription config\n   */\n  async saveConfig(): Promise<void> {\n    const dir = dirname(SUB_CONFIG_PATH);\n    if (!existsSync(dir)) {\n      await mkdir(dir, { recursive: true });\n    }\n    await writeFile(SUB_CONFIG_PATH, JSON.stringify(this.config, null, 2), 'utf-8');\n  }\n\n  /**\n   * Generate a subscription token for a user\n   */\n  async generateToken(userId: string): Promise<string> {\n    const token = randomBytes(16).toString('hex');\n    await this.loadConfig();\n\n    // Remove any existing token for this user\n    for (const [existingToken, uid] of Object.entries(this.config.tokens)) {\n      if (uid === userId) {\n        delete this.config.tokens[existingToken];\n      }\n    }\n\n    this.config.tokens[token] = userId;\n    await this.saveConfig();\n\n    // Also store in user metadata\n    await this.metadataManager.setMetadata(userId, { subscriptionToken: token });\n\n    return token;\n  }\n\n  /**\n   * Get token for a user (generate if needed)\n   */\n  async getOrCreateToken(userId: string): Promise<string> {\n    await this.loadConfig();\n\n    // Check existing\n    for (const [token, uid] of Object.entries(this.config.tokens)) {\n      if (uid === userId) return token;\n    }\n\n    return this.generateToken(userId);\n  }\n\n  /**\n   * Get all user subscription info\n   */\n  async getAllSubscriptions(): Promise<\n    Array<{ userId: string; email: string; token: string; url: string }>\n  > {\n    await this.loadConfig();\n    const users = await this.userManager.listUsers();\n    const result: Array<{ userId: string; email: string; token: string; url: string }> = [];\n\n    for (const user of users) {\n      if (user.status !== 'active') continue;\n      const token = await this.getOrCreateToken(user.id);\n      result.push({\n        userId: user.id,\n        email: user.email,\n        token,\n        url: `/sub/${token}`,\n      });\n    }\n\n    return result;\n  }\n\n  /**\n   * Handle subscription request\n   */\n  private async handleRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {\n    const url = req.url ?? '';\n\n    // CORS headers\n    res.setHeader('Access-Control-Allow-Origin', '*');\n\n    // Health check\n    if (url === '/health') {\n      res.writeHead(200, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({ status: 'ok' }));\n      return;\n    }\n\n    // Subscription endpoint: /sub/{token}\n    const subMatch = url.match(/^\\/sub\\/([a-f0-9]{32})$/);\n    if (!subMatch) {\n      res.writeHead(404, { 'Content-Type': 'text/plain' });\n      res.end('Not Found');\n      return;\n    }\n\n    const token = subMatch[1]!;\n    await this.loadConfig();\n    const userId = this.config.tokens[token];\n\n    if (!userId) {\n      res.writeHead(403, { 'Content-Type': 'text/plain' });\n      res.end('Invalid subscription token');\n      return;\n    }\n\n    try {\n      const shareInfo = await this.userManager.getShareInfo(userId);\n\n      // Build subscription content (base64-encoded links, one per line)\n      const links: string[] = [];\n      if (shareInfo.shareLink) {\n        links.push(shareInfo.shareLink);\n      }\n      if (shareInfo.cdnShareLink) {\n        links.push(shareInfo.cdnShareLink);\n      }\n\n      const content = Buffer.from(links.join('\\n')).toString('base64');\n\n      // User-Agent detection for format (reserved for future Clash/Surge support)\n      const _ua = (req.headers['user-agent'] ?? '').toLowerCase();\n\n      res.writeHead(200, {\n        'Content-Type': 'text/plain; charset=utf-8',\n        'Content-Disposition': `attachment; filename=\"${shareInfo.user.email || 'sub'}\"`,\n        'Profile-Update-Interval': '24',\n        'Subscription-Userinfo': `upload=0; download=0; total=0; expire=0`,\n      });\n      res.end(content);\n    } catch (e) {\n      res.writeHead(500, { 'Content-Type': 'text/plain' });\n      res.end(`Error: ${(e as Error).message}`);\n    }\n  }\n\n  /**\n   * Start the subscription server\n   */\n  async start(): Promise<number> {\n    await this.loadConfig();\n    const port = this.config.port;\n\n    return new Promise((resolve, reject) => {\n      this.server = http.createServer((req, res) => {\n        this.handleRequest(req, res).catch(() => {\n          res.writeHead(500);\n          res.end('Internal Server Error');\n        });\n      });\n\n      this.server.listen(port, '0.0.0.0', () => {\n        this.config.enabled = true;\n        this.saveConfig().catch(() => {});\n        resolve(port);\n      });\n\n      this.server.on('error', (err) => {\n        reject(err);\n      });\n    });\n  }\n\n  /**\n   * Stop the subscription server\n   */\n  async stop(): Promise<void> {\n    return new Promise((resolve) => {\n      if (this.server) {\n        this.server.close(() => {\n          this.server = null;\n          this.config.enabled = false;\n          this.saveConfig().catch(() => {});\n          resolve();\n        });\n      } else {\n        resolve();\n      }\n    });\n  }\n\n  /**\n   * Check if server is running\n   */\n  isRunning(): boolean {\n    return this.server !== null && this.server.listening;\n  }\n\n  /**\n   * Get configured port\n   */\n  getPort(): number {\n    return this.config.port;\n  }\n\n  /**\n   * Set port (requires restart)\n   */\n  async setPort(port: number): Promise<void> {\n    await this.loadConfig();\n    this.config.port = port;\n    await this.saveConfig();\n  }\n}\n", "import React from 'react';\nimport { useNavigation } from '../contexts/NavigationContext.js';\nimport { MainMenu } from '../screens/MainMenu.js';\nimport { ServiceStatus } from '../screens/ServiceStatus.js';\nimport { UserManagement } from '../screens/UserManagement.js';\nimport { UserAdd } from '../screens/UserAdd.js';\nimport { UserDelete } from '../screens/UserDelete.js';\nimport { UserShare } from '../screens/UserShare.js';\nimport { QuotaManagement } from '../screens/QuotaManagement.js';\nimport { QuotaSet } from '../screens/QuotaSet.js';\nimport { QuotaDetails } from '../screens/QuotaDetails.js';\nimport { ConfigManagement } from '../screens/ConfigManagement.js';\nimport { LogViewer } from '../screens/LogViewer.js';\nimport { OnlineUsers } from '../screens/OnlineUsers.js';\nimport { SubscriptionManagement } from '../screens/SubscriptionManagement.js';\n\nexport function Router() {\n  const { currentRoute } = useNavigation();\n\n  switch (currentRoute.screen) {\n    case 'main-menu':\n      return <MainMenu />;\n    case 'service-status':\n      return <ServiceStatus />;\n    case 'user-management':\n      return <UserManagement />;\n    case 'user-add':\n      return <UserAdd />;\n    case 'user-delete':\n      return <UserDelete />;\n    case 'user-share':\n      return <UserShare />;\n    case 'quota-management':\n      return <QuotaManagement />;\n    case 'quota-set':\n      return <QuotaSet />;\n    case 'quota-details':\n      return <QuotaDetails />;\n    case 'config-management':\n      return <ConfigManagement />;\n    case 'log-viewer':\n      return <LogViewer />;\n    case 'online-users':\n      return <OnlineUsers />;\n    case 'subscriptions':\n      return <SubscriptionManagement />;\n    default:\n      return <MainMenu />;\n  }\n}\n", "import { useState, useEffect, useCallback, useRef } from 'react';\nimport { useServices } from '../contexts/ServiceContext.js';\nimport { type DashboardData } from '../components/Dashboard.js';\nimport { OnlineManager } from '../services/online-manager.js';\nimport { SystemMonitor } from '../services/system-monitor.js';\n\nexport function useDashboardData(refreshInterval = 30000) {\n  const { systemdManager, userManager, quotaManager, trafficManager } = useServices();\n  const [data, setData] = useState<DashboardData | null>(null);\n  const [loading, setLoading] = useState(true);\n  const onlineManagerRef = useRef(new OnlineManager());\n  const systemMonitorRef = useRef(new SystemMonitor());\n\n  const refresh = useCallback(async () => {\n    try {\n      const [status, users, quotas] = await Promise.allSettled([\n        systemdManager.getStatus(),\n        userManager.listUsers(),\n        quotaManager.getAllQuotas(),\n      ]);\n\n      const serviceStatus = status.status === 'fulfilled' ? status.value : null;\n      const userList = users.status === 'fulfilled' ? users.value : [];\n      const quotaMap = quotas.status === 'fulfilled' ? quotas.value : {};\n\n      // Calculate quota summary\n      let ok = 0;\n      let warning = 0;\n      let exceeded = 0;\n\n      for (const q of Object.values(quotaMap)) {\n        if (q.status === 'exceeded' || q.status === 'disabled') exceeded++;\n        else if (q.quotaBytes > 0 && q.usedBytes / q.quotaBytes >= 0.8) warning++;\n        else ok++;\n      }\n\n      // Users without quotas count as OK\n      ok += Math.max(0, userList.length - Object.keys(quotaMap).length);\n\n      // Traffic totals\n      let totalTraffic = 0;\n      let uploadTraffic = 0;\n      let downloadTraffic = 0;\n\n      try {\n        const usages = await trafficManager.getAllUsage();\n        for (const u of usages) {\n          totalTraffic += (u.uplink ?? 0) + (u.downlink ?? 0);\n          uploadTraffic += u.uplink ?? 0;\n          downloadTraffic += u.downlink ?? 0;\n        }\n      } catch {\n        // Stats API might not be available\n      }\n\n      // Format uptime\n      let uptime: string | undefined;\n      if (serviceStatus?.uptime) {\n        uptime = serviceStatus.uptime;\n      }\n\n      // Online users (based on stats API traffic diff)\n      let onlineCount: number | undefined;\n      try {\n        const online = await onlineManagerRef.current.getOnlineConnections();\n        onlineCount = online.activeCount;\n      } catch {\n        // Ignore\n      }\n\n      // System metrics\n      const sysMetrics = systemMonitorRef.current.getAll();\n\n      setData({\n        serviceActive: serviceStatus?.active ?? false,\n        uptime,\n        userCount: userList.length,\n        onlineCount,\n        totalTraffic,\n        uploadTraffic,\n        downloadTraffic,\n        quotaSummary: { ok, warning, exceeded },\n        cpuPercent: sysMetrics.cpuPercent,\n        memPercent: sysMetrics.memPercent,\n        diskPercent: sysMetrics.diskPercent,\n      });\n    } catch {\n      // Keep existing data on error\n    } finally {\n      setLoading(false);\n    }\n  }, [systemdManager, userManager, quotaManager, trafficManager]);\n\n  useEffect(() => {\n    refresh();\n    const timer = setInterval(refresh, refreshInterval);\n    return () => clearInterval(timer);\n  }, [refresh, refreshInterval]);\n\n  return { data, loading, refresh };\n}\n", "/**\n * System Monitor Service\n *\n * Collects system resource metrics: CPU, memory, disk, network.\n *\n * @module services/system-monitor\n */\n\nimport os from 'os';\nimport { execSync } from 'child_process';\n\nexport interface SystemMetrics {\n  cpuPercent: number;\n  memTotal: number;\n  memUsed: number;\n  memPercent: number;\n  diskTotal: number;\n  diskUsed: number;\n  diskPercent: number;\n  networkRx: number;\n  networkTx: number;\n  uptime: number;\n  loadAvg: number[];\n}\n\nexport class SystemMonitor {\n  private lastCpuInfo: { idle: number; total: number } | null = null;\n  private lastNetInfo: { rx: number; tx: number; time: number } | null = null;\n\n  /**\n   * Get CPU usage percentage (averaged over interval since last call)\n   */\n  getCpuPercent(): number {\n    const cpus = os.cpus();\n    let idle = 0;\n    let total = 0;\n\n    for (const cpu of cpus) {\n      idle += cpu.times.idle;\n      total += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.irq + cpu.times.idle;\n    }\n\n    if (this.lastCpuInfo) {\n      const idleDiff = idle - this.lastCpuInfo.idle;\n      const totalDiff = total - this.lastCpuInfo.total;\n      this.lastCpuInfo = { idle, total };\n      if (totalDiff === 0) return 0;\n      return Math.round((1 - idleDiff / totalDiff) * 100);\n    }\n\n    this.lastCpuInfo = { idle, total };\n    return 0; // First call, no data yet\n  }\n\n  /**\n   * Get memory usage\n   */\n  getMemory(): { total: number; used: number; percent: number } {\n    const total = os.totalmem();\n    const free = os.freemem();\n    const used = total - free;\n    return {\n      total,\n      used,\n      percent: Math.round((used / total) * 100),\n    };\n  }\n\n  /**\n   * Get disk usage of root partition\n   */\n  getDisk(): { total: number; used: number; percent: number } {\n    try {\n      const output = execSync('df -B1 / 2>/dev/null | tail -1', {\n        encoding: 'utf-8',\n        timeout: 3000,\n      });\n      const parts = output.trim().split(/\\s+/);\n      if (parts.length >= 5) {\n        const total = parseInt(parts[1]!, 10) || 0;\n        const used = parseInt(parts[2]!, 10) || 0;\n        return {\n          total,\n          used,\n          percent: total > 0 ? Math.round((used / total) * 100) : 0,\n        };\n      }\n    } catch {\n      // Fallback\n    }\n    return { total: 0, used: 0, percent: 0 };\n  }\n\n  /**\n   * Get network throughput (bytes/sec since last call)\n   */\n  getNetworkThroughput(): { rx: number; tx: number } {\n    try {\n      const output = execSync('cat /proc/net/dev 2>/dev/null', {\n        encoding: 'utf-8',\n        timeout: 2000,\n      });\n\n      let totalRx = 0;\n      let totalTx = 0;\n\n      for (const line of output.split('\\n')) {\n        const match = line.match(\n          /^\\s*(\\w+):\\s*(\\d+)\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+(\\d+)/\n        );\n        if (match && match[1] !== 'lo') {\n          totalRx += parseInt(match[2]!, 10);\n          totalTx += parseInt(match[3]!, 10);\n        }\n      }\n\n      const now = Date.now();\n\n      if (this.lastNetInfo) {\n        const elapsed = (now - this.lastNetInfo.time) / 1000;\n        const rx = elapsed > 0 ? (totalRx - this.lastNetInfo.rx) / elapsed : 0;\n        const tx = elapsed > 0 ? (totalTx - this.lastNetInfo.tx) / elapsed : 0;\n        this.lastNetInfo = { rx: totalRx, tx: totalTx, time: now };\n        return { rx: Math.max(0, rx), tx: Math.max(0, tx) };\n      }\n\n      this.lastNetInfo = { rx: totalRx, tx: totalTx, time: now };\n    } catch {\n      // /proc not available\n    }\n    return { rx: 0, tx: 0 };\n  }\n\n  /**\n   * Get all system metrics in one call\n   */\n  getAll(): SystemMetrics {\n    const mem = this.getMemory();\n    const disk = this.getDisk();\n    const net = this.getNetworkThroughput();\n\n    return {\n      cpuPercent: this.getCpuPercent(),\n      memTotal: mem.total,\n      memUsed: mem.used,\n      memPercent: mem.percent,\n      diskTotal: disk.total,\n      diskUsed: disk.used,\n      diskPercent: disk.percent,\n      networkRx: net.rx,\n      networkTx: net.tx,\n      uptime: os.uptime(),\n      loadAvg: os.loadavg(),\n    };\n  }\n}\n", "import React from 'react';\nimport { ThemeProvider } from '../components/design-system/ThemeProvider.js';\nimport { I18nProvider } from '../contexts/I18nContext.js';\nimport { ServiceProvider, type ServiceOptions } from '../contexts/ServiceContext.js';\nimport { NavigationProvider } from '../contexts/NavigationContext.js';\nimport { NotificationProvider } from '../contexts/NotificationContext.js';\nimport { AppShell } from './AppShell.js';\n\ninterface AppProps {\n  options: ServiceOptions;\n  version: string;\n}\n\nexport function App({ options, version }: AppProps) {\n  return (\n    <ThemeProvider defaultTheme=\"dark\">\n      <I18nProvider defaultLanguage=\"en\">\n        <ServiceProvider options={options}>\n          <NavigationProvider>\n            <NotificationProvider>\n              <AppShell version={version} />\n            </NotificationProvider>\n          </NavigationProvider>\n        </ServiceProvider>\n      </I18nProvider>\n    </ThemeProvider>\n  );\n}\n"],
  "mappings": "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",
  "names": ["spawn", "code", "error", "React", "chalk", "chalk", "error", "error", "chalk", "chalk", "error", "code", "code", "error", "path", "access", "fsConstants", "info", "access", "fsConstants", "path", "error", "join", "homedir", "chalk", "info", "path", "join", "homedir", "stat", "info", "chalk", "error", "createContext", "useContext", "useState", "useCallback", "fs", "path", "jsx", "createContext", "useState", "setLanguage", "useCallback", "useContext", "createContext", "useContext", "readFile", "writeFile", "access", "readdir", "existsSync", "dirname", "join", "readFile", "error", "dirname", "existsSync", "writeFile", "join", "readdir", "access", "path", "fs", "SystemdManager", "randomUUID", "URLSearchParams", "readFile", "writeFile", "mkdir", "existsSync", "dirname", "error", "existsSync", "readFile", "dirname", "mkdir", "writeFile", "readFile", "writeFile", "mkdir", "existsSync", "dirname", "isValidUuid", "existsSync", "readFile", "dirname", "mkdir", "writeFile", "randomUUID", "network", "security", "URLSearchParams", "readFile", "writeFile", "mkdir", "chmod", "existsSync", "dirname", "isValidEmail", "isValidPort", "existsSync", "readFile", "error", "dirname", "mkdir", "writeFile", "chmod", "existsSync", "readFile", "readFile", "stat", "existsSync", "error", "spawn", "existsSync", "readFile", "stat", "existsSync", "error", "spawn", "code", "stat", "readFile", "exec", "promisify", "execAsync", "promisify", "exec", "error", "jsx", "createContext", "useContext", "createContext", "useContext", "useCallback", "jsx", "createContext", "useCallback", "useContext", "createContext", "useContext", "useState", "useCallback", "jsx", "useState", "Box", "useInput", "jsx", "t", "Box", "Text", "jsx", "jsxs", "t", "Box", "hint", "Text", "Box", "Text", "jsx", "jsxs", "title", "Box", "Text", "Box", "Text", "jsx", "jsxs", "Box", "Text", "Box", "Text", "jsx", "jsxs", "Text", "loading", "t", "Box", "Box", "Text", "jsx", "jsxs", "Box", "Text", "useState", "useMemo", "Box", "Text", "jsx", "jsxs", "useState", "useMemo", "input", "Box", "Text", "React", "Box", "useState", "useCallback", "Box", "Text", "useInput", "jsx", "jsxs", "title", "useState", "useCallback", "useInput", "input", "Box", "Text", "useState", "useEffect", "Text", "jsx", "jsxs", "useState", "useEffect", "Text", "Box", "Text", "useInput", "jsx", "jsxs", "hint", "useInput", "input", "Box", "Text", "jsx", "t", "React", "Box", "Box", "Text", "useState", "useEffect", "useCallback", "useState", "loading", "useCallback", "useEffect", "Text", "jsx", "jsxs", "Text", "Box", "Text", "jsx", "jsxs", "Box", "Text", "jsx", "jsxs", "loading", "Box", "Text", "Box", "Text", "useInput", "useState", "useEffect", "useCallback", "useState", "loading", "useCallback", "useEffect", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "useInput", "input", "Box", "Text", "jsx", "jsxs", "t", "loading", "useInput", "input", "Text", "Box", "useState", "Box", "Text", "React", "useState", "Box", "Text", "useInput", "jsx", "jsxs", "useState", "error", "React", "useInput", "input", "Box", "Text", "jsx", "jsxs", "t", "useState", "Box", "Text", "useState", "Box", "Text", "jsx", "t", "loading", "useState", "Box", "Text", "useState", "useEffect", "Box", "Text", "jsx", "jsxs", "useState", "useEffect", "info", "Box", "Text", "Box", "Text", "useInput", "useState", "useEffect", "useCallback", "useState", "loading", "useCallback", "useEffect", "Text", "jsx", "jsxs", "Text", "jsx", "jsxs", "t", "loading", "useInput", "input", "Text", "Box", "useState", "Box", "Text", "jsx", "jsxs", "input", "useState", "Box", "Text", "useState", "useEffect", "Box", "Text", "useInput", "jsx", "jsxs", "t", "useState", "loading", "useEffect", "useInput", "input", "Box", "Text", "useState", "useEffect", "Box", "jsx", "jsxs", "useState", "loading", "useEffect", "path", "Box", "useState", "useEffect", "Box", "Text", "useInput", "jsx", "jsxs", "t", "useState", "loading", "useEffect", "useInput", "input", "Box", "Text", "Box", "Text", "useState", "useEffect", "useCallback", "execSync", "execSync", "stat", "useState", "loading", "useCallback", "useEffect", "jsx", "jsxs", "t", "loading", "Box", "Text", "useState", "useEffect", "Box", "Text", "useInput", "readFile", "writeFile", "mkdir", "existsSync", "join", "dirname", "homedir", "join", "homedir", "existsSync", "readFile", "dirname", "mkdir", "writeFile", "jsx", "jsxs", "t", "useState", "loading", "useEffect", "useInput", "input", "Box", "Text", "jsx", "useState", "useEffect", "useCallback", "useRef", "os", "execSync", "useState", "loading", "useRef", "useCallback", "useEffect", "Fragment", "jsx", "jsxs", "useState", "useInput", "input", "Box", "jsx", "readFileSync", "dirname", "join", "error", "React"]
}
