'use strict';

var __createBinding = this && this.__createBinding || (Object.create ? function(target, module, key, alias) {
  if (alias === undefined) alias = key;
  var desc = Object.getOwnPropertyDescriptor(module, key);
  if (!desc || ("get" in desc ? !module.__esModule : desc.writable || desc.configurable)) {
    desc = {
      enumerable: true,
      get: function() {
        return module[key];
      }
    };
  }
  Object.defineProperty(target, alias, desc);
} : function(target, module, key, alias) {
  if (alias === undefined) alias = key;
  target[alias] = module[key];
});
var __setModuleDefault = this && this.__setModuleDefault || (Object.create ? function(target, value) {
  Object.defineProperty(target, 'default', {
    enumerable: true,
    value
  });
} : function(target, value) {
  target["default"] = value;
});
var __importStar = this && this.__importStar || function(mod) {
  if (mod && mod.__esModule) {
    return mod;
  }
  var result = {};
  if (mod != null) {
    for (var key in mod) {
      if (key !== 'default' && Object.prototype.hasOwnProperty.call(mod, key)) {
        __createBinding(result, mod, key);
      }
    }
  }
  __setModuleDefault(result, mod);
  return result;
};
Object.defineProperty(exports, '__esModule', {
  'value': true
});
exports.CursorProViewProvider = undefined;
const vscode = __importStar(require("vscode"));
const client_1 = require("../api/client");
const extension_1 = require("../extension");
const account_1 = require('../utils/account');
const path = __importStar(require("path"));
const fs = __importStar(require('fs'));
const child_process_1 = require('child_process');
const util_1 = require("util");
const sqlite_1 = require('../utils/sqlite');
0x0;
const execAsync = util_1.promisify(child_process_1.exec);
class CursorProViewProvider {
  constructor(ref1, ref2) {
      this._extensionUri = ref1;
      this._context = ref2;
      this._hostsPermissionGranted = false;
      this.SNI_PROXY_IP = "154.36.154.163";
      this.CURSOR_DOMAINS = ["api2.cursor.sh", "api3.cursor.sh"];
      this.HOSTS_MARKER_START = "# ===== CursorPro SNI Proxy Start =====";
      this.HOSTS_MARKER_END = "# ===== CursorPro SNI Proxy End =====";
      this._cachedCursorPath = null;
      0x0;
      this._onlineStatusUnsubscribe = client_1.onOnlineStatusChange(ref3 => {
        this._postMessage({
          'type': "networkStatus",
          'online': ref3
        });
      });
    }
    ["resolveWebviewView"](ref4, ref5, ref6) {
      this._view = ref4;
      ref4.webview.options = {
        'enableScripts': true,
        'localResourceRoots': [this._extensionUri]
      };
      ref4.webview.html = this._getHtmlContent(ref4.webview);
      ref4.webview.onDidReceiveMessage(async ref7 => {
        switch (ref7.type) {
          case "activate":
            await this._handleActivate(ref7.key);
            break;
          case 'switch':
            await this._handleSwitch();
            break;
          case "resetMachineId":
            await this._handleResetMachineId();
            break;
          case "disableUpdate":
            await this._handleDisableUpdate();
            break;
          case 'cleanEnv':
            await this._handleCleanEnv();
            break;
          case 'disable':
            await this._handleDisable();
            break;
          case 'toggleProxy':
            await this._handleToggleProxy(ref7.enabled, ref7.url);
            break;
          case 'getProxyStatus':
            await this._handleGetProxyStatus();
            break;
          case "getState":
            await this._sendState();
            break;
          case "retryConnect":
            await this._handleRetryConnect();
            break;
          case "getSeamlessStatus":
            await this._handleGetSeamlessStatus();
            break;
          case "injectSeamless":
            await this._handleInjectSeamless();
            break;
          case "restoreSeamless":
            await this._handleRestoreSeamless();
            break;
          case 'toggleSeamless':
            await this._handleToggleSeamless(ref7.enabled);
            break;
          case 'getUserSwitchStatus':
            await this._handleGetUserSwitchStatus();
            break;
          case "manualSeamlessSwitch":
            await this._handleManualSeamlessSwitch();
            break;
          case "checkUsageBeforeSwitch":
            await this._handleCheckUsageBeforeSwitch(ref7.email);
            break;
          case "confirmSwitch":
            await this._handleManualSeamlessSwitch();
            break;
          case "getCursorPath":
            await this._handleGetCursorPath();
            break;
          case 'getAccountUsage':
            await this._handleGetAccountUsage(ref7.email);
            break;
          case "getAnnouncement":
            await this._handleGetAnnouncement();
            break;
          case 'checkVersion':
            await this._handleCheckVersion();
            break;
          case "getCursorRunningPath":
            await this._handleGetCursorRunningPath();
            break;
          case "reloadWindow":
            vscode.commands.executeCommand("workbench.action.reloadWindow");
            break;
          case 'closeCursor':
            0x0;
            await account_1.closeCursor();
            break;
        }
      });
      this._sendState();
      this._checkKeyStatus();
    }
  async ["_checkKeyStatus"]() {
    const ref8 = this._context.globalState.get("cursorpro.key");
    if (!ref8) {
      return;
    }
    try {
      0x0;
      const ref9 = await client_1.verifyKey(ref8);
      if (ref9.success && ref9.valid) {
        await this._context.globalState.update('cursorpro.expireDate', ref9.expire_date);
        await this._context.globalState.update('cursorpro.switchRemaining', ref9.switch_remaining);
        await this._context.globalState.update("cursorpro.switchLimit", ref9.switch_limit);
        this._postMessage({
          'type': "keyStatusChecked",
          'valid': true,
          'expireDate': ref9.expire_date,
          'switchRemaining': ref9.switch_remaining,
          'switchLimit': ref9.switch_limit
        });
      } else {
        this._postMessage({
          'type': "keyStatusChecked",
          'valid': false,
          'expired': true,
          'error': ref9.error || "激活码已过期或无效"
        });
      }
    } catch (ref10) {
      console.error("[CursorPro] 检查激活码状态失败:", ref10);
    }
  }
  async ["_handleActivate"](ref11) {
    try {
      const ref12 = await this._isSeamlessInjected();
      if (ref12) {
        this._postMessage({
          'type': "activated",
          'success': false,
          'error': "无感换号已启用，请先禁用后再更换授权码"
        });
        return;
      }
      this._cleanProxySettings();
      0x0;
      const ref13 = await client_1.verifyKey(ref11);
      if (ref13.success && ref13.valid) {
        console.log("[CursorPro] 激活成功，后端返回:", {
          'expire_date': ref13.expire_date,
          'switch_remaining': ref13.switch_remaining,
          'switch_limit': ref13.switch_limit
        });
        await this._context.globalState.update("cursorpro.key", ref11);
        await this._context.globalState.update("cursorpro.expireDate", ref13.expire_date);
        await this._context.globalState.update("cursorpro.switchRemaining", ref13.switch_remaining);
        await this._context.globalState.update("cursorpro.switchLimit", ref13.switch_limit);
        this._postMessage({
          'type': "activated",
          'success': true,
          'key': ref11,
          'expireDate': ref13.expire_date,
          'switchRemaining': ref13.switch_remaining,
          'switchLimit': ref13.switch_limit
        });
        0x0;
        extension_1.showStatusBar();
        await this._handleGetUserSwitchStatus();
      } else {
        this._postMessage({
          'type': "activated",
          'success': false,
          'error': ref13.error || "授权码无效"
        });
      }
    } catch (ref14) {
      this._postMessage({
        'type': "activated",
        'success': false,
        'error': "连接服务器失败"
      });
    }
  }
  async ["_handleSwitch"]() {
    const ref15 = this._context.globalState.get("cursorpro.key");
    if (!ref15) {
      this._postMessage({
        'type': 'showToast',
        'message': "请先激活授权码",
        'icon': '⚠️'
      });
      return;
    }
    try {
      0x0;
      const ref16 = await client_1.switchSeamlessToken(ref15);
      if (ref16.switched) {
        await this._context.globalState.update("cursorpro.switchRemaining", ref16.switchRemaining);
        this._postMessage({
          'type': 'switched',
          'success': true,
          'email': ref16.email,
          'switchRemaining': ref16.switchRemaining,
          'switchLimit': this._context.globalState.get("cursorpro.switchLimit") || 0x64
        });
        const ref17 = ref16.switchRemaining ?? 0x0;
        this._postMessage({
          'type': "userSwitchStatus",
          'switchRemaining': ref17,
          'canSwitch': ref17 > 0x0,
          'lockedAccount': ref16.email ? {
            'email': ref16.email
          } : null
        });
      } else {
        this._postMessage({
          'type': 'switched',
          'success': false,
          'error': ref16.message || '换号失败'
        });
      }
    } catch (ref18) {
      this._postMessage({
        'type': 'switched',
        'success': false,
        'error': "连接服务器失败"
      });
    }
  }
  async ["_writeAccountToLocal"](ref19) {
    try {
      const ref20 = process.env.APPDATA || '';
      const ref21 = path.join(ref20, "Cursor", 'User', "globalStorage", "state.vscdb");
      const ref22 = path.join(ref20, "Cursor", 'User', "globalStorage", 'storage.json');
      const ref23 = path.join(ref20, "Cursor", "machineid");
      if (fs.existsSync(ref21)) {
        const ref24 = [];
        if (ref19.accessToken) {
          ref24.push(["cursorAuth/accessToken", ref19.accessToken]);
        }
        if (ref19.refreshToken) {
          ref24.push(["cursorAuth/refreshToken", ref19.refreshToken]);
        }
        if (ref19.email) {
          ref24.push(["cursorAuth/cachedEmail", ref19.email]);
        }
        if (ref19.membership_type) {
          ref24.push(["cursorAuth/stripeMembershipType", ref19.membership_type]);
        }
        if (ref19.sign_up_type) {
          ref24.push(["cursorAuth/cachedSignUpType", ref19.sign_up_type]);
        }
        if (ref19.serviceMachineId) {
          ref24.push(["storage.serviceMachineId", ref19.serviceMachineId]);
        }
        0x0;
        await sqlite_1.sqliteSetBatch(ref21, ref24);
        console.log("[CursorPro] SQLite 数据库已更新");
      }
      if (fs.existsSync(ref22)) {
        const ref25 = JSON.parse(fs.readFileSync(ref22, 'utf-8'));
        if (ref19.machineId) {
          ref25["telemetry.machineId"] = ref19.machineId;
        }
        if (ref19.macMachineId) {
          ref25['telemetry.macMachineId'] = ref19.macMachineId;
        }
        if (ref19.devDeviceId) {
          ref25["telemetry.devDeviceId"] = ref19.devDeviceId;
        }
        if (ref19.sqmId) {
          ref25["telemetry.sqmId"] = ref19.sqmId;
        }
        fs.writeFileSync(ref22, JSON.stringify(ref25, null, 0x4));
        console.log("[CursorPro] storage.json 已更新");
      }
      if (ref19.machineId) {
        fs.writeFileSync(ref23, ref19.machineId);
        console.log("[CursorPro] machineid 文件已更新");
      }
      if (ref19.registryGuid && process.platform === 'win32') {
        try {
          const ref26 = "reg add \"HKLM\\SOFTWARE\\Microsoft\\Cryptography\" /v MachineGuid /t REG_SZ /d \"" + ref19.registryGuid + "\" /f";
          await execAsync(ref26);
          console.log("[CursorPro] 注册表 MachineGuid 已更新");
        } catch (ref27) {
          console.warn("[CursorPro] 注册表写入失败（可能需要管理员权限）:", ref27);
        }
      }
      return true;
    } catch (ref28) {
      console.error("[CursorPro] 写入本地失败:", ref28);
      vscode.window.showErrorMessage("写入失败: " + ref28);
      return false;
    }
  }
  async ["_handleReset"]() {
    await this._context.globalState.update("cursorpro.key", undefined);
    await this._context.globalState.update("cursorpro.expireDate", undefined);
    await this._context.globalState.update('cursorpro.switchRemaining', undefined);
    0x0;
    extension_1.hideStatusBar();
    this._postMessage({
      'type': 'reset',
      'success': true
    });
    vscode.window.showInformationMessage("插件已重置");
  }
  async ['_handleDisable']() {
    await this._handleReset();
    vscode.window.showInformationMessage("插件已停用");
  }
  async ['_checkAdminPrivilege']() {
    if (process.platform !== "win32") {
      return true;
    }
    try {
      await execAsync("reg query \"HKLM\\SOFTWARE\\Microsoft\\Cryptography\" /v MachineGuid 2>nul");
      const ref29 = await execAsync("net session 2>nul")["catch"](() => ({
        'stdout': '',
        'stderr': 'error'
      }));
      return !ref29.stderr;
    } catch (ref30) {
      return false;
    }
  }
  async ["_handleResetMachineId"]() {
      try {
        const ref31 = process.platform;
        if (ref31 === 'win32') {
          const ref32 = await this._checkAdminPrivilege();
          if (!ref32) {
            this._postMessage({
              'type': 'adminPermissionRequired'
            });
            return;
          }
        }
        0x0;
        const ref33 = account_1.getCursorPaths();
        const {
          dbPath: ref34,
          storagePath: ref35,
          machineidPath: ref36
        } = ref33;
        const ref37 = require("crypto");
        const ref38 = ref37.randomBytes(0x20).toString("hex");
        const ref39 = ref37.randomBytes(0x20).toString("hex");
        const ref40 = ref37.randomUUID();
        const ref41 = '{' + ref37.randomUUID().toUpperCase() + '}';
        let ref42 = 0x0;
        let ref43 = [];
        if (fs.existsSync(ref35)) {
          let ref44 = 0x3;
          while (ref44 > 0x0) {
            try {
              const ref45 = JSON.parse(fs.readFileSync(ref35, "utf-8"));
              ref45["telemetry.machineId"] = ref38;
              ref45["telemetry.macMachineId"] = ref39;
              ref45["telemetry.devDeviceId"] = ref40;
              ref45["telemetry.sqmId"] = ref41;
              fs.writeFileSync(ref35, JSON.stringify(ref45, null, 0x4));
              console.log("[CursorPro] storage.json 已更新");
              ref42++;
              break;
            } catch (ref46) {
              ref44--;
              if (ref44 === 0x0) {
                console.warn("[CursorPro] storage.json 更新失败:", ref46.message);
                ref43.push("storage.json");
              } else {
                await new Promise(ref47 => setTimeout(ref47, 0x64));
              }
            }
          }
        } {
          let ref48 = 0x3;
          while (ref48 > 0x0) {
            try {
              const ref49 = path.dirname(ref36);
              if (!fs.existsSync(ref49)) {
                fs.mkdirSync(ref49, {
                  'recursive': true
                });
              }
              fs.writeFileSync(ref36, ref38);
              console.log("[CursorPro] machineid 文件已更新");
              ref42++;
              break;
            } catch (ref50) {
              ref48--;
              if (ref48 === 0x0) {
                console.warn("[CursorPro] machineid 更新失败:", ref50.message);
                ref43.push("machineid");
              } else {
                await new Promise(ref51 => setTimeout(ref51, 0x64));
              }
            }
          }
        }
        if (fs.existsSync(ref34)) {
          let ref52 = 0x3;
          while (ref52 > 0x0) {
            try {
              const ref53 = ref37.randomUUID();
              0x0;
              const ref54 = await sqlite_1.sqliteSetBatch(ref34, [
                ['storage.serviceMachineId', ref53]
              ]);
              if (ref54) {
                console.log("[CursorPro] SQLite 数据库已更新");
                ref42++;
                break;
              } else {
                throw new Error("sqliteSetBatch 返回 false");
              }
            } catch (ref55) {
              ref52--;
              if (ref52 === 0x0) {
                console.warn("[CursorPro] SQLite 更新失败:", ref55.message);
                ref43.push("SQLite");
              } else {
                await new Promise(ref56 => setTimeout(ref56, 0x1f4));
              }
            }
          }
        }
        if (ref31 === "win32") {
          const ref57 = ref37.randomUUID();
          try {
            await execAsync("reg add \"HKLM\\SOFTWARE\\Microsoft\\Cryptography\" /v MachineGuid /t REG_SZ /d \"" + ref57 + "\" /f");
            console.log("[CursorPro] 注册表 MachineGuid 已更新");
            ref42++;
          } catch (ref58) {
            console.warn("[CursorPro] 注册表更新失败（需要管理员权限），已跳过");
            ref43.push("注册表");
          }
        }
        if (ref42 >= 0x2) {
          this._postMessage({
            'type': 'machineIdReset',
            'success': true,
            'needRestart': true,
            'message': ref43.length > 0x0 ? "机器码重置成功（" + ref43.join(", ") + " 更新失败，不影响使用）" : "机器码重置成功"
          });
        } else {
          this._postMessage({
            'type': "showToast",
            'message': "重置部分失败: " + ref43.join(", ") + "。请先完全关闭 Cursor 再试",
            'icon': '⚠️'
          });
        }
      } catch (ref59) {
        this._postMessage({
          'type': "showToast",
          'message': "重置机器码失败: " + ref59,
          'icon': '❌'
        });
      }
    }
    ['_generateRandomMAC']() {
      const ref60 = require('crypto');
      const ref61 = ref60.randomBytes(0x6);
      ref61[0x0] = (ref61[0x0] | 0x2) & 0xfe;
      return Array.from(ref61).map(ref62 => ref62.toString(0x10).padStart(0x2, '0')).join(':');
    }
  async ['_handleDisableUpdate']() {
    try {
      const ref63 = process.env.LOCALAPPDATA || '';
      const ref64 = path.join(ref63, "cursor-updater");
      if (fs.existsSync(ref64)) {
        if (fs.statSync(ref64).isDirectory()) {
          fs.rmSync(ref64, {
            'recursive': true,
            'force': true
          });
        } else {
          fs.unlinkSync(ref64);
        }
      }
      fs.writeFileSync(ref64, '');
      this._postMessage({
        'type': 'showToast',
        'message': "已禁用 Cursor 自动更新",
        'icon': '✅'
      });
    } catch (ref65) {
      this._postMessage({
        'type': 'showToast',
        'message': "禁用自动更新失败: " + ref65,
        'icon': '❌'
      });
    }
  }
  async ["_handleCleanEnv"]() {
      try {
        if (process.platform === "win32") {
          await execAsync("taskkill /F /IM Cursor.exe")["catch"](() => {});
        } else {
          await execAsync("pkill -f Cursor")['catch'](() => {});
        }
        await new Promise(ref66 => setTimeout(ref66, 0x7d0));
        const ref67 = process.env.APPDATA || '';
        const ref68 = process.env.LOCALAPPDATA || '';
        const ref69 = process.env.HOME || process.env.USERPROFILE || '';
        let ref70 = 0x0;
        if (process.platform === "win32") {
          const ref71 = [path.join(ref67, "Cursor"), path.join(ref68, "Cursor"), path.join(ref68, "cursor-updater"), path.join(ref69, ".cursor")];
          for (const ref72 of ref71) {
            try {
              if (fs.existsSync(ref72)) {
                fs.rmSync(ref72, {
                  'recursive': true,
                  'force': true
                });
                ref70++;
                console.log("[CursorPro] 已清理: " + ref72);
              }
            } catch (ref73) {
              console.warn("[CursorPro] 清理失败: " + ref72, ref73);
            }
          }
        } else {
          if (process.platform === "darwin") {
            const ref74 = [path.join(ref69, "Library", "Application Support", "Cursor"), path.join(ref69, "Library", 'Caches', "Cursor"), path.join(ref69, "Library", "Logs", "Cursor"), path.join(ref69, 'Library', "Application Support", 'Caches', "cursor-updater"), path.join(ref69, ".cursor")];
            for (const ref75 of ref74) {
              try {
                if (fs.existsSync(ref75)) {
                  fs.rmSync(ref75, {
                    'recursive': true,
                    'force': true
                  });
                  ref70++;
                }
              } catch (ref76) {
                console.warn("[CursorPro] 清理失败: " + ref75, ref76);
              }
            }
          } else {
            const ref77 = [path.join(ref69, ".config", "Cursor"), path.join(ref69, '.cache', "Cursor"), path.join(ref69, ".local", "share", "Cursor"), path.join(ref69, ".cursor")];
            for (const ref78 of ref77) {
              try {
                if (fs.existsSync(ref78)) {
                  fs.rmSync(ref78, {
                    'recursive': true,
                    'force': true
                  });
                  ref70++;
                }
              } catch (ref79) {
                console.warn("[CursorPro] 清理失败: " + ref78, ref79);
              }
            }
          }
        }
        vscode.window.showInformationMessage("✅ Cursor 环境清理完成！已清理 " + ref70 + " 个目录。请重新启动 Cursor。");
      } catch (ref80) {
        vscode.window.showErrorMessage("清理失败: " + ref80);
      }
    }
    ['_cleanProxySettings']() {
      try {
        const ref81 = process.platform;
        const ref82 = process.env.HOME || process.env.USERPROFILE || '';
        let ref83;
        if (ref81 === "win32") {
          const ref84 = process.env.APPDATA || '';
          ref83 = path.join(ref84, "Cursor", 'User', "settings.json");
        } else {
          if (ref81 === "darwin") {
            ref83 = path.join(ref82, 'Library', "Application Support", "Cursor", 'User', "settings.json");
          } else {
            ref83 = path.join(ref82, ".config", "Cursor", 'User', "settings.json");
          }
        }
        if (!fs.existsSync(ref83)) {
          return;
        }
        const ref85 = fs.readFileSync(ref83, 'utf-8');
        let ref86;
        try {
          ref86 = JSON.parse(ref85);
        } catch {
          return;
        }
        const ref87 = ["http.proxy", "http.proxyStrictSSL", "http.proxySupport", "cursor.general.disableHttp2", "http.noProxy"];
        let ref88 = false;
        for (const ref89 of ref87) {
          if (ref89 in ref86) {
            ref88 = true;
            delete ref86[ref89];
          }
        }
        if (ref88) {
          fs.writeFileSync(ref83, JSON.stringify(ref86, null, 0x4), "utf-8");
          console.log("[CursorPro] 已清理 settings.json 中的旧代理配置");
        }
      } catch (ref90) {
        console.warn("[CursorPro] 清理 settings.json 代理配置失败:", ref90);
      }
    }
    ["_getHostsPath"]() {
      return process.platform === "win32" ? "C:\\Windows\\System32\\drivers\\etc\\hosts" : '/etc/hosts';
    }
    ['_readHostsFile']() {
      try {
        const ref91 = this._getHostsPath();
        if (fs.existsSync(ref91)) {
          return fs.readFileSync(ref91, 'utf-8');
        }
      } catch (ref92) {
        console.error("[CursorPro] Read hosts error:", ref92);
      }
      return '';
    }
    ["_hasHostsConfig"]() {
      const ref93 = this._readHostsFile();
      return ref93.includes(this.HOSTS_MARKER_START);
    }
  async ['_grantHostsWritePermission']() {
    if (process.platform !== "win32") {
      return false;
    }
    try {
      const ref94 = this._getHostsPath();
      const ref95 = process.env.USERNAME || '';
      if (!ref95) {
        return false;
      }
      const ref96 = ref94.replace(/\\/g, "\\\\");
      const ref97 = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command icacls \\\"" + ref96 + "\\\" /grant " + ref95 + ":M' -Verb RunAs -Wait\"";
      await execAsync(ref97);
      this._hostsPermissionGranted = true;
      console.log("[CursorPro] Hosts file permission granted to user:", ref95);
      return true;
    } catch (ref98) {
      console.error("[CursorPro] Grant hosts permission error:", ref98);
      return false;
    }
  }
  async ["_writeHostsFile"](ref99) {
    const ref100 = this._getHostsPath();
    try {
      if (process.platform === "win32") {
        let ref101 = false;
        try {
          fs.writeFileSync(ref100, ref99, 'utf-8');
          ref101 = true;
        } catch (ref102) {
          console.log("[CursorPro] Direct write failed, trying to grant permission");
        }
        if (!ref101) {
          if (!this._hostsPermissionGranted) {
            const ref103 = await this._grantHostsWritePermission();
            if (ref103) {
              try {
                fs.writeFileSync(ref100, ref99, 'utf-8');
                ref101 = true;
              } catch (ref104) {
                console.log("[CursorPro] Write still failed after permission grant");
              }
            }
          }
        }
        if (!ref101) {
          const ref105 = path.join(process.env.TEMP || '', "cursorpro_hosts_temp.txt");
          fs.writeFileSync(ref105, ref99, 'utf-8');
          const ref106 = ref105.replace(/\\/g, "\\\\");
          const ref107 = ref100.replace(/\\/g, "\\\\");
          const ref108 = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command Copy-Item -Path \\\"" + ref106 + "\\\" -Destination \\\"" + ref107 + "\\\" -Force' -Verb RunAs -Wait\"";
          await execAsync(ref108);
          try {
            fs.unlinkSync(ref105);
          } catch {}
        }
        try {
          await execAsync("ipconfig /flushdns");
          console.log("[CursorPro] Windows DNS 缓存已刷新");
        } catch (ref109) {
          console.warn("[CursorPro] Windows DNS 刷新失败:", ref109);
        }
      } else {
        if (process.platform === "darwin") {
          fs.writeFileSync("/tmp/hosts_cursor_temp", ref99, 'utf-8');
          const ref110 = "do shell script \"cp '/tmp/hosts_cursor_temp' '" + ref100 + "' && rm '" + "/tmp/hosts_cursor_temp" + "' && dscacheutil -flushcache && killall -HUP mDNSResponder\" with administrator privileges";
          await execAsync("osascript -e \"" + ref110.replace(/"/g, "\\\"") + "\"");
        } else {
          fs.writeFileSync(ref100, ref99, 'utf-8');
        }
      }
      return true;
    } catch (ref111) {
      console.error("[CursorPro] Write hosts error:", ref111);
      return false;
    }
  }
  async ["_handleToggleProxy"](ref112, ref113) {
    try {
      if (ref112) {
        const ref114 = this._context.globalState.get("cursorpro.key");
        const ref115 = this._context.globalState.get('cursorpro.expireDate');
        if (!ref114) {
          this._postMessage({
            'type': "proxyUpdated",
            'success': false,
            'error': '请先激活授权码'
          });
          this._postMessage({
            'type': 'showToast',
            'message': '请先激活授权码',
            'icon': '⚠️'
          });
          return;
        }
        if (ref115) {
          const ref116 = new Date(ref115).getTime();
          if (Date.now() > ref116) {
            this._postMessage({
              'type': "proxyUpdated",
              'success': false,
              'error': "授权码已过期，无法开启免魔法"
            });
            this._postMessage({
              'type': 'showToast',
              'message': "授权码已过期，无法开启免魔法",
              'icon': '⚠️'
            });
            return;
          }
        }
      }
      this._cleanProxySettings();
      let ref117 = this._readHostsFile();
      const ref118 = ref117.indexOf(this.HOSTS_MARKER_START);
      const ref119 = ref117.indexOf(this.HOSTS_MARKER_END);
      if (ref118 !== -0x1 && ref119 !== -0x1) {
        ref117 = ref117.substring(0x0, ref118) + ref117.substring(ref119 + this.HOSTS_MARKER_END.length);
      }
      ref117 = ref117.replace(/\n{3,}/g, "\n\n").trim();
      if (ref112) {
        const ref120 = this.CURSOR_DOMAINS.map(ref121 => this.SNI_PROXY_IP + " " + ref121).join("\n");
        const ref122 = "\n\n" + this.HOSTS_MARKER_START + "\n" + ref120 + "\n" + this.HOSTS_MARKER_END + "\n";
        ref117 += ref122;
      }
      const ref123 = await this._writeHostsFile(ref117);
      if (ref123) {
        0x0;
        await client_1.updateProxyConfig(ref112, this.SNI_PROXY_IP);
        this._postMessage({
          'type': "proxyUpdated",
          'success': true,
          'enabled': ref112,
          'url': this.SNI_PROXY_IP
        });
        this._postMessage({
          'type': 'showToast',
          'message': ref112 ? "免魔法已开启" : "免魔法已关闭",
          'icon': '✅'
        });
      } else {
        this._postMessage({
          'type': "proxyUpdated",
          'success': false,
          'error': "修改 hosts 文件失败，请确保有管理员权限"
        });
        this._postMessage({
          'type': "showToast",
          'message': "需要管理员权限修改 hosts 文件",
          'icon': '⚠️'
        });
      }
    } catch (ref124) {
      console.error("[CursorPro] Toggle proxy error:", ref124);
      this._postMessage({
        'type': "proxyUpdated",
        'success': false,
        'error': '更新配置失败'
      });
    }
  }
  async ["_handleGetProxyStatus"]() {
    try {
      const ref125 = this._hasHostsConfig();
      this._postMessage({
        'type': "proxyStatus",
        'enabled': ref125,
        'url': ref125 ? this.SNI_PROXY_IP : ''
      });
    } catch (ref126) {
      console.error("[CursorPro] Get proxy status error:", ref126);
      this._postMessage({
        'type': "proxyStatus",
        'enabled': false,
        'url': ''
      });
    }
  }
  async ["_handleGetSeamlessStatus"]() {
    try {
      const ref127 = await this._getWorkbenchPathAsync();
      let ref128 = false;
      if (ref127 && fs.existsSync(ref127)) {
        const ref129 = fs.readFileSync(ref127, 'utf-8');
        ref128 = this._checkInjected(ref129);
      }
      this._postMessage({
        'type': 'seamlessStatus',
        'is_injected': ref128,
        'workbench_path': ref127 || '未找到'
      });
    } catch (ref130) {
      this._postMessage({
        'type': "seamlessStatus",
        'is_injected': false,
        'error': "检测状态失败"
      });
    }
  }
  async ['_getCursorInstallPath']() {
      if (this._cachedCursorPath) {
        return this._cachedCursorPath;
      }
      const ref131 = vscode.workspace.getConfiguration("cursorpro");
      const ref132 = ref131.get("cursorPath");
      if (ref132 && fs.existsSync(ref132)) {
        console.log("[CursorPro] 使用用户配置的 Cursor 路径:", ref132);
        this._cachedCursorPath = ref132;
        return ref132;
      }
      const ref133 = process.platform;
      let ref134 = null;
      try {
        if (ref133 === "win32") {
          try {
            const {
              stdout: ref135
            } = await execAsync("wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul");
            if (ref135) {
              const ref136 = ref135.match(/ExecutablePath=(.+)/);
              if (ref136 && ref136[0x1]) {
                const ref137 = ref136[0x1].trim();
                ref134 = path.dirname(ref137);
              }
            }
          } catch (ref138) {
            console.log("[CursorPro] WMIC 获取路径失败");
          }
          if (!ref134) {
            try {
              const {
                stdout: ref139
              } = await execAsync("powershell -Command \"Get-Process Cursor -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Path\"");
              if (ref139 && ref139.trim()) {
                ref134 = path.dirname(ref139.trim());
              }
            } catch (ref140) {
              console.log("[CursorPro] PowerShell Get-Process 获取路径失败");
            }
          }
          if (!ref134) {
            try {
              const {
                stdout: ref141
              } = await execAsync("reg query \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\" /s /f \"Cursor\" 2>nul | findstr \"InstallLocation\"");
              if (ref141 && ref141.trim()) {
                const ref142 = ref141.match(/InstallLocation\s+REG_SZ\s+(.+)/);
                if (ref142 && ref142[0x1] && fs.existsSync(ref142[0x1].trim())) {
                  ref134 = ref142[0x1].trim();
                }
              }
            } catch (ref143) {
              console.log("[CursorPro] 注册表方法1获取路径失败");
            }
          }
          if (!ref134) {
            try {
              const {
                stdout: ref144
              } = await execAsync("reg query \"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\" /s /f \"Cursor\" 2>nul | findstr \"InstallLocation\"");
              if (ref144 && ref144.trim()) {
                const ref145 = ref144.match(/InstallLocation\s+REG_SZ\s+(.+)/);
                if (ref145 && ref145[0x1] && fs.existsSync(ref145[0x1].trim())) {
                  ref134 = ref145[0x1].trim();
                }
              }
            } catch (ref146) {
              console.log("[CursorPro] 注册表方法2获取路径失败");
            }
          }
          if (!ref134) {
            try {
              const ref147 = path.join(process.env.APPDATA || '', 'Microsoft', "Windows", "Start Menu", 'Programs', 'Cursor.lnk');
              const ref148 = path.join("C:\\ProgramData", 'Microsoft', 'Windows', "Start Menu", "Programs", 'Cursor.lnk');
              for (const ref149 of [ref147, ref148]) {
                if (fs.existsSync(ref149)) {
                  const {
                    stdout: ref150
                  } = await execAsync("powershell -Command \"(New-Object -ComObject WScript.Shell).CreateShortcut('" + ref149.replace(/'/g, "''") + "').TargetPath\"");
                  if (ref150 && ref150.trim() && fs.existsSync(ref150.trim())) {
                    ref134 = path.dirname(ref150.trim());
                    break;
                  }
                }
              }
            } catch (ref151) {
              console.log("[CursorPro] 快捷方式解析获取路径失败");
            }
          }
          if (!ref134) {
            try {
              const {
                stdout: ref152
              } = await execAsync("where cursor 2>nul");
              if (ref152 && ref152.trim()) {
                const ref153 = ref152.trim().split("\n");
                for (const ref154 of ref153) {
                  const ref155 = ref154.trim();
                  if (ref155 && fs.existsSync(ref155)) {
                    ref134 = path.dirname(ref155);
                    break;
                  }
                }
              }
            } catch (ref156) {
              console.log("[CursorPro] where 命令获取路径失败");
            }
          }
          if (!ref134) {
            const ref157 = process.env.LOCALAPPDATA || '';
            const ref158 = process.env.USERPROFILE || '';
            const ref159 = process.env.ProgramFiles || "C:\\Program Files";
            const ref160 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
            const ref161 = [path.join(ref157, "Programs", "Cursor"), path.join(ref157, "Programs", 'cursor'), path.join(ref158, "AppData", "Local", "Programs", "Cursor"), path.join(ref159, "Cursor"), path.join(ref160, "Cursor"), path.join(ref157, "Cursor"), path.join(ref157, 'cursor')];
            for (const ref162 of ref161) {
              if (ref162 && fs.existsSync(ref162)) {
                ref134 = ref162;
                break;
              }
            }
          }
        } else {
          if (ref133 === 'darwin') {
            try {
              const {
                stdout: ref163
              } = await execAsync("lsof -c Cursor 2>/dev/null | grep \"txt\" | grep -i \"Cursor.app\" | head -1 | awk '{print $9}'");
              if (ref163 && ref163.trim()) {
                const ref164 = ref163.trim().match(/(.+\.app)/);
                if (ref164) {
                  ref134 = ref164[0x1];
                }
              }
            } catch (ref165) {}
            if (!ref134) {
              try {
                const {
                  stdout: ref166
                } = await execAsync("ps -eo comm,args | grep -i \"[C]ursor\" | grep -v \"grep\" | head -1");
                if (ref166 && ref166.trim()) {
                  const ref167 = ref166.match(/(\/.+\.app)/);
                  if (ref167) {
                    ref134 = ref167[0x1];
                  }
                }
              } catch (ref168) {
                console.warn("[CursorPro] macOS 获取进程路径失败:", ref168);
              }
            }
            if (!ref134) {
              try {
                const {
                  stdout: ref169
                } = await execAsync("mdfind \"kMDItemCFBundleIdentifier == 'com.todesktop.*cursor*'\" 2>/dev/null | head -1");
                if (ref169 && ref169.trim() && fs.existsSync(ref169.trim())) {
                  ref134 = ref169.trim();
                }
              } catch (ref170) {}
            }
            if (!ref134 && fs.existsSync('/Applications/Cursor.app')) {
              ref134 = '/Applications/Cursor.app';
            }
          } else {
            try {
              const {
                stdout: ref171
              } = await execAsync("pgrep -f \"[c]ursor\" | head -1");
              const ref172 = ref171 && ref171.trim();
              if (ref172) {
                const {
                  stdout: ref173
                } = await execAsync("readlink -f /proc/" + ref172 + "/exe 2>/dev/null");
                if (ref173 && ref173.trim()) {
                  const ref174 = ref173.trim();
                  ref134 = path.dirname(ref174);
                  if (ref134.endsWith('/bin')) {
                    ref134 = path.dirname(ref134);
                  }
                }
              }
            } catch (ref175) {}
            if (!ref134) {
              try {
                const {
                  stdout: ref176
                } = await execAsync("which cursor 2>/dev/null");
                if (ref176 && ref176.trim()) {
                  const ref177 = await execAsync("readlink -f \"" + ref176.trim() + "\" 2>/dev/null");
                  if (ref177.stdout && ref177.stdout.trim()) {
                    ref134 = path.dirname(ref177.stdout.trim());
                    if (ref134.endsWith('/bin')) {
                      ref134 = path.dirname(ref134);
                    }
                  }
                }
              } catch (ref178) {
                console.warn("[CursorPro] Linux 获取进程路径失败:", ref178);
              }
            }
            if (!ref134) {
              const ref179 = ["/opt/Cursor", '/opt/cursor', "/usr/share/cursor", "/usr/lib/cursor", path.join(process.env.HOME || '', ".local/share/cursor"), path.join(process.env.HOME || '', "Applications/cursor")];
              for (const ref180 of ref179) {
                if (fs.existsSync(ref180)) {
                  ref134 = ref180;
                  break;
                }
              }
            }
          }
        }
      } catch (ref181) {
        console.error("[CursorPro] 获取 Cursor 安装路径失败:", ref181);
      }
      if (ref134) {
        this._cachedCursorPath = ref134;
      }
      return ref134;
    }
    ['_getWorkbenchPath']() {
      return this._getWorkbenchPathSync();
    }
    ['_getWorkbenchPathSync']() {
      const ref182 = process.platform;
      if (this._cachedCursorPath) {
        let ref183;
        if (ref182 === "darwin") {
          ref183 = path.join(this._cachedCursorPath, 'Contents', "Resources", "app", "out", 'vs', "workbench", "workbench.desktop.main.js");
        } else {
          ref183 = path.join(this._cachedCursorPath, "resources", "app", "out", 'vs', "workbench", "workbench.desktop.main.js");
        }
        if (fs.existsSync(ref183)) {
          return ref183;
        }
      }
      if (ref182 === 'win32') {
        return null;
      }
      let ref184 = [];
      if (ref182 === "darwin") {
        ref184 = ["/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js"];
      } else {
        ref184 = ["/opt/Cursor/resources/app/out/vs/workbench/workbench.desktop.main.js", '/usr/share/cursor/resources/app/out/vs/workbench/workbench.desktop.main.js'];
      }
      for (const ref185 of ref184) {
        if (fs.existsSync(ref185)) {
          return ref185;
        }
      }
      return null;
    }
  async ["_getWorkbenchPathAsync"]() {
      const ref186 = process.platform;
      const ref187 = await this._getCursorInstallPath();
      if (ref187) {
        let ref188;
        if (ref186 === "darwin") {
          ref188 = path.join(ref187, "Contents", "Resources", "app", "out", 'vs', "workbench", "workbench.desktop.main.js");
        } else {
          ref188 = path.join(ref187, "resources", "app", "out", 'vs', "workbench", "workbench.desktop.main.js");
        }
        if (fs.existsSync(ref188)) {
          return ref188;
        }
      }
      return this._getWorkbenchPathSync();
    }
    ["_checkInjected"](ref189) {
      return ref189.includes("/*i0*/") || ref189.includes('/*i1s*/');
    }
  async ["_isSeamlessInjected"]() {
      try {
        const ref190 = await this._getWorkbenchPathAsync();
        if (ref190 && fs.existsSync(ref190)) {
          const ref191 = fs.readFileSync(ref190, "utf-8");
          return this._checkInjected(ref191);
        }
        return false;
      } catch (ref192) {
        console.error("[CursorPro] 检测无感换号状态失败:", ref192);
        return false;
      }
    }
    ['_getInjectionConfig'](ref193, ref194) {
      return [{
        'name': "注入点0: 完整性检查绕过",
        'scode': '_showNotification(){',
        'replacement': "_showNotification(){/*i0*/}_showNotificationOld(){",
        'restore': {
          'find': "_showNotification(){/*i0*/}_showNotificationOld(){",
          'replace_with': '_showNotification(){'
        }
      }, {
        'name': "注入点1: 核心模块初始化",
        'scode': "this.database.getItems()))",
        'replacement': "this.database.getItems()))/*i1s*/;await(async function(e){if(e.get('releaseNotes/lastVersion')){window.store=e;window.__cpKey='CursorPro2024!@#';window.__cpEnc=function(t){var k=window.__cpKey,r='';for(var i=0;i<t.length;i++)r+=String.fromCharCode(t.charCodeAt(i)^k.charCodeAt(i%k.length));return btoa(r)};window.__cpDec=function(t){var k=window.__cpKey,d=atob(t),r='';for(var i=0;i<d.length;i++)r+=String.fromCharCode(d.charCodeAt(i)^k.charCodeAt(i%k.length));return r};window.__cpGet=function(){try{var d=localStorage.getItem('__cp_token');return d?JSON.parse(window.__cpDec(d)):null}catch(e){return null}};window.__cpSet=function(data){try{localStorage.setItem('__cp_token',window.__cpEnc(JSON.stringify(data)))}catch(e){}};window.__cpApi='" + ref193 + "';window.__cpUserKey='" + ref194 + "';window.__cpVersion=0;console.log('[CP] Initialized with key:','" + ref194 + "'.substring(0,15)+'...')}})(this)/*i1e*/",
        'restore': {
          'find_start': "/*i1s*/",
          'find_end': "/*i1e*/"
        }
      }, {
        'name': "注入点2: 启动时Token同步",
        'scode': "/*i1e*/",
        'replacement': "/*i1e*//*i2s*/;(function(){window.__cpSyncing=false;window.__cpSync=function(){if(window.__cpSyncing){console.log('[CP] Sync already in progress, skip');return}var userKey=window.__cpUserKey;if(!userKey){console.log('[CP] No userKey, skip sync');return}window.__cpSyncing=true;console.log('[CP] Sync with key:',userKey.substring(0,15)+'...');fetch(window.__cpApi+'/api/seamless/get-token?userKey='+encodeURIComponent(userKey)).then(function(r){return r.json()}).then(function(d){window.__cpSyncing=false;if(d.error){console.error('[CP] Sync error:',d.error);return}if(d&&d.accessToken){var oldToken=window.__cpGet();var needUpdate=!oldToken||oldToken.email!==d.email||window.__cpVersion!==d.switchVersion;if(needUpdate){window.__cpVersion=d.switchVersion||0;window.__cpSet({accessToken:d.accessToken,refreshToken:d.refreshToken||'',email:d.email||'',machineIds:d.machineIds||null,switchRemaining:d.switchRemaining,switchVersion:d.switchVersion||0});window.store.set('cursorAuth/accessToken',d.accessToken,-1);if(d.refreshToken)window.store.set('cursorAuth/refreshToken',d.refreshToken,-1);if(d.email)window.store.set('cursor.email',d.email,-1);if(d.is_new&&d.machineIds){if(d.machineIds.devDeviceId)window.store.set('telemetry.devDeviceId',d.machineIds.devDeviceId,-1);if(d.machineIds.machineId)window.store.set('telemetry.machineId',d.machineIds.machineId,-1);if(d.machineIds.macMachineId)window.store.set('telemetry.macMachineId',d.machineIds.macMachineId,-1);if(d.machineIds.sqmId)window.store.set('telemetry.sqmId',d.machineIds.sqmId,-1)}console.log('[CP] Token UPDATED:',d.email,'v'+d.switchVersion)}}}).catch(function(e){window.__cpSyncing=false;console.error('[CP] Sync error:',e)})};console.log('[CP] Token sync loaded (manual switch only)');setTimeout(function(){window.__cpSync()},2000);setInterval(function(){window.__cpSync()},10000)})()/*i2e*/",
        'restore': {
          'find_start': "/*i2s*/",
          'find_end': "/*i2e*/"
        }
      }];
    }
  async ["_handleInjectSeamless"]() {
    try {
      const ref195 = this._context.globalState.get("cursorpro.key");
      if (!ref195) {
        this._postMessage({
          'type': "seamlessInjected",
          'success': false,
          'error': "请先激活授权码"
        });
        return;
      }
      0x0;
      const ref196 = await client_1.getUserSwitchStatus(ref195);
      if (!ref196.valid) {
        this._postMessage({
          'type': "seamlessInjected",
          'success': false,
          'error': ref196.error || "授权码无效"
        });
        return;
      }
      const ref197 = await this._getWorkbenchPathAsync();
      if (!ref197) {
        this._postMessage({
          'type': "seamlessInjected",
          'success': false,
          'error': "启用失败"
        });
        return;
      }
      const ref198 = ref197 + ".backup";
      const ref199 = !this._context.globalState.get("cursorpro.seamlessInjected");
      if (ref199 && fs.existsSync(ref198)) {
        console.log("[CursorPro] 首次启用，从备份恢复干净的 workbench 文件");
        try {
          fs.copyFileSync(ref198, ref197);
          console.log("[CursorPro] 备份恢复成功");
        } catch (ref200) {
          console.error("[CursorPro] 备份恢复失败:", ref200);
        }
      }
      let ref201 = fs.readFileSync(ref197, 'utf-8');
      if (this._checkInjected(ref201)) {
        this._postMessage({
          'type': "showToast",
          'message': "已启用",
          'icon': '✅'
        });
        return;
      }
      if (!fs.existsSync(ref198)) {
        fs.copyFileSync(ref197, ref198);
        console.log("[CursorPro] 创建备份文件");
      }
      0x0;
      const ref202 = client_1.getApiUrl();
      const ref203 = this._getInjectionConfig(ref202, ref195);
      const ref204 = [];
      const ref205 = [];
      for (const ref206 of ref203) {
        if (ref201.includes(ref206.scode)) {
          ref201 = ref201.replace(ref206.scode, ref206.replacement);
          ref204.push(ref206.name);
        } else {
          ref205.push(ref206.name);
        }
      }
      if (ref204.length === 0x0) {
        console.error("[CursorPro] 注入失败，未找到任何注入点");
        console.error("[CursorPro] 文件路径:", ref197);
        console.error("[CursorPro] 文件大小:", ref201.length);
        console.error("[CursorPro] 未找到的注入点:", ref205);
        const ref207 = ref201.includes("_showNotification");
        const ref208 = ref201.includes("getItems()");
        console.error("[CursorPro] 包含 _showNotification:", ref207);
        console.error("[CursorPro] 包含 getItems():", ref208);
        this._postMessage({
          'type': "seamlessInjected",
          'success': false,
          'error': "Cursor 版本不兼容，注入点未找到",
          'details': "路径: " + ref197
        });
        return;
      }
      console.log("[CursorPro] 注入成功，应用的注入点:", ref204);
      if (ref205.length > 0x0) {
        console.warn("[CursorPro] 未找到的注入点:", ref205);
      }
      try {
        fs.writeFileSync(ref197, ref201, "utf-8");
      } catch (ref209) {
        console.error("[CursorPro] 写入文件失败:", ref209);
        if (ref209.code === "EPERM" || ref209.code === 'EACCES' || ref209.code === "EROFS") {
          const ref210 = process.platform;
          let ref211 = "没有写入权限";
          if (ref210 === "darwin") {
            ref211 = "没有写入权限，请在终端执行: sudo chmod -R 777 /Applications/Cursor.app";
          } else if (ref210 === "linux") {
            ref211 = "没有写入权限，请使用 sudo 权限运行或修改文件权限";
          }
          this._postMessage({
            'type': "seamlessInjected",
            'success': false,
            'error': ref211,
            'needAdmin': true,
            'path': ref197
          });
          return;
        }
        throw ref209;
      }
      await this._context.globalState.update("cursorpro.seamlessInjected", true);
      this._postMessage({
        'type': 'seamlessInjected',
        'success': true,
        'applied': ref204,
        'needRestart': true,
        'message': "无感换号已启用"
      });
    } catch (ref212) {
      console.error("[CursorPro] Inject error:", ref212);
      if (ref212.code === "EPERM" || ref212.code === 'EACCES') {
        this._postMessage({
          'type': "seamlessInjected",
          'success': false,
          'error': "没有写入权限",
          'needAdmin': true
        });
        return;
      }
      this._postMessage({
        'type': "seamlessInjected",
        'success': false,
        'error': ref212.message || '注入失败'
      });
    }
  }
  async ["_handleRestoreSeamless"]() {
    try {
      const ref213 = await this._getWorkbenchPathAsync();
      if (!ref213) {
        this._postMessage({
          'type': "seamlessRestored",
          'success': false,
          'error': '未找到Cursor安装目录'
        });
        return;
      }
      let ref214 = fs.readFileSync(ref213, "utf-8");
      if (!this._checkInjected(ref214)) {
        return;
      }
      ref214 = ref214.replace("_showNotification(){/*i0*/}_showNotificationOld(){", "_showNotification(){");
      const ref215 = ref214.indexOf("/*i1s*/");
      const ref216 = ref214.indexOf("/*i1e*/");
      if (ref215 !== -0x1 && ref216 !== -0x1) {
        ref214 = ref214.substring(0x0, ref215) + ref214.substring(ref216 + 0x7);
      }
      const ref217 = ref214.indexOf('/*i2s*/');
      const ref218 = ref214.indexOf("/*i2e*/");
      if (ref217 !== -0x1 && ref218 !== -0x1) {
        ref214 = ref214.substring(0x0, ref217) + ref214.substring(ref218 + 0x7);
      }
      try {
        fs.writeFileSync(ref213, ref214, "utf-8");
      } catch (ref219) {
        if (ref219.code === "EPERM" || ref219.code === "EACCES") {
          this._postMessage({
            'type': "seamlessRestored",
            'success': false,
            'error': "没有写入权限",
            'needAdmin': true
          });
          return;
        }
        throw ref219;
      }
      this._postMessage({
        'type': "seamlessRestored",
        'success': true,
        'needRestart': true,
        'message': "无感换号已禁用"
      });
    } catch (ref220) {
      console.error("[CursorPro] Restore error:", ref220);
      if (ref220.code === "EPERM" || ref220.code === "EACCES") {
        this._postMessage({
          'type': "seamlessRestored",
          'success': false,
          'error': "没有写入权限",
          'needAdmin': true
        });
        return;
      }
      this._postMessage({
        'type': "seamlessRestored",
        'success': false,
        'error': ref220.message || '还原失败'
      });
    }
  }
  async ["_handleToggleSeamless"](ref221) {
    try {
      0x0;
      await client_1.updateSeamlessConfig({
        'enabled': ref221
      });
      this._postMessage({
        'type': "seamlessConfigUpdated",
        'success': true,
        'enabled': ref221
      });
    } catch (ref222) {
      this._postMessage({
        'type': "seamlessConfigUpdated",
        'success': false,
        'error': "更新配置失败"
      });
    }
  }
  async ['_handleGetUserSwitchStatus']() {
    try {
      const ref223 = this._context.globalState.get('cursorpro.key');
      if (!ref223) {
        this._postMessage({
          'type': 'userSwitchStatus',
          'valid': false,
          'switchRemaining': 0x0,
          'canSwitch': false,
          'error': "未激活授权码"
        });
        return;
      }
      0x0;
      const ref224 = await client_1.getUserSwitchStatus(ref223);
      let ref225 = false;
      try {
        0x0;
        const ref226 = await client_1.getSeamlessStatus();
        ref225 = ref226.is_injected || false;
      } catch (ref227) {}
      this._postMessage({
        'type': 'userSwitchStatus',
        ...ref224,
        'seamlessEnabled': ref225
      });
    } catch (ref228) {
      this._postMessage({
        'type': "userSwitchStatus",
        'valid': false,
        'switchRemaining': 0x0,
        'canSwitch': false,
        'error': "获取状态失败"
      });
    }
  }
  async ["_handleGetAccountUsage"](ref229) {
    try {
      if (!ref229) {
        this._postMessage({
          'type': "accountUsage",
          'success': false,
          'error': "未提供账号邮箱"
        });
        return;
      }
      0x0;
      const ref230 = client_1.getApiUrl() + "/api/cursor-accounts/query?email=" + encodeURIComponent(ref229) + '&refresh=true';
      const ref231 = await fetch(ref230);
      const ref232 = await ref231.json();
      if (ref232.success && ref232.data) {
        this._postMessage({
          'type': "accountUsage",
          'success': true,
          'data': ref232.data
        });
        const ref233 = ref232.data.usage || {};
        const ref234 = ref233.totalUsageCount || 0x0;
        const ref235 = parseFloat(ref233.totalCostUSD || 0x0);
        0x0;
        extension_1.updateUsageStatusBar(ref234, ref235);
      } else {
        this._postMessage({
          'type': "accountUsage",
          'success': false,
          'error': ref232.error || "获取用量失败"
        });
      }
    } catch (ref236) {
      this._postMessage({
        'type': "accountUsage",
        'success': false,
        'error': ref236.message || "请求失败"
      });
    }
  }
  async ["_handleGetAnnouncement"]() {
    try {
      0x0;
      const ref237 = client_1.getApiUrl() + "/api/announcements/latest";
      const ref238 = await fetch(ref237);
      const ref239 = await ref238.json();
      if (ref239.success && ref239.data) {
        this._postMessage({
          'type': 'announcement',
          'success': true,
          'data': ref239.data
        });
      } else {
        this._postMessage({
          'type': "announcement",
          'success': false,
          'error': ref239.error || "获取公告失败"
        });
      }
    } catch (ref240) {
      this._postMessage({
        'type': 'announcement',
        'success': false,
        'error': ref240.message || "请求失败"
      });
    }
  }
  async ["_handleCheckVersion"]() {
      try {
        0x0;
        const ref241 = await client_1.getLatestVersion();
        if (ref241.success && ref241.version) {
          const ref242 = ref241.version;
          const ref243 = CursorProViewProvider.CURRENT_VERSION;
          const ref244 = this._compareVersions(ref242, ref243) > 0x0;
          this._postMessage({
            'type': "versionCheck",
            'success': true,
            'currentVersion': ref243,
            'latestVersion': ref242,
            'hasUpdate': ref244
          });
        } else {
          this._postMessage({
            'type': "versionCheck",
            'success': false,
            'currentVersion': CursorProViewProvider.CURRENT_VERSION,
            'error': ref241.error || "获取版本失败"
          });
        }
      } catch (ref245) {
        this._postMessage({
          'type': "versionCheck",
          'success': false,
          'currentVersion': CursorProViewProvider.CURRENT_VERSION,
          'error': ref245.message || "请求失败"
        });
      }
    }
    ["_compareVersions"](ref246, ref247) {
      const ref248 = ref246.split('.').map(Number);
      const ref249 = ref247.split('.').map(Number);
      const ref250 = Math.max(ref248.length, ref249.length);
      for (let ref251 = 0x0; ref251 < ref250; ref251++) {
        const ref252 = ref248[ref251] || 0x0;
        const ref253 = ref249[ref251] || 0x0;
        if (ref252 > ref253) {
          return 0x1;
        }
        if (ref252 < ref253) {
          return -0x1;
        }
      }
      return 0x0;
    }
  async ["_handleGetCursorRunningPath"]() {
    try {
      const ref254 = process.platform;
      let ref255 = "未找到";
      let ref256 = '';
      const ref257 = vscode.workspace.getConfiguration('cursorpro');
      const ref258 = ref257.get('cursorPath');
      if (ref258 && fs.existsSync(ref258)) {
        ref255 = ref258;
        if (ref254 === "darwin") {
          ref256 = path.join(ref258, 'Contents', "Resources", "app", "package.json");
        } else {
          ref256 = path.join(ref258, "resources", "app", "package.json");
        }
        console.log("[CursorPro] 使用用户配置的路径:", ref258);
      } else {
        if (ref254 === "win32") {
          try {
            const {
              stdout: ref259
            } = await execAsync("wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul");
            const ref260 = ref259.match(/ExecutablePath=(.+)/);
            if (ref260 && ref260[0x1]) {
              const ref261 = ref260[0x1].trim();
              ref255 = path.dirname(ref261);
              ref256 = path.join(ref255, "resources", "app", "package.json");
            }
          } catch (ref262) {
            console.log("[CursorPro] WMIC 获取路径失败:", ref262);
          }
          if (ref255 === "未找到") {
            const ref263 = process.env.LOCALAPPDATA || '';
            const ref264 = [path.join(ref263, 'Programs', 'cursor'), path.join(ref263, "cursor")];
            for (const ref265 of ref264) {
              const ref266 = path.join(ref265, "resources", "app", "package.json");
              if (fs.existsSync(ref266)) {
                ref255 = ref265;
                ref256 = ref266;
                break;
              }
            }
          }
        } else {
          if (ref254 === "darwin") {
            ref255 = (await this._getCursorInstallPath()) || "/Applications/Cursor.app";
            ref256 = path.join(ref255, 'Contents', "Resources", 'app', "package.json");
          } else {
            const ref267 = process.env.HOME || '';
            const ref268 = ["/usr/share/cursor", path.join(ref267, ".local", "share", "cursor")];
            for (const ref269 of ref268) {
              if (fs.existsSync(ref269)) {
                ref255 = ref269;
                ref256 = path.join(ref269, "resources", 'app', "package.json");
                break;
              }
            }
          }
        }
      }
      const ref270 = ref256 && fs.existsSync(ref256);
      let ref271 = '';
      if (ref270) {
        try {
          const ref272 = fs.readFileSync(ref256, 'utf-8');
          const ref273 = JSON.parse(ref272);
          ref271 = ref273.version || '';
          console.log("[CursorPro] 从路径获取 Cursor 版本:", ref271);
        } catch (ref274) {
          console.log("[CursorPro] 读取 package.json 失败:", ref274);
        }
      }
      this._postMessage({
        'type': 'cursorRunningPath',
        'path': ref255,
        'packageJsonPath': ref256,
        'packageExists': ref270,
        'cursorVersion': ref271
      });
    } catch (ref275) {
      this._postMessage({
        'type': 'cursorRunningPath',
        'path': "获取失败: " + (ref275.message || ref275),
        'packageJsonPath': '',
        'packageExists': false,
        'cursorVersion': ''
      });
    }
  }
  async ["_handleCheckUsageBeforeSwitch"](ref276) {
    try {
      const ref277 = this._context.globalState.get("cursorpro.key");
      if (!ref277) {
        this._postMessage({
          'type': 'usageCheckResult',
          'success': false,
          'error': "未激活授权码"
        });
        return;
      }
      if (!ref276) {
        this._postMessage({
          'type': "usageCheckResult",
          'success': true,
          'needConfirm': false
        });
        return;
      }
      0x0;
      const ref278 = client_1.getApiUrl() + '/api/cursor-accounts/query?email=' + encodeURIComponent(ref276) + "&refresh=false";
      const ref279 = await fetch(ref278);
      const ref280 = await ref279.json();
      if (ref280.success && ref280.data) {
        const ref281 = ref280.data.usage || {};
        const ref282 = parseFloat(ref281.totalCostUSD || 0x0);
        if (ref282 < 0xa) {
          this._postMessage({
            'type': 'usageCheckResult',
            'success': true,
            'needConfirm': true,
            'costUSD': ref282.toFixed(0x2),
            'email': ref276
          });
        } else {
          this._postMessage({
            'type': 'usageCheckResult',
            'success': true,
            'needConfirm': false
          });
        }
      } else {
        this._postMessage({
          'type': 'usageCheckResult',
          'success': true,
          'needConfirm': false
        });
      }
    } catch (ref283) {
      this._postMessage({
        'type': 'usageCheckResult',
        'success': true,
        'needConfirm': false
      });
    }
  }
  async ['_handleManualSeamlessSwitch']() {
    try {
      const ref284 = this._context.globalState.get("cursorpro.key");
      if (!ref284) {
        this._postMessage({
          'type': 'manualSeamlessSwitched',
          'success': false,
          'error': "未激活授权码"
        });
        return;
      }
      0x0;
      const ref285 = await client_1.switchSeamlessToken(ref284);
      if (ref285.switched) {
        if (ref285.email) {
          await this._context.globalState.update("cursorpro.seamlessCurrentAccount", ref285.email);
        }
        this._postMessage({
          'type': 'manualSeamlessSwitched',
          'success': true,
          'email': ref285.email,
          'switchRemaining': ref285.switchRemaining
        });
      } else {
        const ref286 = ref285.message || ref285.error || "换号失败";
        this._postMessage({
          'type': 'manualSeamlessSwitched',
          'success': false,
          'error': ref286
        });
      }
    } catch (ref287) {
      const ref288 = ref287?.['message'] || "连接服务器失败";
      this._postMessage({
        'type': 'manualSeamlessSwitched',
        'success': false,
        'error': ref288
      });
    }
  }
  async ["_handleGetCursorPath"]() {
    try {
      const ref289 = process.platform;
      let ref290 = '';
      let ref291 = '';
      if (ref289 === "win32") {
        try {
          const {
            stdout: ref292
          } = await execAsync("wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul");
          const ref293 = ref292.match(/ExecutablePath=(.+)/);
          if (ref293 && ref293[0x1]) {
            const ref294 = ref293[0x1].trim();
            ref290 = path.dirname(ref294);
          }
        } catch (ref295) {
          try {
            const {
              stdout: ref296
            } = await execAsync("powershell -Command \"Get-Process Cursor -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Path\"");
            if (ref296.trim()) {
              ref290 = path.dirname(ref296.trim());
            }
          } catch (ref297) {
            console.warn("[CursorPro] 获取进程路径失败:", ref297);
          }
        }
        const ref298 = process.env.APPDATA || '';
        ref291 = path.join(ref298, "Cursor");
      } else {
        if (ref289 === "darwin") {
          try {
            const {
              stdout: ref299
            } = await execAsync("ps aux | grep -i \"[C]ursor\" | head -1 | awk '{print $11}'");
            if (ref299.trim()) {
              const ref300 = ref299.trim();
              const ref301 = ref300.match(/(.+\.app)/);
              if (ref301) {
                ref290 = ref301[0x1];
              } else {
                ref290 = path.dirname(ref300);
              }
            }
          } catch (ref302) {
            console.warn("[CursorPro] 获取进程路径失败:", ref302);
          }
          const ref303 = process.env.HOME || '';
          ref291 = path.join(ref303, 'Library', "Application Support", "Cursor");
        } else {
          try {
            const {
              stdout: ref304
            } = await execAsync("ps aux | grep -i \"[c]ursor\" | head -1 | awk '{print $11}'");
            if (ref304.trim()) {
              ref290 = path.dirname(ref304.trim());
            }
          } catch (ref305) {
            console.warn("[CursorPro] 获取进程路径失败:", ref305);
          }
          const ref306 = process.env.HOME || '';
          ref291 = path.join(ref306, '.config', "Cursor");
        }
      }
      if (!ref290) {
        ref290 = '未检测到运行中的Cursor进程';
      }
      let ref307 = '';
      if (ref290 && !ref290.includes("未检测")) {
        if (ref289 === "win32") {
          ref307 = path.join(ref290, 'resources', "app", 'out', 'vs', 'workbench', "workbench.desktop.main.js");
        } else {
          if (ref289 === "darwin") {
            ref307 = path.join(ref290, "Contents", "Resources", "app", 'out', 'vs', 'workbench', 'workbench.desktop.main.js');
          } else {
            ref307 = path.join(ref290, "resources", "app", 'out', 'vs', "workbench", "workbench.desktop.main.js");
          }
        }
        if (!fs.existsSync(ref307)) {
          ref307 = (await this._getWorkbenchPathAsync()) || "未找到";
        }
      } else {
        ref307 = (await this._getWorkbenchPathAsync()) || "未找到";
      }
      const ref308 = ref290 && !ref290.includes("未检测") ? fs.existsSync(ref290) : false;
      const ref309 = ref291 ? fs.existsSync(ref291) : false;
      this._postMessage({
        'type': "cursorPath",
        'cursorPath': ref308 ? ref290 : ref290 || "未找到",
        'dataPath': ref309 ? ref291 : "未找到",
        'workbenchPath': ref307,
        'platform': ref289
      });
    } catch (ref310) {
      this._postMessage({
        'type': "cursorPath",
        'cursorPath': '获取失败',
        'dataPath': '获取失败',
        'workbenchPath': '获取失败',
        'error': ref310.message
      });
    }
  }
  async ['_loadAccountsFromDB']() {
    try {
      0x0;
      const ref311 = account_1.getCursorPaths();
      const {
        dbPath: ref312
      } = ref311;
      if (!fs.existsSync(ref312)) {
        return [];
      }
      0x0;
      const ref313 = await sqlite_1.sqliteGet(ref312, "cursorAuth/accessToken");
      0x0;
      const ref314 = await sqlite_1.sqliteGet(ref312, "cursorAuth/refreshToken");
      0x0;
      const ref315 = await sqlite_1.sqliteGet(ref312, "cursorAuth/cachedEmail");
      if (ref313 && ref315) {
        return [{
          'email': ref315,
          'access_token': ref313,
          'refresh_token': ref314 || ref313
        }];
      }
      return [];
    } catch (ref316) {
      console.error("[CursorPro] 读取账号失败:", ref316);
      return [];
    }
  }
  async ["_sendState"]() {
    const ref317 = this._context.globalState.get("cursorpro.key");
    const ref318 = this._context.globalState.get('cursorpro.expireDate');
    const ref319 = this._context.globalState.get('cursorpro.switchRemaining');
    const ref320 = this._context.globalState.get("cursorpro.switchLimit");
    const ref321 = await this._getCursorVersion();
    0x0;
    const ref322 = client_1.getOnlineStatus();
    this._postMessage({
      'type': "state",
      'isActivated': !!ref317,
      'key': ref317 || '',
      'expireDate': ref318 || '',
      'switchRemaining': ref319 ?? 0x0,
      'switchLimit': ref320 ?? 0x64,
      'cursorVersion': ref321,
      'isOnline': ref322
    });
  }
  async ["_handleRetryConnect"]() {
    try {
      const ref323 = this._context.globalState.get('cursorpro.key');
      if (ref323) {
        0x0;
        await client_1.verifyKey(ref323);
      } else {
        0x0;
        const ref324 = client_1.getApiUrl() + '/api/announcements/latest';
        await fetch(ref324, {
          'method': 'GET'
        });
      }
      await this._sendState();
      this._postMessage({
        'type': "networkStatus",
        'online': true
      });
    } catch (ref325) {
      console.error("[CursorPro] Retry connect failed:", ref325);
      this._postMessage({
        'type': "networkStatus",
        'online': false
      });
    }
  }
  async ["_getCursorVersion"]() {
      try {
        const ref326 = process.platform;
        const ref327 = [];
        const ref328 = await this._getCursorInstallPath();
        if (ref328) {
          if (ref326 === "darwin") {
            ref327.push(path.join(ref328, "Contents", "Resources", 'app', 'package.json'));
          } else {
            ref327.push(path.join(ref328, "resources", 'app', "package.json"));
          }
        }
        if (ref326 === "win32") {
          const ref329 = process.env.LOCALAPPDATA || '';
          const ref330 = process.env.USERPROFILE || '';
          const ref331 = process.env.ProgramFiles || "C:\\Program Files";
          const ref332 = process.env['ProgramFiles(x86)'] || "C:\\Program Files (x86)";
          ref327.push(path.join(ref329, "Programs", "Cursor", "resources", "app", "package.json"), path.join(ref329, "Programs", "cursor", "resources", 'app', "package.json"), path.join(ref330, "AppData", "Local", "Programs", "Cursor", "resources", 'app', "package.json"), path.join(ref331, "Cursor", "resources", 'app', "package.json"), path.join(ref331, "cursor", "resources", 'app', "package.json"), path.join(ref332, "Cursor", "resources", 'app', "package.json"));
        } else {
          if (ref326 === "darwin") {
            ref327.push('/Applications/Cursor.app/Contents/Resources/app/package.json');
          } else {
            const ref333 = process.env.HOME || '';
            ref327.push("/usr/share/cursor/resources/app/package.json", "/opt/Cursor/resources/app/package.json", "/opt/cursor/resources/app/package.json", path.join(ref333, ".local", 'share', "cursor", "resources", 'app', "package.json"));
          }
        }
        for (const ref334 of ref327) {
          try {
            if (fs.existsSync(ref334)) {
              const ref335 = fs.readFileSync(ref334, "utf-8");
              const ref336 = JSON.parse(ref335);
              if (ref336.version) {
                console.log("[CursorPro] 找到 Cursor 版本:", ref336.version, "路径:", ref334);
                return ref336.version;
              }
            }
          } catch (ref337) {
            console.log("[CursorPro] 尝试路径失败:", ref334, ref337);
          }
        }
        try {
          const ref338 = require("vscode");
          if (ref338.version) {
            console.log("[CursorPro] 使用 VS Code API 获取版本:", ref338.version);
            return ref338.version;
          }
        } catch (ref339) {}
        console.log("[CursorPro] 未找到 Cursor 版本，尝试的路径:", ref327);
        return '未知';
      } catch (ref340) {
        console.error("[CursorPro] 获取 Cursor 版本失败:", ref340);
        return '未知';
      }
    }
    ['_postMessage'](ref341) {
      this._view?.["webview"]["postMessage"](ref341);
    }
    ["_getNonce"]() {
      let ref342 = '';
      for (let ref343 = 0x0; ref343 < 0x20; ref343++) {
        ref342 += 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(Math.floor(Math.random() * 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.length));
      }
      return ref342;
    }
    ["_getHtmlContent"](ref344) {
      const ref345 = this._getNonce();
      return "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-" + ref345 + "'; img-src " + ref344.cspSource + " https: data:; font-src " + ref344.cspSource + `; worker-src 'none';">
    <title>CursorPro</title>
    <script nonce="` + ref345 + `">
        // 尽早清理 Service Worker（在 head 中执行，比 body 更早）
        if ('serviceWorker' in navigator) {
            navigator.serviceWorker.getRegistrations().then(function(regs) {
                regs.forEach(function(reg) { reg.unregister(); });
            }).catch(function() {});
        }
    </script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            background: #1e1e1e;
            color: #cccccc;
            padding: 12px;
            font-size: 13px;
        }
        
        .section {
            margin-bottom: 16px;
            padding: 12px;
            background: #252526;
            border-radius: 6px;
        }
        
        .section-title {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 12px;
            font-size: 13px;
            color: #ffffff;
        }
        
        .section-title .icon {
            font-size: 16px;
        }
        
        .status-badge {
            margin-left: auto;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 11px;
        }
        
        .status-badge.inactive {
            background: #6e3232;
            color: #ff6b6b;
        }
        
        .status-badge.active {
            background: #2d4a3e;
            color: #4ade80;
        }
        
        .input-group {
            display: flex;
            gap: 8px;
            margin-bottom: 12px;
        }
        
        input[type="text"] {
            flex: 1;
            padding: 8px 12px;
            background: #3c3c3c;
            border: 1px solid #4a4a4a;
            border-radius: 4px;
            color: #ffffff;
            font-size: 13px;
        }
        
        input[type="text"]::placeholder {
            color: #888888;
        }
        
        input[type="text"]:focus {
            outline: none;
            border-color: #007acc;
        }
        
        .btn {
            padding: 8px 16px;
            border: none;
            border-radius: 4px;
            font-size: 13px;
            cursor: pointer;
            font-weight: 500;
            transition: opacity 0.2s;
        }
        
        .btn:hover {
            opacity: 0.9;
        }
        
        .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        
        .btn-primary {
            background: #007acc;
            color: white;
        }
        
        .btn-purple {
            background: #8b5cf6;
            color: white;
        }
        
        .btn-blue {
            background: #3b82f6;
            color: white;
        }
        
        .btn-red {
            background: #ef4444;
            color: white;
        }
        
        .btn-block {
            display: block;
            width: 100%;
            margin-bottom: 8px;
        }
        
        .info-row {
            display: flex;
            justify-content: space-between;
            padding: 6px 0;
            border-bottom: 1px solid #3c3c3c;
        }
        
        .info-row:last-child {
            border-bottom: none;
        }
        
        .info-label {
            color: #888888;
        }
        
        .info-value {
            color: #ffffff;
        }
        
        .usage-row {
            display: flex;
            gap: 12px;
            margin-bottom: 8px;
        }
        
        .usage-row:last-of-type {
            margin-bottom: 0;
        }
        
        .usage-item {
            flex: 1;
            display: flex;
            justify-content: space-between;
            padding: 6px 10px;
            background: #2d2d2d;
            border-radius: 4px;
        }
        
        .switch-container {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .switch {
            position: relative;
            width: 40px;
            height: 20px;
        }
        
        .switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        
        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #4a4a4a;
            border-radius: 20px;
            transition: 0.3s;
        }
        
        .slider:before {
            position: absolute;
            content: "";
            height: 16px;
            width: 16px;
            left: 2px;
            bottom: 2px;
            background-color: white;
            border-radius: 50%;
            transition: 0.3s;
        }
        
        input:checked + .slider {
            background-color: #8b5cf6;
        }
        
        input:checked + .slider:before {
            transform: translateX(20px);
        }
        
        /* 小尺寸开关样式 */
        .switch-sm {
            position: relative;
            width: 32px;
            height: 16px;
        }
        
        .switch-sm .slider:before {
            height: 12px;
            width: 12px;
            left: 2px;
            bottom: 2px;
        }
        
        .switch-sm input:checked + .slider:before {
            transform: translateX(16px);
        }
        
        .pro-badge {
            background: linear-gradient(90deg, #8b5cf6, #d946ef);
            padding: 2px 6px;
            border-radius: 4px;
            font-size: 10px;
            font-weight: bold;
            color: white;
        }
        
        .footer {
            margin-top: 16px;
            padding: 12px;
            background: linear-gradient(135deg, rgba(60, 60, 60, 0.3) 0%, rgba(40, 40, 40, 0.5) 100%);
            border-radius: 8px;
            border: 1px solid rgba(255, 255, 255, 0.05);
        }
        
        .footer-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .auto-start {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 11px;
            color: #888;
        }
        
        .cursor-version {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 11px;
            color: #666;
            padding: 4px 10px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 12px;
        }
        
        .cursor-version .version-num {
            color: #a78bfa;
            font-weight: 500;
        }
        
        /* 自定义弹窗样式 */
        .modal-overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.85);
            backdrop-filter: blur(4px);
            z-index: 1000;
            justify-content: center;
            align-items: center;
            animation: fadeIn 0.2s ease;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }
        
        @keyframes slideIn {
            from { 
                opacity: 0;
                transform: scale(0.9) translateY(-10px);
            }
            to { 
                opacity: 1;
                transform: scale(1) translateY(0);
            }
        }
        
        .modal-overlay.show {
            display: flex;
        }
        
        .modal-content {
            background: linear-gradient(145deg, #1e1e1e 0%, #2a2a2a 100%);
            border-radius: 12px;
            padding: 16px 20px;
            max-width: 260px;
            width: 90%;
            text-align: center;
            box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.05);
            animation: slideIn 0.2s ease;
        }
        
        .modal-icon {
            width: 44px;
            height: 44px;
            margin: 0 auto 12px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 22px;
        }
        
        .modal-icon.warning {
            background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
            box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
        }
        
        .modal-icon.success {
            background: linear-gradient(135deg, #10b981 0%, #059669 100%);
            box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
        }
        
        .modal-title {
            font-size: 15px;
            font-weight: 600;
            color: #fff;
            margin-bottom: 6px;
        }
        
        .modal-message {
            font-size: 12px;
            color: #9ca3af;
            margin-bottom: 16px;
            line-height: 1.5;
        }
        
        .modal-buttons {
            display: flex;
            gap: 8px;
            justify-content: center;
        }
        
        .modal-btn {
            padding: 8px 16px;
            border: none;
            border-radius: 8px;
            font-size: 12px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.15s ease;
        }
        
        .modal-btn.primary {
            background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
            color: white;
            box-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);
        }
        
        .modal-btn.primary:hover {
            box-shadow: 0 4px 12px rgba(139, 92, 246, 0.5);
        }
        
        .modal-btn.secondary {
            background: rgba(255, 255, 255, 0.08);
            color: #9ca3af;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .modal-btn.secondary:hover {
            background: rgba(255, 255, 255, 0.12);
            color: #fff;
        }
        
        .modal-btn.single {
            background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
            color: white;
            box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);
            min-width: 100px;
        }
        
        .modal-btn.single:hover {
            box-shadow: 0 4px 12px rgba(59, 130, 246, 0.5);
        }
        
        .highlight {
            color: #4ade80;
            font-weight: 600;
        }
        
        .key-display {
            cursor: pointer;
            transition: color 0.2s;
        }
        
        .key-display:hover {
            color: #007acc;
        }
        
        .key-display.copied {
            color: #4ade80 !important;
        }
        
        /* Loading 状态样式 */
        .btn.loading {
            position: relative;
            pointer-events: none;
            opacity: 0.7;
        }
        
        .btn.loading .btn-text {
            visibility: hidden;
        }
        
        .btn.loading::after {
            content: '';
            position: absolute;
            width: 16px;
            height: 16px;
            top: 50%;
            left: 50%;
            margin-left: -8px;
            margin-top: -8px;
            border: 2px solid transparent;
            border-top-color: #fff;
            border-radius: 50%;
            animation: spin 0.8s linear infinite;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        
        .refresh-btn.loading {
            animation: spin 1s linear infinite;
            pointer-events: none;
        }
        
        /* 公告样式 */
        .announcement-badge {
            margin-left: auto;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 11px;
            text-transform: uppercase;
        }
        
        .announcement-badge.info {
            background: #1e3a5f;
            color: #60a5fa;
        }
        
        .announcement-badge.warning {
            background: #5c4a1f;
            color: #fbbf24;
        }
        
        .announcement-badge.error {
            background: #6e3232;
            color: #f87171;
        }
        
        .announcement-badge.success {
            background: #2d4a3e;
            color: #4ade80;
        }
        
        .announcement-title {
            font-size: 14px;
            font-weight: 600;
            color: #ffffff;
            margin-bottom: 8px;
            line-height: 1.4;
        }
        
        .announcement-content {
            font-size: 12px;
            color: #b0b0b0;
            line-height: 1.6;
            word-break: break-word;
        }
        
        .announcement-link {
            color: #60a5fa;
            text-decoration: none;
            border-bottom: 1px dashed #60a5fa;
            transition: all 0.2s;
            cursor: pointer;
        }
        
        .announcement-link:hover {
            color: #93c5fd;
            border-bottom-color: #93c5fd;
        }
        
        /* Toast 通知样式 */
        .toast-container {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            display: flex;
            justify-content: center;
            padding: 12px;
            pointer-events: none;
            z-index: 2000;
        }
        
        .toast {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px 16px;
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            border: 1px solid rgba(74, 222, 128, 0.3);
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4), 0 0 20px rgba(74, 222, 128, 0.1);
            transform: translateY(-100px);
            opacity: 0;
            transition: all 0.3s ease;
            pointer-events: auto;
        }
        
        .toast.show {
            transform: translateY(0);
            opacity: 1;
        }
        
        .toast-icon {
            font-size: 16px;
        }
        
        .toast-message {
            font-size: 12px;
            color: #e0e0e0;
            max-width: 280px;
            word-break: break-all;
        }
        
        /* 离线状态提示样式 */
        .offline-banner {
            display: none;
            align-items: center;
            gap: 8px;
            padding: 10px 14px;
            margin-bottom: 12px;
            background: linear-gradient(135deg, #7f1d1d 0%, #991b1b 100%);
            border: 1px solid rgba(239, 68, 68, 0.3);
            border-radius: 8px;
            animation: slideDown 0.3s ease;
        }
        
        .offline-banner.show {
            display: flex;
        }
        
        @keyframes slideDown {
            from {
                opacity: 0;
                transform: translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        .offline-banner .offline-icon {
            font-size: 18px;
            flex-shrink: 0;
        }
        
        .offline-banner .offline-text {
            flex: 1;
        }
        
        .offline-banner .offline-title {
            font-size: 12px;
            font-weight: 600;
            color: #fca5a5;
            margin-bottom: 2px;
        }
        
        .offline-banner .offline-desc {
            font-size: 11px;
            color: #fecaca;
            opacity: 0.8;
        }
        
        .offline-banner .retry-btn {
            padding: 4px 10px;
            background: rgba(255, 255, 255, 0.15);
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 4px;
            color: #fff;
            font-size: 11px;
            cursor: pointer;
            transition: all 0.2s;
            flex-shrink: 0;
        }
        
        .offline-banner .retry-btn:hover {
            background: rgba(255, 255, 255, 0.25);
        }
        
        .offline-banner .retry-btn.loading {
            pointer-events: none;
            opacity: 0.7;
        }
        
        /* 顶部更新提醒条 */
        .update-banner {
            position: sticky;
            top: 0;
            left: 0;
            right: 0;
            background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
            color: #fff;
            padding: 8px 12px;
            font-size: 12px;
            display: none;
            align-items: center;
            justify-content: center;
            gap: 8px;
            z-index: 1000;
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
        }
        .update-banner.show {
            display: flex;
        }
        .update-banner .update-icon {
            font-size: 14px;
        }
        .update-banner .update-text {
            font-weight: 500;
        }
        .update-banner .update-version {
            background: rgba(255,255,255,0.2);
            padding: 2px 6px;
            border-radius: 4px;
            font-size: 11px;
        }
        .update-banner .update-close {
            margin-left: auto;
            background: none;
            border: none;
            color: #fff;
            cursor: pointer;
            font-size: 16px;
            padding: 0 4px;
            opacity: 0.8;
        }
        .update-banner .update-close:hover {
            opacity: 1;
        }
        
    </style>
</head>
<body>
    <!-- 顶部更新提醒条 -->
    <div class="update-banner" id="updateBanner">
        <span class="update-icon">🚀</span>
        <span class="update-text">发现新版本</span>
        <span class="update-version" id="updateBannerVersion">v0.0</span>
        <button class="update-close" id="updateBannerClose" title="关闭">×</button>
    </div>
    
    <!-- 管理员权限提示弹窗 -->
    <div class="modal-overlay" id="adminModal">
        <div class="modal-content">
            <div class="modal-icon warning">🔐</div>
            <div class="modal-title">需要管理员权限</div>
            <div class="modal-message">
                请关闭 Cursor，右键点击图标<br>
                选择 <span class="highlight">以管理员身份运行</span>
            </div>
            <div class="modal-buttons">
                <button class="modal-btn single" id="adminModalClose">我知道了</button>
            </div>
        </div>
    </div>
    
    <!-- 重置机器码权限提示弹窗 -->
    <div class="modal-overlay" id="resetPermissionModal">
        <div class="modal-content">
            <div class="modal-icon warning">🔐</div>
            <div class="modal-title">需要管理员权限</div>
            <div class="modal-message" style="text-align: left; line-height: 1.8;">
                重置机器码需要管理员权限才能完整执行。<br><br>
                请按以下步骤操作：<br>
                <span style="color: #fbbf24;">1.</span> 完全关闭 Cursor<br>
                <span style="color: #fbbf24;">2.</span> 右键点击 Cursor 图标<br>
                <span style="color: #fbbf24;">3.</span> 选择 <span class="highlight">以管理员身份运行</span><br>
                <span style="color: #fbbf24;">4.</span> 再次点击重置机器码
            </div>
            <div class="modal-buttons">
                <button class="modal-btn single" id="resetPermissionClose">我知道了</button>
            </div>
        </div>
    </div>
    
    <!-- 重启提示弹窗 -->
    <div class="modal-overlay" id="restartModal">
        <div class="modal-content">
            <div class="modal-icon success">✓</div>
            <div class="modal-title" id="restartModalTitle">操作成功</div>
            <div class="modal-message">
                需要重启 Cursor 才能生效
            </div>
            <div class="modal-buttons">
                <button class="modal-btn primary" id="restartNowBtn">立即重启</button>
                <button class="modal-btn secondary" id="restartLaterBtn">稍后</button>
            </div>
        </div>
    </div>
    
    <!-- 激活码过期弹窗 -->
    <div class="modal-overlay" id="expiredModal">
        <div class="modal-content">
            <div class="modal-icon" style="background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);">⏰</div>
            <div class="modal-title">激活码已过期</div>
            <div class="modal-message">
                您的激活码已过期，请续费后继续使用
            </div>
            <div class="modal-buttons">
                <button class="modal-btn single" id="expiredModalClose">我知道了</button>
            </div>
        </div>
    </div>
    
    <!-- 清理环境确认弹窗 -->
    <div class="modal-overlay" id="cleanEnvModal">
        <div class="modal-content">
            <div class="modal-icon warning">⚠️</div>
            <div class="modal-title">清理 Cursor 环境</div>
            <div class="modal-message">
                此操作会删除所有配置和登录信息<br>确定要继续吗？
            </div>
            <div class="modal-buttons">
                <button class="modal-btn primary" id="cleanEnvConfirmBtn">确定清理</button>
                <button class="modal-btn secondary" id="cleanEnvCancelBtn">取消</button>
            </div>
        </div>
    </div>
    
    <!-- 换号确认弹窗 -->
    <div class="modal-overlay" id="switchConfirmModal">
        <div class="modal-content">
            <div class="modal-icon warning">💰</div>
            <div class="modal-title">账号未使用完</div>
            <div class="modal-message">
                当前账号 <span id="switchConfirmEmail" style="color:#4caf50;"></span><br>
                已用额度: <span id="switchConfirmCost" style="color:#ff9800;font-weight:bold;">$0.00</span> (不足 $10)<br><br>
                确定要换号吗？
            </div>
            <div class="modal-buttons">
                <button class="modal-btn primary" id="switchConfirmBtn">确认换号</button>
                <button class="modal-btn secondary" id="switchCancelBtn">取消</button>
            </div>
        </div>
    </div>
    
    <!-- 离线状态提示 -->
    <div class="offline-banner" id="offlineBanner">
        <span class="offline-icon">📡</span>
        <div class="offline-text">
            <div class="offline-title">网络连接失败</div>
            <div class="offline-desc">请检查网络后重试</div>
        </div>
        <button class="retry-btn" id="retryConnectBtn">重试</button>
    </div>
    
    <!-- 软件授权 -->
    <div class="section">
        <div class="section-title">
            <span class="icon">🔐</span>
            <span>软件授权</span>
            <span class="status-badge" id="authStatus">未授权</span>
        </div>
        
        <div class="input-group">
            <input type="text" id="keyInput" placeholder="请输入CDK激活码">
            <button class="btn btn-primary" id="activateBtn"><span class="btn-text">激活</span></button>
        </div>
        
        <div class="info-row">
            <span class="info-label">激活码</span>
            <span class="info-value key-display" id="keyDisplay" title="点击复制">尚未激活</span>
        </div>
        <div class="info-row">
            <span class="info-label">到期时间</span>
            <span class="info-value" id="expireDate">尚未激活</span>
        </div>
    </div>
    
    <!-- 账号数据 (已隐藏) -->
    <div class="section" style="display:none;">
        <div class="section-title">
            <span class="icon">👤</span>
            <span>账号数据</span>
            <span class="status-badge" id="accountStatus">未激活</span>
        </div>
        
        <div class="info-row">
            <span class="info-label">CI积分余额</span>
            <span class="info-value">0 <button style="background:none;border:none;color:#007acc;cursor:pointer;">🔄</button></span>
        </div>
        
        <button class="btn btn-purple btn-block" id="switchBtn" disabled>换号</button>
        <button class="btn btn-blue btn-block" id="resetBtn">重置机器码</button>
        <button class="btn btn-blue btn-block" id="disableUpdateBtn">禁用自动更新</button>
        <button class="btn btn-blue btn-block" id="cleanEnvBtn">清理Cursor环境</button>
        <button class="btn btn-red btn-block" id="disableBtn">停用插件</button>
    </div>
    
    <!-- 无感换号 -->
    <div class="section">
        <div class="section-title">
            <span class="icon">⚡</span>
            <span>无感换号</span>
            <span class="status-badge" id="seamlessStatus">未启用</span>
        </div>
        
        <div class="info-row">
            <span class="info-label">积分</span>
            <span class="info-value" id="seamlessSwitchRemaining">0</span>
        </div>
        
        <div class="info-row">
            <span class="info-label">当前账号</span>
            <span class="info-value" style="font-size:11px;" id="seamlessCurrentAccount">未分配</span>
        </div>
        
        <div class="switch-container" style="margin: 12px 0;">
            <span>免魔法模式</span>
            <span class="pro-badge">PRO</span>
            <span style="margin-left: auto; color: #888; font-size: 11px;"></span>
            <label class="switch">
                <input type="checkbox" id="seamlessProxySwitch">
                <span class="slider"></span>
            </label>
        </div>
        
        <button class="btn btn-purple btn-block" id="enableSeamlessBtn" disabled><span class="btn-text">启用无感换号</span></button>
        <button class="btn btn-red btn-block" id="seamlessResetMachineBtn" style="display:none;"><span class="btn-text">重置机器码</span></button>
        <button class="btn btn-red btn-block" id="disableSeamlessBtn" style="display:none;"><span class="btn-text">禁用无感换号</span></button>
        <button class="btn btn-blue btn-block" id="manualSwitchBtn" style="display:none;" disabled><span class="btn-text">一键换号(扣1积分)</span></button>
    </div>
    
    <!-- 账号用量 -->
    <div class="section" id="usageSection" style="display:none;">
        <div class="section-title">
            <span class="icon">📊</span>
            <span>账号用量</span>
            <button class="btn" style="margin-left:auto;padding:4px 8px;font-size:11px;background:#3c3c3c;" id="refreshUsageBtn">🔄</button>
        </div>
        
        <div class="usage-row">
            <div class="usage-item">
                <span class="info-label">会员类型</span>
                <span class="info-value" id="usageMemberType">-</span>
            </div>
            <div class="usage-item">
                <span class="info-label">试用剩余</span>
                <span class="info-value" id="usageTrialDays">-</span>
            </div>
        </div>
        <div class="usage-row">
            <div class="usage-item">
                <span class="info-label">请求次数</span>
                <span class="info-value" id="usageRequestCount">-</span>
            </div>
            <div class="usage-item">
                <span class="info-label">已用额度</span>
                <span class="info-value" id="usageCostUSD">-</span>
            </div>
        </div>
        <p style="font-size:10px;color:#666;margin-top:8px;text-align:center;" id="usageUpdateTime">-</p>
    </div>
    
    <!-- 公告 -->
    <div class="section" id="announcementSection" style="display:none;">
        <div class="section-title">
            <span class="icon" id="announcementIcon">📢</span>
            <span>公告</span>
            <span class="announcement-badge" id="announcementBadge">info</span>
        </div>
        <div class="announcement-title" id="announcementTitle"></div>
        <div class="announcement-content" id="announcementContent"></div>
        <p style="font-size:10px;color:#666;margin-top:8px;text-align:right;" id="announcementTime"></p>
    </div>
    
    <!-- 版本信息 -->
    <div class="section" id="versionSection">
        <div class="section-title">
            <span class="icon">📦</span>
            <span>版本信息</span>
            <span class="status-badge" id="versionStatus" style="display:none;">有更新</span>
        </div>
        <div class="info-row">
            <span class="info-label">当前版本</span>
            <span class="info-value" id="currentVersion">-</span>
        </div>
        <div class="info-row" id="latestVersionRow" style="display:none;">
            <span class="info-label">最新版本</span>
            <span class="info-value" id="latestVersion" style="color:#4caf50;">-</span>
        </div>
        <p id="updateHint" style="font-size:11px;color:#ff9800;margin-top:8px;display:none;">
            ⚠️ 发现新版本，请更新插件以获取最新功能
        </p>
    </div>
    
    <!-- 页脚 -->
    <div class="footer">
        <div class="footer-row">
            <div class="auto-start">
                <span>自动启动</span>
                <label class="switch switch-sm">
                    <input type="checkbox" id="autoStartSwitch" checked>
                    <span class="slider"></span>
                </label>
            </div>
            <div class="cursor-version">
                <span>Cursor</span>
                <span class="version-num" id="cursorVersion">0.0.0</span>
            </div>
        </div>
        <div class="footer-row" style="margin-top: 8px;">
            <div style="font-size: 10px; color: #666; word-break: break-all;">
                <span>路径: </span>
                <span id="cursorPath" style="color: #888;">获取中...</span>
            </div>
        </div>
    </div>
    
    <!-- Toast 通知 -->
    <div class="toast-container" id="toastContainer">
        <div class="toast" id="toast">
            <span class="toast-icon" id="toastIcon">✅</span>
            <span class="toast-message" id="toastMessage"></span>
        </div>
    </div>
    
    <script nonce="` + ref345 + `">
        const vscode = acquireVsCodeApi();
        
        // 元素引用
        const keyInput = document.getElementById('keyInput');
        const activateBtn = document.getElementById('activateBtn');
        const switchBtn = document.getElementById('switchBtn');
        const resetBtn = document.getElementById('resetBtn');
        const disableUpdateBtn = document.getElementById('disableUpdateBtn');
        const cleanEnvBtn = document.getElementById('cleanEnvBtn');
        const disableBtn = document.getElementById('disableBtn');
        const authStatus = document.getElementById('authStatus');
        const accountStatus = document.getElementById('accountStatus');
        const keyDisplay = document.getElementById('keyDisplay');
        const switchCount = document.getElementById('switchCount');
        const expireDate = document.getElementById('expireDate');
        const cursorVersion = document.getElementById('cursorVersion');
        const cursorPath = document.getElementById('cursorPath');
        
        // 离线状态元素
        const offlineBanner = document.getElementById('offlineBanner');
        const retryConnectBtn = document.getElementById('retryConnectBtn');
        
        // 无感换号元素
        const seamlessStatus = document.getElementById('seamlessStatus');
        const seamlessProxySwitch = document.getElementById('seamlessProxySwitch');
        const enableSeamlessBtn = document.getElementById('enableSeamlessBtn');
        const disableSeamlessBtn = document.getElementById('disableSeamlessBtn');
        const manualSwitchBtn = document.getElementById('manualSwitchBtn');
        const seamlessResetMachineBtn = document.getElementById('seamlessResetMachineBtn');
        const seamlessSwitchRemaining = document.getElementById('seamlessSwitchRemaining');
        const seamlessCurrentAccount = document.getElementById('seamlessCurrentAccount');
        
        // 用量显示元素
        const usageSection = document.getElementById('usageSection');
        const refreshUsageBtn = document.getElementById('refreshUsageBtn');
        const usageMemberType = document.getElementById('usageMemberType');
        const usageTrialDays = document.getElementById('usageTrialDays');
        const usageRequestCount = document.getElementById('usageRequestCount');
        const usageCostUSD = document.getElementById('usageCostUSD');
        const usageUpdateTime = document.getElementById('usageUpdateTime');
        
        // 公告元素
        const announcementSection = document.getElementById('announcementSection');
        const announcementIcon = document.getElementById('announcementIcon');
        const announcementBadge = document.getElementById('announcementBadge');
        const announcementTitle = document.getElementById('announcementTitle');
        const announcementContent = document.getElementById('announcementContent');
        const announcementTime = document.getElementById('announcementTime');
        
        // 版本元素
        const versionSection = document.getElementById('versionSection');
        const versionStatus = document.getElementById('versionStatus');
        const currentVersionEl = document.getElementById('currentVersion');
        const latestVersionEl = document.getElementById('latestVersion');
        const latestVersionRow = document.getElementById('latestVersionRow');
        const updateHint = document.getElementById('updateHint');
        
        // 顶部更新提醒条
        const updateBanner = document.getElementById('updateBanner');
        const updateBannerVersion = document.getElementById('updateBannerVersion');
        const updateBannerClose = document.getElementById('updateBannerClose');
        
        // Toast 元素
        const toast = document.getElementById('toast');
        const toastIcon = document.getElementById('toastIcon');
        const toastMessage = document.getElementById('toastMessage');
        let toastTimer = null;
        
        // 显示 Toast 通知
        function showToast(message, icon = '✅', duration = 10000) {
            // 清除之前的定时器
            if (toastTimer) {
                clearTimeout(toastTimer);
            }
            
            toastIcon.textContent = icon;
            toastMessage.textContent = message;
            toast.classList.add('show');
            
            // 设置自动隐藏
            toastTimer = setTimeout(() => {
                toast.classList.remove('show');
            }, duration);
        }
        
        // 禁用换号按钮并显示倒计时
        let switchBtnCountdownTimer = null;
        const originalSwitchBtnText = '一键换号(扣1积分)';
        
        function disableSwitchBtnWithCountdown(seconds) {
            // 清除之前的定时器
            if (switchBtnCountdownTimer) {
                clearInterval(switchBtnCountdownTimer);
            }
            
            let remaining = seconds;
            manualSwitchBtn.disabled = true;
            manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';
            
            switchBtnCountdownTimer = setInterval(() => {
                remaining--;
                if (remaining <= 0) {
                    clearInterval(switchBtnCountdownTimer);
                    switchBtnCountdownTimer = null;
                    manualSwitchBtn.disabled = false;
                    manualSwitchBtn.querySelector('.btn-text').textContent = originalSwitchBtnText;
                } else {
                    manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';
                }
            }, 1000);
        }
        
        // 弹窗元素
        const adminModal = document.getElementById('adminModal');
        const adminModalClose = document.getElementById('adminModalClose');
        const resetPermissionModal = document.getElementById('resetPermissionModal');
        const resetPermissionClose = document.getElementById('resetPermissionClose');
        const restartModal = document.getElementById('restartModal');
        const restartModalTitle = document.getElementById('restartModalTitle');
        const restartNowBtn = document.getElementById('restartNowBtn');
        const restartLaterBtn = document.getElementById('restartLaterBtn');
        const expiredModal = document.getElementById('expiredModal');
        const expiredModalClose = document.getElementById('expiredModalClose');
        const cleanEnvModal = document.getElementById('cleanEnvModal');
        const cleanEnvConfirmBtn = document.getElementById('cleanEnvConfirmBtn');
        const cleanEnvCancelBtn = document.getElementById('cleanEnvCancelBtn');
        
        // 换号确认弹窗元素
        const switchConfirmModal = document.getElementById('switchConfirmModal');
        const switchConfirmEmail = document.getElementById('switchConfirmEmail');
        const switchConfirmCost = document.getElementById('switchConfirmCost');
        const switchConfirmBtn = document.getElementById('switchConfirmBtn');
        const switchCancelBtn = document.getElementById('switchCancelBtn');
        
        // 显示管理员权限弹窗
        function showAdminModal() {
            adminModal.classList.add('show');
        }
        
        // 显示重置机器码权限提示弹窗
        function showAdminPermissionModal() {
            resetPermissionModal.classList.add('show');
        }
        
        // 重置机器码权限弹窗 - 关闭按钮
        resetPermissionClose.addEventListener('click', () => {
            resetPermissionModal.classList.remove('show');
        });
        
        // 点击遮罩关闭权限提示弹窗
        resetPermissionModal.addEventListener('click', (e) => {
            if (e.target === resetPermissionModal) {
                resetPermissionModal.classList.remove('show');
            }
        });
        
        // 显示重启提示弹窗
        let restartModalAction = 'reload'; // 'reload' 或 'close'
        
        function showRestartModal(title, action = 'reload') {
            restartModalTitle.textContent = title || '操作成功';
            restartModalAction = action;
            // 根据操作类型更新按钮文字
            restartNowBtn.textContent = action === 'close' ? '立即关闭 Cursor' : '立即重启';
            restartModal.classList.add('show');
        }
        
        // 显示过期弹窗
        function showExpiredModal() {
            expiredModal.classList.add('show');
        }
        
        // 关闭管理员弹窗
        adminModalClose.addEventListener('click', () => {
            adminModal.classList.remove('show');
        });
        
        // 点击遮罩关闭管理员弹窗
        adminModal.addEventListener('click', (e) => {
            if (e.target === adminModal) {
                adminModal.classList.remove('show');
            }
        });
        
        // 立即重启/关闭按钮
        restartNowBtn.addEventListener('click', () => {
            restartModal.classList.remove('show');
            if (restartModalAction === 'close') {
                // 完全关闭 Cursor
                vscode.postMessage({ type: 'closeCursor' });
            } else {
                // 重新加载窗口
            vscode.postMessage({ type: 'reloadWindow' });
            }
        });
        
        // 稍后手动按钮
        restartLaterBtn.addEventListener('click', () => {
            restartModal.classList.remove('show');
        });
        
        // 点击遮罩关闭重启弹窗
        restartModal.addEventListener('click', (e) => {
            if (e.target === restartModal) {
                restartModal.classList.remove('show');
            }
        });
        
        // 关闭过期弹窗
        expiredModalClose.addEventListener('click', () => {
            expiredModal.classList.remove('show');
        });
        
        // 点击遮罩关闭过期弹窗
        expiredModal.addEventListener('click', (e) => {
            if (e.target === expiredModal) {
                expiredModal.classList.remove('show');
            }
        });
        
        // 当前账号邮箱（用于查询用量）
        let currentAccountEmail = '';
        let usageRefreshInterval = null;
        // 存储完整激活码（用于复制）
        let fullActivationKey = '';
        // 当前剩余换号次数
        let currentSwitchRemaining = 0;
        // 当前到期时间
        let currentExpireDate = '';
        
        // 检查卡密是否已过期
        function isKeyExpired() {
            if (!currentExpireDate) return true;
            try {
                const expireTime = new Date(currentExpireDate).getTime();
                return Date.now() > expireTime;
            } catch {
                return true;
            }
        }
        
        // 格式化到期时间为北京时间
        function formatExpireDate(dateStr) {
            if (!dateStr) return '';
            try {
                // 后端返回的时间没有时区标识，假设是 UTC 时间
                // 将空格替换为T，并添加Z表示UTC
                let utcStr = dateStr;
                if (!dateStr.includes('T') && !dateStr.includes('Z') && !dateStr.includes('+')) {
                    utcStr = dateStr.replace(' ', 'T') + 'Z';
                }
                const date = new Date(utcStr);
                
                // 使用中国时区格式化（UTC+8）
                return date.toLocaleString('zh-CN', {
                    timeZone: 'Asia/Shanghai',
                    year: 'numeric',
                    month: '2-digit',
                    day: '2-digit',
                    hour: '2-digit',
                    minute: '2-digit',
                    second: '2-digit',
                    hour12: false
                });
            } catch {
                return dateStr;  // 格式化失败返回原始值
            }
        }
        
        // 隐藏激活码后几位
        function maskKey(key) {
            if (!key || key.length <= 8) return key;
            return key.substring(0, key.length - 4) + '****';
        }
        
        // 点击激活码复制
        keyDisplay.addEventListener('click', () => {
            if (!fullActivationKey) return;
            navigator.clipboard.writeText(fullActivationKey).then(() => {
                keyDisplay.classList.add('copied');
                const originalText = keyDisplay.textContent;
                keyDisplay.textContent = '已复制!';
                setTimeout(() => {
                    keyDisplay.textContent = maskKey(fullActivationKey);
                    keyDisplay.classList.remove('copied');
                }, 1000);
            }).catch(() => {
                // 降级方案
                const textarea = document.createElement('textarea');
                textarea.value = fullActivationKey;
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
                keyDisplay.classList.add('copied');
                keyDisplay.textContent = '已复制!';
                setTimeout(() => {
                    keyDisplay.textContent = maskKey(fullActivationKey);
                    keyDisplay.classList.remove('copied');
                }, 1000);
            });
        });
        
        // Loading 状态控制
        function setButtonLoading(btn, loading) {
            if (loading) {
                btn.classList.add('loading');
                btn.disabled = true;
            } else {
                btn.classList.remove('loading');
                // 注意：某些按钮可能需要保持禁用状态，由调用方控制
            }
        }
        
        function setRefreshLoading(btn, loading) {
            if (loading) {
                btn.classList.add('loading');
            } else {
                btn.classList.remove('loading');
            }
        }
        
        // 获取初始状态
        vscode.postMessage({ type: 'getState' });
        vscode.postMessage({ type: 'getSeamlessStatus' });
        vscode.postMessage({ type: 'getUserSwitchStatus' });
        vscode.postMessage({ type: 'getProxyStatus' });
        vscode.postMessage({ type: 'getAnnouncement' });
        vscode.postMessage({ type: 'checkVersion' });
        vscode.postMessage({ type: 'getCursorRunningPath' });
        
        // 激活按钮
        activateBtn.addEventListener('click', () => {
            const key = keyInput.value.trim();
            if (!key) {
                return;
            }
            setButtonLoading(activateBtn, true);
            vscode.postMessage({ type: 'activate', key });
        });
        
        // 换号按钮
        switchBtn.addEventListener('click', () => {
            vscode.postMessage({ type: 'switch' });
        });
        
        // 重置机器码按钮
        resetBtn.addEventListener('click', () => {
            vscode.postMessage({ type: 'resetMachineId' });
        });
        
        // 禁用自动更新按钮
        disableUpdateBtn.addEventListener('click', () => {
            vscode.postMessage({ type: 'disableUpdate' });
        });
        
        // 清理Cursor环境按钮 - 显示确认弹窗
        cleanEnvBtn.addEventListener('click', () => {
            cleanEnvModal.classList.add('show');
        });
        
        // 确认清理
        cleanEnvConfirmBtn.addEventListener('click', () => {
            cleanEnvModal.classList.remove('show');
            vscode.postMessage({ type: 'cleanEnv' });
        });
        
        // 取消清理
        cleanEnvCancelBtn.addEventListener('click', () => {
            cleanEnvModal.classList.remove('show');
        });
        
        // 点击遮罩关闭清理弹窗
        cleanEnvModal.addEventListener('click', (e) => {
            if (e.target === cleanEnvModal) {
                cleanEnvModal.classList.remove('show');
            }
        });
        
        // 停用按钮
        disableBtn.addEventListener('click', () => {
            vscode.postMessage({ type: 'disable' });
        });
        
        // 关闭更新提醒条
        updateBannerClose.addEventListener('click', () => {
            updateBanner.classList.remove('show');
        });
        
        // 免魔法开关
        seamlessProxySwitch.addEventListener('change', (e) => {
            const wantEnabled = e.target.checked;
            
            // 如果要开启免魔法，检查卡密是否过期（只要没过期就可以用，不管换号次数）
            if (wantEnabled && isKeyExpired()) {
                e.target.checked = false;
                showToast('授权码已过期，无法开启免魔法', '⚠️', 3000);
                return;
            }
            
            vscode.postMessage({ 
                type: 'toggleProxy', 
                enabled: wantEnabled,
                url: ''
            });
        });
        
        // 无感换号 - 启用按钮
        enableSeamlessBtn.addEventListener('click', () => {
            setButtonLoading(enableSeamlessBtn, true);
            vscode.postMessage({ type: 'injectSeamless' });
        });
        
        // 无感换号 - 禁用按钮
        disableSeamlessBtn.addEventListener('click', () => {
            setButtonLoading(disableSeamlessBtn, true);
            vscode.postMessage({ type: 'restoreSeamless' });
        });
        
        // 无感换号 - 手动换号按钮（先检查用量）
        manualSwitchBtn.addEventListener('click', () => {
            setButtonLoading(manualSwitchBtn, true);
            // 传递当前显示的账号邮箱
            vscode.postMessage({ type: 'checkUsageBeforeSwitch', email: currentAccountEmail });
        });
        
        // 换号确认弹窗 - 确认按钮
        switchConfirmBtn.addEventListener('click', () => {
            switchConfirmModal.classList.remove('show');
            setButtonLoading(manualSwitchBtn, true);
            vscode.postMessage({ type: 'confirmSwitch' });
        });
        
        // 换号确认弹窗 - 取消按钮
        switchCancelBtn.addEventListener('click', () => {
            switchConfirmModal.classList.remove('show');
            setButtonLoading(manualSwitchBtn, false);
            manualSwitchBtn.disabled = false;
        });
        
        // 换号确认弹窗 - 点击遮罩关闭
        switchConfirmModal.addEventListener('click', (e) => {
            if (e.target === switchConfirmModal) {
                switchConfirmModal.classList.remove('show');
                setButtonLoading(manualSwitchBtn, false);
                manualSwitchBtn.disabled = false;
            }
        });
        
        // 无感换号区域 - 重置机器码按钮
        seamlessResetMachineBtn.addEventListener('click', () => {
            vscode.postMessage({ type: 'resetMachineId' });
        });
        
        // 刷新用量按钮
        refreshUsageBtn.addEventListener('click', () => {
            if (currentAccountEmail) {
                setRefreshLoading(refreshUsageBtn, true);
                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });
            }
        });
        
        // 刷新用量函数
        function refreshUsage() {
            if (currentAccountEmail) {
                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });
            }
        }
        
        // 启动用量定时刷新 (每分钟一次)
        function startUsageRefresh() {
            if (usageRefreshInterval) {
                clearInterval(usageRefreshInterval);
            }
            // 立即刷新一次
            refreshUsage();
            // 每60秒刷新一次
            usageRefreshInterval = setInterval(refreshUsage, 60000);
        }
        
        // 停止用量刷新
        function stopUsageRefresh() {
            if (usageRefreshInterval) {
                clearInterval(usageRefreshInterval);
                usageRefreshInterval = null;
            }
        }
        
        // 更新用量显示
        function updateUsageDisplay(data) {
            if (!data) return;
            
            const subscription = data.subscription || {};
            const usage = data.usage || {};
            
            // 会员类型
            const memberTypeMap = {
                'free_trial': '免费试用',
                'pro': 'Pro会员',
                'free': '免费版',
                'business': '商业版'
            };
            usageMemberType.textContent = memberTypeMap[subscription.membershipType] || subscription.membershipType || '-';
            
            // 试用剩余天数
            if (subscription.daysRemainingOnTrial !== undefined && subscription.daysRemainingOnTrial !== null) {
                usageTrialDays.textContent = subscription.daysRemainingOnTrial + ' 天';
                usageTrialDays.style.color = subscription.daysRemainingOnTrial <= 3 ? '#f87171' : '#4ade80';
            } else {
                usageTrialDays.textContent = '-';
                usageTrialDays.style.color = '#fff';
            }
            
            // 请求次数
            usageRequestCount.textContent = (usage.totalUsageCount || 0) + ' 次';
            
            // 已用额度
            const costUSD = usage.totalCostUSD || 0;
            usageCostUSD.textContent = '$' + costUSD.toFixed(2);
            usageCostUSD.style.color = costUSD > 5 ? '#f87171' : (costUSD > 2 ? '#fbbf24' : '#4ade80');
            
            // 更新时间
            usageUpdateTime.textContent = '更新于 ' + new Date().toLocaleTimeString();
        }
        
        // 解析公告内容中的链接 {文字URL}
        function parseAnnouncementContent(content) {
            if (!content) return '';
            
            // 转义 HTML 特殊字符
            let escaped = content
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;');
            
            // 匹配 {文字https://...} 或 {文字http://...} 格式
            const linkRegex = /\{([^}]+?)(https?:\/\/[^}]+)\}/g;
            
            escaped = escaped.replace(linkRegex, function(match, text, url) {
                return '<a href="' + url + '" class="announcement-link" target="_blank">' + text + '</a>';
            });
            
            // 将换行符转换为 <br>
            escaped = escaped.replace(/\n/g, '<br>');
            
            return escaped;
        }
        
        // 更新公告显示
        function updateAnnouncementDisplay(data) {
            if (!data || !data.is_active) {
                announcementSection.style.display = 'none';
                return;
            }
            
            // 显示公告区域
            announcementSection.style.display = 'block';
            
            // 设置图标和类型徽章
            const typeConfig = {
                'info': { icon: '📢', text: '通知', class: 'info' },
                'warning': { icon: '⚠️', text: '警告', class: 'warning' },
                'error': { icon: '🚨', text: '重要', class: 'error' },
                'success': { icon: '✅', text: '好消息', class: 'success' }
            };
            
            const config = typeConfig[data.type] || typeConfig['info'];
            announcementIcon.textContent = config.icon;
            announcementBadge.textContent = config.text;
            announcementBadge.className = 'announcement-badge ' + config.class;
            
            // 设置标题和内容（解析链接）
            announcementTitle.textContent = data.title || '';
            announcementContent.innerHTML = parseAnnouncementContent(data.content || '');
            
            // 设置时间
            if (data.created_at) {
                const date = new Date(data.created_at);
                announcementTime.textContent = date.toLocaleDateString('zh-CN', {
                    year: 'numeric',
                    month: '2-digit',
                    day: '2-digit',
                    hour: '2-digit',
                    minute: '2-digit'
                });
            } else {
                announcementTime.textContent = '';
            }
        }
        
        // 处理来自扩展的消息
        window.addEventListener('message', event => {
            const message = event.data;
            
            switch (message.type) {
                case 'state':
                    updateUI(message);
                    break;
                case 'activated':
                    setButtonLoading(activateBtn, false);
                    activateBtn.disabled = false;
                    if (message.success) {
                        // 调试日志
                        console.log('[CursorPro] 前端收到激活成功消息:', message);
                        
                        authStatus.textContent = '已授权';
                        authStatus.className = 'status-badge active';
                        accountStatus.textContent = '已激活';
                        accountStatus.className = 'status-badge active';
                        switchBtn.disabled = false;
                        // 更新激活码显示（使用后端返回的 key）
                        fullActivationKey = message.key || keyInput.value;
                        keyDisplay.textContent = maskKey(fullActivationKey);
                        // 更新到期时间
                        console.log('[CursorPro] 更新到期时间:', message.expireDate);
                        currentExpireDate = message.expireDate || '';
                        expireDate.textContent = formatExpireDate(currentExpireDate) || '未知';
                        // 更新换号次数
                        if (message.switchRemaining !== undefined) {
                            currentSwitchRemaining = message.switchRemaining;
                            switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);
                        }
                        // 清空输入框
                        keyInput.value = '';
                        showToast('授权码激活成功！', '✅', 10000);
                    } else {
                        showToast(message.error || '激活失败', '❌', 10000);
                    }
                    break;
                case 'switched':
                    if (message.success) {
                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);
                        showToast('换号成功: ' + (message.email || ''), '✅', 10000);
                    } else {
                        showToast(message.error || '换号失败', '❌', 10000);
                    }
                    break;
                case 'reset':
                    authStatus.textContent = '未授权';
                    authStatus.className = 'status-badge inactive';
                    accountStatus.textContent = '未激活';
                    accountStatus.className = 'status-badge inactive';
                    switchBtn.disabled = true;
                    keyInput.value = '';
                    fullActivationKey = '';
                    keyDisplay.textContent = '尚未激活';
                    expireDate.textContent = '尚未激活';
                    break;
                
                // 激活码状态检查结果
                case 'keyStatusChecked':
                    if (message.valid) {
                        // 激活码有效，更新显示
                        currentExpireDate = message.expireDate || '';
                        currentSwitchRemaining = message.switchRemaining || 0;
                        expireDate.textContent = formatExpireDate(currentExpireDate);
                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);
                    } else if (message.expired) {
                        // 激活码已过期，显示提示并重置状态
                        currentExpireDate = '';
                        currentSwitchRemaining = 0;
                        authStatus.textContent = '已过期';
                        authStatus.className = 'status-badge inactive';
                        authStatus.style.background = '#6e3232';
                        authStatus.style.color = '#ff6b6b';
                        expireDate.textContent = '已过期';
                        expireDate.style.color = '#f87171';
                        switchBtn.disabled = true;
                        enableSeamlessBtn.disabled = true;
                        // 如果免魔法已开启，自动关闭
                        if (seamlessProxySwitch.checked) {
                            seamlessProxySwitch.checked = false;
                            vscode.postMessage({ type: 'toggleProxy', enabled: false, url: '' });
                        }
                        // 显示过期弹窗
                        showExpiredModal();
                    }
                    break;
                
                // 用户换号状态
                case 'userSwitchStatus':
                    const remaining = message.switchRemaining || 0;
                    const canSwitch = remaining > 0;
                    
                    // 更新全局变量
                    currentSwitchRemaining = remaining;
                    
                    seamlessSwitchRemaining.textContent = remaining.toString();
                    seamlessSwitchRemaining.style.color = canSwitch ? '#4ade80' : '#f87171';
                    
                    if (message.lockedAccount) {
                        seamlessCurrentAccount.textContent = message.lockedAccount.email;
                        
                        // 设置当前账号邮箱并启动用量刷新
                        if (message.lockedAccount.email && message.lockedAccount.email !== currentAccountEmail) {
                            currentAccountEmail = message.lockedAccount.email;
                            usageSection.style.display = 'block';
                            startUsageRefresh();
                        }
                    } else {
                        seamlessCurrentAccount.textContent = '未分配';
                        
                        // 没有锁定账号时隐藏用量区域
                        currentAccountEmail = '';
                        usageSection.style.display = 'none';
                        stopUsageRefresh();
                    }
                    
                    // 根据剩余次数控制手动换号按钮状态
                    if (!canSwitch) {
                        manualSwitchBtn.disabled = true;
                    }
                    // 启用无感换号按钮不受积分限制，只有过期才禁用
                    enableSeamlessBtn.disabled = isKeyExpired();
                    
                    // 如果无感换号已启用，显示手动换号按钮和重置机器码按钮
                    if (message.seamlessEnabled && canSwitch) {
                        manualSwitchBtn.style.display = 'block';
                        manualSwitchBtn.disabled = false;
                        setButtonLoading(manualSwitchBtn, false);
                        seamlessResetMachineBtn.style.display = 'block';
                    }
                    break;
                
                // 账号用量
                case 'accountUsage':
                    setRefreshLoading(refreshUsageBtn, false);
                    if (message.success && message.data) {
                        updateUsageDisplay(message.data);
                    } else {
                        usageUpdateTime.textContent = '获取失败: ' + (message.error || '未知错误');
                        usageUpdateTime.style.color = '#f87171';
                    }
                    break;
                
                // 无感换号状态
                case 'seamlessStatus':
                    if (message.is_injected) {
                        seamlessStatus.textContent = '已启用';
                        seamlessStatus.className = 'status-badge active';
                        enableSeamlessBtn.style.display = 'none';
                        disableSeamlessBtn.style.display = 'block';
                        disableSeamlessBtn.disabled = false;
                        setButtonLoading(disableSeamlessBtn, false);
                        manualSwitchBtn.style.display = 'block';
                        manualSwitchBtn.disabled = false;
                        setButtonLoading(manualSwitchBtn, false);
                        seamlessResetMachineBtn.style.display = 'block';
                    } else {
                        seamlessStatus.textContent = '未启用';
                        seamlessStatus.className = 'status-badge inactive';
                        enableSeamlessBtn.style.display = 'block';
                        setButtonLoading(enableSeamlessBtn, false);
                        // 启用按钮不受积分限制，只有过期才禁用
                        enableSeamlessBtn.disabled = isKeyExpired();
                        disableSeamlessBtn.style.display = 'none';
                        manualSwitchBtn.style.display = 'none';
                        seamlessResetMachineBtn.style.display = 'none';
                    }
                    break;
                
                case 'seamlessInjected':
                    setButtonLoading(enableSeamlessBtn, false);
                    enableSeamlessBtn.disabled = false;
                    if (message.success) {
                        seamlessStatus.textContent = '已启用';
                        seamlessStatus.className = 'status-badge active';
                        enableSeamlessBtn.style.display = 'none';
                        disableSeamlessBtn.style.display = 'block';
                        manualSwitchBtn.style.display = 'block';
                        seamlessResetMachineBtn.style.display = 'block';
                        // 刷新用户状态
                        vscode.postMessage({ type: 'getUserSwitchStatus' });
                        // 显示重启提示弹窗
                        if (message.needRestart) {
                            showRestartModal(message.message || '无感换号已启用');
                        }
                    } else {
                        // 如果是权限错误，显示自定义弹窗
                        if (message.needAdmin) {
                            // Mac/Linux 权限问题，显示详细提示
                            var errorMsg = message.error || '没有写入权限';
                            if (message.path) {
                                errorMsg += '\n路径: ' + message.path;
                            }
                            showToast(errorMsg, '🔐', 15000);
                        } else {
                            // 显示详细错误
                            var detailMsg = message.error || '启用失败';
                            if (message.details) {
                                detailMsg += '\n' + message.details;
                            }
                            showToast(detailMsg, '❌', 15000);
                        }
                    }
                    break;
                
                case 'seamlessRestored':
                    setButtonLoading(disableSeamlessBtn, false);
                    disableSeamlessBtn.disabled = false;
                    if (message.success) {
                        seamlessStatus.textContent = '未启用';
                        seamlessStatus.className = 'status-badge inactive';
                        enableSeamlessBtn.style.display = 'block';
                        disableSeamlessBtn.style.display = 'none';
                        manualSwitchBtn.style.display = 'none';
                        seamlessResetMachineBtn.style.display = 'none';
                        // 显示重启提示弹窗
                        if (message.needRestart) {
                            showRestartModal(message.message || '无感换号已禁用');
                        }
                    } else {
                        // 如果是权限错误，显示自定义弹窗
                        if (message.needAdmin) {
                            showAdminModal();
                        } else {
                            showToast(message.error || '禁用失败', '❌', 10000);
                        }
                    }
                    break;
                
                // 用量检查结果
                case 'usageCheckResult':
                    if (message.success) {
                        if (message.needConfirm) {
                            // 需要确认，显示弹窗（按钮保持可用状态，等用户选择）
                            setButtonLoading(manualSwitchBtn, false);
                            manualSwitchBtn.disabled = false;
                            switchConfirmEmail.textContent = message.email || '';
                            switchConfirmCost.textContent = '$' + (message.costUSD || '0.00');
                            switchConfirmModal.classList.add('show');
                        } else {
                            // 不需要确认，直接换号
                            vscode.postMessage({ type: 'confirmSwitch' });
                        }
                    } else {
                        setButtonLoading(manualSwitchBtn, false);
                        manualSwitchBtn.disabled = false;
                        showToast(message.error || '检查失败', '❌', 5000);
                    }
                    break;
                
                case 'manualSeamlessSwitched':
                    setButtonLoading(manualSwitchBtn, false);
                    if (message.success) {
                        seamlessSwitchRemaining.textContent = (message.switchRemaining || 0).toString();
                        seamlessCurrentAccount.textContent = message.email || '未知';
                        // 显示 Toast 通知，10秒后消失
                        showToast('已切换到: ' + (message.email || '新账号') + '，约10秒内自动生效', '✅', 10000);
                        // 刷新状态
                        vscode.postMessage({ type: 'getUserSwitchStatus' });
                        // 禁用按钮10秒，显示倒计时
                        disableSwitchBtnWithCountdown(10);
                    } else {
                        manualSwitchBtn.disabled = false;
                        showToast(message.error || '换号失败', '❌', 5000);
                    }
                    break;
                
                case 'proxyStatus':
                    // 设置免魔法开关状态
                    seamlessProxySwitch.checked = message.enabled;
                    break;
                
                // 公告
                case 'announcement':
                    if (message.success && message.data) {
                        updateAnnouncementDisplay(message.data);
                    } else {
                        announcementSection.style.display = 'none';
                    }
                    break;
                
                // 版本检查
                case 'versionCheck':
                    currentVersionEl.textContent = message.currentVersion || '-';
                    if (message.success && message.hasUpdate) {
                        // 有更新
                        latestVersionEl.textContent = message.latestVersion;
                        latestVersionRow.style.display = 'flex';
                        versionStatus.style.display = 'inline-block';
                        versionStatus.style.background = '#ff9800';
                        updateHint.style.display = 'block';
                        
                        // 显示顶部更新提醒条
                        updateBannerVersion.textContent = 'v' + message.latestVersion;
                        updateBanner.classList.add('show');
                    } else if (message.success) {
                        // 已是最新版
                        versionStatus.textContent = '最新';
                        versionStatus.style.display = 'inline-block';
                        versionStatus.style.background = '#4caf50';
                        latestVersionRow.style.display = 'none';
                        updateHint.style.display = 'none';
                        updateBanner.classList.remove('show');
                    }
                    break;
                
                // Cursor 运行路径
                case 'cursorRunningPath':
                    if (message.path) {
                        const pathText = message.path + (message.packageExists ? ' ✓' : ' ✗');
                        cursorPath.textContent = pathText;
                        cursorPath.style.color = message.packageExists ? '#4ade80' : '#f87171';
                        // 同时更新版本号
                        if (message.cursorVersion) {
                            cursorVersion.textContent = message.cursorVersion;
                        }
                    } else {
                        cursorPath.textContent = '未找到';
                        cursorPath.style.color = '#f87171';
                    }
                    break;
                
                // 管理员权限不足提示
                case 'adminPermissionRequired':
                    showAdminPermissionModal();
                    break;
                
                // 机器码重置
                case 'machineIdReset':
                    if (message.success && message.needRestart) {
                        // 机器码重置需要完全关闭 Cursor，不是 reload
                        showRestartModal(message.message || '机器码重置成功', 'close');
                    }
                    break;
                
                // 通用 Toast 消息
                case 'showToast':
                    showToast(message.message || '', message.icon || '📢', 10000);
                    break;
                
                // 网络状态
                case 'networkStatus':
                    updateOfflineStatus(!message.online);
                    break;
            }
        });
        
        // 离线状态显示/隐藏
        let wasOffline = false; // 跟踪之前是否离线
        function updateOfflineStatus(isOffline) {
            if (isOffline) {
                offlineBanner.classList.add('show');
                wasOffline = true;
            } else {
                offlineBanner.classList.remove('show');
                // 只有从离线恢复到在线时才刷新状态
                if (wasOffline) {
                    wasOffline = false;
                    vscode.postMessage({ type: 'getState' });
                    vscode.postMessage({ type: 'getUserSwitchStatus' });
                }
            }
        }
        
        // 重试连接按钮
        retryConnectBtn.addEventListener('click', async () => {
            retryConnectBtn.classList.add('loading');
            retryConnectBtn.textContent = '连接中...';
            
            // 发起真正的网络请求来测试网络
            vscode.postMessage({ type: 'retryConnect' });
            
            // 5秒后恢复按钮状态（给网络请求足够时间）
            setTimeout(() => {
                retryConnectBtn.classList.remove('loading');
                retryConnectBtn.textContent = '重试';
            }, 5000);
        });
        
        function updateUI(state) {
            if (state.isActivated) {
                authStatus.textContent = '已授权';
                authStatus.className = 'status-badge active';
                accountStatus.textContent = '已激活';
                accountStatus.className = 'status-badge active';
                switchBtn.disabled = false;
                fullActivationKey = state.key;
                keyDisplay.textContent = maskKey(fullActivationKey);
                // 更新到期时间
                currentExpireDate = state.expireDate || '';
                expireDate.textContent = formatExpireDate(currentExpireDate);
                // 更新换号次数
                if (state.switchRemaining !== undefined) {
                    currentSwitchRemaining = state.switchRemaining;
                    switchCount.textContent = state.switchRemaining + '/' + (state.switchLimit || 100);
                }
                // 启用无感换号按钮（只有过期才禁用）
                enableSeamlessBtn.disabled = isKeyExpired();
            }
            cursorVersion.textContent = state.cursorVersion || '0.0.0';
            
            // 根据网络状态显示/隐藏离线提示
            if (state.isOnline === false) {
                offlineBanner.classList.add('show');
                wasOffline = true;
            } else if (state.isOnline === true) {
                // 网络恢复，隐藏离线提示
                offlineBanner.classList.remove('show');
                wasOffline = false;
            }
        }
    </script>
</body>
</html>`;
    }
}
exports.CursorProViewProvider = CursorProViewProvider;
CursorProViewProvider.CURRENT_VERSION = '0.4.5';