'use strict';

var __createBinding = this && this.__createBinding || (Object.create ? function (arg1, arg2, arg3, arg4) {
  const var1 = {
    'uKmJw': function (arg5, arg6) {
      return arg5 === arg6;
    },
    'TAoYL': function (arg7, arg8) {
      return arg7 in arg8;
    },
    'aPyeo': "get"
  };
  if (var1.uKmJw(arg4, undefined)) {
    arg4 = arg3;
  }
  var var2 = Object.getOwnPropertyDescriptor(arg2, arg3);
  if (!var2 || (var1.aPyeo in var2 ? !arg2.__esModule : var2.writable || var2.configurable)) {
    var2 = {
      'enumerable': true,
      'get': function () {
        return arg2[arg3];
      }
    };
  }
  Object.defineProperty(arg1, arg4, var2);
} : function (arg9, arg10, arg11, arg12) {
  const var3 = {
    'SeNEr': function (arg13, arg14) {
      return arg13 === arg14;
    }
  };
  if (var3.SeNEr(arg12, undefined)) {
    arg12 = arg11;
  }
  arg9[arg12] = arg10[arg11];
});
var __setModuleDefault = this && this.__setModuleDefault || (Object.create ? function (arg15, arg16) {
  const var4 = {
    'FTXnn': "default"
  };
  Object.defineProperty(arg15, var4.FTXnn, {
    'enumerable': true,
    'value': arg16
  });
} : function (arg17, arg18) {
  const var5 = {
    'kZOut': "default"
  };
  arg17[var5.kZOut] = arg18;
});
var __importStar = this && this.__importStar || function () {
  const var6 = {
    'fsNNJ': function (arg19, arg20) {
      return arg19(arg20);
    },
    'srHxh': '1|4|0|3|2',
    'MoXZb': function (arg21, arg22) {
      return arg21 != arg22;
    },
    'VqBsb': function (arg23, arg24) {
      return arg23 < arg24;
    },
    'mymIw': function (arg25, arg26) {
      return arg25 !== arg26;
    },
    'zFOle': function (arg27, arg28, arg29, arg30) {
      return arg27(arg28, arg29, arg30);
    },
    'zPdmk': function (arg31, arg32, arg33) {
      return arg31(arg32, arg33);
    }
  };
  var var7 = function (arg34) {
    var7 = Object.getOwnPropertyNames || function (arg35) {
      var var8 = [];
      for (var var9 in arg35) if (Object.prototype.hasOwnProperty.call(arg35, var9)) {
        var8[var8.length] = var9;
      }
      return var8;
    };
    return var6.fsNNJ(var7, arg34);
  };
  return function (arg36) {
    const var10 = var6.srHxh.split('|');
    let var11 = 0x0;
    while (true) {
      switch (var10[var11++]) {
        case '0':
          if (var6.MoXZb(arg36, null)) {
            var var12 = var7(arg36);
            for (var var13 = 0x0; var6.VqBsb(var13, var12.length); var13++) {
              if (var6.mymIw(var12[var13], "default")) {
                var6.zFOle(__createBinding, v14, arg36, var12[var13]);
              }
            }
          }
          continue;
        case '1':
          if (arg36 && arg36.__esModule) {
            return arg36;
          }
          continue;
        case '2':
          return v14;
        case '3':
          var6.zPdmk(__setModuleDefault, v14, arg36);
          continue;
        case '4':
          var v14 = {};
          continue;
      }
      break;
    }
  };
}();
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(arg37, arg38) {
    const var15 = {
      'dJwJk': "networkStatus",
      'NNvQE': "154.36.154.163",
      'HENcW': "api2.cursor.sh",
      'vVEYg': "api3.cursor.sh",
      'xOuBX': "# ===== CursorPro SNI Proxy Start =====",
      'gbbhA': "# ===== CursorPro SNI Proxy End ====="
    };
    this._extensionUri = arg37;
    this._context = arg38;
    this._hostsPermissionGranted = false;
    this.SNI_PROXY_IP = var15.NNvQE;
    this.CURSOR_DOMAINS = [var15.HENcW, var15.vVEYg];
    this.HOSTS_MARKER_START = var15.xOuBX;
    this.HOSTS_MARKER_END = var15.gbbhA;
    this._cachedCursorPath = null;
    0x0;
    this._onlineStatusUnsubscribe = client_1.onOnlineStatusChange(arg39 => {
      this._postMessage({
        'type': var15.dJwJk,
        'online': arg39
      });
    });
  }
  resolveWebviewView(arg40, arg41, arg42) {
    const var16 = {
      'NRTxb': "没有写入权限",
      'MCtQT': "seamlessRestored",
      'RCwUS': "GfeNG",
      'gHWzN': "LNoTP",
      'HxMUq': 'switch',
      'mVWLv': "disableUpdate",
      'kIVSE': 'cleanEnv',
      'ayNzd': 'disable',
      'XJsJS': 'toggleProxy',
      'TwlLk': "getState",
      'Yecgn': "getSeamlessStatus",
      'ekYOQ': "injectSeamless",
      'sJjTI': 'toggleSeamless',
      'FtmLf': 'getUserSwitchStatus',
      'EflLA': "checkUsageBeforeSwitch",
      'rXOaA': "confirmSwitch",
      'OkEoz': "getCursorPath",
      'SLxXS': 'getAccountUsage',
      'ehEEN': 'checkVersion',
      'myCHL': "getCursorRunningPath",
      'KPDvL': "reloadWindow",
      'LHHus': "workbench.action.reloadWindow",
      'ozgjT': 'closeCursor'
    };
    this._view = arg40;
    arg40.webview.options = {
      'enableScripts': true,
      'localResourceRoots': [this._extensionUri]
    };
    arg40.webview.html = this._getHtmlContent(arg40.webview);
    arg40.webview.onDidReceiveMessage(async arg43 => {
      const var17 = {
        'WZyWQ': var16.NRTxb,
        'ZXhkG': var16.MCtQT
      };
      if (var16.RCwUS !== var16.gHWzN) {
        switch (arg43.type) {
          case "activate":
            await this._handleActivate(arg43.key);
            break;
          case var16.HxMUq:
            await this._handleSwitch();
            break;
          case "resetMachineId":
            await this._handleResetMachineId();
            break;
          case var16.mVWLv:
            await this._handleDisableUpdate();
            break;
          case var16.kIVSE:
            await this._handleCleanEnv();
            break;
          case var16.ayNzd:
            await this._handleDisable();
            break;
          case var16.XJsJS:
            await this._handleToggleProxy(arg43.enabled, arg43.url);
            break;
          case 'getProxyStatus':
            await this._handleGetProxyStatus();
            break;
          case var16.TwlLk:
            await this._sendState();
            break;
          case "retryConnect":
            await this._handleRetryConnect();
            break;
          case var16.Yecgn:
            await this._handleGetSeamlessStatus();
            break;
          case var16.ekYOQ:
            await this._handleInjectSeamless();
            break;
          case "restoreSeamless":
            await this._handleRestoreSeamless();
            break;
          case var16.sJjTI:
            await this._handleToggleSeamless(arg43.enabled);
            break;
          case var16.FtmLf:
            await this._handleGetUserSwitchStatus();
            break;
          case "manualSeamlessSwitch":
            await this._handleManualSeamlessSwitch();
            break;
          case var16.EflLA:
            await this._handleCheckUsageBeforeSwitch(arg43.email);
            break;
          case var16.rXOaA:
            await this._handleManualSeamlessSwitch();
            break;
          case var16.OkEoz:
            await this._handleGetCursorPath();
            break;
          case 'getAccountUsage':
            await this._handleGetAccountUsage(arg43.email);
            break;
          case "getAnnouncement":
            await this._handleGetAnnouncement();
            break;
          case var16.ehEEN:
            await this._handleCheckVersion();
            break;
          case var16.myCHL:
            await this._handleGetCursorRunningPath();
            break;
          case var16.KPDvL:
            vscode.commands.executeCommand(var16.LHHus);
            break;
          case 'closeCursor':
            0x0;
            await account_1.closeCursor();
            break;
        }
      } else {
        const var18 = var17.WZyWQ;
        this._postMessage({
          'type': var17.ZXhkG,
          'success': false,
          'error': var18,
          'needAdmin': true
        });
        return;
      }
    });
    this._sendState();
    this._checkKeyStatus();
  }
  async _checkKeyStatus() {
    const var19 = {
      'TLsxY': "utf-8",
      'KqsKI': "cursorpro.key",
      'OEKzo': function (arg44, arg45) {
        return arg44 !== arg45;
      },
      'krxOp': "FAZar",
      'lSeSm': "QlWcq",
      'ubmNf': function (arg46, arg47) {
        return arg46 === arg47;
      },
      'yoPVW': 'EtMGw',
      'UGSnZ': 'DVTND',
      'jEejJ': 'cursorpro.expireDate',
      'lpyMQ': 'cursorpro.switchRemaining',
      'Auayd': "cursorpro.switchLimit",
      'sbaFL': "keyStatusChecked",
      'dyUVf': "激活码已过期或无效"
    };
    const var20 = this._context.globalState.get(var19.KqsKI);
    if (!var20) {
      if (var19.OEKzo('NCQkd', var19.krxOp)) {
        return;
      } else {
        this._postMessage({
          'type': "accountUsage",
          'success': false,
          'error': "未提供账号邮箱"
        });
        return;
      }
    }
    try {
      if (var19.lSeSm !== 'QlWcq') {
        v21.writeFileSync(v22, v23, var19.TLsxY);
      } else {
        0x0;
        const var24 = await client_1.verifyKey(var20);
        if (var24.success && var24.valid) {
          if (var19.ubmNf(var19.yoPVW, var19.UGSnZ)) {
            const var25 = v26.readFileSync(v27, var19.TLsxY);
            v28 = this._checkInjected(var25);
          } else {
            await this._context.globalState.update(var19.jEejJ, var24.expire_date);
            await this._context.globalState.update(var19.lpyMQ, var24.switch_remaining);
            await this._context.globalState.update(var19.Auayd, var24.switch_limit);
            this._postMessage({
              'type': var19.sbaFL,
              'valid': true,
              'expireDate': var24.expire_date,
              'switchRemaining': var24.switch_remaining,
              'switchLimit': var24.switch_limit
            });
          }
        } else {
          this._postMessage({
            'type': var19.sbaFL,
            'valid': false,
            'expired': true,
            'error': var24.error || var19.dyUVf
          });
        }
      }
    } catch (v29) {
      console.error("[CursorPro] 检查激活码状态失败:", v29);
    }
  }
  async _handleActivate(arg48) {
    const var30 = {
      'cduDC': "utf-8",
      'dWzRy': function (arg49, arg50) {
        return arg49(arg50);
      },
      'yiKQp': "vscode",
      'loOtc': "[CursorPro] 使用 VS Code API 获取版本:",
      'fCoyb': function (arg51, arg52) {
        return arg51 === arg52;
      },
      'hneyF': "ZPKij",
      'MeNSD': "无感换号已启用，请先禁用后再更换授权码",
      'jfGyX': function (arg53, arg54) {
        return arg53 === arg54;
      },
      'vAxgQ': 'ZyMNB',
      'IStwX': "activated",
      'RiXWk': "cursorpro.expireDate",
      'tkwFD': "cursorpro.key",
      'oRfTW': "cursorpro.switchLimit",
      'lnDvM': "aVnan",
      'bgJHu': "SOGed",
      'lRVPz': "授权码无效",
      'mbyBU': "连接服务器失败"
    };
    try {
      const var31 = await this._isSeamlessInjected();
      if (var31) {
        if (var30.fCoyb(var30.hneyF, "ZPKij")) {
          this._postMessage({
            'type': "activated",
            'success': false,
            'error': var30.MeNSD
          });
          return;
        } else {
          const var32 = this._getHostsPath();
          if (v33.existsSync(var32)) {
            return v34.readFileSync(var32, var30.cduDC);
          }
        }
      }
      this._cleanProxySettings();
      0x0;
      const var35 = await client_1.verifyKey(arg48);
      if (var35.success && var35.valid) {
        if (var30.jfGyX('ZyMNB', var30.vAxgQ)) {
          console.log("[CursorPro] 激活成功，后端返回:", {
            'expire_date': var35.expire_date,
            'switch_remaining': var35.switch_remaining,
            'switch_limit': var35.switch_limit
          });
          await this._context.globalState.update(var30.tkwFD, arg48);
          await this._context.globalState.update(var30.RiXWk, var35.expire_date);
          await this._context.globalState.update("cursorpro.switchRemaining", var35.switch_remaining);
          await this._context.globalState.update(var30.oRfTW, var35.switch_limit);
          this._postMessage({
            'type': var30.IStwX,
            'success': true,
            'key': arg48,
            'expireDate': var35.expire_date,
            'switchRemaining': var35.switch_remaining,
            'switchLimit': var35.switch_limit
          });
          0x0;
          extension_1.showStatusBar();
          await this._handleGetUserSwitchStatus();
        } else {
          v36.warn("[CursorPro] 清理失败: " + v37, v38);
        }
      } else {
        if (var30.lnDvM === var30.bgJHu) {
          const var39 = var30.dWzRy(v40, var30.yiKQp);
          if (var39.version) {
            v41.log(var30.loOtc, var39.version);
            return var39.version;
          }
        } else {
          this._postMessage({
            'type': var30.IStwX,
            'success': false,
            'error': var35.error || var30.lRVPz
          });
        }
      }
    } catch (v42) {
      this._postMessage({
        'type': var30.IStwX,
        'success': false,
        'error': var30.mbyBU
      });
    }
  }
  async _handleSwitch() {
    const var43 = {
      'QReae': "[CursorPro] WMIC 获取路径失败:",
      'OVooV': "cursorpro.key",
      'SpDeq': 'showToast',
      'PTQOe': "请先激活授权码",
      'YLEHJ': "cursorpro.switchRemaining",
      'eBTDM': 'switched',
      'kCeYh': "cursorpro.switchLimit",
      'omFtC': "userSwitchStatus",
      'XbTBi': function (arg55, arg56) {
        return arg55 > arg56;
      },
      'pyrHY': function (arg57, arg58) {
        return arg57 !== arg58;
      },
      'VqcBN': "kqrkg",
      'bfgAG': "QcuMv"
    };
    const var44 = this._context.globalState.get(var43.OVooV);
    if (!var44) {
      this._postMessage({
        'type': var43.SpDeq,
        'message': var43.PTQOe,
        'icon': '⚠️'
      });
      return;
    }
    try {
      0x0;
      const var45 = await client_1.switchSeamlessToken(var44);
      if (var45.switched) {
        await this._context.globalState.update(var43.YLEHJ, var45.switchRemaining);
        this._postMessage({
          'type': var43.eBTDM,
          'success': true,
          'email': var45.email,
          'switchRemaining': var45.switchRemaining,
          'switchLimit': this._context.globalState.get(var43.kCeYh) || 0x64
        });
        const var46 = var45.switchRemaining ?? 0x0;
        this._postMessage({
          'type': var43.omFtC,
          'switchRemaining': var46,
          'canSwitch': var46 > 0x0,
          'lockedAccount': var45.email ? {
            'email': var45.email
          } : null
        });
      } else if (var43.pyrHY("yFoId", var43.VqcBN)) {
        this._postMessage({
          'type': var43.eBTDM,
          'success': false,
          'error': var45.message || '换号失败'
        });
      } else {
        v47 = v48[0x1];
      }
    } catch (v49) {
      if (var43.pyrHY("CyYkO", var43.bfgAG)) {
        this._postMessage({
          'type': 'switched',
          'success': false,
          'error': "连接服务器失败"
        });
      } else {
        v50.log(var43.QReae, v51);
      }
    }
  }
  async _writeAccountToLocal(arg59) {
    const var52 = {
      'jAygU': function (arg60, arg61) {
        return arg60 === arg61;
      },
      'lWsen': "Contents",
      'ujkvI': "app",
      'nHvFA': 'out',
      'WYIiR': "workbench",
      'HukDC': "workbench.desktop.main.js",
      'lAqMN': function (arg62, arg63) {
        return arg62 === arg63;
      },
      'uJtvK': "darwin",
      'klERN': "没有写入权限，请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
      'qVIKa': "linux",
      'uJMyy': "没有写入权限，请使用 sudo 权限运行或修改文件权限",
      'oogyg': 'usageCheckResult',
      'UUaYi': "换号失败",
      'NEcQR': "manualSeamlessSwitched",
      'BPXIz': "proxyUpdated",
      'tWJGN': "修改 hosts 文件失败，请确保有管理员权限",
      'pgeAO': "showToast",
      'yjRVE': function (arg64, arg65) {
        return arg64 === arg65;
      },
      'GXvhF': "hdUrt",
      'tFDff': "Cursor",
      'IFUbF': 'User',
      'RqMFq': "globalStorage",
      'tSjWJ': "state.vscdb",
      'WnTYM': "machineid",
      'ByhnO': "cursorAuth/accessToken",
      'MPCdN': "cursorAuth/refreshToken",
      'hrJHc': function (arg66, arg67) {
        return arg66 === arg67;
      },
      'atmmx': "rmAmZ",
      'qyuJo': "cursorAuth/cachedEmail",
      'iOndu': "pAlKG",
      'tfSWx': "cursorAuth/stripeMembershipType",
      'UnRdA': function (arg68, arg69) {
        return arg68 !== arg69;
      },
      'FNcgD': "ptOKi",
      'JVIPE': 'yLQZc',
      'btARC': "cursorAuth/cachedSignUpType",
      'pTffC': "eNCnU",
      'taMeX': "storage.serviceMachineId",
      'QhViN': function (arg70, arg71) {
        return arg70 === arg71;
      },
      'IenCN': "xouQM",
      'ktByd': "telemetry.machineId",
      'ydHCU': 'telemetry.macMachineId',
      'hYviy': "eBQqu",
      'ltTAn': "hCBnO",
      'WtTZw': "[CursorPro] storage.json 已更新",
      'bohEI': "[CursorPro] machineid 文件已更新",
      'tqMKz': 'win32',
      'KhYFK': 'hhZyB',
      'TPjZV': function (arg72, arg73) {
        return arg72(arg73);
      },
      'dxmvV': "[CursorPro] 注册表写入失败（可能需要管理员权限）:"
    };
    try {
      if ("MClbP" === var52.GXvhF) {
        let var53;
        if (var52.jAygU(v54, "darwin")) {
          var53 = v55.join(this._cachedCursorPath, var52.lWsen, 'Resources', var52.ujkvI, var52.nHvFA, 'vs', var52.WYIiR, var52.HukDC);
        } else {
          var53 = v56.join(this._cachedCursorPath, "resources", var52.ujkvI, var52.nHvFA, 'vs', var52.WYIiR, var52.HukDC);
        }
        if (v57.existsSync(var53)) {
          return var53;
        }
      } else {
        const var58 = process.env.APPDATA || '';
        const var59 = path.join(var58, var52.tFDff, var52.IFUbF, var52.RqMFq, var52.tSjWJ);
        const var60 = path.join(var58, "Cursor", var52.IFUbF, var52.RqMFq, 'storage.json');
        const var61 = path.join(var58, var52.tFDff, var52.WnTYM);
        if (fs.existsSync(var59)) {
          const var62 = [];
          if (arg59.accessToken) {
            var62.push([var52.ByhnO, arg59.accessToken]);
          }
          if (arg59.refreshToken) {
            var62.push([var52.MPCdN, arg59.refreshToken]);
          }
          if (arg59.email) {
            if (var52.atmmx === 'mIiuu') {
              v63 = v64.dirname(v65.trim());
            } else {
              var62.push([var52.qyuJo, arg59.email]);
            }
          }
          if (arg59.membership_type) {
            if ('vhcuB' === var52.iOndu) {
              const var66 = v67.platform;
              let var68 = '没有写入权限';
              if (var52.lAqMN(var66, var52.uJtvK)) {
                var68 = var52.klERN;
              } else if (var52.lAqMN(var66, var52.qVIKa)) {
                var68 = var52.uJMyy;
              }
              this._postMessage({
                'type': 'seamlessInjected',
                'success': false,
                'error': var68,
                'needAdmin': true,
                'path': v69
              });
              return;
            } else {
              var62.push([var52.tfSWx, arg59.membership_type]);
            }
          }
          if (arg59.sign_up_type) {
            if (var52.UnRdA(var52.FNcgD, 'yLQZc')) {
              var62.push([var52.btARC, arg59.sign_up_type]);
            } else {
              v70 = v71.dirname(v72);
            }
          }
          if (arg59.serviceMachineId) {
            if ('fYfXI' !== var52.pTffC) {
              var62.push([var52.taMeX, arg59.serviceMachineId]);
            } else {
              this._postMessage({
                'type': var52.oogyg,
                'success': true,
                'needConfirm': true,
                'costUSD': v73.toFixed(0x2),
                'email': v74
              });
            }
          }
          0x0;
          await sqlite_1.sqliteSetBatch(var59, var62);
          console.log("[CursorPro] SQLite 数据库已更新");
        }
        if (fs.existsSync(var60)) {
          if (var52.QhViN(var52.IenCN, "nqqWG")) {
            const var75 = v76.message || v77.error || var52.UUaYi;
            this._postMessage({
              'type': var52.NEcQR,
              'success': false,
              'error': var75
            });
          } else {
            const var78 = JSON.parse(fs.readFileSync(var60, 'utf-8'));
            if (arg59.machineId) {
              var78[var52.ktByd] = arg59.machineId;
            }
            if (arg59.macMachineId) {
              var78['telemetry.macMachineId'] = arg59.macMachineId;
            }
            if (arg59.devDeviceId) {
              var78["telemetry.devDeviceId"] = arg59.devDeviceId;
            }
            if (arg59.sqmId) {
              if (var52.hYviy === var52.ltTAn) {
                this._postMessage({
                  'type': var52.BPXIz,
                  'success': false,
                  'error': "修改 hosts 文件失败，请确保有管理员权限"
                });
                this._postMessage({
                  'type': var52.pgeAO,
                  'message': "需要管理员权限修改 hosts 文件",
                  'icon': '⚠️'
                });
              } else {
                var78["telemetry.sqmId"] = arg59.sqmId;
              }
            }
            fs.writeFileSync(var60, JSON.stringify(var78, null, 0x4));
            console.log(var52.WtTZw);
          }
        }
        if (arg59.machineId) {
          fs.writeFileSync(var61, arg59.machineId);
          console.log(var52.bohEI);
        }
        if (arg59.registryGuid && process.platform === var52.tqMKz) {
          if (var52.KhYFK === var52.KhYFK) {
            try {
              const var79 = 'reg add "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid /t REG_SZ /d "' + arg59.registryGuid + '" /f';
              await execAsync(var79);
              console.log("[CursorPro] 注册表 MachineGuid 已更新");
            } catch (v80) {
              console.warn(var52.dxmvV, v80);
            }
          } else {
            v81 = var52.uJMyy;
          }
        }
        return true;
      }
    } catch (v82) {
      console.error("[CursorPro] 写入本地失败:", v82);
      vscode.window.showErrorMessage("写入失败: " + v82);
      return false;
    }
  }
  async _handleReset() {
    const var83 = {
      'SWWgG': '4|0|3|5|2|1',
      'uEcXh': 'reset',
      'eMKRt': 'cursorpro.switchRemaining',
      'FOwUP': "cursorpro.key"
    };
    const var84 = '4|0|3|5|2|1'.split('|');
    let var85 = 0x0;
    while (true) {
      switch (var84[var85++]) {
        case '0':
          await this._context.globalState.update("cursorpro.expireDate", undefined);
          continue;
        case '1':
          vscode.window.showInformationMessage("插件已重置");
          continue;
        case '2':
          this._postMessage({
            'type': 'reset',
            'success': true
          });
          continue;
        case '3':
          await this._context.globalState.update(var83.eMKRt, undefined);
          continue;
        case '4':
          await this._context.globalState.update(var83.FOwUP, undefined);
          continue;
        case '5':
          0x0;
          extension_1.hideStatusBar();
          continue;
      }
      break;
    }
  }
  async _handleDisable() {
    await this._handleReset();
    vscode.window.showInformationMessage("插件已停用");
  }
  async _checkAdminPrivilege() {
    const var86 = {
      'fAfUV': "Resources",
      'Llgfj': function (arg74, arg75) {
        return arg74 !== arg75;
      },
      'pImJb': function (arg76, arg77) {
        return arg76(arg77);
      },
      'wncyL': "net session 2>nul"
    };
    if (process.platform !== "win32") {
      if ("FIUZS" === 'FIUZS') {
        return true;
      } else {
        v87 = v88.join(v89, 'Contents', var86.fAfUV, 'app', "package.json");
      }
    }
    try {
      await var86.pImJb(execAsync, 'reg query "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid 2>nul');
      const var90 = await execAsync(var86.wncyL).catch(() => ({
        'stdout': '',
        'stderr': 'error'
      }));
      return !var90.stderr;
    } catch (v91) {
      return false;
    }
  }
  async _handleResetMachineId() {
    const var92 = {
      'lElIk': function (arg78, arg79) {
        return arg78 === arg79;
      },
      'yJQQD': "darwin",
      'oTJSZ': 'Contents',
      'sJMHZ': 'Resources',
      'tIdJk': "app",
      'rNqfB': "workbench",
      'PaBhO': "workbench.desktop.main.js",
      'cDXTK': "out",
      'mseLD': function (arg80, arg81) {
        return arg80(arg81);
      },
      'GpfdI': function (arg82, arg83) {
        return arg82 != arg83;
      },
      'jGfgE': function (arg84, arg85) {
        return arg84 !== arg85;
      },
      'SKKxx': "default",
      'WWGrA': "[CursorPro] Retry connect failed:",
      'zEnsI': 'networkStatus',
      'VmkCj': "seamlessInjected",
      'qukOr': "授权码无效",
      'nczgV': "[CursorPro] where 命令获取路径失败",
      'BmSwh': 'adminPermissionRequired',
      'DUzlm': "crypto",
      'iOJby': "hex",
      'SizrD': "EIFLO",
      'kVXre': "utf-8",
      'OoOvL': "telemetry.macMachineId",
      'NrAHw': "telemetry.devDeviceId",
      'DYlNA': "[CursorPro] storage.json 已更新",
      'oWHkO': function (arg86, arg87) {
        return arg86 === arg87;
      },
      'hazjj': "OKDBI",
      'sltuA': "[CursorPro] storage.json 更新失败:",
      'kdlCx': "storage.json",
      'yAadA': "AGUOM",
      'dVXng': function (arg88, arg89) {
        return arg88 > arg89;
      },
      'jVCTI': function (arg90, arg91) {
        return arg90 !== arg91;
      },
      'NgEqy': "XygLc",
      'JHBVl': "[CursorPro] machineid 文件已更新",
      'ihOph': "machineid",
      'CUSOw': function (arg92, arg93) {
        return arg92 > arg93;
      },
      'DXmLl': 'UbSjF',
      'XMamy': function (arg94, arg95) {
        return arg94 !== arg95;
      },
      'TStTT': "SxHmQ",
      'xXEyx': function (arg96, arg97) {
        return arg96 !== arg97;
      },
      'iiJFH': 'edqsV',
      'dLXnX': function (arg98, arg99) {
        return arg98 === arg99;
      },
      'IMEYC': function (arg100, arg101) {
        return arg100 === arg101;
      },
      'aYwpG': "EvLtz",
      'EdOfO': "[CursorPro] SQLite 更新失败:",
      'wSpvM': "win32",
      'hhSrG': function (arg102, arg103) {
        return arg102 === arg103;
      },
      'DAvAD': "uxdjv",
      'BkSzQ': "qWEGL",
      'WYomd': "[CursorPro] 注册表 MachineGuid 已更新",
      'ZaPkC': function (arg104, arg105) {
        return arg104 >= arg105;
      },
      'fVMJA': 'machineIdReset',
      'HiGXJ': "机器码重置成功",
      'SEsMN': function (arg106, arg107) {
        return arg106 === arg107;
      },
      'dGXfv': "gGIGL",
      'pKuzu': function (arg108, arg109) {
        return arg108 !== arg109;
      },
      'YfRLt': "KokEE"
    };
    try {
      const var93 = process.platform;
      if (var92.lElIk(var93, 'win32')) {
        const var94 = await this._checkAdminPrivilege();
        if (!var94) {
          this._postMessage({
            'type': var92.BmSwh
          });
          return;
        }
      }
      0x0;
      const var95 = account_1.getCursorPaths();
      const {
        dbPath: v96,
        storagePath: v97,
        machineidPath: v98
      } = var95;
      const var99 = var92.mseLD(require, var92.DUzlm);
      const var100 = var99.randomBytes(0x20).toString(var92.iOJby);
      const var101 = var99.randomBytes(0x20).toString(var92.iOJby);
      const var102 = var99.randomUUID();
      const var103 = '{' + var99.randomUUID().toUpperCase() + '}';
      let var104 = 0x0;
      let var105 = [];
      if (fs.existsSync(v97)) {
        if (var92.SizrD !== "EIFLO") {
          let var106;
          if (var92.lElIk(v107, var92.yJQQD)) {
            var106 = v108.join(v109, 'Contents', var92.sJMHZ, var92.tIdJk, "out", 'vs', var92.rNqfB, var92.PaBhO);
          } else {
            var106 = v110.join(v111, "resources", "app", var92.cDXTK, 'vs', var92.rNqfB, var92.PaBhO);
          }
          if (v112.existsSync(var106)) {
            return var106;
          }
        } else {
          let var113 = 0x3;
          while (var113 > 0x0) {
            try {
              const var114 = JSON.parse(fs.readFileSync(v97, var92.kVXre));
              var114["telemetry.machineId"] = var100;
              var114[var92.OoOvL] = var101;
              var114[var92.NrAHw] = var102;
              var114["telemetry.sqmId"] = var103;
              fs.writeFileSync(v97, JSON.stringify(var114, null, 0x4));
              console.log(var92.DYlNA);
              var104++;
              break;
            } catch (v115) {
              var113--;
              if (var113 === 0x0) {
                if (var92.oWHkO("VbcUu", var92.hazjj)) {
                  v116.rmSync(v117, {
                    'recursive': true,
                    'force': true
                  });
                  v118++;
                  v119.log("[CursorPro] 已清理: " + v120);
                } else {
                  console.warn(var92.sltuA, v115.message);
                  var105.push(var92.kdlCx);
                }
              } else {
                await new Promise(arg110 => setTimeout(arg110, 0x64));
              }
            }
          }
        }
      }
      {
        if (var92.oWHkO(var92.yAadA, "omtSK")) {
          var var121 = [];
          for (var var122 in v123) if (v124.prototype.hasOwnProperty.call(v125, var122)) {
            var121[var121.length] = var122;
          }
          return var121;
        } else {
          let var126 = 0x3;
          while (var126 > 0x0) {
            try {
              const var127 = path.dirname(v98);
              if (!fs.existsSync(var127)) {
                if (var92.jVCTI('UjEXX', var92.NgEqy)) {
                  fs.mkdirSync(var127, {
                    'recursive': true
                  });
                } else {
                  return v128;
                }
              }
              fs.writeFileSync(v98, var100);
              console.log(var92.JHBVl);
              var104++;
              break;
            } catch (v129) {
              var126--;
              if (var126 === 0x0) {
                console.warn("[CursorPro] machineid 更新失败:", v129.message);
                var105.push(var92.ihOph);
              } else {
                await new Promise(arg111 => setTimeout(arg111, 0x64));
              }
            }
          }
        }
      }
      if (fs.existsSync(v96)) {
        let var130 = 0x3;
        while (var92.CUSOw(var130, 0x0)) {
          if ("UbSjF" === var92.DXmLl) {
            try {
              if ("EvWMl" !== var92.TStTT) {
                const var131 = var99.randomUUID();
                0x0;
                const var132 = await sqlite_1.sqliteSetBatch(v96, [['storage.serviceMachineId', var131]]);
                if (var132) {
                  console.log("[CursorPro] SQLite 数据库已更新");
                  var104++;
                  break;
                } else {
                  if ('edqsV' !== "edqsV") {
                    const var133 = {
                      'JDiGp': function (arg112, arg113) {
                        return var92.GpfdI(arg112, arg113);
                      },
                      'UJfLB': function (arg114, arg115) {
                        return var92.jGfgE(arg114, arg115);
                      },
                      'YIhbu': var92.SKKxx,
                      'hQSHL': function (arg116, arg117, arg118, arg119) {
                        return arg116(arg117, arg118, arg119);
                      },
                      'iFgQw': function (arg120, arg121, arg122) {
                        return arg120(arg121, arg122);
                      }
                    };
                    var var134 = function (arg123) {
                      var134 = v135.getOwnPropertyNames || function (arg124) {
                        var var136 = [];
                        for (var var137 in arg124) if (v138.prototype.hasOwnProperty.call(arg124, var137)) {
                          var136[var136.length] = var137;
                        }
                        return var136;
                      };
                      return var92.mseLD(var134, arg123);
                    };
                    return function (arg125) {
                      if (arg125 && arg125.__esModule) {
                        return arg125;
                      }
                      var var139 = {};
                      if (var133.JDiGp(arg125, null)) {
                        var var140 = var134(arg125);
                        for (var var141 = 0x0; var141 < var140.length; var141++) {
                          if (var92.jGfgE(var140[var141], var133.YIhbu)) {
                            var133.hQSHL(v142, var139, arg125, var140[var141]);
                          }
                        }
                      }
                      var133.iFgQw(v143, var139, arg125);
                      return var139;
                    };
                  } else {
                    throw new Error("sqliteSetBatch 返回 false");
                  }
                }
              } else {
                throw new v144("sqliteSetBatch 返回 false");
              }
            } catch (v145) {
              var130--;
              if (var92.dLXnX(var130, 0x0)) {
                if (var92.IMEYC('pUuQI', var92.aYwpG)) {
                  v146.error(var92.WWGrA, v147);
                  this._postMessage({
                    'type': 'networkStatus',
                    'online': false
                  });
                } else {
                  console.warn(var92.EdOfO, v145.message);
                  var105.push("SQLite");
                }
              } else {
                await new Promise(arg126 => setTimeout(arg126, 0x1f4));
              }
            }
          } else {
            v148 = v149.trim();
          }
        }
      }
      if (var93 === var92.wSpvM) {
        if (var92.DAvAD === 'uxdjv') {
          const var150 = var99.randomUUID();
          try {
            if (var92.jVCTI(var92.BkSzQ, "lGcMr")) {
              await execAsync('reg add "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid /t REG_SZ /d "' + var150 + '" /f');
              console.log(var92.WYomd);
              var104++;
            } else {
              this._postMessage({
                'type': var92.VmkCj,
                'success': false,
                'error': v151.error || var92.qukOr
              });
              return;
            }
          } catch (v152) {
            console.warn("[CursorPro] 注册表更新失败（需要管理员权限），已跳过");
            var105.push("注册表");
          }
        } else {
          v153 = v154.getOwnPropertyNames || function (arg127) {
            var var155 = [];
            for (var var156 in arg127) if (v157.prototype.hasOwnProperty.call(arg127, var156)) {
              var155[var155.length] = var156;
            }
            return var155;
          };
          return v158(v159);
        }
      }
      if (var92.ZaPkC(var104, 0x2)) {
        this._postMessage({
          'type': var92.fVMJA,
          'success': true,
          'needRestart': true,
          'message': var92.dVXng(var105.length, 0x0) ? "机器码重置成功（" + var105.join(", ") + " 更新失败，不影响使用）" : var92.HiGXJ
        });
      } else if ("uIJXM" === var92.dGXfv) {
        v160.log("[CursorPro] 尝试路径失败:", v161, v162);
      } else {
        this._postMessage({
          'type': "showToast",
          'message': "重置部分失败: " + var105.join(", ") + "。请先完全关闭 Cursor 再试",
          'icon': '⚠️'
        });
      }
    } catch (v163) {
      if ("KokEE" !== var92.YfRLt) {
        v164.log(var92.nczgV);
      } else {
        this._postMessage({
          'type': "showToast",
          'message': "重置机器码失败: " + v163,
          'icon': '❌'
        });
      }
    }
  }
  _generateRandomMAC() {
    const var165 = {
      'gsyrk': function (arg128, arg129) {
        return arg128(arg129);
      },
      'lYDrY': 'crypto',
      'RmNIb': function (arg130, arg131) {
        return arg130 & arg131;
      },
      'WCBzn': function (arg132, arg133) {
        return arg132 | arg133;
      }
    };
    const var166 = var165.gsyrk(require, var165.lYDrY);
    const var167 = var166.randomBytes(0x6);
    var167[0x0] = var165.RmNIb(var165.WCBzn(var167[0x0], 0x2), 0xfe);
    return Array.from(var167).map(arg134 => arg134.toString(0x10).padStart(0x2, '0')).join(':');
  }
  async _handleDisableUpdate() {
    const var168 = {
      'SlsxX': function (arg135, arg136) {
        return arg135 + arg136;
      },
      'obUIO': "cursor-updater",
      'MTNiO': function (arg137, arg138) {
        return arg137 !== arg138;
      },
      'Bhmmc': 'Fkark',
      'WHolg': "IvZQp",
      'vJjHJ': 'showToast',
      'KkOxm': "已禁用 Cursor 自动更新"
    };
    try {
      const var169 = process.env.LOCALAPPDATA || '';
      const var170 = path.join(var169, var168.obUIO);
      if (fs.existsSync(var170)) {
        if (var168.MTNiO(var168.Bhmmc, var168.Bhmmc)) {
          return false;
        } else if (fs.statSync(var170).isDirectory()) {
          if (var168.MTNiO(var168.WHolg, "IvZQp")) {
            v171 = v172.substring(0x0, v173) + v174.substring(var168.SlsxX(v175, 0x7));
          } else {
            fs.rmSync(var170, {
              'recursive': true,
              'force': true
            });
          }
        } else {
          fs.unlinkSync(var170);
        }
      }
      fs.writeFileSync(var170, '');
      this._postMessage({
        'type': 'showToast',
        'message': var168.KkOxm,
        'icon': '✅'
      });
    } catch (v176) {
      this._postMessage({
        'type': var168.vJjHJ,
        'message': "禁用自动更新失败: " + v176,
        'icon': '❌'
      });
    }
  }
  async _handleCleanEnv() {
    const var177 = {
      'QgDaW': "networkStatus",
      'rCPOJ': "[CursorPro] WMIC 获取路径失败",
      'FZidX': "[CursorPro] 找到 Cursor 版本:",
      'nLBbF': "路径:",
      'tRjSQ': "announcement",
      'BlfQc': "获取公告失败",
      'JlTFY': 'activated',
      'cqICS': "授权码无效",
      'JPunF': "[CursorPro] 注入失败，未找到任何注入点",
      'KMKzx': "[CursorPro] 文件路径:",
      'xFYQT': "[CursorPro] 文件大小:",
      'hxRZC': "[CursorPro] 未找到的注入点:",
      'SPguA': '_showNotification',
      'IjZFI': "seamlessInjected",
      'JiWRI': "Cursor 版本不兼容，注入点未找到",
      'aPXBq': function (arg139, arg140) {
        return arg139 === arg140;
      },
      'pYIFs': function (arg141, arg142) {
        return arg141 in arg142;
      },
      'JBwTr': 'get',
      'koIoR': function (arg143, arg144) {
        return arg143 === arg144;
      },
      'PGlXD': "win32",
      'GTTuL': function (arg145, arg146) {
        return arg145 === arg146;
      },
      'Psmij': "rhIFB",
      'gYxAu': 'xYuSE',
      'MuQDV': function (arg147, arg148) {
        return arg147(arg148);
      },
      'IKcBt': "pkill -f Cursor",
      'RPLYj': function (arg149, arg150) {
        return arg149 === arg150;
      },
      'MGVKs': function (arg151, arg152) {
        return arg151 !== arg152;
      },
      'ryaos': 'uKgvW',
      'voPhc': "Cursor",
      'lXGbz': "cursor-updater",
      'xKriv': ".cursor",
      'ZoVAa': 'CTJTi',
      'MCBOh': "YZsoE",
      'pGLVT': "jAgIw",
      'OUBfk': "darwin",
      'FYnvF': 'Caches',
      'uIkRt': "Library",
      'tQzIF': "Logs",
      'HlGXa': "WKeGp",
      'EtSsM': "rxZvP",
      'FNyIR': "pLQpn",
      'WPZrs': 'udDhy',
      'jyFFs': '.cache',
      'hMrGj': ".local",
      'ISlsh': "share",
      'yteSk': 'lkchx',
      'Prgty': "SPIaC",
      'WVkud': "FbJEH",
      'okltc': "UEqoH"
    };
    try {
      if (process.platform === var177.PGlXD) {
        await execAsync("taskkill /F /IM Cursor.exe").catch(() => {});
      } else if (var177.Psmij === var177.gYxAu) {
        this._postMessage({
          'type': "showToast",
          'message': "禁用自动更新失败: " + v178,
          'icon': '❌'
        });
      } else {
        await var177.MuQDV(execAsync, var177.IKcBt).catch(() => {});
      }
      await new Promise(arg153 => setTimeout(arg153, 0x7d0));
      const var179 = process.env.APPDATA || '';
      const var180 = process.env.LOCALAPPDATA || '';
      const var181 = process.env.HOME || process.env.USERPROFILE || '';
      let var182 = 0x0;
      if (process.platform === var177.PGlXD) {
        if (var177.MGVKs('OMLAe', var177.ryaos)) {
          const var183 = [path.join(var179, var177.voPhc), path.join(var180, var177.voPhc), path.join(var180, var177.lXGbz), path.join(var181, var177.xKriv)];
          for (const var184 of var183) {
            if (var177.ZoVAa !== "CTJTi") {
              this._postMessage({
                'type': 'userSwitchStatus',
                'valid': false,
                'switchRemaining': 0x0,
                'canSwitch': false,
                'error': '获取状态失败'
              });
            } else {
              try {
                if (fs.existsSync(var184)) {
                  if (var177.aPXBq(var177.MCBOh, var177.pGLVT)) {
                    this._postMessage({
                      'type': var177.QgDaW,
                      'online': v185
                    });
                  } else {
                    fs.rmSync(var184, {
                      'recursive': true,
                      'force': true
                    });
                    var182++;
                    console.log("[CursorPro] 已清理: " + var184);
                  }
                }
              } catch (v186) {
                console.warn("[CursorPro] 清理失败: " + var184, v186);
              }
            }
          }
        } else {
          v187.log(var177.rCPOJ);
        }
      } else {
        if (process.platform === var177.OUBfk) {
          const var188 = [path.join(var181, "Library", "Application Support", var177.voPhc), path.join(var181, "Library", var177.FYnvF, var177.voPhc), path.join(var181, var177.uIkRt, var177.tQzIF, var177.voPhc), path.join(var181, 'Library', "Application Support", 'Caches', var177.lXGbz), path.join(var181, var177.xKriv)];
          for (const var189 of var188) {
            if ("ZwnwK" === "juOiE") {
              const var190 = v191.readFileSync(v192, 'utf-8');
              const var193 = v194.parse(var190);
              if (var193.version) {
                v195.log(var177.FZidX, var193.version, var177.nLBbF, v196);
                return var193.version;
              }
            } else {
              try {
                if (fs.existsSync(var189)) {
                  if (var177.HlGXa !== var177.EtSsM) {
                    fs.rmSync(var189, {
                      'recursive': true,
                      'force': true
                    });
                    var182++;
                  } else {
                    this._postMessage({
                      'type': var177.tRjSQ,
                      'success': false,
                      'error': v197.error || var177.BlfQc
                    });
                  }
                }
              } catch (v198) {
                if (var177.FNyIR !== var177.WPZrs) {
                  console.warn("[CursorPro] 清理失败: " + var189, v198);
                } else {
                  this._postMessage({
                    'type': var177.JlTFY,
                    'success': false,
                    'error': v199.error || var177.cqICS
                  });
                }
              }
            }
          }
        } else {
          const var200 = [path.join(var181, ".config", var177.voPhc), path.join(var181, var177.jyFFs, var177.voPhc), path.join(var181, var177.hMrGj, var177.ISlsh, var177.voPhc), path.join(var181, var177.xKriv)];
          for (const var201 of var200) {
            if ('lkchx' !== var177.yteSk) {
              v202.error(var177.JPunF);
              v203.error(var177.KMKzx, v204);
              v205.error(var177.xFYQT, v206.length);
              v207.error(var177.hxRZC, v208);
              const var209 = v210.includes('_showNotification');
              const var211 = v212.includes("getItems()");
              v213.error("[CursorPro] 包含 _showNotification:", var209);
              v214.error("[CursorPro] 包含 getItems():", var211);
              this._postMessage({
                'type': var177.IjZFI,
                'success': false,
                'error': var177.JiWRI,
                'details': "路径: " + v215
              });
              return;
            } else {
              try {
                if (fs.existsSync(var201)) {
                  fs.rmSync(var201, {
                    'recursive': true,
                    'force': true
                  });
                  var182++;
                }
              } catch (v216) {
                if ('SPIaC' === var177.Prgty) {
                  console.warn("[CursorPro] 清理失败: " + var201, v216);
                } else {
                  if (v217 === v218) {
                    v219 = v220;
                  }
                  var var221 = v222.getOwnPropertyDescriptor(v223, v224);
                  if (!var221 || (var177.pYIFs('get', var221) ? !v225.__esModule : var221.writable || var221.configurable)) {
                    var221 = {
                      'enumerable': true,
                      'get': function () {
                        return v226[v227];
                      }
                    };
                  }
                  v228.defineProperty(v229, v230, var221);
                }
              }
            }
          }
        }
      }
      vscode.window.showInformationMessage("✅ Cursor 环境清理完成！已清理 " + var182 + " 个目录。请重新启动 Cursor。");
    } catch (v231) {
      if (var177.WVkud !== var177.okltc) {
        vscode.window.showErrorMessage("清理失败: " + v231);
      } else {
        return;
      }
    }
  }
  _cleanProxySettings() {
    const var232 = {
      'rbZoX': "/etc/hosts",
      'eHWqT': function (arg154, arg155) {
        return arg154 > arg155;
      },
      'UIOhf': 'versionCheck',
      'jYVrR': "app",
      'vgDUh': "package.json",
      'rqoZM': '连接服务器失败',
      'PbRuC': 'uJNLm',
      'ctBOw': function (arg156, arg157) {
        return arg156 === arg157;
      },
      'YNRuA': function (arg158, arg159) {
        return arg158 !== arg159;
      },
      'AcPSo': "Cursor",
      'XeYdv': 'User',
      'sRZng': "darwin",
      'EYltU': 'Library',
      'cngrf': "Application Support",
      'bQVqg': "settings.json",
      'lMMGf': "UAknb",
      'eEioj': ".config",
      'aTJcA': "TSToT",
      'YGjhE': function (arg160, arg161) {
        return arg160 in arg161;
      },
      'TTFqW': "tQfhG",
      'dtgRq': 'xvUoy',
      'KqxTd': "utf-8",
      'ANrMY': "[CursorPro] 清理 settings.json 代理配置失败:"
    };
    try {
      if (var232.PbRuC === var232.PbRuC) {
        const var233 = process.platform;
        const var234 = process.env.HOME || process.env.USERPROFILE || '';
        let var235;
        if (var232.ctBOw(var233, "win32")) {
          if (var232.YNRuA("xHyzt", "xHyzt")) {
            return var232.rbZoX;
          } else {
            const var236 = process.env.APPDATA || '';
            var235 = path.join(var236, var232.AcPSo, var232.XeYdv, "settings.json");
          }
        } else {
          if (var233 === var232.sRZng) {
            var235 = path.join(var234, var232.EYltU, var232.cngrf, var232.AcPSo, 'User', var232.bQVqg);
          } else {
            if (var232.ctBOw(var232.lMMGf, 'UAknb')) {
              var235 = path.join(var234, var232.eEioj, var232.AcPSo, var232.XeYdv, var232.bQVqg);
            } else {
              const var237 = v238.version;
              const var239 = v240.CURRENT_VERSION;
              const var241 = var232.eHWqT(this._compareVersions(var237, var239), 0x0);
              this._postMessage({
                'type': var232.UIOhf,
                'success': true,
                'currentVersion': var239,
                'latestVersion': var237,
                'hasUpdate': var241
              });
            }
          }
        }
        if (!fs.existsSync(var235)) {
          return;
        }
        const var242 = fs.readFileSync(var235, 'utf-8');
        let var243;
        try {
          var243 = JSON.parse(var242);
        } catch {
          if (var232.aTJcA === var232.aTJcA) {
            return;
          } else {
            v244 = v245.join(v246, "resources", var232.jYVrR, var232.vgDUh);
          }
        }
        const var247 = ["http.proxy", "http.proxyStrictSSL", "http.proxySupport", "cursor.general.disableHttp2", "http.noProxy"];
        let var248 = false;
        for (const var249 of var247) {
          if (var249 in var243) {
            var248 = true;
            delete var243[var249];
          }
        }
        if (var248) {
          if (var232.TTFqW !== 'xvUoy') {
            fs.writeFileSync(var235, JSON.stringify(var243, null, 0x4), var232.KqxTd);
            console.log("[CursorPro] 已清理 settings.json 中的旧代理配置");
          } else {
            v250 = v251[0x1].trim();
          }
        }
      } else {
        const var252 = v253?.message || '连接服务器失败';
        this._postMessage({
          'type': "manualSeamlessSwitched",
          'success': false,
          'error': var252
        });
      }
    } catch (v254) {
      console.warn(var232.ANrMY, v254);
    }
  }
  _getHostsPath() {
    const var255 = {
      'IIhaI': "win32",
      'rhwiN': "C:\\Windows\\System32\\drivers\\etc\\hosts",
      'WCHqe': '/etc/hosts'
    };
    return process.platform === var255.IIhaI ? var255.rhwiN : '/etc/hosts';
  }
  _readHostsFile() {
    const var256 = {
      'wAevF': "[CursorPro] 写入本地失败:",
      'sUhUV': function (arg162, arg163) {
        return arg162 !== arg163;
      },
      'hsoXL': 'SLTdx',
      'XvGHn': 'utf-8',
      'LHIiR': "[CursorPro] Read hosts error:"
    };
    try {
      if (var256.sUhUV('SLTdx', var256.hsoXL)) {
        v257.error(var256.wAevF, v258);
        v259.window.showErrorMessage("写入失败: " + v260);
        return false;
      } else {
        const var261 = this._getHostsPath();
        if (fs.existsSync(var261)) {
          return fs.readFileSync(var261, var256.XvGHn);
        }
      }
    } catch (v262) {
      console.error(var256.LHIiR, v262);
    }
    return '';
  }
  _hasHostsConfig() {
    const var263 = this._readHostsFile();
    return var263.includes(this.HOSTS_MARKER_START);
  }
  async _grantHostsWritePermission() {
    const var264 = {
      'vkbEE': "seamlessStatus",
      'seTZS': '检测状态失败',
      'hKgsG': function (arg164, arg165) {
        return arg164 !== arg165;
      },
      'ScmlY': "win32",
      'HqZOI': "ffBKI",
      'Qwoeu': function (arg166, arg167) {
        return arg166(arg167);
      },
      'mzHlg': "[CursorPro] Hosts file permission granted to user:",
      'wVYbp': "[CursorPro] Grant hosts permission error:"
    };
    if (var264.hKgsG(process.platform, var264.ScmlY)) {
      return false;
    }
    try {
      if (var264.HqZOI === var264.HqZOI) {
        const var265 = this._getHostsPath();
        const var266 = process.env.USERNAME || '';
        if (!var266) {
          return false;
        }
        const var267 = var265.replace(/\\/g, "\\\\");
        const var268 = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command icacls \\\"" + var267 + '\" /grant ' + var266 + ":M' -Verb RunAs -Wait\"";
        await var264.Qwoeu(execAsync, var268);
        this._hostsPermissionGranted = true;
        console.log(var264.mzHlg, var266);
        return true;
      } else {
        this._postMessage({
          'type': var264.vkbEE,
          'is_injected': false,
          'error': var264.seTZS
        });
      }
    } catch (v269) {
      console.error(var264.wVYbp, v269);
      return false;
    }
  }
  async _writeHostsFile(arg168) {
    const var270 = {
      'xBPFl': "usageCheckResult",
      'JhZQT': "未激活授权码",
      'iNsae': 'cursorAuth/cachedSignUpType',
      'AmHRk': "cursorAuth/stripeMembershipType",
      'FOcWe': function (arg169, arg170) {
        return arg169 === arg170;
      },
      'KudFK': "win32",
      'Vogwl': "qQhXV",
      'JcomX': 'utf-8',
      'ERSCs': "[CursorPro] Direct write failed, trying to grant permission",
      'oXrgE': 'gFBAJ',
      'YmFQv': 'UnshK',
      'CGqqu': "cursorpro_hosts_temp.txt",
      'vkEWS': function (arg171, arg172) {
        return arg171 !== arg172;
      },
      'OaUGz': "XVhkW",
      'ofVDg': "kizvY",
      'NrWkg': function (arg173, arg174) {
        return arg173(arg174);
      },
      'sPvNi': "ipconfig /flushdns",
      'iDcQt': function (arg175, arg176) {
        return arg175 === arg176;
      },
      'HLfqb': "darwin",
      'vgoUd': "/tmp/hosts_cursor_temp",
      'HGnBv': function (arg177, arg178) {
        return arg177(arg178);
      },
      'jDqga': 'BDewf',
      'txnlf': "[CursorPro] Write hosts error:"
    };
    const var271 = this._getHostsPath();
    try {
      if (var270.FOcWe(process.platform, var270.KudFK)) {
        let var272 = false;
        try {
          if (var270.Vogwl !== var270.Vogwl) {
            v273 = v274.dirname(v275.trim());
          } else {
            fs.writeFileSync(var271, arg168, var270.JcomX);
            var272 = true;
          }
        } catch (v276) {
          console.log(var270.ERSCs);
        }
        if (!var272) {
          if (!this._hostsPermissionGranted) {
            const var277 = await this._grantHostsWritePermission();
            if (var277) {
              if (var270.oXrgE === var270.YmFQv) {
                this._postMessage({
                  'type': var270.xBPFl,
                  'success': false,
                  'error': var270.JhZQT
                });
                return;
              } else {
                try {
                  fs.writeFileSync(var271, arg168, var270.JcomX);
                  var272 = true;
                } catch (v278) {
                  console.log("[CursorPro] Write still failed after permission grant");
                }
              }
            }
          }
        }
        if (!var272) {
          const var279 = path.join(process.env.TEMP || '', var270.CGqqu);
          fs.writeFileSync(var279, arg168, var270.JcomX);
          const var280 = var279.replace(/\\/g, "\\\\");
          const var281 = var271.replace(/\\/g, "\\\\");
          const var282 = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command Copy-Item -Path \\\"" + var280 + '\" -Destination \"' + var281 + "\\\" -Force' -Verb RunAs -Wait\"";
          await execAsync(var282);
          try {
            if (var270.OaUGz !== var270.ofVDg) {
              fs.unlinkSync(var279);
            } else {
              v283.push([var270.iNsae, v284.sign_up_type]);
            }
          } catch {}
        }
        try {
          await var270.NrWkg(execAsync, var270.sPvNi);
          console.log("[CursorPro] Windows DNS 缓存已刷新");
        } catch (v285) {
          console.warn("[CursorPro] Windows DNS 刷新失败:", v285);
        }
      } else {
        if (var270.iDcQt(process.platform, var270.HLfqb)) {
          const var286 = var270.vgoUd;
          fs.writeFileSync(var286, arg168, var270.JcomX);
          const var287 = "do shell script \"cp '" + var286 + "' '" + var271 + "' && rm '" + var286 + "' && dscacheutil -flushcache && killall -HUP mDNSResponder\" with administrator privileges";
          await var270.HGnBv(execAsync, 'osascript -e "' + var287.replace(/"/g, "\\\"") + "\"");
        } else {
          fs.writeFileSync(var271, arg168, var270.JcomX);
        }
      }
      return true;
    } catch (v288) {
      console.error(var270.txnlf, v288);
      return false;
    }
  }
  async _handleToggleProxy(arg179, arg180) {
    const var289 = {
      'ejdVR': "[CursorPro] 检测无感换号状态失败:",
      'PEste': function (arg181, arg182) {
        return arg181 === arg182;
      },
      'hgedP': "win32",
      'qGQVl': "[CursorPro] macOS 获取进程路径失败:",
      'uJGtI': function (arg183, arg184) {
        return arg183 !== arg184;
      },
      'JOyUC': "owyly",
      'abtRx': "JZnQC",
      'bPNQC': "cursorpro.key",
      'XKRmO': 'cursorpro.expireDate',
      'lrUSI': "proxyUpdated",
      'wngsU': '请先激活授权码',
      'bNcBC': 'showToast',
      'wbUaU': "nMubd",
      'qvcRi': function (arg185, arg186) {
        return arg185 > arg186;
      },
      'rBQDv': "授权码已过期，无法开启免魔法",
      'RrtRU': function (arg187, arg188) {
        return arg187 !== arg188;
      },
      'PoFgx': "BHFHl",
      'xXref': function (arg189, arg190) {
        return arg189 + arg190;
      },
      'HwXSS': function (arg191, arg192) {
        return arg191 !== arg192;
      },
      'LwgUG': "ejFIc",
      'yTNgQ': "QrGmP",
      'rATBP': "免魔法已关闭",
      'jtzgG': "修改 hosts 文件失败，请确保有管理员权限",
      'SfnWE': '更新配置失败'
    };
    try {
      if ("JCMUi" === "JCMUi") {
        if (arg179) {
          if (var289.uJGtI(var289.JOyUC, var289.abtRx)) {
            const var290 = this._context.globalState.get(var289.bPNQC);
            const var291 = this._context.globalState.get('cursorpro.expireDate');
            if (!var290) {
              this._postMessage({
                'type': var289.lrUSI,
                'success': false,
                'error': var289.wngsU
              });
              this._postMessage({
                'type': var289.bNcBC,
                'message': '请先激活授权码',
                'icon': '⚠️'
              });
              return;
            }
            if (var291) {
              if (var289.wbUaU === var289.wbUaU) {
                const var292 = new Date(var291).getTime();
                if (var289.qvcRi(Date.now(), var292)) {
                  this._postMessage({
                    'type': var289.lrUSI,
                    'success': false,
                    'error': var289.rBQDv
                  });
                  this._postMessage({
                    'type': var289.bNcBC,
                    'message': var289.rBQDv,
                    'icon': '⚠️'
                  });
                  return;
                }
              } else {
                v293.error("[CursorPro] 检测无感换号状态失败:", v294);
                return false;
              }
            }
          } else {
            return true;
          }
        }
        this._cleanProxySettings();
        let var295 = this._readHostsFile();
        const var296 = var295.indexOf(this.HOSTS_MARKER_START);
        const var297 = var295.indexOf(this.HOSTS_MARKER_END);
        if (var289.uJGtI(var296, -0x1) && var297 !== -0x1) {
          if (var289.PoFgx !== 'jcvMA') {
            var295 = var295.substring(0x0, var296) + var295.substring(var289.xXref(var297, this.HOSTS_MARKER_END.length));
          } else {
            return var289.PEste(v298.platform, var289.hgedP) ? "C:\\Windows\\System32\\drivers\\etc\\hosts" : "/etc/hosts";
          }
        }
        var295 = var295.replace(/\n{3,}/g, "\n\n").trim();
        if (arg179) {
          const var299 = this.CURSOR_DOMAINS.map(arg193 => this.SNI_PROXY_IP + " " + arg193).join("\n");
          const var300 = "\n\n" + this.HOSTS_MARKER_START + "\n" + var299 + "\n" + this.HOSTS_MARKER_END + "\n";
          var295 += var300;
        }
        const var301 = await this._writeHostsFile(var295);
        if (var301) {
          if (var289.LwgUG !== var289.yTNgQ) {
            0x0;
            await client_1.updateProxyConfig(arg179, this.SNI_PROXY_IP);
            this._postMessage({
              'type': var289.lrUSI,
              'success': true,
              'enabled': arg179,
              'url': this.SNI_PROXY_IP
            });
            this._postMessage({
              'type': var289.bNcBC,
              'message': arg179 ? "免魔法已开启" : var289.rATBP,
              'icon': '✅'
            });
          } else {
            v302.log("[CursorPro] 快捷方式解析获取路径失败");
          }
        } else {
          this._postMessage({
            'type': "proxyUpdated",
            'success': false,
            'error': var289.jtzgG
          });
          this._postMessage({
            'type': "showToast",
            'message': "需要管理员权限修改 hosts 文件",
            'icon': '⚠️'
          });
        }
      } else {
        v303.warn(var289.qGQVl, v304);
      }
    } catch (v305) {
      console.error("[CursorPro] Toggle proxy error:", v305);
      this._postMessage({
        'type': var289.lrUSI,
        'success': false,
        'error': var289.SfnWE
      });
    }
  }
  async _handleGetProxyStatus() {
    const var306 = {
      'fZAIy': "[CursorPro] Get proxy status error:",
      'wipaS': "proxyStatus"
    };
    try {
      const var307 = this._hasHostsConfig();
      this._postMessage({
        'type': "proxyStatus",
        'enabled': var307,
        'url': var307 ? this.SNI_PROXY_IP : ''
      });
    } catch (v308) {
      console.error(var306.fZAIy, v308);
      this._postMessage({
        'type': var306.wipaS,
        'enabled': false,
        'url': ''
      });
    }
  }
  async _handleGetSeamlessStatus() {
    const var309 = {
      'KFUBS': 'seamlessStatus',
      'rCNDh': '未找到'
    };
    try {
      const var310 = await this._getWorkbenchPathAsync();
      let var311 = false;
      if (var310 && fs.existsSync(var310)) {
        const var312 = fs.readFileSync(var310, 'utf-8');
        var311 = this._checkInjected(var312);
      }
      this._postMessage({
        'type': var309.KFUBS,
        'is_injected': var311,
        'workbench_path': var310 || '未找到'
      });
    } catch (v313) {
      this._postMessage({
        'type': "seamlessStatus",
        'is_injected': false,
        'error': "检测状态失败"
      });
    }
  }
  async _getCursorInstallPath() {
    const var314 = {
      'Dikkd': "showToast",
      'jsXpS': "请先激活授权码",
      'YOVDn': "更新配置失败",
      'iTlfT': "[CursorPro] 创建备份文件",
      'yLNTm': 'resources',
      'GeHhf': 'app',
      'CXUfC': "package.json",
      'UtnZu': "[CursorPro] 读取账号失败:",
      'gnUSM': "[CursorPro] 写入文件失败:",
      'bYxaW': function (arg194, arg195) {
        return arg194 === arg195;
      },
      'EgKGn': "EPERM",
      'EAHLk': function (arg196, arg197) {
        return arg196 === arg197;
      },
      'WjWcW': "EACCES",
      'MQZgl': "EROFS",
      'oengj': function (arg198, arg199) {
        return arg198 === arg199;
      },
      'Aarxw': 'darwin',
      'DJbBl': "没有写入权限，请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
      'aREDm': "seamlessInjected",
      'iIXMD': "usageCheckResult",
      'BDJnl': function (arg200, arg201) {
        return arg200(arg201);
      },
      'DtDgA': function (arg202, arg203) {
        return arg202 < arg203;
      },
      'mmvWR': "[CursorPro] SQLite 更新失败:",
      'oaRrk': "SQLite",
      'CTVdA': function (arg204, arg205) {
        return arg204 * arg205;
      },
      'Uuffn': 'userSwitchStatus',
      'rBiqx': "未激活授权码",
      'rQFft': "cursorPath",
      'RnudW': "[CursorPro] 使用用户配置的 Cursor 路径:",
      'PVaIE': "win32",
      'XfqQZ': function (arg206, arg207) {
        return arg206(arg207);
      },
      'DeasY': function (arg208, arg209) {
        return arg208 !== arg209;
      },
      'AsIZj': "qoucU",
      'nqiCC': 'DFFnS',
      'QVuwP': "[CursorPro] WMIC 获取路径失败",
      'dRsNK': 'YbsJH',
      'jErMS': "KgPWK",
      'NyxMG': 'powershell -Command "Get-Process Cursor -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Path"',
      'wEuDv': function (arg210, arg211) {
        return arg210 !== arg211;
      },
      'XOHNV': "PCmsj",
      'TGItL': "[CursorPro] PowerShell Get-Process 获取路径失败",
      'thwli': 'reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall" /s /f "Cursor" 2>nul | findstr "InstallLocation"',
      'VMcWU': 'xkLFN',
      'QxSsa': "VRqTq",
      'dCyzn': "qGOpJ",
      'fdUBf': "WEzFK",
      'PIiyE': "[CursorPro] 注册表方法1获取路径失败",
      'sbJjp': function (arg212, arg213) {
        return arg212(arg213);
      },
      'ZzzNm': "reg query \"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\" /s /f \"Cursor\" 2>nul | findstr \"InstallLocation\"",
      'nbZaF': function (arg214, arg215) {
        return arg214 === arg215;
      },
      'wbtDv': "vnDbD",
      'cNdLq': 'xFoOA',
      'FZvwj': 'OHDPB',
      'UneuY': 'Microsoft',
      'qsIby': "Windows",
      'EHZof': 'Cursor.lnk',
      'jjkbK': "C:\\ProgramData",
      'BtFbH': "Start Menu",
      'JdBJc': function (arg216, arg217) {
        return arg216(arg217);
      },
      'jsxnQ': function (arg218, arg219) {
        return arg218 === arg219;
      },
      'qBUXV': "[CursorPro] 快捷方式解析获取路径失败",
      'exySU': "vhjCP",
      'TGkVo': function (arg220, arg221) {
        return arg220 !== arg221;
      },
      'suGMP': "BQAEU",
      'UFTPT': "[CursorPro] where 命令获取路径失败",
      'DmbzX': "C:\\Program Files",
      'pezWM': "ProgramFiles(x86)",
      'siiYr': "Programs",
      'qYQbK': "Cursor",
      'IrvuT': 'cursor',
      'GSVlF': "AppData",
      'MCVpB': "Local",
      'PDSZm': "XrXcG",
      'EgLjx': function (arg222, arg223) {
        return arg222 !== arg223;
      },
      'HILVh': "iDOKM",
      'smRnq': "EZQju",
      'goLBO': function (arg224, arg225) {
        return arg224(arg225);
      },
      'PfsJK': function (arg226, arg227) {
        return arg226 !== arg227;
      },
      'SZhcT': "kFqGj",
      'NkvWo': "AvPWh",
      'fIoaQ': function (arg228, arg229) {
        return arg228 === arg229;
      },
      'AEQys': "DLzJi",
      'DMxiK': "fmKaB",
      'KCchE': "ps -eo comm,args | grep -i \"[C]ursor\" | grep -v \"grep\" | head -1",
      'oSNCM': "[CursorPro] macOS 获取进程路径失败:",
      'vFKuA': function (arg230, arg231) {
        return arg230 !== arg231;
      },
      'BzqQS': "LPxcr",
      'Iiavz': function (arg232, arg233) {
        return arg232(arg233);
      },
      'DTxsT': "mdfind \"kMDItemCFBundleIdentifier == 'com.todesktop.*cursor*'\" 2>/dev/null | head -1",
      'Duhra': '/Applications/Cursor.app',
      'TWejg': function (arg234, arg235) {
        return arg234(arg235);
      },
      'hHnTm': function (arg236, arg237) {
        return arg236(arg237);
      },
      'ytsfa': '/bin',
      'fYZrC': 'BDrEe',
      'TLLsB': "which cursor 2>/dev/null",
      'IGQIN': "RTVew",
      'rbFqJ': "[CursorPro] Linux 获取进程路径失败:",
      'WgRyf': "/opt/Cursor",
      'XOLnJ': '/opt/cursor',
      'fxGJt': "/usr/share/cursor",
      'lzEMa': "/usr/lib/cursor",
      'gQXjY': "Applications/cursor",
      'EghBP': "[CursorPro] 获取 Cursor 安装路径失败:"
    };
    if (this._cachedCursorPath) {
      return this._cachedCursorPath;
    }
    const var315 = vscode.workspace.getConfiguration("cursorpro");
    const var316 = var315.get(var314.rQFft);
    if (var316 && fs.existsSync(var316)) {
      console.log(var314.RnudW, var316);
      this._cachedCursorPath = var316;
      return var316;
    }
    const var317 = process.platform;
    let var318 = null;
    try {
      if (var317 === var314.PVaIE) {
        try {
          const {
            stdout: v319
          } = await execAsync("wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul");
          if (v319) {
            if (var314.DeasY(var314.AsIZj, var314.AsIZj)) {
              this._postMessage({
                'type': var314.Dikkd,
                'message': var314.jsXpS,
                'icon': '⚠️'
              });
              return;
            } else {
              const var320 = v319.match(/ExecutablePath=(.+)/);
              if (var320 && var320[0x1]) {
                if (var314.nqiCC === "qzRkG") {
                  this._postMessage({
                    'type': "showToast",
                    'message': "重置机器码失败: " + v321,
                    'icon': '❌'
                  });
                } else {
                  const var322 = var320[0x1].trim();
                  var318 = path.dirname(var322);
                }
              }
            }
          }
        } catch (v323) {
          console.log(var314.QVuwP);
        }
        if (!var318) {
          if ('YbsJH' !== var314.jErMS) {
            try {
              const {
                stdout: v324
              } = await var314.BDJnl(execAsync, var314.NyxMG);
              if (v324 && v324.trim()) {
                var318 = path.dirname(v324.trim());
              }
            } catch (v325) {
              if (var314.wEuDv(var314.XOHNV, "idSrD")) {
                console.log(var314.TGItL);
              } else if (v326.includes(v327.scode)) {
                v328 = v329.replace(v330.scode, v331.replacement);
                v332.push(v333.name);
              } else {
                v334.push(v335.name);
              }
            }
          } else {
            v336 = v337.dirname(v338);
          }
        }
        if (!var318) {
          try {
            const {
              stdout: v339
            } = await execAsync(var314.thwli);
            if (v339 && v339.trim()) {
              const var340 = v339.match(/InstallLocation\s+REG_SZ\s+(.+)/);
              if (var340 && var340[0x1] && fs.existsSync(var340[0x1].trim())) {
                if (var314.VMcWU !== var314.QxSsa) {
                  var318 = var340[0x1].trim();
                } else {
                  this._postMessage({
                    'type': "proxyUpdated",
                    'success': false,
                    'error': var314.jsXpS
                  });
                  this._postMessage({
                    'type': var314.Dikkd,
                    'message': var314.jsXpS,
                    'icon': '⚠️'
                  });
                  return;
                }
              }
            }
          } catch (v341) {
            if (var314.dCyzn !== var314.fdUBf) {
              console.log(var314.PIiyE);
            } else {
              this._postMessage({
                'type': 'seamlessConfigUpdated',
                'success': false,
                'error': var314.YOVDn
              });
            }
          }
        }
        if (!var318) {
          try {
            const {
              stdout: v342
            } = await execAsync(var314.ZzzNm);
            if (v342 && v342.trim()) {
              const var343 = v342.match(/InstallLocation\s+REG_SZ\s+(.+)/);
              if (var343 && var343[0x1] && fs.existsSync(var343[0x1].trim())) {
                if (var314.nbZaF(var314.wbtDv, var314.cNdLq)) {
                  v344 = v345.replace(v346.scode, v347.replacement);
                  v348.push(v349.name);
                } else {
                  var318 = var343[0x1].trim();
                }
              }
            }
          } catch (v350) {
            console.log("[CursorPro] 注册表方法2获取路径失败");
          }
        }
        if (!var318) {
          if (var314.FZvwj !== 'ASYNt') {
            try {
              const var351 = path.join(process.env.APPDATA || '', var314.UneuY, var314.qsIby, "Start Menu", 'Programs', var314.EHZof);
              const var352 = path.join(var314.jjkbK, var314.UneuY, 'Windows', var314.BtFbH, "Programs", var314.EHZof);
              for (const var353 of [var351, var352]) {
                if (fs.existsSync(var353)) {
                  const {
                    stdout: v354
                  } = await execAsync("powershell -Command \"(New-Object -ComObject WScript.Shell).CreateShortcut('" + var353.replace(/'/g, "''") + "').TargetPath\"");
                  if (v354 && v354.trim() && fs.existsSync(v354.trim())) {
                    if (var314.jsxnQ("EzvlI", "EzvlI")) {
                      var318 = path.dirname(v354.trim());
                      break;
                    } else {
                      v355 = ["/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js"];
                    }
                  }
                }
              }
            } catch (v356) {
              console.log(var314.qBUXV);
            }
          } else {
            const var357 = v358.match(/ExecutablePath=(.+)/);
            if (var357 && var357[0x1]) {
              const var359 = var357[0x1].trim();
              v360 = v361.dirname(var359);
            }
          }
        }
        if (!var318) {
          if (var314.exySU === var314.exySU) {
            try {
              const {
                stdout: v362
              } = await var314.JdBJc(execAsync, "where cursor 2>nul");
              if (v362 && v362.trim()) {
                const var363 = v362.trim().split("\n");
                for (const var364 of var363) {
                  const var365 = var364.trim();
                  if (var365 && fs.existsSync(var365)) {
                    var318 = path.dirname(var365);
                    break;
                  }
                }
              }
            } catch (v366) {
              if ("BQAEU" !== var314.suGMP) {
                v367.copyFileSync(v368, v369);
                v370.log(var314.iTlfT);
              } else {
                console.log(var314.UFTPT);
              }
            }
          } else {
            const var371 = v372[0x1].trim();
            v373 = v374.dirname(var371);
            v375 = v376.join(v377, var314.yLNTm, var314.GeHhf, var314.CXUfC);
          }
        }
        if (!var318) {
          const var378 = process.env.LOCALAPPDATA || '';
          const var379 = process.env.USERPROFILE || '';
          const var380 = process.env.ProgramFiles || var314.DmbzX;
          const var381 = process.env[var314.pezWM] || "C:\\Program Files (x86)";
          const var382 = [path.join(var378, var314.siiYr, var314.qYQbK), path.join(var378, var314.siiYr, var314.IrvuT), path.join(var379, var314.GSVlF, var314.MCVpB, var314.siiYr, var314.qYQbK), path.join(var380, var314.qYQbK), path.join(var381, "Cursor"), path.join(var378, var314.qYQbK), path.join(var378, var314.IrvuT)];
          for (const var383 of var382) {
            if (var314.EAHLk("mDWBe", var314.PDSZm)) {
              v384.error(var314.UtnZu, v385);
              return [];
            } else {
              if (var383 && fs.existsSync(var383)) {
                var318 = var383;
                break;
              }
            }
          }
        }
      } else {
        if (var317 === var314.Aarxw) {
          if (var314.EgLjx(var314.HILVh, "mPbmb")) {
            try {
              if ("VYhDm" === var314.smRnq) {
                v386.error(var314.gnUSM, v387);
                if (var314.bYxaW(v388.code, var314.EgKGn) || var314.EAHLk(v389.code, var314.WjWcW) || v390.code === var314.MQZgl) {
                  const var391 = v392.platform;
                  let var393 = "没有写入权限";
                  if (var314.oengj(var391, 'darwin')) {
                    var393 = var314.DJbBl;
                  } else if (var391 === "linux") {
                    var393 = "没有写入权限，请使用 sudo 权限运行或修改文件权限";
                  }
                  this._postMessage({
                    'type': var314.aREDm,
                    'success': false,
                    'error': var393,
                    'needAdmin': true,
                    'path': v394
                  });
                  return;
                }
                throw v395;
              } else {
                const {
                  stdout: v396
                } = await var314.goLBO(execAsync, "lsof -c Cursor 2>/dev/null | grep \"txt\" | grep -i \"Cursor.app\" | head -1 | awk '{print $9}'");
                if (v396 && v396.trim()) {
                  if (var314.SZhcT !== var314.SZhcT) {
                    this._postMessage({
                      'type': "usageCheckResult",
                      'success': true,
                      'needConfirm': false
                    });
                  } else {
                    const var397 = v396.trim().match(/(.+\.app)/);
                    if (var397) {
                      if (var314.bYxaW(var314.NkvWo, 'hsffN')) {
                        this._postMessage({
                          'type': var314.iIXMD,
                          'success': true,
                          'needConfirm': false
                        });
                        return;
                      } else {
                        var318 = var397[0x1];
                      }
                    }
                  }
                }
              }
            } catch (v398) {}
            if (!var318) {
              try {
                if (var314.fIoaQ(var314.AEQys, var314.DMxiK)) {
                  const var399 = v400.data.usage || {};
                  const var401 = var314.BDJnl(v402, var399.totalCostUSD || 0x0);
                  if (var314.DtDgA(var401, 0xa)) {
                    this._postMessage({
                      'type': var314.iIXMD,
                      'success': true,
                      'needConfirm': true,
                      'costUSD': var401.toFixed(0x2),
                      'email': v403
                    });
                  } else {
                    this._postMessage({
                      'type': var314.iIXMD,
                      'success': true,
                      'needConfirm': false
                    });
                  }
                } else {
                  const {
                    stdout: v404
                  } = await execAsync(var314.KCchE);
                  if (v404 && v404.trim()) {
                    const var405 = v404.match(/(\/.+\.app)/);
                    if (var405) {
                      var318 = var405[0x1];
                    }
                  }
                }
              } catch (v406) {
                console.warn(var314.oSNCM, v406);
              }
            }
            if (!var318) {
              if (var314.vFKuA("LPxcr", var314.BzqQS)) {
                v407.error("[CursorPro] Write hosts error:", v408);
                return false;
              } else {
                try {
                  const {
                    stdout: v409
                  } = await execAsync(var314.DTxsT);
                  if (v409 && v409.trim() && fs.existsSync(v409.trim())) {
                    var318 = v409.trim();
                  }
                } catch (v410) {}
              }
            }
            if (!var318 && fs.existsSync('/Applications/Cursor.app')) {
              var318 = var314.Duhra;
            }
          } else {
            v411.warn(var314.mmvWR, v412.message);
            v413.push(var314.oaRrk);
          }
        } else {
          try {
            const {
              stdout: v414
            } = await execAsync('pgrep -f "[c]ursor" | head -1');
            const var415 = v414 && v414.trim();
            if (var415) {
              const {
                stdout: v416
              } = await var314.hHnTm(execAsync, "readlink -f /proc/" + var415 + "/exe 2>/dev/null");
              if (v416 && v416.trim()) {
                const var417 = v416.trim();
                var318 = path.dirname(var417);
                if (var318.endsWith(var314.ytsfa)) {
                  var318 = path.dirname(var318);
                }
              }
            }
          } catch (v418) {}
          if (!var318) {
            if ("BDrEe" !== var314.fYZrC) {
              let var419 = '';
              const var420 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
              for (let var421 = 0x0; var421 < 0x20; var421++) {
                var419 += var420.charAt(v422.floor(v423.random() * var420.length));
              }
              return var419;
            } else {
              try {
                const {
                  stdout: v424
                } = await var314.BDJnl(execAsync, var314.TLLsB);
                if (v424 && v424.trim()) {
                  const var425 = await execAsync('readlink -f "' + v424.trim() + '" 2>/dev/null');
                  if (var425.stdout && var425.stdout.trim()) {
                    var318 = path.dirname(var425.stdout.trim());
                    if (var318.endsWith('/bin')) {
                      if (var314.oengj(var314.IGQIN, "ZRSMl")) {
                        this._postMessage({
                          'type': 'userSwitchStatus',
                          'valid': false,
                          'switchRemaining': 0x0,
                          'canSwitch': false,
                          'error': var314.rBiqx
                        });
                        return;
                      } else {
                        var318 = path.dirname(var318);
                      }
                    }
                  }
                }
              } catch (v426) {
                console.warn(var314.rbFqJ, v426);
              }
            }
          }
          if (!var318) {
            const var427 = [var314.WgRyf, var314.XOLnJ, var314.fxGJt, var314.lzEMa, path.join(process.env.HOME || '', ".local/share/cursor"), path.join(process.env.HOME || '', var314.gQXjY)];
            for (const var428 of var427) {
              if (fs.existsSync(var428)) {
                var318 = var428;
                break;
              }
            }
          }
        }
      }
    } catch (v429) {
      console.error(var314.EghBP, v429);
    }
    if (var318) {
      this._cachedCursorPath = var318;
    }
    return var318;
  }
  _getWorkbenchPath() {
    return this._getWorkbenchPathSync();
  }
  _getWorkbenchPathSync() {
    const var430 = {
      'UfpAf': "storage.serviceMachineId",
      'Anviz': "[CursorPro] machineid 更新失败:",
      'VVCFs': "machineid",
      'JyreV': function (arg238, arg239) {
        return arg238(arg239);
      },
      'LuKVI': 'crypto',
      'SWJRm': function (arg240, arg241) {
        return arg240 & arg241;
      },
      'FQssd': function (arg242, arg243) {
        return arg242 !== arg243;
      },
      'eUATr': function (arg244, arg245) {
        return arg244 === arg245;
      },
      'jTUqv': "darwin",
      'VLslV': 'xuLZV',
      'UWqNM': "app",
      'sQFsh': "out",
      'eRJjA': "workbench",
      'gkqWe': "workbench.desktop.main.js",
      'ZSOkm': function (arg246, arg247) {
        return arg246 !== arg247;
      },
      'SccyE': "kWVws",
      'dVhNW': "resources",
      'VfwmP': function (arg248, arg249) {
        return arg248 === arg249;
      },
      'NyLwi': "/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js",
      'aJjyB': 'qRWfN',
      'bWpPz': "/opt/Cursor/resources/app/out/vs/workbench/workbench.desktop.main.js"
    };
    const var431 = process.platform;
    if (this._cachedCursorPath) {
      if (var430.FQssd('zZyLK', "PQRiM")) {
        let var432;
        if (var430.eUATr(var431, var430.jTUqv)) {
          if (var430.eUATr("xuLZV", 'xuLZV')) {
            var432 = path.join(this._cachedCursorPath, 'Contents', "Resources", var430.UWqNM, var430.sQFsh, 'vs', var430.eRJjA, var430.gkqWe);
          } else {
            v433.push([var430.UfpAf, v434.serviceMachineId]);
          }
        } else if (var430.ZSOkm("XbfIf", var430.SccyE)) {
          var432 = path.join(this._cachedCursorPath, var430.dVhNW, "app", var430.sQFsh, 'vs', var430.eRJjA, "workbench.desktop.main.js");
        } else {
          v435.warn(var430.Anviz, v436.message);
          v437.push(var430.VVCFs);
        }
        if (fs.existsSync(var432)) {
          return var432;
        }
      } else {
        return [];
      }
    }
    if (var430.eUATr(var431, 'win32')) {
      return null;
    }
    let var438 = [];
    if (var430.VfwmP(var431, var430.jTUqv)) {
      var438 = [var430.NyLwi];
    } else {
      if ('DESET' !== var430.aJjyB) {
        var438 = [var430.bWpPz, '/usr/share/cursor/resources/app/out/vs/workbench/workbench.desktop.main.js'];
      } else {
        const var439 = var430.JyreV(v440, 'crypto');
        const var441 = var439.randomBytes(0x6);
        var441[0x0] = var430.SWJRm(var441[0x0] | 0x2, 0xfe);
        return v442.from(var441).map(arg250 => arg250.toString(0x10).padStart(0x2, '0')).join(':');
      }
    }
    for (const var443 of var438) {
      if (fs.existsSync(var443)) {
        return var443;
      }
    }
    return null;
  }
  async _getWorkbenchPathAsync() {
    const var444 = {
      'diJhY': "C:\\Program Files",
      'BHmwx': "ProgramFiles(x86)",
      'xDKiN': "C:\\Program Files (x86)",
      'aIUry': "Programs",
      'oemiO': "Cursor",
      'wNjLv': "resources",
      'BzPhh': "package.json",
      'dNHJx': "cursor",
      'JBwsK': "app",
      'NoEGQ': "AppData",
      'GOKzJ': "Local",
      'okosv': 'versionCheck',
      'ktVBs': function (arg251, arg252) {
        return arg251 === arg252;
      },
      'fYTsi': "EUUHA",
      'idevD': "eXeOK",
      'SJHtk': function (arg253, arg254) {
        return arg253 === arg254;
      },
      'AJPrD': "darwin",
      'qcilt': function (arg255, arg256) {
        return arg255 === arg256;
      },
      'yQEWX': "vUlDT",
      'Knhyl': "Contents",
      'NPYXr': "Resources",
      'xDNVo': "out",
      'Lnhsa': "workbench",
      'ejmIv': "workbench.desktop.main.js",
      'yfprZ': "dtGAS"
    };
    const var445 = process.platform;
    const var446 = await this._getCursorInstallPath();
    if (var446) {
      if (var444.ktVBs(var444.fYTsi, var444.idevD)) {
        const var447 = v448[0x1].trim();
        v449 = v450.dirname(var447);
      } else {
        let var451;
        if (var445 === var444.AJPrD) {
          if (var444.qcilt(var444.yQEWX, var444.yQEWX)) {
            var451 = path.join(var446, var444.Knhyl, var444.NPYXr, var444.JBwsK, var444.xDNVo, 'vs', var444.Lnhsa, var444.ejmIv);
          } else {
            const var452 = v453.env.LOCALAPPDATA || '';
            const var454 = v455.env.USERPROFILE || '';
            const var456 = v457.env.ProgramFiles || var444.diJhY;
            const var458 = v459.env[var444.BHmwx] || var444.xDKiN;
            v460.push(v461.join(var452, var444.aIUry, var444.oemiO, var444.wNjLv, "app", var444.BzPhh), v462.join(var452, var444.aIUry, var444.dNHJx, var444.wNjLv, var444.JBwsK, var444.BzPhh), v463.join(var454, var444.NoEGQ, var444.GOKzJ, var444.aIUry, var444.oemiO, "resources", var444.JBwsK, "package.json"), v464.join(var456, "Cursor", "resources", "app", var444.BzPhh), v465.join(var456, var444.dNHJx, var444.wNjLv, var444.JBwsK, var444.BzPhh), v466.join(var458, var444.oemiO, "resources", var444.JBwsK, "package.json"));
          }
        } else {
          var451 = path.join(var446, var444.wNjLv, var444.JBwsK, var444.xDNVo, 'vs', var444.Lnhsa, "workbench.desktop.main.js");
        }
        if (fs.existsSync(var451)) {
          if (var444.yfprZ === var444.yfprZ) {
            return var451;
          } else {
            this._postMessage({
              'type': var444.okosv,
              'success': false,
              'currentVersion': v467.CURRENT_VERSION,
              'error': v468.message || "请求失败"
            });
          }
        }
      }
    }
    return this._getWorkbenchPathSync();
  }
  _checkInjected(arg257) {
    const var469 = {
      'WkvEt': "/*i0*/"
    };
    return arg257.includes(var469.WkvEt) || arg257.includes('/*i1s*/');
  }
  async _isSeamlessInjected() {
    const var470 = {
      'gPIxP': "utf-8",
      'ntlpp': "[CursorPro] 检测无感换号状态失败:"
    };
    try {
      const var471 = await this._getWorkbenchPathAsync();
      if (var471 && fs.existsSync(var471)) {
        const var472 = fs.readFileSync(var471, var470.gPIxP);
        return this._checkInjected(var472);
      }
      return false;
    } catch (v473) {
      console.error(var470.ntlpp, v473);
      return false;
    }
  }
  _getInjectionConfig(arg258, arg259) {
    const var474 = {
      'FgaCg': '_showNotification(){',
      'OHrmM': "_showNotification(){/*i0*/}_showNotificationOld(){",
      'CRApk': "注入点1: 核心模块初始化",
      'YatzY': "this.database.getItems()))",
      'MqHGw': "/*i1s*/",
      'OSWSK': "/*i1e*/",
      'QXMFr': "注入点2: 启动时Token同步",
      'hxXLs': "/*i2e*/"
    };
    return [{
      'name': "注入点0: 完整性检查绕过",
      'scode': var474.FgaCg,
      'replacement': "_showNotification(){/*i0*/}_showNotificationOld(){",
      'restore': {
        'find': var474.OHrmM,
        'replace_with': var474.FgaCg
      }
    }, {
      'name': "注入点1: 核心模块初始化",
      'scode': var474.YatzY,
      '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='" + arg258 + "';window.__cpUserKey='" + arg259 + "';window.__cpVersion=0;console.log('[CP] Initialized with key:','" + arg259 + "'.substring(0,15)+'...')}})(this)/*i1e*/",
      'restore': {
        'find_start': var474.MqHGw,
        'find_end': var474.OSWSK
      }
    }, {
      'name': var474.QXMFr,
      'scode': var474.OSWSK,
      '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': var474.hxXLs
      }
    }];
  }
  async _handleInjectSeamless() {
    const var475 = {
      'eAudc': 'resources',
      'ZnFEJ': 'app',
      'QGTLQ': 'package.json',
      'yDFID': "激活码已过期或无效",
      'XoRrm': "darwin",
      'zcMpa': "Contents",
      'cTyAN': "Resources",
      'UNUES': "[CursorPro] 使用用户配置的路径:",
      'IJzdz': "未检测到运行中的Cursor进程",
      'VGOST': "activated",
      'vySBX': "无感换号已启用，请先禁用后再更换授权码",
      'OUNoh': "[CursorPro] Read hosts error:",
      'gzoYo': "[CursorPro] 备份恢复失败:",
      'nmpHW': function (arg260, arg261) {
        return arg260 !== arg261;
      },
      'mZDVz': 'reoBh',
      'XlzQa': "seamlessInjected",
      'RKaZM': "授权码无效",
      'wFOsZ': function (arg262, arg263) {
        return arg262 === arg263;
      },
      'uTxRa': "wecNx",
      'NQBnu': "启用失败",
      'QwROM': function (arg264, arg265) {
        return arg264 + arg265;
      },
      'KPHtC': ".backup",
      'BJIgK': "cursorpro.seamlessInjected",
      'asGDz': function (arg266, arg267) {
        return arg266 === arg267;
      },
      'AvMcE': "grpZy",
      'NFNQK': "[CursorPro] 首次启用，从备份恢复干净的 workbench 文件",
      'ApEZm': "[CursorPro] 备份恢复成功",
      'WEdcP': function (arg268, arg269) {
        return arg268 === arg269;
      },
      'NwiBk': "jYehy",
      'fWqWm': "gRHmI",
      'PuBtb': function (arg270, arg271) {
        return arg270 === arg271;
      },
      'QPTVv': "[CursorPro] 注入失败，未找到任何注入点",
      'bwZyq': "[CursorPro] 文件路径:",
      'isjyP': "[CursorPro] 文件大小:",
      'nGlvY': "_showNotification",
      'eLVeH': "getItems()",
      'JDsIJ': "[CursorPro] 包含 _showNotification:",
      'Spptx': "[CursorPro] 包含 getItems():",
      'OaqMs': "Cursor 版本不兼容，注入点未找到",
      'CqvrX': function (arg272, arg273) {
        return arg272 > arg273;
      },
      'tdJex': "[CursorPro] 未找到的注入点:",
      'IsXFU': function (arg274, arg275) {
        return arg274 === arg275;
      },
      'NpueJ': "txcqo",
      'chYLS': "[CursorPro] 写入文件失败:",
      'qFuwX': 'EACCES',
      'jWyZD': "没有写入权限，请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
      'nsFtB': function (arg276, arg277) {
        return arg276 === arg277;
      },
      'vryqQ': "linux",
      'FiwIr': "gWxzY",
      'NnBbT': "qchHx",
      'kofbg': "没有写入权限，请使用 sudo 权限运行或修改文件权限",
      'WedEJ': "无感换号已启用",
      'jiObk': "nUNdq",
      'chXsS': "[CursorPro] Inject error:",
      'PfOPU': "EPERM",
      'GZrDV': function (arg278, arg279) {
        return arg278 === arg279;
      },
      'SUpCK': 'TKgrk',
      'JOonS': "rIkKS",
      'uvZZD': "没有写入权限"
    };
    try {
      const var476 = this._context.globalState.get("cursorpro.key");
      if (!var476) {
        if (var475.nmpHW("dlteM", 'reoBh')) {
          this._postMessage({
            'type': var475.XlzQa,
            'success': false,
            'error': "请先激活授权码"
          });
          return;
        } else {
          v477.push(v478.join(v479, var475.eAudc, var475.ZnFEJ, var475.QGTLQ));
        }
      }
      0x0;
      const var480 = await client_1.getUserSwitchStatus(var476);
      if (!var480.valid) {
        this._postMessage({
          'type': var475.XlzQa,
          'success': false,
          'error': var480.error || var475.RKaZM
        });
        return;
      }
      const var481 = await this._getWorkbenchPathAsync();
      if (!var481) {
        if (var475.wFOsZ(var475.uTxRa, var475.uTxRa)) {
          this._postMessage({
            'type': var475.XlzQa,
            'success': false,
            'error': var475.NQBnu
          });
          return;
        } else {
          this._postMessage({
            'type': 'keyStatusChecked',
            'valid': false,
            'expired': true,
            'error': v482.error || var475.yDFID
          });
        }
      }
      const var483 = var475.QwROM(var481, var475.KPHtC);
      const var484 = !this._context.globalState.get(var475.BJIgK);
      if (var484 && fs.existsSync(var483)) {
        if (var475.asGDz("xfseF", var475.AvMcE)) {
          v485 = v486;
          if (v487 === var475.XoRrm) {
            v488 = v489.join(v490, var475.zcMpa, var475.cTyAN, var475.ZnFEJ, 'package.json');
          } else {
            v491 = v492.join(v493, var475.eAudc, var475.ZnFEJ, 'package.json');
          }
          v494.log(var475.UNUES, v495);
        } else {
          console.log(var475.NFNQK);
          try {
            fs.copyFileSync(var483, var481);
            console.log(var475.ApEZm);
          } catch (v496) {
            console.error(var475.gzoYo, v496);
          }
        }
      }
      let var497 = fs.readFileSync(var481, 'utf-8');
      if (this._checkInjected(var497)) {
        this._postMessage({
          'type': "showToast",
          'message': "已启用",
          'icon': '✅'
        });
        return;
      }
      if (!fs.existsSync(var483)) {
        fs.copyFileSync(var481, var483);
        console.log("[CursorPro] 创建备份文件");
      }
      0x0;
      const var498 = client_1.getApiUrl();
      const var499 = this._getInjectionConfig(var498, var476);
      const var500 = [];
      const var501 = [];
      for (const var502 of var499) {
        if (var475.NwiBk === var475.fWqWm) {
          v503 = var475.IJzdz;
        } else if (var497.includes(var502.scode)) {
          var497 = var497.replace(var502.scode, var502.replacement);
          var500.push(var502.name);
        } else {
          var501.push(var502.name);
        }
      }
      if (var475.PuBtb(var500.length, 0x0)) {
        console.error(var475.QPTVv);
        console.error(var475.bwZyq, var481);
        console.error(var475.isjyP, var497.length);
        console.error("[CursorPro] 未找到的注入点:", var501);
        const var504 = var497.includes(var475.nGlvY);
        const var505 = var497.includes(var475.eLVeH);
        console.error(var475.JDsIJ, var504);
        console.error(var475.Spptx, var505);
        this._postMessage({
          'type': var475.XlzQa,
          'success': false,
          'error': var475.OaqMs,
          'details': "路径: " + var481
        });
        return;
      }
      console.log("[CursorPro] 注入成功，应用的注入点:", var500);
      if (var475.CqvrX(var501.length, 0x0)) {
        console.warn(var475.tdJex, var501);
      }
      try {
        if (var475.IsXFU("nYkuW", "oAKop")) {
          v506.warn("[CursorPro] 获取进程路径失败:", v507);
        } else {
          fs.writeFileSync(var481, var497, "utf-8");
        }
      } catch (v508) {
        if (var475.nmpHW("txcqo", var475.NpueJ)) {
          this._postMessage({
            'type': var475.VGOST,
            'success': false,
            'error': var475.vySBX
          });
          return;
        } else {
          console.error(var475.chYLS, v508);
          if (var475.IsXFU(v508.code, "EPERM") || var475.WEdcP(v508.code, var475.qFuwX) || v508.code === "EROFS") {
            const var509 = process.platform;
            let var510 = "没有写入权限";
            if (var475.WEdcP(var509, var475.XoRrm)) {
              var510 = var475.jWyZD;
            } else if (var509 === var475.vryqQ) {
              if (var475.FiwIr === var475.NnBbT) {
                v511.error(var475.OUNoh, v512);
              } else {
                var510 = var475.kofbg;
              }
            }
            this._postMessage({
              'type': var475.XlzQa,
              'success': false,
              'error': var510,
              'needAdmin': true,
              'path': var481
            });
            return;
          }
          throw v508;
        }
      }
      await this._context.globalState.update(var475.BJIgK, true);
      this._postMessage({
        'type': 'seamlessInjected',
        'success': true,
        'applied': var500,
        'needRestart': true,
        'message': var475.WedEJ
      });
    } catch (v513) {
      if (var475.jiObk !== 'nUNdq') {
        const var514 = this._readHostsFile();
        return var514.includes(this.HOSTS_MARKER_START);
      } else {
        console.error(var475.chXsS, v513);
        if (v513.code === var475.PfOPU || v513.code === var475.qFuwX) {
          if (var475.SUpCK === var475.JOonS) {
            v515.error(var475.gzoYo, v516);
          } else {
            const var517 = var475.uvZZD;
            this._postMessage({
              'type': var475.XlzQa,
              'success': false,
              'error': var517,
              'needAdmin': true
            });
            return;
          }
        }
        this._postMessage({
          'type': var475.XlzQa,
          'success': false,
          'error': v513.message || '注入失败'
        });
      }
    }
  }
  async _handleRestoreSeamless() {
    const var518 = {
      'fNFwN': function (arg280, arg281) {
        return arg280 === arg281;
      },
      'qzWvm': "gPXAj",
      'iIeEk': "utf-8",
      'hXGdP': "_showNotification(){/*i0*/}_showNotificationOld(){",
      'TTVZf': "_showNotification(){",
      'gtuTM': "/*i1e*/",
      'GRbOi': function (arg282, arg283) {
        return arg282 !== arg283;
      },
      'SIJlB': function (arg284, arg285) {
        return arg284 + arg285;
      },
      'lhoIl': '/*i2s*/',
      'rihJn': "/*i2e*/",
      'UKjaP': function (arg286, arg287) {
        return arg286 !== arg287;
      },
      'gfXYq': "kmqvv",
      'oXUXx': function (arg288, arg289) {
        return arg288 + arg289;
      },
      'hFPNQ': function (arg290, arg291) {
        return arg290 === arg291;
      },
      'iKOOs': function (arg292, arg293) {
        return arg292 === arg293;
      },
      'yKkFV': "uoVdW",
      'uxIzt': "tzZLb",
      'PVsoN': "没有写入权限",
      'dzulQ': "seamlessRestored",
      'wYcDp': "[CursorPro] Restore error:",
      'yoKCW': "EPERM",
      'dGgrN': function (arg294, arg295) {
        return arg294 === arg295;
      },
      'ybPXs': "EACCES"
    };
    try {
      const var519 = await this._getWorkbenchPathAsync();
      if (!var519) {
        if ("JnQIK" === var518.qzWvm) {
          return v520;
        } else {
          this._postMessage({
            'type': "seamlessRestored",
            'success': false,
            'error': '未找到Cursor安装目录'
          });
          return;
        }
      }
      let var521 = fs.readFileSync(var519, var518.iIeEk);
      if (!this._checkInjected(var521)) {
        return;
      }
      var521 = var521.replace(var518.hXGdP, var518.TTVZf);
      const var522 = var521.indexOf("/*i1s*/");
      const var523 = var521.indexOf(var518.gtuTM);
      if (var522 !== -0x1 && var523 !== -0x1) {
        var521 = var521.substring(0x0, var522) + var521.substring(var523 + 0x7);
      }
      const var524 = var521.indexOf(var518.lhoIl);
      const var525 = var521.indexOf(var518.rihJn);
      if (var524 !== -0x1 && var525 !== -0x1) {
        if (var518.UKjaP('kmqvv', var518.gfXYq)) {
          v526.unlinkSync(v527);
        } else {
          var521 = var518.oXUXx(var521.substring(0x0, var524), var521.substring(var525 + 0x7));
        }
      }
      try {
        fs.writeFileSync(var519, var521, var518.iIeEk);
      } catch (v528) {
        if (var518.hFPNQ(v528.code, "EPERM") || v528.code === "EACCES") {
          if (var518.iKOOs(var518.yKkFV, var518.uxIzt)) {
            v529 = v530[0x1];
          } else {
            const var531 = var518.PVsoN;
            this._postMessage({
              'type': var518.dzulQ,
              'success': false,
              'error': var531,
              'needAdmin': true
            });
            return;
          }
        }
        throw v528;
      }
      this._postMessage({
        'type': var518.dzulQ,
        'success': true,
        'needRestart': true,
        'message': "无感换号已禁用"
      });
    } catch (v532) {
      console.error(var518.wYcDp, v532);
      if (v532.code === var518.yoKCW || var518.dGgrN(v532.code, var518.ybPXs)) {
        const var533 = "没有写入权限";
        this._postMessage({
          'type': var518.dzulQ,
          'success': false,
          'error': var533,
          'needAdmin': true
        });
        return;
      }
      this._postMessage({
        'type': var518.dzulQ,
        'success': false,
        'error': v532.message || '还原失败'
      });
    }
  }
  async _handleToggleSeamless(arg296) {
    const var534 = {
      'uMKkd': "dSScr",
      'puuTf': 'OoEdP',
      'GMeLW': "seamlessConfigUpdated",
      'xfsPC': function (arg297, arg298) {
        return arg297 === arg298;
      },
      'gwHNY': "SZovO",
      'DbkSk': "更新配置失败"
    };
    try {
      if (var534.uMKkd === 'OoEdP') {
        try {
          if (v535.existsSync(v536)) {
            v537.rmSync(v538, {
              'recursive': true,
              'force': true
            });
            v539++;
          }
        } catch (v540) {
          v541.warn("[CursorPro] 清理失败: " + v542, v540);
        }
      } else {
        0x0;
        await client_1.updateSeamlessConfig({
          'enabled': arg296
        });
        this._postMessage({
          'type': var534.GMeLW,
          'success': true,
          'enabled': arg296
        });
      }
    } catch (v543) {
      if (var534.xfsPC("lzzwb", var534.gwHNY)) {
        return this._getWorkbenchPathSync();
      } else {
        this._postMessage({
          'type': var534.GMeLW,
          'success': false,
          'error': var534.DbkSk
        });
      }
    }
  }
  async _handleGetUserSwitchStatus() {
    const var544 = {
      'iTdeY': "tFzAd",
      'sJbdj': 'userSwitchStatus',
      'Bzqze': 'TSpKd',
      'HRNLC': function (arg299, arg300) {
        return arg299 !== arg300;
      },
      'BIPgO': "NMuKY",
      'zFtlx': "获取状态失败"
    };
    try {
      if (var544.iTdeY !== var544.iTdeY) {
        v545.push(["cursorAuth/cachedEmail", v546.email]);
      } else {
        const var547 = this._context.globalState.get('cursorpro.key');
        if (!var547) {
          this._postMessage({
            'type': var544.sJbdj,
            'valid': false,
            'switchRemaining': 0x0,
            'canSwitch': false,
            'error': "未激活授权码"
          });
          return;
        }
        0x0;
        const var548 = await client_1.getUserSwitchStatus(var547);
        let var549 = false;
        try {
          if ('TSpKd' === "TSpKd") {
            0x0;
            const var550 = await client_1.getSeamlessStatus();
            var549 = var550.is_injected || false;
          } else {
            v551.warn("[CursorPro] 清理失败: " + v552, v553);
          }
        } catch (v554) {}
        this._postMessage({
          'type': 'userSwitchStatus',
          ...var548,
          'seamlessEnabled': var549
        });
      }
    } catch (v555) {
      if ("ObXTw" !== var544.BIPgO) {
        this._postMessage({
          'type': "userSwitchStatus",
          'valid': false,
          'switchRemaining': 0x0,
          'canSwitch': false,
          'error': var544.zFtlx
        });
      } else {
        const var556 = 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-" + var556 + "'; img-src " + v557.cspSource + " https: data:; font-src " + v558.cspSource + "; worker-src 'none';\">\n    <title>CursorPro</title>\n    <script nonce=\"" + var556 + "\">\n        // 尽早清理 Service Worker（在 head 中执行，比 body 更早）\n        if ('serviceWorker' in navigator) {\n            navigator.serviceWorker.getRegistrations().then(function(regs) {\n                regs.forEach(function(reg) { reg.unregister(); });\n            }).catch(function() {});\n        }\n    </script>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n        \n        body {\n            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n            background: #1e1e1e;\n            color: #cccccc;\n            padding: 12px;\n            font-size: 13px;\n        }\n        \n        .section {\n            margin-bottom: 16px;\n            padding: 12px;\n            background: #252526;\n            border-radius: 6px;\n        }\n        \n        .section-title {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            margin-bottom: 12px;\n            font-size: 13px;\n            color: #ffffff;\n        }\n        \n        .section-title .icon {\n            font-size: 16px;\n        }\n        \n        .status-badge {\n            margin-left: auto;\n            padding: 2px 8px;\n            border-radius: 4px;\n            font-size: 11px;\n        }\n        \n        .status-badge.inactive {\n            background: #6e3232;\n            color: #ff6b6b;\n        }\n        \n        .status-badge.active {\n            background: #2d4a3e;\n            color: #4ade80;\n        }\n        \n        .input-group {\n            display: flex;\n            gap: 8px;\n            margin-bottom: 12px;\n        }\n        \n        input[type=\"text\"] {\n            flex: 1;\n            padding: 8px 12px;\n            background: #3c3c3c;\n            border: 1px solid #4a4a4a;\n            border-radius: 4px;\n            color: #ffffff;\n            font-size: 13px;\n        }\n        \n        input[type=\"text\"]::placeholder {\n            color: #888888;\n        }\n        \n        input[type=\"text\"]:focus {\n            outline: none;\n            border-color: #007acc;\n        }\n        \n        .btn {\n            padding: 8px 16px;\n            border: none;\n            border-radius: 4px;\n            font-size: 13px;\n            cursor: pointer;\n            font-weight: 500;\n            transition: opacity 0.2s;\n        }\n        \n        .btn:hover {\n            opacity: 0.9;\n        }\n        \n        .btn:disabled {\n            opacity: 0.5;\n            cursor: not-allowed;\n        }\n        \n        .btn-primary {\n            background: #007acc;\n            color: white;\n        }\n        \n        .btn-purple {\n            background: #8b5cf6;\n            color: white;\n        }\n        \n        .btn-blue {\n            background: #3b82f6;\n            color: white;\n        }\n        \n        .btn-red {\n            background: #ef4444;\n            color: white;\n        }\n        \n        .btn-block {\n            display: block;\n            width: 100%;\n            margin-bottom: 8px;\n        }\n        \n        .info-row {\n            display: flex;\n            justify-content: space-between;\n            padding: 6px 0;\n            border-bottom: 1px solid #3c3c3c;\n        }\n        \n        .info-row:last-child {\n            border-bottom: none;\n        }\n        \n        .info-label {\n            color: #888888;\n        }\n        \n        .info-value {\n            color: #ffffff;\n        }\n        \n        .usage-row {\n            display: flex;\n            gap: 12px;\n            margin-bottom: 8px;\n        }\n        \n        .usage-row:last-of-type {\n            margin-bottom: 0;\n        }\n        \n        .usage-item {\n            flex: 1;\n            display: flex;\n            justify-content: space-between;\n            padding: 6px 10px;\n            background: #2d2d2d;\n            border-radius: 4px;\n        }\n        \n        .switch-container {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n        }\n        \n        .switch {\n            position: relative;\n            width: 40px;\n            height: 20px;\n        }\n        \n        .switch input {\n            opacity: 0;\n            width: 0;\n            height: 0;\n        }\n        \n        .slider {\n            position: absolute;\n            cursor: pointer;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            background-color: #4a4a4a;\n            border-radius: 20px;\n            transition: 0.3s;\n        }\n        \n        .slider:before {\n            position: absolute;\n            content: \"\";\n            height: 16px;\n            width: 16px;\n            left: 2px;\n            bottom: 2px;\n            background-color: white;\n            border-radius: 50%;\n            transition: 0.3s;\n        }\n        \n        input:checked + .slider {\n            background-color: #8b5cf6;\n        }\n        \n        input:checked + .slider:before {\n            transform: translateX(20px);\n        }\n        \n        /* 小尺寸开关样式 */\n        .switch-sm {\n            position: relative;\n            width: 32px;\n            height: 16px;\n        }\n        \n        .switch-sm .slider:before {\n            height: 12px;\n            width: 12px;\n            left: 2px;\n            bottom: 2px;\n        }\n        \n        .switch-sm input:checked + .slider:before {\n            transform: translateX(16px);\n        }\n        \n        .pro-badge {\n            background: linear-gradient(90deg, #8b5cf6, #d946ef);\n            padding: 2px 6px;\n            border-radius: 4px;\n            font-size: 10px;\n            font-weight: bold;\n            color: white;\n        }\n        \n        .footer {\n            margin-top: 16px;\n            padding: 12px;\n            background: linear-gradient(135deg, rgba(60, 60, 60, 0.3) 0%, rgba(40, 40, 40, 0.5) 100%);\n            border-radius: 8px;\n            border: 1px solid rgba(255, 255, 255, 0.05);\n        }\n        \n        .footer-row {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n        \n        .auto-start {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            font-size: 11px;\n            color: #888;\n        }\n        \n        .cursor-version {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n            font-size: 11px;\n            color: #666;\n            padding: 4px 10px;\n            background: rgba(0, 0, 0, 0.2);\n            border-radius: 12px;\n        }\n        \n        .cursor-version .version-num {\n            color: #a78bfa;\n            font-weight: 500;\n        }\n        \n        /* 自定义弹窗样式 */\n        .modal-overlay {\n            display: none;\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            backdrop-filter: blur(4px);\n            z-index: 1000;\n            justify-content: center;\n            align-items: center;\n            animation: fadeIn 0.2s ease;\n        }\n        \n        @keyframes fadeIn {\n            from { opacity: 0; }\n            to { opacity: 1; }\n        }\n        \n        @keyframes slideIn {\n            from { \n                opacity: 0;\n                transform: scale(0.9) translateY(-10px);\n            }\n            to { \n                opacity: 1;\n                transform: scale(1) translateY(0);\n            }\n        }\n        \n        .modal-overlay.show {\n            display: flex;\n        }\n        \n        .modal-content {\n            background: linear-gradient(145deg, #1e1e1e 0%, #2a2a2a 100%);\n            border-radius: 12px;\n            padding: 16px 20px;\n            max-width: 260px;\n            width: 90%;\n            text-align: center;\n            box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.05);\n            animation: slideIn 0.2s ease;\n        }\n        \n        .modal-icon {\n            width: 44px;\n            height: 44px;\n            margin: 0 auto 12px;\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-size: 22px;\n        }\n        \n        .modal-icon.warning {\n            background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n            box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);\n        }\n        \n        .modal-icon.success {\n            background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n            box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);\n        }\n        \n        .modal-title {\n            font-size: 15px;\n            font-weight: 600;\n            color: #fff;\n            margin-bottom: 6px;\n        }\n        \n        .modal-message {\n            font-size: 12px;\n            color: #9ca3af;\n            margin-bottom: 16px;\n            line-height: 1.5;\n        }\n        \n        .modal-buttons {\n            display: flex;\n            gap: 8px;\n            justify-content: center;\n        }\n        \n        .modal-btn {\n            padding: 8px 16px;\n            border: none;\n            border-radius: 8px;\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: all 0.15s ease;\n        }\n        \n        .modal-btn.primary {\n            background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n            color: white;\n            box-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);\n        }\n        \n        .modal-btn.primary:hover {\n            box-shadow: 0 4px 12px rgba(139, 92, 246, 0.5);\n        }\n        \n        .modal-btn.secondary {\n            background: rgba(255, 255, 255, 0.08);\n            color: #9ca3af;\n            border: 1px solid rgba(255, 255, 255, 0.1);\n        }\n        \n        .modal-btn.secondary:hover {\n            background: rgba(255, 255, 255, 0.12);\n            color: #fff;\n        }\n        \n        .modal-btn.single {\n            background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n            color: white;\n            box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);\n            min-width: 100px;\n        }\n        \n        .modal-btn.single:hover {\n            box-shadow: 0 4px 12px rgba(59, 130, 246, 0.5);\n        }\n        \n        .highlight {\n            color: #4ade80;\n            font-weight: 600;\n        }\n        \n        .key-display {\n            cursor: pointer;\n            transition: color 0.2s;\n        }\n        \n        .key-display:hover {\n            color: #007acc;\n        }\n        \n        .key-display.copied {\n            color: #4ade80 !important;\n        }\n        \n        /* Loading 状态样式 */\n        .btn.loading {\n            position: relative;\n            pointer-events: none;\n            opacity: 0.7;\n        }\n        \n        .btn.loading .btn-text {\n            visibility: hidden;\n        }\n        \n        .btn.loading::after {\n            content: '';\n            position: absolute;\n            width: 16px;\n            height: 16px;\n            top: 50%;\n            left: 50%;\n            margin-left: -8px;\n            margin-top: -8px;\n            border: 2px solid transparent;\n            border-top-color: #fff;\n            border-radius: 50%;\n            animation: spin 0.8s linear infinite;\n        }\n        \n        @keyframes spin {\n            to { transform: rotate(360deg); }\n        }\n        \n        .refresh-btn.loading {\n            animation: spin 1s linear infinite;\n            pointer-events: none;\n        }\n        \n        /* 公告样式 */\n        .announcement-badge {\n            margin-left: auto;\n            padding: 2px 8px;\n            border-radius: 4px;\n            font-size: 11px;\n            text-transform: uppercase;\n        }\n        \n        .announcement-badge.info {\n            background: #1e3a5f;\n            color: #60a5fa;\n        }\n        \n        .announcement-badge.warning {\n            background: #5c4a1f;\n            color: #fbbf24;\n        }\n        \n        .announcement-badge.error {\n            background: #6e3232;\n            color: #f87171;\n        }\n        \n        .announcement-badge.success {\n            background: #2d4a3e;\n            color: #4ade80;\n        }\n        \n        .announcement-title {\n            font-size: 14px;\n            font-weight: 600;\n            color: #ffffff;\n            margin-bottom: 8px;\n            line-height: 1.4;\n        }\n        \n        .announcement-content {\n            font-size: 12px;\n            color: #b0b0b0;\n            line-height: 1.6;\n            word-break: break-word;\n        }\n        \n        .announcement-link {\n            color: #60a5fa;\n            text-decoration: none;\n            border-bottom: 1px dashed #60a5fa;\n            transition: all 0.2s;\n            cursor: pointer;\n        }\n        \n        .announcement-link:hover {\n            color: #93c5fd;\n            border-bottom-color: #93c5fd;\n        }\n        \n        /* Toast 通知样式 */\n        .toast-container {\n            position: fixed;\n            top: 0;\n            left: 0;\n            right: 0;\n            display: flex;\n            justify-content: center;\n            padding: 12px;\n            pointer-events: none;\n            z-index: 2000;\n        }\n        \n        .toast {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            padding: 10px 16px;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            border: 1px solid rgba(74, 222, 128, 0.3);\n            border-radius: 8px;\n            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4), 0 0 20px rgba(74, 222, 128, 0.1);\n            transform: translateY(-100px);\n            opacity: 0;\n            transition: all 0.3s ease;\n            pointer-events: auto;\n        }\n        \n        .toast.show {\n            transform: translateY(0);\n            opacity: 1;\n        }\n        \n        .toast-icon {\n            font-size: 16px;\n        }\n        \n        .toast-message {\n            font-size: 12px;\n            color: #e0e0e0;\n            max-width: 280px;\n            word-break: break-all;\n        }\n        \n        /* 离线状态提示样式 */\n        .offline-banner {\n            display: none;\n            align-items: center;\n            gap: 8px;\n            padding: 10px 14px;\n            margin-bottom: 12px;\n            background: linear-gradient(135deg, #7f1d1d 0%, #991b1b 100%);\n            border: 1px solid rgba(239, 68, 68, 0.3);\n            border-radius: 8px;\n            animation: slideDown 0.3s ease;\n        }\n        \n        .offline-banner.show {\n            display: flex;\n        }\n        \n        @keyframes slideDown {\n            from {\n                opacity: 0;\n                transform: translateY(-10px);\n            }\n            to {\n                opacity: 1;\n                transform: translateY(0);\n            }\n        }\n        \n        .offline-banner .offline-icon {\n            font-size: 18px;\n            flex-shrink: 0;\n        }\n        \n        .offline-banner .offline-text {\n            flex: 1;\n        }\n        \n        .offline-banner .offline-title {\n            font-size: 12px;\n            font-weight: 600;\n            color: #fca5a5;\n            margin-bottom: 2px;\n        }\n        \n        .offline-banner .offline-desc {\n            font-size: 11px;\n            color: #fecaca;\n            opacity: 0.8;\n        }\n        \n        .offline-banner .retry-btn {\n            padding: 4px 10px;\n            background: rgba(255, 255, 255, 0.15);\n            border: 1px solid rgba(255, 255, 255, 0.2);\n            border-radius: 4px;\n            color: #fff;\n            font-size: 11px;\n            cursor: pointer;\n            transition: all 0.2s;\n            flex-shrink: 0;\n        }\n        \n        .offline-banner .retry-btn:hover {\n            background: rgba(255, 255, 255, 0.25);\n        }\n        \n        .offline-banner .retry-btn.loading {\n            pointer-events: none;\n            opacity: 0.7;\n        }\n        \n        /* 顶部更新提醒条 */\n        .update-banner {\n            position: sticky;\n            top: 0;\n            left: 0;\n            right: 0;\n            background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);\n            color: #fff;\n            padding: 8px 12px;\n            font-size: 12px;\n            display: none;\n            align-items: center;\n            justify-content: center;\n            gap: 8px;\n            z-index: 1000;\n            box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n        }\n        .update-banner.show {\n            display: flex;\n        }\n        .update-banner .update-icon {\n            font-size: 14px;\n        }\n        .update-banner .update-text {\n            font-weight: 500;\n        }\n        .update-banner .update-version {\n            background: rgba(255,255,255,0.2);\n            padding: 2px 6px;\n            border-radius: 4px;\n            font-size: 11px;\n        }\n        .update-banner .update-close {\n            margin-left: auto;\n            background: none;\n            border: none;\n            color: #fff;\n            cursor: pointer;\n            font-size: 16px;\n            padding: 0 4px;\n            opacity: 0.8;\n        }\n        .update-banner .update-close:hover {\n            opacity: 1;\n        }\n        \n    </style>\n</head>\n<body>\n    <!-- 顶部更新提醒条 -->\n    <div class=\"update-banner\" id=\"updateBanner\">\n        <span class=\"update-icon\">🚀</span>\n        <span class=\"update-text\">发现新版本</span>\n        <span class=\"update-version\" id=\"updateBannerVersion\">v0.0</span>\n        <button class=\"update-close\" id=\"updateBannerClose\" title=\"关闭\">×</button>\n    </div>\n    \n    <!-- 管理员权限提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"adminModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">🔐</div>\n            <div class=\"modal-title\">需要管理员权限</div>\n            <div class=\"modal-message\">\n                请关闭 Cursor，右键点击图标<br>\n                选择 <span class=\"highlight\">以管理员身份运行</span>\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"adminModalClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 重置机器码权限提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"resetPermissionModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">🔐</div>\n            <div class=\"modal-title\">需要管理员权限</div>\n            <div class=\"modal-message\" style=\"text-align: left; line-height: 1.8;\">\n                重置机器码需要管理员权限才能完整执行。<br><br>\n                请按以下步骤操作：<br>\n                <span style=\"color: #fbbf24;\">1.</span> 完全关闭 Cursor<br>\n                <span style=\"color: #fbbf24;\">2.</span> 右键点击 Cursor 图标<br>\n                <span style=\"color: #fbbf24;\">3.</span> 选择 <span class=\"highlight\">以管理员身份运行</span><br>\n                <span style=\"color: #fbbf24;\">4.</span> 再次点击重置机器码\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"resetPermissionClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 重启提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"restartModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon success\">✓</div>\n            <div class=\"modal-title\" id=\"restartModalTitle\">操作成功</div>\n            <div class=\"modal-message\">\n                需要重启 Cursor 才能生效\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"restartNowBtn\">立即重启</button>\n                <button class=\"modal-btn secondary\" id=\"restartLaterBtn\">稍后</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 激活码过期弹窗 -->\n    <div class=\"modal-overlay\" id=\"expiredModal\">\n        <div class=\"modal-content\">\n            <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>\n            <div class=\"modal-title\">激活码已过期</div>\n            <div class=\"modal-message\">\n                您的激活码已过期，请续费后继续使用\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"expiredModalClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 清理环境确认弹窗 -->\n    <div class=\"modal-overlay\" id=\"cleanEnvModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">⚠️</div>\n            <div class=\"modal-title\">清理 Cursor 环境</div>\n            <div class=\"modal-message\">\n                此操作会删除所有配置和登录信息<br>确定要继续吗？\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"cleanEnvConfirmBtn\">确定清理</button>\n                <button class=\"modal-btn secondary\" id=\"cleanEnvCancelBtn\">取消</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 换号确认弹窗 -->\n    <div class=\"modal-overlay\" id=\"switchConfirmModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">💰</div>\n            <div class=\"modal-title\">账号未使用完</div>\n            <div class=\"modal-message\">\n                当前账号 <span id=\"switchConfirmEmail\" style=\"color:#4caf50;\"></span><br>\n                已用额度: <span id=\"switchConfirmCost\" style=\"color:#ff9800;font-weight:bold;\">$0.00</span> (不足 $10)<br><br>\n                确定要换号吗？\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"switchConfirmBtn\">确认换号</button>\n                <button class=\"modal-btn secondary\" id=\"switchCancelBtn\">取消</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 离线状态提示 -->\n    <div class=\"offline-banner\" id=\"offlineBanner\">\n        <span class=\"offline-icon\">📡</span>\n        <div class=\"offline-text\">\n            <div class=\"offline-title\">网络连接失败</div>\n            <div class=\"offline-desc\">请检查网络后重试</div>\n        </div>\n        <button class=\"retry-btn\" id=\"retryConnectBtn\">重试</button>\n    </div>\n    \n    <!-- 软件授权 -->\n    <div class=\"section\">\n        <div class=\"section-title\">\n            <span class=\"icon\">🔐</span>\n            <span>软件授权</span>\n            <span class=\"status-badge\" id=\"authStatus\">未授权</span>\n        </div>\n        \n        <div class=\"input-group\">\n            <input type=\"text\" id=\"keyInput\" placeholder=\"请输入CDK激活码\">\n            <button class=\"btn btn-primary\" id=\"activateBtn\"><span class=\"btn-text\">激活</span></button>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">激活码</span>\n            <span class=\"info-value key-display\" id=\"keyDisplay\" title=\"点击复制\">尚未激活</span>\n        </div>\n        <div class=\"info-row\">\n            <span class=\"info-label\">到期时间</span>\n            <span class=\"info-value\" id=\"expireDate\">尚未激活</span>\n        </div>\n    </div>\n    \n    <!-- 账号数据 (已隐藏) -->\n    <div class=\"section\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\">👤</span>\n            <span>账号数据</span>\n            <span class=\"status-badge\" id=\"accountStatus\">未激活</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">CI积分余额</span>\n            <span class=\"info-value\">0 <button style=\"background:none;border:none;color:#007acc;cursor:pointer;\">🔄</button></span>\n        </div>\n        \n        <button class=\"btn btn-purple btn-block\" id=\"switchBtn\" disabled>换号</button>\n        <button class=\"btn btn-blue btn-block\" id=\"resetBtn\">重置机器码</button>\n        <button class=\"btn btn-blue btn-block\" id=\"disableUpdateBtn\">禁用自动更新</button>\n        <button class=\"btn btn-blue btn-block\" id=\"cleanEnvBtn\">清理Cursor环境</button>\n        <button class=\"btn btn-red btn-block\" id=\"disableBtn\">停用插件</button>\n    </div>\n    \n    <!-- 无感换号 -->\n    <div class=\"section\">\n        <div class=\"section-title\">\n            <span class=\"icon\">⚡</span>\n            <span>无感换号</span>\n            <span class=\"status-badge\" id=\"seamlessStatus\">未启用</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">积分</span>\n            <span class=\"info-value\" id=\"seamlessSwitchRemaining\">0</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">当前账号</span>\n            <span class=\"info-value\" style=\"font-size:11px;\" id=\"seamlessCurrentAccount\">未分配</span>\n        </div>\n        \n        <div class=\"switch-container\" style=\"margin: 12px 0;\">\n            <span>免魔法模式</span>\n            <span class=\"pro-badge\">PRO</span>\n            <span style=\"margin-left: auto; color: #888; font-size: 11px;\"></span>\n            <label class=\"switch\">\n                <input type=\"checkbox\" id=\"seamlessProxySwitch\">\n                <span class=\"slider\"></span>\n            </label>\n        </div>\n        \n        <button class=\"btn btn-purple btn-block\" id=\"enableSeamlessBtn\" disabled><span class=\"btn-text\">启用无感换号</span></button>\n        <button class=\"btn btn-red btn-block\" id=\"seamlessResetMachineBtn\" style=\"display:none;\"><span class=\"btn-text\">重置机器码</span></button>\n        <button class=\"btn btn-red btn-block\" id=\"disableSeamlessBtn\" style=\"display:none;\"><span class=\"btn-text\">禁用无感换号</span></button>\n        <button class=\"btn btn-blue btn-block\" id=\"manualSwitchBtn\" style=\"display:none;\" disabled><span class=\"btn-text\">一键换号(扣1积分)</span></button>\n    </div>\n    \n    <!-- 账号用量 -->\n    <div class=\"section\" id=\"usageSection\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\">📊</span>\n            <span>账号用量</span>\n            <button class=\"btn\" style=\"margin-left:auto;padding:4px 8px;font-size:11px;background:#3c3c3c;\" id=\"refreshUsageBtn\">🔄</button>\n        </div>\n        \n        <div class=\"usage-row\">\n            <div class=\"usage-item\">\n                <span class=\"info-label\">会员类型</span>\n                <span class=\"info-value\" id=\"usageMemberType\">-</span>\n            </div>\n            <div class=\"usage-item\">\n                <span class=\"info-label\">试用剩余</span>\n                <span class=\"info-value\" id=\"usageTrialDays\">-</span>\n            </div>\n        </div>\n        <div class=\"usage-row\">\n            <div class=\"usage-item\">\n                <span class=\"info-label\">请求次数</span>\n                <span class=\"info-value\" id=\"usageRequestCount\">-</span>\n            </div>\n            <div class=\"usage-item\">\n                <span class=\"info-label\">已用额度</span>\n                <span class=\"info-value\" id=\"usageCostUSD\">-</span>\n            </div>\n        </div>\n        <p style=\"font-size:10px;color:#666;margin-top:8px;text-align:center;\" id=\"usageUpdateTime\">-</p>\n    </div>\n    \n    <!-- 公告 -->\n    <div class=\"section\" id=\"announcementSection\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\" id=\"announcementIcon\">📢</span>\n            <span>公告</span>\n            <span class=\"announcement-badge\" id=\"announcementBadge\">info</span>\n        </div>\n        <div class=\"announcement-title\" id=\"announcementTitle\"></div>\n        <div class=\"announcement-content\" id=\"announcementContent\"></div>\n        <p style=\"font-size:10px;color:#666;margin-top:8px;text-align:right;\" id=\"announcementTime\"></p>\n    </div>\n    \n    <!-- 版本信息 -->\n    <div class=\"section\" id=\"versionSection\">\n        <div class=\"section-title\">\n            <span class=\"icon\">📦</span>\n            <span>版本信息</span>\n            <span class=\"status-badge\" id=\"versionStatus\" style=\"display:none;\">有更新</span>\n        </div>\n        <div class=\"info-row\">\n            <span class=\"info-label\">当前版本</span>\n            <span class=\"info-value\" id=\"currentVersion\">-</span>\n        </div>\n        <div class=\"info-row\" id=\"latestVersionRow\" style=\"display:none;\">\n            <span class=\"info-label\">最新版本</span>\n            <span class=\"info-value\" id=\"latestVersion\" style=\"color:#4caf50;\">-</span>\n        </div>\n        <p id=\"updateHint\" style=\"font-size:11px;color:#ff9800;margin-top:8px;display:none;\">\n            ⚠️ 发现新版本，请更新插件以获取最新功能\n        </p>\n    </div>\n    \n    <!-- 页脚 -->\n    <div class=\"footer\">\n        <div class=\"footer-row\">\n            <div class=\"auto-start\">\n                <span>自动启动</span>\n                <label class=\"switch switch-sm\">\n                    <input type=\"checkbox\" id=\"autoStartSwitch\" checked>\n                    <span class=\"slider\"></span>\n                </label>\n            </div>\n            <div class=\"cursor-version\">\n                <span>Cursor</span>\n                <span class=\"version-num\" id=\"cursorVersion\">0.0.0</span>\n            </div>\n        </div>\n        <div class=\"footer-row\" style=\"margin-top: 8px;\">\n            <div style=\"font-size: 10px; color: #666; word-break: break-all;\">\n                <span>路径: </span>\n                <span id=\"cursorPath\" style=\"color: #888;\">获取中...</span>\n            </div>\n        </div>\n    </div>\n    \n    <!-- Toast 通知 -->\n    <div class=\"toast-container\" id=\"toastContainer\">\n        <div class=\"toast\" id=\"toast\">\n            <span class=\"toast-icon\" id=\"toastIcon\">✅</span>\n            <span class=\"toast-message\" id=\"toastMessage\"></span>\n        </div>\n    </div>\n    \n    <script nonce=\"" + var556 + "\">\n        const vscode = acquireVsCodeApi();\n        \n        // 元素引用\n        const keyInput = document.getElementById('keyInput');\n        const activateBtn = document.getElementById('activateBtn');\n        const switchBtn = document.getElementById('switchBtn');\n        const resetBtn = document.getElementById('resetBtn');\n        const disableUpdateBtn = document.getElementById('disableUpdateBtn');\n        const cleanEnvBtn = document.getElementById('cleanEnvBtn');\n        const disableBtn = document.getElementById('disableBtn');\n        const authStatus = document.getElementById('authStatus');\n        const accountStatus = document.getElementById('accountStatus');\n        const keyDisplay = document.getElementById('keyDisplay');\n        const switchCount = document.getElementById('switchCount');\n        const expireDate = document.getElementById('expireDate');\n        const cursorVersion = document.getElementById('cursorVersion');\n        const cursorPath = document.getElementById('cursorPath');\n        \n        // 离线状态元素\n        const offlineBanner = document.getElementById('offlineBanner');\n        const retryConnectBtn = document.getElementById('retryConnectBtn');\n        \n        // 无感换号元素\n        const seamlessStatus = document.getElementById('seamlessStatus');\n        const seamlessProxySwitch = document.getElementById('seamlessProxySwitch');\n        const enableSeamlessBtn = document.getElementById('enableSeamlessBtn');\n        const disableSeamlessBtn = document.getElementById('disableSeamlessBtn');\n        const manualSwitchBtn = document.getElementById('manualSwitchBtn');\n        const seamlessResetMachineBtn = document.getElementById('seamlessResetMachineBtn');\n        const seamlessSwitchRemaining = document.getElementById('seamlessSwitchRemaining');\n        const seamlessCurrentAccount = document.getElementById('seamlessCurrentAccount');\n        \n        // 用量显示元素\n        const usageSection = document.getElementById('usageSection');\n        const refreshUsageBtn = document.getElementById('refreshUsageBtn');\n        const usageMemberType = document.getElementById('usageMemberType');\n        const usageTrialDays = document.getElementById('usageTrialDays');\n        const usageRequestCount = document.getElementById('usageRequestCount');\n        const usageCostUSD = document.getElementById('usageCostUSD');\n        const usageUpdateTime = document.getElementById('usageUpdateTime');\n        \n        // 公告元素\n        const announcementSection = document.getElementById('announcementSection');\n        const announcementIcon = document.getElementById('announcementIcon');\n        const announcementBadge = document.getElementById('announcementBadge');\n        const announcementTitle = document.getElementById('announcementTitle');\n        const announcementContent = document.getElementById('announcementContent');\n        const announcementTime = document.getElementById('announcementTime');\n        \n        // 版本元素\n        const versionSection = document.getElementById('versionSection');\n        const versionStatus = document.getElementById('versionStatus');\n        const currentVersionEl = document.getElementById('currentVersion');\n        const latestVersionEl = document.getElementById('latestVersion');\n        const latestVersionRow = document.getElementById('latestVersionRow');\n        const updateHint = document.getElementById('updateHint');\n        \n        // 顶部更新提醒条\n        const updateBanner = document.getElementById('updateBanner');\n        const updateBannerVersion = document.getElementById('updateBannerVersion');\n        const updateBannerClose = document.getElementById('updateBannerClose');\n        \n        // Toast 元素\n        const toast = document.getElementById('toast');\n        const toastIcon = document.getElementById('toastIcon');\n        const toastMessage = document.getElementById('toastMessage');\n        let toastTimer = null;\n        \n        // 显示 Toast 通知\n        function showToast(message, icon = '✅', duration = 10000) {\n            // 清除之前的定时器\n            if (toastTimer) {\n                clearTimeout(toastTimer);\n            }\n            \n            toastIcon.textContent = icon;\n            toastMessage.textContent = message;\n            toast.classList.add('show');\n            \n            // 设置自动隐藏\n            toastTimer = setTimeout(() => {\n                toast.classList.remove('show');\n            }, duration);\n        }\n        \n        // 禁用换号按钮并显示倒计时\n        let switchBtnCountdownTimer = null;\n        const originalSwitchBtnText = '一键换号(扣1积分)';\n        \n        function disableSwitchBtnWithCountdown(seconds) {\n            // 清除之前的定时器\n            if (switchBtnCountdownTimer) {\n                clearInterval(switchBtnCountdownTimer);\n            }\n            \n            let remaining = seconds;\n            manualSwitchBtn.disabled = true;\n            manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';\n            \n            switchBtnCountdownTimer = setInterval(() => {\n                remaining--;\n                if (remaining <= 0) {\n                    clearInterval(switchBtnCountdownTimer);\n                    switchBtnCountdownTimer = null;\n                    manualSwitchBtn.disabled = false;\n                    manualSwitchBtn.querySelector('.btn-text').textContent = originalSwitchBtnText;\n                } else {\n                    manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';\n                }\n            }, 1000);\n        }\n        \n        // 弹窗元素\n        const adminModal = document.getElementById('adminModal');\n        const adminModalClose = document.getElementById('adminModalClose');\n        const resetPermissionModal = document.getElementById('resetPermissionModal');\n        const resetPermissionClose = document.getElementById('resetPermissionClose');\n        const restartModal = document.getElementById('restartModal');\n        const restartModalTitle = document.getElementById('restartModalTitle');\n        const restartNowBtn = document.getElementById('restartNowBtn');\n        const restartLaterBtn = document.getElementById('restartLaterBtn');\n        const expiredModal = document.getElementById('expiredModal');\n        const expiredModalClose = document.getElementById('expiredModalClose');\n        const cleanEnvModal = document.getElementById('cleanEnvModal');\n        const cleanEnvConfirmBtn = document.getElementById('cleanEnvConfirmBtn');\n        const cleanEnvCancelBtn = document.getElementById('cleanEnvCancelBtn');\n        \n        // 换号确认弹窗元素\n        const switchConfirmModal = document.getElementById('switchConfirmModal');\n        const switchConfirmEmail = document.getElementById('switchConfirmEmail');\n        const switchConfirmCost = document.getElementById('switchConfirmCost');\n        const switchConfirmBtn = document.getElementById('switchConfirmBtn');\n        const switchCancelBtn = document.getElementById('switchCancelBtn');\n        \n        // 显示管理员权限弹窗\n        function showAdminModal() {\n            adminModal.classList.add('show');\n        }\n        \n        // 显示重置机器码权限提示弹窗\n        function showAdminPermissionModal() {\n            resetPermissionModal.classList.add('show');\n        }\n        \n        // 重置机器码权限弹窗 - 关闭按钮\n        resetPermissionClose.addEventListener('click', () => {\n            resetPermissionModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭权限提示弹窗\n        resetPermissionModal.addEventListener('click', (e) => {\n            if (e.target === resetPermissionModal) {\n                resetPermissionModal.classList.remove('show');\n            }\n        });\n        \n        // 显示重启提示弹窗\n        let restartModalAction = 'reload'; // 'reload' 或 'close'\n        \n        function showRestartModal(title, action = 'reload') {\n            restartModalTitle.textContent = title || '操作成功';\n            restartModalAction = action;\n            // 根据操作类型更新按钮文字\n            restartNowBtn.textContent = action === 'close' ? '立即关闭 Cursor' : '立即重启';\n            restartModal.classList.add('show');\n        }\n        \n        // 显示过期弹窗\n        function showExpiredModal() {\n            expiredModal.classList.add('show');\n        }\n        \n        // 关闭管理员弹窗\n        adminModalClose.addEventListener('click', () => {\n            adminModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭管理员弹窗\n        adminModal.addEventListener('click', (e) => {\n            if (e.target === adminModal) {\n                adminModal.classList.remove('show');\n            }\n        });\n        \n        // 立即重启/关闭按钮\n        restartNowBtn.addEventListener('click', () => {\n            restartModal.classList.remove('show');\n            if (restartModalAction === 'close') {\n                // 完全关闭 Cursor\n                vscode.postMessage({ type: 'closeCursor' });\n            } else {\n                // 重新加载窗口\n            vscode.postMessage({ type: 'reloadWindow' });\n            }\n        });\n        \n        // 稍后手动按钮\n        restartLaterBtn.addEventListener('click', () => {\n            restartModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭重启弹窗\n        restartModal.addEventListener('click', (e) => {\n            if (e.target === restartModal) {\n                restartModal.classList.remove('show');\n            }\n        });\n        \n        // 关闭过期弹窗\n        expiredModalClose.addEventListener('click', () => {\n            expiredModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭过期弹窗\n        expiredModal.addEventListener('click', (e) => {\n            if (e.target === expiredModal) {\n                expiredModal.classList.remove('show');\n            }\n        });\n        \n        // 当前账号邮箱（用于查询用量）\n        let currentAccountEmail = '';\n        let usageRefreshInterval = null;\n        // 存储完整激活码（用于复制）\n        let fullActivationKey = '';\n        // 当前剩余换号次数\n        let currentSwitchRemaining = 0;\n        // 当前到期时间\n        let currentExpireDate = '';\n        \n        // 检查卡密是否已过期\n        function isKeyExpired() {\n            if (!currentExpireDate) return true;\n            try {\n                const expireTime = new Date(currentExpireDate).getTime();\n                return Date.now() > expireTime;\n            } catch {\n                return true;\n            }\n        }\n        \n        // 格式化到期时间为北京时间\n        function formatExpireDate(dateStr) {\n            if (!dateStr) return '';\n            try {\n                // 后端返回的时间没有时区标识，假设是 UTC 时间\n                // 将空格替换为T，并添加Z表示UTC\n                let utcStr = dateStr;\n                if (!dateStr.includes('T') && !dateStr.includes('Z') && !dateStr.includes('+')) {\n                    utcStr = dateStr.replace(' ', 'T') + 'Z';\n                }\n                const date = new Date(utcStr);\n                \n                // 使用中国时区格式化（UTC+8）\n                return date.toLocaleString('zh-CN', {\n                    timeZone: 'Asia/Shanghai',\n                    year: 'numeric',\n                    month: '2-digit',\n                    day: '2-digit',\n                    hour: '2-digit',\n                    minute: '2-digit',\n                    second: '2-digit',\n                    hour12: false\n                });\n            } catch {\n                return dateStr;  // 格式化失败返回原始值\n            }\n        }\n        \n        // 隐藏激活码后几位\n        function maskKey(key) {\n            if (!key || key.length <= 8) return key;\n            return key.substring(0, key.length - 4) + '****';\n        }\n        \n        // 点击激活码复制\n        keyDisplay.addEventListener('click', () => {\n            if (!fullActivationKey) return;\n            navigator.clipboard.writeText(fullActivationKey).then(() => {\n                keyDisplay.classList.add('copied');\n                const originalText = keyDisplay.textContent;\n                keyDisplay.textContent = '已复制!';\n                setTimeout(() => {\n                    keyDisplay.textContent = maskKey(fullActivationKey);\n                    keyDisplay.classList.remove('copied');\n                }, 1000);\n            }).catch(() => {\n                // 降级方案\n                const textarea = document.createElement('textarea');\n                textarea.value = fullActivationKey;\n                document.body.appendChild(textarea);\n                textarea.select();\n                document.execCommand('copy');\n                document.body.removeChild(textarea);\n                keyDisplay.classList.add('copied');\n                keyDisplay.textContent = '已复制!';\n                setTimeout(() => {\n                    keyDisplay.textContent = maskKey(fullActivationKey);\n                    keyDisplay.classList.remove('copied');\n                }, 1000);\n            });\n        });\n        \n        // Loading 状态控制\n        function setButtonLoading(btn, loading) {\n            if (loading) {\n                btn.classList.add('loading');\n                btn.disabled = true;\n            } else {\n                btn.classList.remove('loading');\n                // 注意：某些按钮可能需要保持禁用状态，由调用方控制\n            }\n        }\n        \n        function setRefreshLoading(btn, loading) {\n            if (loading) {\n                btn.classList.add('loading');\n            } else {\n                btn.classList.remove('loading');\n            }\n        }\n        \n        // 获取初始状态\n        vscode.postMessage({ type: 'getState' });\n        vscode.postMessage({ type: 'getSeamlessStatus' });\n        vscode.postMessage({ type: 'getUserSwitchStatus' });\n        vscode.postMessage({ type: 'getProxyStatus' });\n        vscode.postMessage({ type: 'getAnnouncement' });\n        vscode.postMessage({ type: 'checkVersion' });\n        vscode.postMessage({ type: 'getCursorRunningPath' });\n        \n        // 激活按钮\n        activateBtn.addEventListener('click', () => {\n            const key = keyInput.value.trim();\n            if (!key) {\n                return;\n            }\n            setButtonLoading(activateBtn, true);\n            vscode.postMessage({ type: 'activate', key });\n        });\n        \n        // 换号按钮\n        switchBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'switch' });\n        });\n        \n        // 重置机器码按钮\n        resetBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'resetMachineId' });\n        });\n        \n        // 禁用自动更新按钮\n        disableUpdateBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'disableUpdate' });\n        });\n        \n        // 清理Cursor环境按钮 - 显示确认弹窗\n        cleanEnvBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.add('show');\n        });\n        \n        // 确认清理\n        cleanEnvConfirmBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.remove('show');\n            vscode.postMessage({ type: 'cleanEnv' });\n        });\n        \n        // 取消清理\n        cleanEnvCancelBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭清理弹窗\n        cleanEnvModal.addEventListener('click', (e) => {\n            if (e.target === cleanEnvModal) {\n                cleanEnvModal.classList.remove('show');\n            }\n        });\n        \n        // 停用按钮\n        disableBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'disable' });\n        });\n        \n        // 关闭更新提醒条\n        updateBannerClose.addEventListener('click', () => {\n            updateBanner.classList.remove('show');\n        });\n        \n        // 免魔法开关\n        seamlessProxySwitch.addEventListener('change', (e) => {\n            const wantEnabled = e.target.checked;\n            \n            // 如果要开启免魔法，检查卡密是否过期（只要没过期就可以用，不管换号次数）\n            if (wantEnabled && isKeyExpired()) {\n                e.target.checked = false;\n                showToast('授权码已过期，无法开启免魔法', '⚠️', 3000);\n                return;\n            }\n            \n            vscode.postMessage({ \n                type: 'toggleProxy', \n                enabled: wantEnabled,\n                url: ''\n            });\n        });\n        \n        // 无感换号 - 启用按钮\n        enableSeamlessBtn.addEventListener('click', () => {\n            setButtonLoading(enableSeamlessBtn, true);\n            vscode.postMessage({ type: 'injectSeamless' });\n        });\n        \n        // 无感换号 - 禁用按钮\n        disableSeamlessBtn.addEventListener('click', () => {\n            setButtonLoading(disableSeamlessBtn, true);\n            vscode.postMessage({ type: 'restoreSeamless' });\n        });\n        \n        // 无感换号 - 手动换号按钮（先检查用量）\n        manualSwitchBtn.addEventListener('click', () => {\n            setButtonLoading(manualSwitchBtn, true);\n            // 传递当前显示的账号邮箱\n            vscode.postMessage({ type: 'checkUsageBeforeSwitch', email: currentAccountEmail });\n        });\n        \n        // 换号确认弹窗 - 确认按钮\n        switchConfirmBtn.addEventListener('click', () => {\n            switchConfirmModal.classList.remove('show');\n            setButtonLoading(manualSwitchBtn, true);\n            vscode.postMessage({ type: 'confirmSwitch' });\n        });\n        \n        // 换号确认弹窗 - 取消按钮\n        switchCancelBtn.addEventListener('click', () => {\n            switchConfirmModal.classList.remove('show');\n            setButtonLoading(manualSwitchBtn, false);\n            manualSwitchBtn.disabled = false;\n        });\n        \n        // 换号确认弹窗 - 点击遮罩关闭\n        switchConfirmModal.addEventListener('click', (e) => {\n            if (e.target === switchConfirmModal) {\n                switchConfirmModal.classList.remove('show');\n                setButtonLoading(manualSwitchBtn, false);\n                manualSwitchBtn.disabled = false;\n            }\n        });\n        \n        // 无感换号区域 - 重置机器码按钮\n        seamlessResetMachineBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'resetMachineId' });\n        });\n        \n        // 刷新用量按钮\n        refreshUsageBtn.addEventListener('click', () => {\n            if (currentAccountEmail) {\n                setRefreshLoading(refreshUsageBtn, true);\n                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });\n            }\n        });\n        \n        // 刷新用量函数\n        function refreshUsage() {\n            if (currentAccountEmail) {\n                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });\n            }\n        }\n        \n        // 启动用量定时刷新 (每分钟一次)\n        function startUsageRefresh() {\n            if (usageRefreshInterval) {\n                clearInterval(usageRefreshInterval);\n            }\n            // 立即刷新一次\n            refreshUsage();\n            // 每60秒刷新一次\n            usageRefreshInterval = setInterval(refreshUsage, 60000);\n        }\n        \n        // 停止用量刷新\n        function stopUsageRefresh() {\n            if (usageRefreshInterval) {\n                clearInterval(usageRefreshInterval);\n                usageRefreshInterval = null;\n            }\n        }\n        \n        // 更新用量显示\n        function updateUsageDisplay(data) {\n            if (!data) return;\n            \n            const subscription = data.subscription || {};\n            const usage = data.usage || {};\n            \n            // 会员类型\n            const memberTypeMap = {\n                'free_trial': '免费试用',\n                'pro': 'Pro会员',\n                'free': '免费版',\n                'business': '商业版'\n            };\n            usageMemberType.textContent = memberTypeMap[subscription.membershipType] || subscription.membershipType || '-';\n            \n            // 试用剩余天数\n            if (subscription.daysRemainingOnTrial !== undefined && subscription.daysRemainingOnTrial !== null) {\n                usageTrialDays.textContent = subscription.daysRemainingOnTrial + ' 天';\n                usageTrialDays.style.color = subscription.daysRemainingOnTrial <= 3 ? '#f87171' : '#4ade80';\n            } else {\n                usageTrialDays.textContent = '-';\n                usageTrialDays.style.color = '#fff';\n            }\n            \n            // 请求次数\n            usageRequestCount.textContent = (usage.totalUsageCount || 0) + ' 次';\n            \n            // 已用额度\n            const costUSD = usage.totalCostUSD || 0;\n            usageCostUSD.textContent = '$' + costUSD.toFixed(2);\n            usageCostUSD.style.color = costUSD > 5 ? '#f87171' : (costUSD > 2 ? '#fbbf24' : '#4ade80');\n            \n            // 更新时间\n            usageUpdateTime.textContent = '更新于 ' + new Date().toLocaleTimeString();\n        }\n        \n        // 解析公告内容中的链接 {文字URL}\n        function parseAnnouncementContent(content) {\n            if (!content) return '';\n            \n            // 转义 HTML 特殊字符\n            let escaped = content\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;')\n                .replace(/\"/g, '&quot;');\n            \n            // 匹配 {文字https://...} 或 {文字http://...} 格式\n            const linkRegex = /\\{([^}]+?)(https?:\\/\\/[^}]+)\\}/g;\n            \n            escaped = escaped.replace(linkRegex, function(match, text, url) {\n                return '<a href=\"' + url + '\" class=\"announcement-link\" target=\"_blank\">' + text + '</a>';\n            });\n            \n            // 将换行符转换为 <br>\n            escaped = escaped.replace(/\\n/g, '<br>');\n            \n            return escaped;\n        }\n        \n        // 更新公告显示\n        function updateAnnouncementDisplay(data) {\n            if (!data || !data.is_active) {\n                announcementSection.style.display = 'none';\n                return;\n            }\n            \n            // 显示公告区域\n            announcementSection.style.display = 'block';\n            \n            // 设置图标和类型徽章\n            const typeConfig = {\n                'info': { icon: '📢', text: '通知', class: 'info' },\n                'warning': { icon: '⚠️', text: '警告', class: 'warning' },\n                'error': { icon: '🚨', text: '重要', class: 'error' },\n                'success': { icon: '✅', text: '好消息', class: 'success' }\n            };\n            \n            const config = typeConfig[data.type] || typeConfig.info;\n            announcementIcon.textContent = config.icon;\n            announcementBadge.textContent = config.text;\n            announcementBadge.className = 'announcement-badge ' + config.class;\n            \n            // 设置标题和内容（解析链接）\n            announcementTitle.textContent = data.title || '';\n            announcementContent.innerHTML = parseAnnouncementContent(data.content || '');\n            \n            // 设置时间\n            if (data.created_at) {\n                const date = new Date(data.created_at);\n                announcementTime.textContent = date.toLocaleDateString('zh-CN', {\n                    year: 'numeric',\n                    month: '2-digit',\n                    day: '2-digit',\n                    hour: '2-digit',\n                    minute: '2-digit'\n                });\n            } else {\n                announcementTime.textContent = '';\n            }\n        }\n        \n        // 处理来自扩展的消息\n        window.addEventListener('message', event => {\n            const message = event.data;\n            \n            switch (message.type) {\n                case 'state':\n                    updateUI(message);\n                    break;\n                case 'activated':\n                    setButtonLoading(activateBtn, false);\n                    activateBtn.disabled = false;\n                    if (message.success) {\n                        // 调试日志\n                        console.log('[CursorPro] 前端收到激活成功消息:', message);\n                        \n                        authStatus.textContent = '已授权';\n                        authStatus.className = 'status-badge active';\n                        accountStatus.textContent = '已激活';\n                        accountStatus.className = 'status-badge active';\n                        switchBtn.disabled = false;\n                        // 更新激活码显示（使用后端返回的 key）\n                        fullActivationKey = message.key || keyInput.value;\n                        keyDisplay.textContent = maskKey(fullActivationKey);\n                        // 更新到期时间\n                        console.log('[CursorPro] 更新到期时间:', message.expireDate);\n                        currentExpireDate = message.expireDate || '';\n                        expireDate.textContent = formatExpireDate(currentExpireDate) || '未知';\n                        // 更新换号次数\n                        if (message.switchRemaining !== undefined) {\n                            currentSwitchRemaining = message.switchRemaining;\n                            switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                        }\n                        // 清空输入框\n                        keyInput.value = '';\n                        showToast('授权码激活成功！', '✅', 10000);\n                    } else {\n                        showToast(message.error || '激活失败', '❌', 10000);\n                    }\n                    break;\n                case 'switched':\n                    if (message.success) {\n                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                        showToast('换号成功: ' + (message.email || ''), '✅', 10000);\n                    } else {\n                        showToast(message.error || '换号失败', '❌', 10000);\n                    }\n                    break;\n                case 'reset':\n                    authStatus.textContent = '未授权';\n                    authStatus.className = 'status-badge inactive';\n                    accountStatus.textContent = '未激活';\n                    accountStatus.className = 'status-badge inactive';\n                    switchBtn.disabled = true;\n                    keyInput.value = '';\n                    fullActivationKey = '';\n                    keyDisplay.textContent = '尚未激活';\n                    expireDate.textContent = '尚未激活';\n                    break;\n                \n                // 激活码状态检查结果\n                case 'keyStatusChecked':\n                    if (message.valid) {\n                        // 激活码有效，更新显示\n                        currentExpireDate = message.expireDate || '';\n                        currentSwitchRemaining = message.switchRemaining || 0;\n                        expireDate.textContent = formatExpireDate(currentExpireDate);\n                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                    } else if (message.expired) {\n                        // 激活码已过期，显示提示并重置状态\n                        currentExpireDate = '';\n                        currentSwitchRemaining = 0;\n                        authStatus.textContent = '已过期';\n                        authStatus.className = 'status-badge inactive';\n                        authStatus.style.background = '#6e3232';\n                        authStatus.style.color = '#ff6b6b';\n                        expireDate.textContent = '已过期';\n                        expireDate.style.color = '#f87171';\n                        switchBtn.disabled = true;\n                        enableSeamlessBtn.disabled = true;\n                        // 如果免魔法已开启，自动关闭\n                        if (seamlessProxySwitch.checked) {\n                            seamlessProxySwitch.checked = false;\n                            vscode.postMessage({ type: 'toggleProxy', enabled: false, url: '' });\n                        }\n                        // 显示过期弹窗\n                        showExpiredModal();\n                    }\n                    break;\n                \n                // 用户换号状态\n                case 'userSwitchStatus':\n                    const remaining = message.switchRemaining || 0;\n                    const canSwitch = remaining > 0;\n                    \n                    // 更新全局变量\n                    currentSwitchRemaining = remaining;\n                    \n                    seamlessSwitchRemaining.textContent = remaining.toString();\n                    seamlessSwitchRemaining.style.color = canSwitch ? '#4ade80' : '#f87171';\n                    \n                    if (message.lockedAccount) {\n                        seamlessCurrentAccount.textContent = message.lockedAccount.email;\n                        \n                        // 设置当前账号邮箱并启动用量刷新\n                        if (message.lockedAccount.email && message.lockedAccount.email !== currentAccountEmail) {\n                            currentAccountEmail = message.lockedAccount.email;\n                            usageSection.style.display = 'block';\n                            startUsageRefresh();\n                        }\n                    } else {\n                        seamlessCurrentAccount.textContent = '未分配';\n                        \n                        // 没有锁定账号时隐藏用量区域\n                        currentAccountEmail = '';\n                        usageSection.style.display = 'none';\n                        stopUsageRefresh();\n                    }\n                    \n                    // 根据剩余次数控制手动换号按钮状态\n                    if (!canSwitch) {\n                        manualSwitchBtn.disabled = true;\n                    }\n                    // 启用无感换号按钮不受积分限制，只有过期才禁用\n                    enableSeamlessBtn.disabled = isKeyExpired();\n                    \n                    // 如果无感换号已启用，显示手动换号按钮和重置机器码按钮\n                    if (message.seamlessEnabled && canSwitch) {\n                        manualSwitchBtn.style.display = 'block';\n                        manualSwitchBtn.disabled = false;\n                        setButtonLoading(manualSwitchBtn, false);\n                        seamlessResetMachineBtn.style.display = 'block';\n                    }\n                    break;\n                \n                // 账号用量\n                case 'accountUsage':\n                    setRefreshLoading(refreshUsageBtn, false);\n                    if (message.success && message.data) {\n                        updateUsageDisplay(message.data);\n                    } else {\n                        usageUpdateTime.textContent = '获取失败: ' + (message.error || '未知错误');\n                        usageUpdateTime.style.color = '#f87171';\n                    }\n                    break;\n                \n                // 无感换号状态\n                case 'seamlessStatus':\n                    if (message.is_injected) {\n                        seamlessStatus.textContent = '已启用';\n                        seamlessStatus.className = 'status-badge active';\n                        enableSeamlessBtn.style.display = 'none';\n                        disableSeamlessBtn.style.display = 'block';\n                        disableSeamlessBtn.disabled = false;\n                        setButtonLoading(disableSeamlessBtn, false);\n                        manualSwitchBtn.style.display = 'block';\n                        manualSwitchBtn.disabled = false;\n                        setButtonLoading(manualSwitchBtn, false);\n                        seamlessResetMachineBtn.style.display = 'block';\n                    } else {\n                        seamlessStatus.textContent = '未启用';\n                        seamlessStatus.className = 'status-badge inactive';\n                        enableSeamlessBtn.style.display = 'block';\n                        setButtonLoading(enableSeamlessBtn, false);\n                        // 启用按钮不受积分限制，只有过期才禁用\n                        enableSeamlessBtn.disabled = isKeyExpired();\n                        disableSeamlessBtn.style.display = 'none';\n                        manualSwitchBtn.style.display = 'none';\n                        seamlessResetMachineBtn.style.display = 'none';\n                    }\n                    break;\n                \n                case 'seamlessInjected':\n                    setButtonLoading(enableSeamlessBtn, false);\n                    enableSeamlessBtn.disabled = false;\n                    if (message.success) {\n                        seamlessStatus.textContent = '已启用';\n                        seamlessStatus.className = 'status-badge active';\n                        enableSeamlessBtn.style.display = 'none';\n                        disableSeamlessBtn.style.display = 'block';\n                        manualSwitchBtn.style.display = 'block';\n                        seamlessResetMachineBtn.style.display = 'block';\n                        // 刷新用户状态\n                        vscode.postMessage({ type: 'getUserSwitchStatus' });\n                        // 显示重启提示弹窗\n                        if (message.needRestart) {\n                            showRestartModal(message.message || '无感换号已启用');\n                        }\n                    } else {\n                        // 如果是权限错误，显示自定义弹窗\n                        if (message.needAdmin) {\n                            // Mac/Linux 权限问题，显示详细提示\n                            var errorMsg = message.error || '没有写入权限';\n                            if (message.path) {\n                                errorMsg += '\\n路径: ' + message.path;\n                            }\n                            showToast(errorMsg, '🔐', 15000);\n                        } else {\n                            // 显示详细错误\n                            var detailMsg = message.error || '启用失败';\n                            if (message.details) {\n                                detailMsg += '\\n' + message.details;\n                            }\n                            showToast(detailMsg, '❌', 15000);\n                        }\n                    }\n                    break;\n                \n                case 'seamlessRestored':\n                    setButtonLoading(disableSeamlessBtn, false);\n                    disableSeamlessBtn.disabled = false;\n                    if (message.success) {\n                        seamlessStatus.textContent = '未启用';\n                        seamlessStatus.className = 'status-badge inactive';\n                        enableSeamlessBtn.style.display = 'block';\n                        disableSeamlessBtn.style.display = 'none';\n                        manualSwitchBtn.style.display = 'none';\n                        seamlessResetMachineBtn.style.display = 'none';\n                        // 显示重启提示弹窗\n                        if (message.needRestart) {\n                            showRestartModal(message.message || '无感换号已禁用');\n                        }\n                    } else {\n                        // 如果是权限错误，显示自定义弹窗\n                        if (message.needAdmin) {\n                            showAdminModal();\n                        } else {\n                            showToast(message.error || '禁用失败', '❌', 10000);\n                        }\n                    }\n                    break;\n                \n                // 用量检查结果\n                case 'usageCheckResult':\n                    if (message.success) {\n                        if (message.needConfirm) {\n                            // 需要确认，显示弹窗（按钮保持可用状态，等用户选择）\n                            setButtonLoading(manualSwitchBtn, false);\n                            manualSwitchBtn.disabled = false;\n                            switchConfirmEmail.textContent = message.email || '';\n                            switchConfirmCost.textContent = '$' + (message.costUSD || '0.00');\n                            switchConfirmModal.classList.add('show');\n                        } else {\n                            // 不需要确认，直接换号\n                            vscode.postMessage({ type: 'confirmSwitch' });\n                        }\n                    } else {\n                        setButtonLoading(manualSwitchBtn, false);\n                        manualSwitchBtn.disabled = false;\n                        showToast(message.error || '检查失败', '❌', 5000);\n                    }\n                    break;\n                \n                case 'manualSeamlessSwitched':\n                    setButtonLoading(manualSwitchBtn, false);\n                    if (message.success) {\n                        seamlessSwitchRemaining.textContent = (message.switchRemaining || 0).toString();\n                        seamlessCurrentAccount.textContent = message.email || '未知';\n                        // 显示 Toast 通知，10秒后消失\n                        showToast('已切换到: ' + (message.email || '新账号') + '，约10秒内自动生效', '✅', 10000);\n                        // 刷新状态\n                        vscode.postMessage({ type: 'getUserSwitchStatus' });\n                        // 禁用按钮10秒，显示倒计时\n                        disableSwitchBtnWithCountdown(10);\n                    } else {\n                        manualSwitchBtn.disabled = false;\n                        showToast(message.error || '换号失败', '❌', 5000);\n                    }\n                    break;\n                \n                case 'proxyStatus':\n                    // 设置免魔法开关状态\n                    seamlessProxySwitch.checked = message.enabled;\n                    break;\n                \n                // 公告\n                case 'announcement':\n                    if (message.success && message.data) {\n                        updateAnnouncementDisplay(message.data);\n                    } else {\n                        announcementSection.style.display = 'none';\n                    }\n                    break;\n                \n                // 版本检查\n                case 'versionCheck':\n                    currentVersionEl.textContent = message.currentVersion || '-';\n                    if (message.success && message.hasUpdate) {\n                        // 有更新\n                        latestVersionEl.textContent = message.latestVersion;\n                        latestVersionRow.style.display = 'flex';\n                        versionStatus.style.display = 'inline-block';\n                        versionStatus.style.background = '#ff9800';\n                        updateHint.style.display = 'block';\n                        \n                        // 显示顶部更新提醒条\n                        updateBannerVersion.textContent = 'v' + message.latestVersion;\n                        updateBanner.classList.add('show');\n                    } else if (message.success) {\n                        // 已是最新版\n                        versionStatus.textContent = '最新';\n                        versionStatus.style.display = 'inline-block';\n                        versionStatus.style.background = '#4caf50';\n                        latestVersionRow.style.display = 'none';\n                        updateHint.style.display = 'none';\n                        updateBanner.classList.remove('show');\n                    }\n                    break;\n                \n                // Cursor 运行路径\n                case 'cursorRunningPath':\n                    if (message.path) {\n                        const pathText = message.path + (message.packageExists ? ' ✓' : ' ✗');\n                        cursorPath.textContent = pathText;\n                        cursorPath.style.color = message.packageExists ? '#4ade80' : '#f87171';\n                        // 同时更新版本号\n                        if (message.cursorVersion) {\n                            cursorVersion.textContent = message.cursorVersion;\n                        }\n                    } else {\n                        cursorPath.textContent = '未找到';\n                        cursorPath.style.color = '#f87171';\n                    }\n                    break;\n                \n                // 管理员权限不足提示\n                case 'adminPermissionRequired':\n                    showAdminPermissionModal();\n                    break;\n                \n                // 机器码重置\n                case 'machineIdReset':\n                    if (message.success && message.needRestart) {\n                        // 机器码重置需要完全关闭 Cursor，不是 reload\n                        showRestartModal(message.message || '机器码重置成功', 'close');\n                    }\n                    break;\n                \n                // 通用 Toast 消息\n                case 'showToast':\n                    showToast(message.message || '', message.icon || '📢', 10000);\n                    break;\n                \n                // 网络状态\n                case 'networkStatus':\n                    updateOfflineStatus(!message.online);\n                    break;\n            }\n        });\n        \n        // 离线状态显示/隐藏\n        let wasOffline = false; // 跟踪之前是否离线\n        function updateOfflineStatus(isOffline) {\n            if (isOffline) {\n                offlineBanner.classList.add('show');\n                wasOffline = true;\n            } else {\n                offlineBanner.classList.remove('show');\n                // 只有从离线恢复到在线时才刷新状态\n                if (wasOffline) {\n                    wasOffline = false;\n                    vscode.postMessage({ type: 'getState' });\n                    vscode.postMessage({ type: 'getUserSwitchStatus' });\n                }\n            }\n        }\n        \n        // 重试连接按钮\n        retryConnectBtn.addEventListener('click', async () => {\n            retryConnectBtn.classList.add('loading');\n            retryConnectBtn.textContent = '连接中...';\n            \n            // 发起真正的网络请求来测试网络\n            vscode.postMessage({ type: 'retryConnect' });\n            \n            // 5秒后恢复按钮状态（给网络请求足够时间）\n            setTimeout(() => {\n                retryConnectBtn.classList.remove('loading');\n                retryConnectBtn.textContent = '重试';\n            }, 5000);\n        });\n        \n        function updateUI(state) {\n            if (state.isActivated) {\n                authStatus.textContent = '已授权';\n                authStatus.className = 'status-badge active';\n                accountStatus.textContent = '已激活';\n                accountStatus.className = 'status-badge active';\n                switchBtn.disabled = false;\n                fullActivationKey = state.key;\n                keyDisplay.textContent = maskKey(fullActivationKey);\n                // 更新到期时间\n                currentExpireDate = state.expireDate || '';\n                expireDate.textContent = formatExpireDate(currentExpireDate);\n                // 更新换号次数\n                if (state.switchRemaining !== undefined) {\n                    currentSwitchRemaining = state.switchRemaining;\n                    switchCount.textContent = state.switchRemaining + '/' + (state.switchLimit || 100);\n                }\n                // 启用无感换号按钮（只有过期才禁用）\n                enableSeamlessBtn.disabled = isKeyExpired();\n            }\n            cursorVersion.textContent = state.cursorVersion || '0.0.0';\n            \n            // 根据网络状态显示/隐藏离线提示\n            if (state.isOnline === false) {\n                offlineBanner.classList.add('show');\n                wasOffline = true;\n            } else if (state.isOnline === true) {\n                // 网络恢复，隐藏离线提示\n                offlineBanner.classList.remove('show');\n                wasOffline = false;\n            }\n        }\n    </script>\n</body>\n</html>";
      }
    }
  }
  async _handleGetAccountUsage(arg301) {
    const var559 = {
      'kwSDs': "[CursorPro] Toggle proxy error:",
      'cuNHx': "proxyUpdated",
      'AlVbI': '更新配置失败',
      'cBprM': "accountUsage",
      'pLAQo': "未提供账号邮箱",
      'XCtgT': function (arg302, arg303) {
        return arg302(arg303);
      },
      'LcuLD': "获取用量失败",
      'JvSqa': "NYkng",
      'rptjh': "请求失败"
    };
    try {
      if (!arg301) {
        this._postMessage({
          'type': var559.cBprM,
          'success': false,
          'error': var559.pLAQo
        });
        return;
      }
      0x0;
      const var560 = client_1.getApiUrl() + "/api/cursor-accounts/query?email=" + var559.XCtgT(encodeURIComponent, arg301) + '&refresh=true';
      const var561 = await var559.XCtgT(fetch, var560);
      const var562 = await var561.json();
      if (var562.success && var562.data) {
        this._postMessage({
          'type': var559.cBprM,
          'success': true,
          'data': var562.data
        });
        const var563 = var562.data.usage || {};
        const var564 = var563.totalUsageCount || 0x0;
        const var565 = var559.XCtgT(parseFloat, var563.totalCostUSD || 0x0);
        0x0;
        extension_1.updateUsageStatusBar(var564, var565);
      } else {
        this._postMessage({
          'type': var559.cBprM,
          'success': false,
          'error': var562.error || var559.LcuLD
        });
      }
    } catch (v566) {
      if (var559.JvSqa !== 'NYkng') {
        v567.error(var559.kwSDs, v568);
        this._postMessage({
          'type': var559.cuNHx,
          'success': false,
          'error': var559.AlVbI
        });
      } else {
        this._postMessage({
          'type': var559.cBprM,
          'success': false,
          'error': v566.message || var559.rptjh
        });
      }
    }
  }
  async _handleGetAnnouncement() {
    const var569 = {
      'eXcSu': "cursorpro.key",
      'wCuhU': "cursorpro.expireDate",
      'tQyYP': '请先激活授权码',
      'fEjcy': function (arg304, arg305) {
        return arg304 > arg305;
      },
      'GLUmw': "proxyUpdated",
      'Bjkrw': '授权码已过期，无法开启免魔法',
      'trGXG': 'showToast',
      'aCZjy': function (arg306, arg307) {
        return arg306(arg307);
      },
      'aHNrz': 'announcement',
      'PynOc': function (arg308, arg309) {
        return arg308 === arg309;
      },
      'LjnPR': 'ysOwe',
      'RdeWm': "获取公告失败",
      'XcVTX': "请求失败"
    };
    try {
      0x0;
      const var570 = client_1.getApiUrl() + "/api/announcements/latest";
      const var571 = await var569.aCZjy(fetch, var570);
      const var572 = await var571.json();
      if (var572.success && var572.data) {
        this._postMessage({
          'type': var569.aHNrz,
          'success': true,
          'data': var572.data
        });
      } else {
        if ('ysOwe' === var569.LjnPR) {
          this._postMessage({
            'type': "announcement",
            'success': false,
            'error': var572.error || var569.RdeWm
          });
        } else {
          const var573 = this._context.globalState.get(var569.eXcSu);
          const var574 = this._context.globalState.get(var569.wCuhU);
          if (!var573) {
            this._postMessage({
              'type': 'proxyUpdated',
              'success': false,
              'error': '请先激活授权码'
            });
            this._postMessage({
              'type': "showToast",
              'message': var569.tQyYP,
              'icon': '⚠️'
            });
            return;
          }
          if (var574) {
            const var575 = new v576(var574).getTime();
            if (var569.fEjcy(v577.now(), var575)) {
              this._postMessage({
                'type': var569.GLUmw,
                'success': false,
                'error': var569.Bjkrw
              });
              this._postMessage({
                'type': var569.trGXG,
                'message': "授权码已过期，无法开启免魔法",
                'icon': '⚠️'
              });
              return;
            }
          }
        }
      }
    } catch (v578) {
      this._postMessage({
        'type': var569.aHNrz,
        'success': false,
        'error': v578.message || var569.XcVTX
      });
    }
  }
  async _handleCheckVersion() {
    const var579 = {
      'HgWOc': "[CursorPro] 使用用户配置的 Cursor 路径:",
      'QXFeq': function (arg310, arg311) {
        return arg310 > arg311;
      },
      'lYCxA': "versionCheck",
      'QtoxZ': function (arg312, arg313) {
        return arg312 === arg313;
      },
      'xqknY': "vUHCr",
      'GbNrd': "请求失败"
    };
    try {
      0x0;
      const var580 = await client_1.getLatestVersion();
      if (var580.success && var580.version) {
        const var581 = var580.version;
        const var582 = CursorProViewProvider.CURRENT_VERSION;
        const var583 = var579.QXFeq(this._compareVersions(var581, var582), 0x0);
        this._postMessage({
          'type': var579.lYCxA,
          'success': true,
          'currentVersion': var582,
          'latestVersion': var581,
          'hasUpdate': var583
        });
      } else {
        this._postMessage({
          'type': var579.lYCxA,
          'success': false,
          'currentVersion': CursorProViewProvider.CURRENT_VERSION,
          'error': var580.error || "获取版本失败"
        });
      }
    } catch (v584) {
      if (var579.QtoxZ(var579.xqknY, "LOWQh")) {
        v585.log(var579.HgWOc, v586);
        this._cachedCursorPath = v587;
        return v588;
      } else {
        this._postMessage({
          'type': "versionCheck",
          'success': false,
          'currentVersion': CursorProViewProvider.CURRENT_VERSION,
          'error': v584.message || var579.GbNrd
        });
      }
    }
  }
  _compareVersions(arg314, arg315) {
    const var589 = {
      'PMKNW': function (arg316, arg317) {
        return arg316 < arg317;
      },
      'qyNxu': function (arg318, arg319) {
        return arg318 > arg319;
      },
      'HZvmu': function (arg320, arg321) {
        return arg320 < arg321;
      }
    };
    const var590 = arg314.split('.').map(Number);
    const var591 = arg315.split('.').map(Number);
    const var592 = Math.max(var590.length, var591.length);
    for (let var593 = 0x0; var593 < var592; var593++) {
      const var594 = var590[var593] || 0x0;
      const var595 = var591[var593] || 0x0;
      if (var589.qyNxu(var594, var595)) {
        return 0x1;
      }
      if (var594 < var595) {
        return -0x1;
      }
    }
    return 0x0;
  }
  async _handleGetCursorRunningPath() {
    const var596 = {
      'SsULC': "[CursorPro] 使用 VS Code API 获取版本:",
      'AwKfF': 'utf-8',
      'zAvXx': "UBmxB",
      'QhWXL': "未找到",
      'bZBTW': 'cursorpro',
      'vlHDb': 'cursorPath',
      'ONVXL': function (arg322, arg323) {
        return arg322 === arg323;
      },
      'JPYoo': "darwin",
      'nEYhA': 'Contents',
      'EbBLW': "Resources",
      'lMfdt': "app",
      'MFjtx': "package.json",
      'NjVqB': "[CursorPro] 使用用户配置的路径:",
      'Wxyfp': "win32",
      'JSWuW': "BbiYe",
      'ACRef': "wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul",
      'ydRHF': "resources",
      'ANYDK': function (arg324, arg325) {
        return arg324 === arg325;
      },
      'rEwYQ': "snkgX",
      'YxYZp': "BoVlO",
      'Qvzam': function (arg326, arg327) {
        return arg326 === arg327;
      },
      'FyfZA': function (arg328, arg329) {
        return arg328 !== arg329;
      },
      'eCMQp': 'DZGqD',
      'QKwAH': 'Programs',
      'eEobw': "cursor",
      'aouCU': "ZhNbs",
      'XXRrw': "WrYgR",
      'biXGl': "/Applications/Cursor.app",
      'ErbAO': "/usr/share/cursor",
      'vvvXG': ".local",
      'kVBXU': "share",
      'sxYuF': "mnjXn",
      'sYfMC': "WRpnS",
      'UFfHe': "[CursorPro] 从路径获取 Cursor 版本:",
      'HLsOj': 'cursorRunningPath',
      'stZTh': "获取失败: "
    };
    try {
      if ("UBmxB" !== var596.zAvXx) {
        return [{
          'email': v597,
          'access_token': v598,
          'refresh_token': v599 || v600
        }];
      } else {
        const var601 = process.platform;
        let var602 = var596.QhWXL;
        let var603 = '';
        const var604 = vscode.workspace.getConfiguration(var596.bZBTW);
        const var605 = var604.get(var596.vlHDb);
        if (var605 && fs.existsSync(var605)) {
          var602 = var605;
          if (var601 === var596.JPYoo) {
            var603 = path.join(var605, var596.nEYhA, var596.EbBLW, var596.lMfdt, var596.MFjtx);
          } else {
            var603 = path.join(var605, "resources", var596.lMfdt, var596.MFjtx);
          }
          console.log(var596.NjVqB, var605);
        } else {
          if (var601 === var596.Wxyfp) {
            try {
              if (var596.JSWuW === "eKgQY") {
                v606 = true;
                delete v607[v608];
              } else {
                const {
                  stdout: v609
                } = await execAsync(var596.ACRef);
                const var610 = v609.match(/ExecutablePath=(.+)/);
                if (var610 && var610[0x1]) {
                  const var611 = var610[0x1].trim();
                  var602 = path.dirname(var611);
                  var603 = path.join(var602, var596.ydRHF, var596.lMfdt, var596.MFjtx);
                }
              }
            } catch (v612) {
              if (var596.rEwYQ === var596.YxYZp) {
                v613.log(var596.SsULC, v614.version);
                return v615.version;
              } else {
                console.log("[CursorPro] WMIC 获取路径失败:", v612);
              }
            }
            if (var602 === var596.QhWXL) {
              if (var596.FyfZA("DZGqD", var596.eCMQp)) {
                try {
                  const var616 = this._getHostsPath();
                  if (v617.existsSync(var616)) {
                    return v618.readFileSync(var616, var596.AwKfF);
                  }
                } catch (v619) {
                  v620.error("[CursorPro] Read hosts error:", v619);
                }
                return '';
              } else {
                const var621 = process.env.LOCALAPPDATA || '';
                const var622 = [path.join(var621, var596.QKwAH, 'cursor'), path.join(var621, var596.eEobw)];
                for (const var623 of var622) {
                  const var624 = path.join(var623, var596.ydRHF, "app", var596.MFjtx);
                  if (fs.existsSync(var624)) {
                    var602 = var623;
                    var603 = var624;
                    break;
                  }
                }
              }
            }
          } else {
            if (var601 === "darwin") {
              if (var596.Qvzam(var596.aouCU, var596.XXRrw)) {
                return null;
              } else {
                var602 = (await this._getCursorInstallPath()) || var596.biXGl;
                var603 = path.join(var602, var596.nEYhA, var596.EbBLW, 'app', var596.MFjtx);
              }
            } else {
              const var625 = process.env.HOME || '';
              const var626 = [var596.ErbAO, path.join(var625, var596.vvvXG, var596.kVBXU, var596.eEobw)];
              for (const var627 of var626) {
                if (fs.existsSync(var627)) {
                  var602 = var627;
                  var603 = path.join(var627, var596.ydRHF, 'app', "package.json");
                  break;
                }
              }
            }
          }
        }
        const var628 = var603 && fs.existsSync(var603);
        let var629 = '';
        if (var628) {
          try {
            if (var596.sxYuF === var596.sYfMC) {
              if (v630.existsSync(v631)) {
                return v632;
              }
            } else {
              const var633 = fs.readFileSync(var603, var596.AwKfF);
              const var634 = JSON.parse(var633);
              var629 = var634.version || '';
              console.log(var596.UFfHe, var629);
            }
          } catch (v635) {
            console.log("[CursorPro] 读取 package.json 失败:", v635);
          }
        }
        this._postMessage({
          'type': 'cursorRunningPath',
          'path': var602,
          'packageJsonPath': var603,
          'packageExists': var628,
          'cursorVersion': var629
        });
      }
    } catch (v636) {
      this._postMessage({
        'type': var596.HLsOj,
        'path': "获取失败: " + (v636.message || v636),
        'packageJsonPath': '',
        'packageExists': false,
        'cursorVersion': ''
      });
    }
  }
  async _handleCheckUsageBeforeSwitch(arg330) {
    const var637 = {
      'sEVKj': "[CursorPro] PowerShell Get-Process 获取路径失败",
      'kcIfn': "[CursorPro] Direct write failed, trying to grant permission",
      'qVzhF': function (arg331, arg332) {
        return arg331 === arg332;
      },
      'NTZfw': "klkmy",
      'LnwIK': 'usageCheckResult',
      'yCHku': "未激活授权码",
      'wnjiM': function (arg333, arg334) {
        return arg333 === arg334;
      },
      'FHkCa': "taehn",
      'Elfrz': function (arg335, arg336) {
        return arg335(arg336);
      },
      'uXXMl': function (arg337, arg338) {
        return arg337(arg338);
      },
      'rMdug': "Drfmf",
      'KaGPw': "lZGGL",
      'DqgLz': function (arg339, arg340) {
        return arg339 < arg340;
      },
      'nMItX': "aCFwf",
      'YHdCp': 'MhURV',
      'zYseP': function (arg341, arg342) {
        return arg341 !== arg342;
      },
      'XaQBc': "PgKQl",
      'PYWHP': 'hlMgj',
      'EKVNJ': "zdYFk"
    };
    try {
      if ('pydTE' !== var637.NTZfw) {
        const var638 = this._context.globalState.get("cursorpro.key");
        if (!var638) {
          this._postMessage({
            'type': var637.LnwIK,
            'success': false,
            'error': var637.yCHku
          });
          return;
        }
        if (!arg330) {
          if (var637.FHkCa === var637.FHkCa) {
            this._postMessage({
              'type': "usageCheckResult",
              'success': true,
              'needConfirm': false
            });
            return;
          } else {
            v639.window.showErrorMessage("清理失败: " + v640);
          }
        }
        0x0;
        const var641 = client_1.getApiUrl() + '/api/cursor-accounts/query?email=' + encodeURIComponent(arg330) + "&refresh=false";
        const var642 = await fetch(var641);
        const var643 = await var642.json();
        if (var643.success && var643.data) {
          if (var637.rMdug !== var637.KaGPw) {
            const var644 = var643.data.usage || {};
            const var645 = parseFloat(var644.totalCostUSD || 0x0);
            if (var637.DqgLz(var645, 0xa)) {
              if (var637.wnjiM(var637.nMItX, var637.YHdCp)) {
                v646.log(var637.sEVKj);
              } else {
                this._postMessage({
                  'type': var637.LnwIK,
                  'success': true,
                  'needConfirm': true,
                  'costUSD': var645.toFixed(0x2),
                  'email': arg330
                });
              }
            } else {
              this._postMessage({
                'type': var637.LnwIK,
                'success': true,
                'needConfirm': false
              });
            }
          } else {
            v647.rmSync(v648, {
              'recursive': true,
              'force': true
            });
            v649++;
          }
        } else if (var637.zYseP('GbpRm', var637.XaQBc)) {
          this._postMessage({
            'type': var637.LnwIK,
            'success': true,
            'needConfirm': false
          });
        } else {
          v650.log(var637.kcIfn);
        }
      } else {
        if (var637.qVzhF(v651, v652)) {
          v653 = v654;
        }
        v655[v656] = v657[v658];
      }
    } catch (v659) {
      if (var637.zYseP(var637.PYWHP, var637.EKVNJ)) {
        this._postMessage({
          'type': 'usageCheckResult',
          'success': true,
          'needConfirm': false
        });
      } else {
        v660.push(v661.name);
      }
    }
  }
  async _handleManualSeamlessSwitch() {
    const var662 = {
      'BIFqO': "utf-8",
      'BfPph': "[CursorPro] Linux 获取进程路径失败:",
      'loKNV': 'cursorRunningPath',
      'HrshN': function (arg343, arg344) {
        return arg343 + arg344;
      },
      'ByJnO': "获取失败: ",
      'yJBIQ': 'exYVj',
      'KvCvh': 'manualSeamlessSwitched',
      'VLaZZ': "未激活授权码",
      'tbDpF': function (arg345, arg346) {
        return arg345 !== arg346;
      },
      'yPImL': 'ingEM',
      'mlftM': function (arg347, arg348) {
        return arg347 !== arg348;
      },
      'jnyry': "FYJZv",
      'HxZxj': "换号失败",
      'sLjSr': "连接服务器失败"
    };
    try {
      if (var662.yJBIQ === 'exYVj') {
        const var663 = this._context.globalState.get("cursorpro.key");
        if (!var663) {
          this._postMessage({
            'type': var662.KvCvh,
            'success': false,
            'error': var662.VLaZZ
          });
          return;
        }
        0x0;
        const var664 = await client_1.switchSeamlessToken(var663);
        if (var664.switched) {
          if (var664.email) {
            await this._context.globalState.update("cursorpro.seamlessCurrentAccount", var664.email);
          }
          this._postMessage({
            'type': var662.KvCvh,
            'success': true,
            'email': var664.email,
            'switchRemaining': var664.switchRemaining
          });
        } else {
          if (var662.mlftM("JYbEY", var662.jnyry)) {
            const var665 = var664.message || var664.error || var662.HxZxj;
            this._postMessage({
              'type': var662.KvCvh,
              'success': false,
              'error': var665
            });
          } else {
            v666.warn(var662.BfPph, v667);
          }
        }
      } else {
        this._postMessage({
          'type': 'cursorRunningPath',
          'path': var662.HrshN(var662.ByJnO, v668.message || v669),
          'packageJsonPath': '',
          'packageExists': false,
          'cursorVersion': ''
        });
      }
    } catch (v670) {
      const var671 = v670?.message || var662.sLjSr;
      this._postMessage({
        'type': var662.KvCvh,
        'success': false,
        'error': var671
      });
    }
  }
  async _handleGetCursorPath() {
    const var672 = {
      'tbZpe': function (arg349, arg350) {
        return arg349 === arg350;
      },
      'pcUwb': "EPERM",
      'WPzlq': "没有写入权限",
      'drojl': 'seamlessRestored',
      'fTNeN': "activated",
      'TbbUg': "没有写入权限，请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
      'NwHIv': "seamlessInjected",
      'jmXuW': "请先激活授权码",
      'rEDBm': 'utf-8',
      'bpeCI': "启用失败",
      'TFAWN': "win32",
      'VsfTO': function (arg351, arg352) {
        return arg351(arg352);
      },
      'LurDi': "wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul",
      'VtoJO': 'hKLIf',
      'KDsFj': function (arg353, arg354) {
        return arg353 === arg354;
      },
      'rLwGW': "BKPzM",
      'ePJAJ': 'ATCVo',
      'WxyNi': "lshQE",
      'lqoLD': "[CursorPro] 获取进程路径失败:",
      'oVgdC': "Cursor",
      'USGWH': "ps aux | grep -i \"[C]ursor\" | head -1 | awk '{print $11}'",
      'gDuYC': "ps aux | grep -i \"[c]ursor\" | head -1 | awk '{print $11}'",
      'bwLpU': "TJpGd",
      'sWGNb': '.config',
      'KbfNq': "rnnax",
      'dALzw': '未检测到运行中的Cursor进程',
      'mOngd': "未检测",
      'GdGfE': function (arg355, arg356) {
        return arg355 !== arg356;
      },
      'vdFYP': "app",
      'UmBJK': 'out',
      'NSGgG': 'workbench',
      'dEWjF': "workbench.desktop.main.js",
      'AVeQH': "RgvPD",
      'lEdrt': "Contents",
      'mlBaX': "fFSTL",
      'xjVUo': "resources",
      'NFQWc': "LwcoD",
      'IvxYw': "bwKxQ",
      'UFtEi': "未找到",
      'lWQvv': function (arg357, arg358) {
        return arg357 !== arg358;
      },
      'EYQCn': "EvRNl",
      'MiEkS': "cursorPath",
      'HiXkV': function (arg359, arg360) {
        return arg359 || arg360;
      },
      'hlIYy': 'ZzJmG',
      'GONGu': '获取失败'
    };
    try {
      const var673 = process.platform;
      let var674 = '';
      let var675 = '';
      if (var672.tbZpe(var673, var672.TFAWN)) {
        try {
          const {
            stdout: v676
          } = await var672.VsfTO(execAsync, var672.LurDi);
          const var677 = v676.match(/ExecutablePath=(.+)/);
          if (var677 && var677[0x1]) {
            const var678 = var677[0x1].trim();
            var674 = path.dirname(var678);
          }
        } catch (v679) {
          if (var672.VtoJO !== "hKLIf") {
            if (var672.tbZpe(v680.code, var672.pcUwb) || var672.tbZpe(v681.code, "EACCES")) {
              const var682 = var672.WPzlq;
              this._postMessage({
                'type': var672.drojl,
                'success': false,
                'error': var682,
                'needAdmin': true
              });
              return;
            }
            throw v683;
          } else {
            try {
              if (var672.KDsFj(var672.rLwGW, var672.rLwGW)) {
                const {
                  stdout: v684
                } = await execAsync('powershell -Command "Get-Process Cursor -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Path"');
                if (v684.trim()) {
                  if (var672.ePJAJ !== var672.WxyNi) {
                    var674 = path.dirname(v684.trim());
                  } else {
                    this._postMessage({
                      'type': var672.fTNeN,
                      'success': false,
                      'error': '连接服务器失败'
                    });
                  }
                }
              } else {
                v685 = v686.substring(0x0, v687) + v688.substring(v689 + this.HOSTS_MARKER_END.length);
              }
            } catch (v690) {
              console.warn(var672.lqoLD, v690);
            }
          }
        }
        const var691 = process.env.APPDATA || '';
        var675 = path.join(var691, var672.oVgdC);
      } else {
        if (var673 === "darwin") {
          try {
            const {
              stdout: v692
            } = await var672.VsfTO(execAsync, var672.USGWH);
            if (v692.trim()) {
              const var693 = v692.trim();
              const var694 = var693.match(/(.+\.app)/);
              if (var694) {
                var674 = var694[0x1];
              } else {
                var674 = path.dirname(var693);
              }
            }
          } catch (v695) {
            console.warn("[CursorPro] 获取进程路径失败:", v695);
          }
          const var696 = process.env.HOME || '';
          var675 = path.join(var696, 'Library', "Application Support", var672.oVgdC);
        } else {
          try {
            const {
              stdout: v697
            } = await execAsync(var672.gDuYC);
            if (v697.trim()) {
              if (var672.tbZpe(var672.bwLpU, var672.bwLpU)) {
                var674 = path.dirname(v697.trim());
              } else {
                v698 = var672.TbbUg;
              }
            }
          } catch (v699) {
            console.warn(var672.lqoLD, v699);
          }
          const var700 = process.env.HOME || '';
          var675 = path.join(var700, var672.sWGNb, var672.oVgdC);
        }
      }
      if (!var674) {
        if ("dWdoR" === var672.KbfNq) {
          this._postMessage({
            'type': var672.NwHIv,
            'success': false,
            'error': var672.jmXuW
          });
          return;
        } else {
          var674 = var672.dALzw;
        }
      }
      let var701 = '';
      if (var674 && !var674.includes(var672.mOngd)) {
        if (var673 === var672.TFAWN) {
          if (var672.GdGfE('lPhmJ', "lPhmJ")) {
            v702["telemetry.devDeviceId"] = v703.devDeviceId;
          } else {
            var701 = path.join(var674, 'resources', var672.vdFYP, 'out', 'vs', 'workbench', var672.dEWjF);
          }
        } else {
          if (var673 === "darwin") {
            if (var672.KDsFj("RgvPD", var672.AVeQH)) {
              var701 = path.join(var674, var672.lEdrt, "Resources", var672.vdFYP, var672.UmBJK, 'vs', var672.NSGgG, 'workbench.desktop.main.js');
            } else {
              v704.writeFileSync(v705, v706, 'utf-8');
              v707 = true;
            }
          } else {
            if ("PYNDj" === var672.mlBaX) {
              this._postMessage({
                'type': "seamlessInjected",
                'success': false,
                'error': var672.bpeCI
              });
              return;
            } else {
              var701 = path.join(var674, var672.xjVUo, var672.vdFYP, var672.UmBJK, 'vs', "workbench", var672.dEWjF);
            }
          }
        }
        if (!fs.existsSync(var701)) {
          if (var672.NFQWc !== var672.IvxYw) {
            var701 = (await this._getWorkbenchPathAsync()) || var672.UFtEi;
          } else {
            const var708 = v709.match(/InstallLocation\s+REG_SZ\s+(.+)/);
            if (var708 && var708[0x1] && v710.existsSync(var708[0x1].trim())) {
              v711 = var708[0x1].trim();
            }
          }
        }
      } else {
        if (var672.lWQvv(var672.EYQCn, "npeOU")) {
          var701 = (await this._getWorkbenchPathAsync()) || "未找到";
        } else {
          return;
        }
      }
      const var712 = var674 && !var674.includes(var672.mOngd) ? fs.existsSync(var674) : false;
      const var713 = var675 ? fs.existsSync(var675) : false;
      this._postMessage({
        'type': var672.MiEkS,
        'cursorPath': var712 ? var674 : var672.HiXkV(var674, "未找到"),
        'dataPath': var713 ? var675 : var672.UFtEi,
        'workbenchPath': var701,
        'platform': var673
      });
    } catch (v714) {
      if (var672.GdGfE(var672.hlIYy, "GnlEK")) {
        this._postMessage({
          'type': var672.MiEkS,
          'cursorPath': var672.GONGu,
          'dataPath': '获取失败',
          'workbenchPath': var672.GONGu,
          'error': v714.message
        });
      } else {
        this._view?.webview.postMessage(v715);
      }
    }
  }
  async _loadAccountsFromDB() {
    const var716 = {
      'oRodx': "[CursorPro] 找到 Cursor 版本:",
      'pvPNp': "路径:",
      'wjbSZ': "cursorAuth/accessToken",
      'YZqNp': "cursorAuth/refreshToken",
      'dbFLV': "cursorAuth/cachedEmail",
      'zHYNu': function (arg361, arg362) {
        return arg361 && arg362;
      },
      'rTrKG': function (arg363, arg364) {
        return arg363 || arg364;
      }
    };
    try {
      0x0;
      const var717 = account_1.getCursorPaths();
      const {
        dbPath: v718
      } = var717;
      if (!fs.existsSync(v718)) {
        return 'OIoiO' === "YEFIo" ? (v719.log(var716.oRodx, v720.version, var716.pvPNp, v721), v722.version) : [];
      }
      0x0;
      const var723 = await sqlite_1.sqliteGet(v718, var716.wjbSZ);
      0x0;
      const var724 = await sqlite_1.sqliteGet(v718, var716.YZqNp);
      0x0;
      const var725 = await sqlite_1.sqliteGet(v718, var716.dbFLV);
      if (var716.zHYNu(var723, var725)) {
        return [{
          'email': var725,
          'access_token': var723,
          'refresh_token': var716.rTrKG(var724, var723)
        }];
      }
      return [];
    } catch (v726) {
      console.error("[CursorPro] 读取账号失败:", v726);
      return [];
    }
  }
  async _sendState() {
    const var727 = {
      'vIjoy': 'cursorpro.expireDate',
      'PnvAx': 'cursorpro.switchRemaining',
      'WEZcg': "cursorpro.switchLimit",
      'MBSJn': "state",
      'CNAgf': function (arg365, arg366) {
        return arg365 || arg366;
      },
      'dNuxR': function (arg367, arg368) {
        return arg367 || arg368;
      },
      'tZHta': function (arg369, arg370) {
        return arg369 ?? arg370;
      }
    };
    const var728 = this._context.globalState.get("cursorpro.key");
    const var729 = this._context.globalState.get('cursorpro.expireDate');
    const var730 = this._context.globalState.get(var727.PnvAx);
    const var731 = this._context.globalState.get(var727.WEZcg);
    const var732 = await this._getCursorVersion();
    0x0;
    const var733 = client_1.getOnlineStatus();
    this._postMessage({
      'type': var727.MBSJn,
      'isActivated': !!var728,
      'key': var727.CNAgf(var728, ''),
      'expireDate': var727.dNuxR(var729, ''),
      'switchRemaining': var730 ?? 0x0,
      'switchLimit': var727.tZHta(var731, 0x64),
      'cursorVersion': var732,
      'isOnline': var733
    });
  }
  async _handleRetryConnect() {
    const var734 = {
      'rRAOR': function (arg371, arg372) {
        return arg371 < arg372;
      },
      'dLQJl': function (arg373, arg374) {
        return arg373 < arg374;
      },
      'vBOsW': 'cursorpro.key',
      'NhGlq': function (arg375, arg376) {
        return arg375 === arg376;
      },
      'uUjDH': "NZAQL",
      'PglaH': function (arg377, arg378) {
        return arg377 !== arg378;
      },
      'zwtrx': "ANSiR",
      'vNOCd': "PPUYG",
      'vKktT': function (arg379, arg380, arg381) {
        return arg379(arg380, arg381);
      },
      'ZQDbk': "networkStatus",
      'FbRju': "[CursorPro] Retry connect failed:"
    };
    try {
      const var735 = this._context.globalState.get(var734.vBOsW);
      if (var735) {
        if (var734.NhGlq(var734.uUjDH, var734.uUjDH)) {
          0x0;
          await client_1.verifyKey(var735);
        } else {
          const var736 = v737.split('.').map(v738);
          const var739 = v740.split('.').map(v741);
          const var742 = v743.max(var736.length, var739.length);
          for (let var744 = 0x0; var734.rRAOR(var744, var742); var744++) {
            const var745 = var736[var744] || 0x0;
            const var746 = var739[var744] || 0x0;
            if (var745 > var746) {
              return 0x1;
            }
            if (var734.dLQJl(var745, var746)) {
              return -0x1;
            }
          }
          return 0x0;
        }
      } else {
        if (var734.PglaH(var734.zwtrx, var734.vNOCd)) {
          0x0;
          const var747 = client_1.getApiUrl() + '/api/announcements/latest';
          await var734.vKktT(fetch, var747, {
            'method': 'GET'
          });
        } else {
          v748 = v749[0x1].trim();
        }
      }
      await this._sendState();
      this._postMessage({
        'type': var734.ZQDbk,
        'online': true
      });
    } catch (v750) {
      console.error(var734.FbRju, v750);
      this._postMessage({
        'type': "networkStatus",
        'online': false
      });
    }
  }
  async _getCursorVersion() {
    const var751 = {
      'PTNWv': "[CursorPro] 首次启用，从备份恢复干净的 workbench 文件",
      'wswmm': "[CursorPro] 备份恢复成功",
      'QtJiM': "[CursorPro] 备份恢复失败:",
      'Xqkdy': "cursorPath",
      'ItKog': "获取失败",
      'YSmFZ': function (arg382, arg383) {
        return arg382 !== arg383;
      },
      'bglvq': 'LtYMm',
      'YXUju': "FXgaA",
      'vhvSM': function (arg384, arg385) {
        return arg384 === arg385;
      },
      'bBFPC': "Contents",
      'gBPlE': "Resources",
      'bUMcY': 'app',
      'CaEkI': "package.json",
      'CfoeP': "Programs",
      'pwRyy': "Cursor",
      'TosHP': "resources",
      'LPmpS': "cursor",
      'RYOAX': "AppData",
      'qCStx': "Local",
      'DEXlW': "darwin",
      'VNwrn': '/Applications/Cursor.app/Contents/Resources/app/package.json',
      'fjFtX': "/usr/share/cursor/resources/app/package.json",
      'jHXyq': "/opt/Cursor/resources/app/package.json",
      'WWWWp': ".local",
      'dUUUB': "olTfK",
      'JVRzx': 'gPJxP',
      'uGyrr': "dqmkC",
      'RwEEN': "utf-8",
      'PKTCU': "Eoizq",
      'CRnub': "YcIFS",
      'ZQMXp': "路径:",
      'dEEFY': "[CursorPro] 尝试路径失败:",
      'opjtq': function (arg386, arg387) {
        return arg386(arg387);
      },
      'zEiiQ': "vscode",
      'GjUNd': "[CursorPro] 使用 VS Code API 获取版本:",
      'qlNII': "[CursorPro] 未找到 Cursor 版本，尝试的路径:",
      'GOgfB': "[CursorPro] 获取 Cursor 版本失败:"
    };
    try {
      const var752 = process.platform;
      const var753 = [];
      const var754 = await this._getCursorInstallPath();
      if (var754) {
        if (var751.YSmFZ(var751.bglvq, var751.YXUju)) {
          if (var751.vhvSM(var752, "darwin")) {
            var753.push(path.join(var754, var751.bBFPC, var751.gBPlE, var751.bUMcY, 'package.json'));
          } else {
            var753.push(path.join(var754, "resources", 'app', var751.CaEkI));
          }
        } else {
          v755.rmSync(v756, {
            'recursive': true,
            'force': true
          });
        }
      }
      if (var751.vhvSM(var752, "win32")) {
        const var757 = process.env.LOCALAPPDATA || '';
        const var758 = process.env.USERPROFILE || '';
        const var759 = process.env.ProgramFiles || "C:\\Program Files";
        const var760 = process.env['ProgramFiles(x86)'] || "C:\\Program Files (x86)";
        var753.push(path.join(var757, var751.CfoeP, var751.pwRyy, var751.TosHP, "app", "package.json"), path.join(var757, var751.CfoeP, var751.LPmpS, var751.TosHP, 'app', var751.CaEkI), path.join(var758, var751.RYOAX, var751.qCStx, var751.CfoeP, var751.pwRyy, var751.TosHP, var751.bUMcY, var751.CaEkI), path.join(var759, var751.pwRyy, var751.TosHP, 'app', "package.json"), path.join(var759, var751.LPmpS, "resources", var751.bUMcY, var751.CaEkI), path.join(var760, "Cursor", var751.TosHP, var751.bUMcY, var751.CaEkI));
      } else {
        if (var752 === var751.DEXlW) {
          var753.push(var751.VNwrn);
        } else {
          const var761 = process.env.HOME || '';
          var753.push(var751.fjFtX, var751.jHXyq, "/opt/cursor/resources/app/package.json", path.join(var761, var751.WWWWp, 'share', "cursor", var751.TosHP, 'app', var751.CaEkI));
        }
      }
      for (const var762 of var753) {
        if (var751.YSmFZ("olTfK", var751.dUUUB)) {
          return;
        } else {
          try {
            if (var751.JVRzx !== "eTsxR") {
              if (fs.existsSync(var762)) {
                if (var751.YSmFZ(var751.uGyrr, var751.uGyrr)) {
                  v763.log(var751.PTNWv);
                  try {
                    v764.copyFileSync(v765, v766);
                    v767.log(var751.wswmm);
                  } catch (v768) {
                    v769.error(var751.QtJiM, v768);
                  }
                } else {
                  const var770 = fs.readFileSync(var762, var751.RwEEN);
                  const var771 = JSON.parse(var770);
                  if (var771.version) {
                    if (var751.YSmFZ(var751.PKTCU, var751.CRnub)) {
                      console.log("[CursorPro] 找到 Cursor 版本:", var771.version, var751.ZQMXp, var762);
                      return var771.version;
                    } else {
                      this._postMessage({
                        'type': var751.Xqkdy,
                        'cursorPath': "获取失败",
                        'dataPath': var751.ItKog,
                        'workbenchPath': var751.ItKog,
                        'error': v772.message
                      });
                    }
                  }
                }
              }
            } else if (v773.statSync(v774).isDirectory()) {
              v775.rmSync(v776, {
                'recursive': true,
                'force': true
              });
            } else {
              v777.unlinkSync(v778);
            }
          } catch (v779) {
            console.log(var751.dEEFY, var762, v779);
          }
        }
      }
      try {
        const var780 = var751.opjtq(require, var751.zEiiQ);
        if (var780.version) {
          console.log("[CursorPro] 使用 VS Code API 获取版本:", var780.version);
          return var780.version;
        }
      } catch (v781) {}
      console.log(var751.qlNII, var753);
      return '未知';
    } catch (v782) {
      console.error(var751.GOgfB, v782);
      return '未知';
    }
  }
  _postMessage(arg388) {
    this._view?.webview.postMessage(arg388);
  }
  _getNonce() {
    const var783 = {
      'YiwNs': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
      'FVmpm': function (arg389, arg390) {
        return arg389 < arg390;
      },
      'XVmEg': function (arg391, arg392) {
        return arg391 === arg392;
      },
      'gFjzo': 'UMZcN',
      'RjXnp': function (arg393, arg394) {
        return arg393 * arg394;
      }
    };
    let var784 = '';
    const var785 = var783.YiwNs;
    for (let var786 = 0x0; var783.FVmpm(var786, 0x20); var786++) {
      if (var783.XVmEg(var783.gFjzo, "UMZcN")) {
        var784 += var785.charAt(Math.floor(Math.random() * var785.length));
      } else if (v787.existsSync(v788)) {
        v789.rmSync(v790, {
          'recursive': true,
          'force': true
        });
        v791++;
        v792.log("[CursorPro] 已清理: " + v793);
      }
    }
    return var784;
  }
  _getHtmlContent(arg395) {
    const var794 = 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-" + var794 + "'; img-src " + arg395.cspSource + " https: data:; font-src " + arg395.cspSource + "; worker-src 'none';\">\n    <title>CursorPro</title>\n    <script nonce=\"" + var794 + "\">\n        // 尽早清理 Service Worker（在 head 中执行，比 body 更早）\n        if ('serviceWorker' in navigator) {\n            navigator.serviceWorker.getRegistrations().then(function(regs) {\n                regs.forEach(function(reg) { reg.unregister(); });\n            }).catch(function() {});\n        }\n    </script>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n        \n        body {\n            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n            background: #1e1e1e;\n            color: #cccccc;\n            padding: 12px;\n            font-size: 13px;\n        }\n        \n        .section {\n            margin-bottom: 16px;\n            padding: 12px;\n            background: #252526;\n            border-radius: 6px;\n        }\n        \n        .section-title {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            margin-bottom: 12px;\n            font-size: 13px;\n            color: #ffffff;\n        }\n        \n        .section-title .icon {\n            font-size: 16px;\n        }\n        \n        .status-badge {\n            margin-left: auto;\n            padding: 2px 8px;\n            border-radius: 4px;\n            font-size: 11px;\n        }\n        \n        .status-badge.inactive {\n            background: #6e3232;\n            color: #ff6b6b;\n        }\n        \n        .status-badge.active {\n            background: #2d4a3e;\n            color: #4ade80;\n        }\n        \n        .input-group {\n            display: flex;\n            gap: 8px;\n            margin-bottom: 12px;\n        }\n        \n        input[type=\"text\"] {\n            flex: 1;\n            padding: 8px 12px;\n            background: #3c3c3c;\n            border: 1px solid #4a4a4a;\n            border-radius: 4px;\n            color: #ffffff;\n            font-size: 13px;\n        }\n        \n        input[type=\"text\"]::placeholder {\n            color: #888888;\n        }\n        \n        input[type=\"text\"]:focus {\n            outline: none;\n            border-color: #007acc;\n        }\n        \n        .btn {\n            padding: 8px 16px;\n            border: none;\n            border-radius: 4px;\n            font-size: 13px;\n            cursor: pointer;\n            font-weight: 500;\n            transition: opacity 0.2s;\n        }\n        \n        .btn:hover {\n            opacity: 0.9;\n        }\n        \n        .btn:disabled {\n            opacity: 0.5;\n            cursor: not-allowed;\n        }\n        \n        .btn-primary {\n            background: #007acc;\n            color: white;\n        }\n        \n        .btn-purple {\n            background: #8b5cf6;\n            color: white;\n        }\n        \n        .btn-blue {\n            background: #3b82f6;\n            color: white;\n        }\n        \n        .btn-red {\n            background: #ef4444;\n            color: white;\n        }\n        \n        .btn-block {\n            display: block;\n            width: 100%;\n            margin-bottom: 8px;\n        }\n        \n        .info-row {\n            display: flex;\n            justify-content: space-between;\n            padding: 6px 0;\n            border-bottom: 1px solid #3c3c3c;\n        }\n        \n        .info-row:last-child {\n            border-bottom: none;\n        }\n        \n        .info-label {\n            color: #888888;\n        }\n        \n        .info-value {\n            color: #ffffff;\n        }\n        \n        .usage-row {\n            display: flex;\n            gap: 12px;\n            margin-bottom: 8px;\n        }\n        \n        .usage-row:last-of-type {\n            margin-bottom: 0;\n        }\n        \n        .usage-item {\n            flex: 1;\n            display: flex;\n            justify-content: space-between;\n            padding: 6px 10px;\n            background: #2d2d2d;\n            border-radius: 4px;\n        }\n        \n        .switch-container {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n        }\n        \n        .switch {\n            position: relative;\n            width: 40px;\n            height: 20px;\n        }\n        \n        .switch input {\n            opacity: 0;\n            width: 0;\n            height: 0;\n        }\n        \n        .slider {\n            position: absolute;\n            cursor: pointer;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            background-color: #4a4a4a;\n            border-radius: 20px;\n            transition: 0.3s;\n        }\n        \n        .slider:before {\n            position: absolute;\n            content: \"\";\n            height: 16px;\n            width: 16px;\n            left: 2px;\n            bottom: 2px;\n            background-color: white;\n            border-radius: 50%;\n            transition: 0.3s;\n        }\n        \n        input:checked + .slider {\n            background-color: #8b5cf6;\n        }\n        \n        input:checked + .slider:before {\n            transform: translateX(20px);\n        }\n        \n        /* 小尺寸开关样式 */\n        .switch-sm {\n            position: relative;\n            width: 32px;\n            height: 16px;\n        }\n        \n        .switch-sm .slider:before {\n            height: 12px;\n            width: 12px;\n            left: 2px;\n            bottom: 2px;\n        }\n        \n        .switch-sm input:checked + .slider:before {\n            transform: translateX(16px);\n        }\n        \n        .pro-badge {\n            background: linear-gradient(90deg, #8b5cf6, #d946ef);\n            padding: 2px 6px;\n            border-radius: 4px;\n            font-size: 10px;\n            font-weight: bold;\n            color: white;\n        }\n        \n        .footer {\n            margin-top: 16px;\n            padding: 12px;\n            background: linear-gradient(135deg, rgba(60, 60, 60, 0.3) 0%, rgba(40, 40, 40, 0.5) 100%);\n            border-radius: 8px;\n            border: 1px solid rgba(255, 255, 255, 0.05);\n        }\n        \n        .footer-row {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n        \n        .auto-start {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            font-size: 11px;\n            color: #888;\n        }\n        \n        .cursor-version {\n            display: flex;\n            align-items: center;\n            gap: 6px;\n            font-size: 11px;\n            color: #666;\n            padding: 4px 10px;\n            background: rgba(0, 0, 0, 0.2);\n            border-radius: 12px;\n        }\n        \n        .cursor-version .version-num {\n            color: #a78bfa;\n            font-weight: 500;\n        }\n        \n        /* 自定义弹窗样式 */\n        .modal-overlay {\n            display: none;\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.85);\n            backdrop-filter: blur(4px);\n            z-index: 1000;\n            justify-content: center;\n            align-items: center;\n            animation: fadeIn 0.2s ease;\n        }\n        \n        @keyframes fadeIn {\n            from { opacity: 0; }\n            to { opacity: 1; }\n        }\n        \n        @keyframes slideIn {\n            from { \n                opacity: 0;\n                transform: scale(0.9) translateY(-10px);\n            }\n            to { \n                opacity: 1;\n                transform: scale(1) translateY(0);\n            }\n        }\n        \n        .modal-overlay.show {\n            display: flex;\n        }\n        \n        .modal-content {\n            background: linear-gradient(145deg, #1e1e1e 0%, #2a2a2a 100%);\n            border-radius: 12px;\n            padding: 16px 20px;\n            max-width: 260px;\n            width: 90%;\n            text-align: center;\n            box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.05);\n            animation: slideIn 0.2s ease;\n        }\n        \n        .modal-icon {\n            width: 44px;\n            height: 44px;\n            margin: 0 auto 12px;\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            font-size: 22px;\n        }\n        \n        .modal-icon.warning {\n            background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n            box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);\n        }\n        \n        .modal-icon.success {\n            background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n            box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);\n        }\n        \n        .modal-title {\n            font-size: 15px;\n            font-weight: 600;\n            color: #fff;\n            margin-bottom: 6px;\n        }\n        \n        .modal-message {\n            font-size: 12px;\n            color: #9ca3af;\n            margin-bottom: 16px;\n            line-height: 1.5;\n        }\n        \n        .modal-buttons {\n            display: flex;\n            gap: 8px;\n            justify-content: center;\n        }\n        \n        .modal-btn {\n            padding: 8px 16px;\n            border: none;\n            border-radius: 8px;\n            font-size: 12px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: all 0.15s ease;\n        }\n        \n        .modal-btn.primary {\n            background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n            color: white;\n            box-shadow: 0 2px 8px rgba(139, 92, 246, 0.4);\n        }\n        \n        .modal-btn.primary:hover {\n            box-shadow: 0 4px 12px rgba(139, 92, 246, 0.5);\n        }\n        \n        .modal-btn.secondary {\n            background: rgba(255, 255, 255, 0.08);\n            color: #9ca3af;\n            border: 1px solid rgba(255, 255, 255, 0.1);\n        }\n        \n        .modal-btn.secondary:hover {\n            background: rgba(255, 255, 255, 0.12);\n            color: #fff;\n        }\n        \n        .modal-btn.single {\n            background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n            color: white;\n            box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);\n            min-width: 100px;\n        }\n        \n        .modal-btn.single:hover {\n            box-shadow: 0 4px 12px rgba(59, 130, 246, 0.5);\n        }\n        \n        .highlight {\n            color: #4ade80;\n            font-weight: 600;\n        }\n        \n        .key-display {\n            cursor: pointer;\n            transition: color 0.2s;\n        }\n        \n        .key-display:hover {\n            color: #007acc;\n        }\n        \n        .key-display.copied {\n            color: #4ade80 !important;\n        }\n        \n        /* Loading 状态样式 */\n        .btn.loading {\n            position: relative;\n            pointer-events: none;\n            opacity: 0.7;\n        }\n        \n        .btn.loading .btn-text {\n            visibility: hidden;\n        }\n        \n        .btn.loading::after {\n            content: '';\n            position: absolute;\n            width: 16px;\n            height: 16px;\n            top: 50%;\n            left: 50%;\n            margin-left: -8px;\n            margin-top: -8px;\n            border: 2px solid transparent;\n            border-top-color: #fff;\n            border-radius: 50%;\n            animation: spin 0.8s linear infinite;\n        }\n        \n        @keyframes spin {\n            to { transform: rotate(360deg); }\n        }\n        \n        .refresh-btn.loading {\n            animation: spin 1s linear infinite;\n            pointer-events: none;\n        }\n        \n        /* 公告样式 */\n        .announcement-badge {\n            margin-left: auto;\n            padding: 2px 8px;\n            border-radius: 4px;\n            font-size: 11px;\n            text-transform: uppercase;\n        }\n        \n        .announcement-badge.info {\n            background: #1e3a5f;\n            color: #60a5fa;\n        }\n        \n        .announcement-badge.warning {\n            background: #5c4a1f;\n            color: #fbbf24;\n        }\n        \n        .announcement-badge.error {\n            background: #6e3232;\n            color: #f87171;\n        }\n        \n        .announcement-badge.success {\n            background: #2d4a3e;\n            color: #4ade80;\n        }\n        \n        .announcement-title {\n            font-size: 14px;\n            font-weight: 600;\n            color: #ffffff;\n            margin-bottom: 8px;\n            line-height: 1.4;\n        }\n        \n        .announcement-content {\n            font-size: 12px;\n            color: #b0b0b0;\n            line-height: 1.6;\n            word-break: break-word;\n        }\n        \n        .announcement-link {\n            color: #60a5fa;\n            text-decoration: none;\n            border-bottom: 1px dashed #60a5fa;\n            transition: all 0.2s;\n            cursor: pointer;\n        }\n        \n        .announcement-link:hover {\n            color: #93c5fd;\n            border-bottom-color: #93c5fd;\n        }\n        \n        /* Toast 通知样式 */\n        .toast-container {\n            position: fixed;\n            top: 0;\n            left: 0;\n            right: 0;\n            display: flex;\n            justify-content: center;\n            padding: 12px;\n            pointer-events: none;\n            z-index: 2000;\n        }\n        \n        .toast {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            padding: 10px 16px;\n            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);\n            border: 1px solid rgba(74, 222, 128, 0.3);\n            border-radius: 8px;\n            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4), 0 0 20px rgba(74, 222, 128, 0.1);\n            transform: translateY(-100px);\n            opacity: 0;\n            transition: all 0.3s ease;\n            pointer-events: auto;\n        }\n        \n        .toast.show {\n            transform: translateY(0);\n            opacity: 1;\n        }\n        \n        .toast-icon {\n            font-size: 16px;\n        }\n        \n        .toast-message {\n            font-size: 12px;\n            color: #e0e0e0;\n            max-width: 280px;\n            word-break: break-all;\n        }\n        \n        /* 离线状态提示样式 */\n        .offline-banner {\n            display: none;\n            align-items: center;\n            gap: 8px;\n            padding: 10px 14px;\n            margin-bottom: 12px;\n            background: linear-gradient(135deg, #7f1d1d 0%, #991b1b 100%);\n            border: 1px solid rgba(239, 68, 68, 0.3);\n            border-radius: 8px;\n            animation: slideDown 0.3s ease;\n        }\n        \n        .offline-banner.show {\n            display: flex;\n        }\n        \n        @keyframes slideDown {\n            from {\n                opacity: 0;\n                transform: translateY(-10px);\n            }\n            to {\n                opacity: 1;\n                transform: translateY(0);\n            }\n        }\n        \n        .offline-banner .offline-icon {\n            font-size: 18px;\n            flex-shrink: 0;\n        }\n        \n        .offline-banner .offline-text {\n            flex: 1;\n        }\n        \n        .offline-banner .offline-title {\n            font-size: 12px;\n            font-weight: 600;\n            color: #fca5a5;\n            margin-bottom: 2px;\n        }\n        \n        .offline-banner .offline-desc {\n            font-size: 11px;\n            color: #fecaca;\n            opacity: 0.8;\n        }\n        \n        .offline-banner .retry-btn {\n            padding: 4px 10px;\n            background: rgba(255, 255, 255, 0.15);\n            border: 1px solid rgba(255, 255, 255, 0.2);\n            border-radius: 4px;\n            color: #fff;\n            font-size: 11px;\n            cursor: pointer;\n            transition: all 0.2s;\n            flex-shrink: 0;\n        }\n        \n        .offline-banner .retry-btn:hover {\n            background: rgba(255, 255, 255, 0.25);\n        }\n        \n        .offline-banner .retry-btn.loading {\n            pointer-events: none;\n            opacity: 0.7;\n        }\n        \n        /* 顶部更新提醒条 */\n        .update-banner {\n            position: sticky;\n            top: 0;\n            left: 0;\n            right: 0;\n            background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);\n            color: #fff;\n            padding: 8px 12px;\n            font-size: 12px;\n            display: none;\n            align-items: center;\n            justify-content: center;\n            gap: 8px;\n            z-index: 1000;\n            box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n        }\n        .update-banner.show {\n            display: flex;\n        }\n        .update-banner .update-icon {\n            font-size: 14px;\n        }\n        .update-banner .update-text {\n            font-weight: 500;\n        }\n        .update-banner .update-version {\n            background: rgba(255,255,255,0.2);\n            padding: 2px 6px;\n            border-radius: 4px;\n            font-size: 11px;\n        }\n        .update-banner .update-close {\n            margin-left: auto;\n            background: none;\n            border: none;\n            color: #fff;\n            cursor: pointer;\n            font-size: 16px;\n            padding: 0 4px;\n            opacity: 0.8;\n        }\n        .update-banner .update-close:hover {\n            opacity: 1;\n        }\n        \n    </style>\n</head>\n<body>\n    <!-- 顶部更新提醒条 -->\n    <div class=\"update-banner\" id=\"updateBanner\">\n        <span class=\"update-icon\">🚀</span>\n        <span class=\"update-text\">发现新版本</span>\n        <span class=\"update-version\" id=\"updateBannerVersion\">v0.0</span>\n        <button class=\"update-close\" id=\"updateBannerClose\" title=\"关闭\">×</button>\n    </div>\n    \n    <!-- 管理员权限提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"adminModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">🔐</div>\n            <div class=\"modal-title\">需要管理员权限</div>\n            <div class=\"modal-message\">\n                请关闭 Cursor，右键点击图标<br>\n                选择 <span class=\"highlight\">以管理员身份运行</span>\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"adminModalClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 重置机器码权限提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"resetPermissionModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">🔐</div>\n            <div class=\"modal-title\">需要管理员权限</div>\n            <div class=\"modal-message\" style=\"text-align: left; line-height: 1.8;\">\n                重置机器码需要管理员权限才能完整执行。<br><br>\n                请按以下步骤操作：<br>\n                <span style=\"color: #fbbf24;\">1.</span> 完全关闭 Cursor<br>\n                <span style=\"color: #fbbf24;\">2.</span> 右键点击 Cursor 图标<br>\n                <span style=\"color: #fbbf24;\">3.</span> 选择 <span class=\"highlight\">以管理员身份运行</span><br>\n                <span style=\"color: #fbbf24;\">4.</span> 再次点击重置机器码\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"resetPermissionClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 重启提示弹窗 -->\n    <div class=\"modal-overlay\" id=\"restartModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon success\">✓</div>\n            <div class=\"modal-title\" id=\"restartModalTitle\">操作成功</div>\n            <div class=\"modal-message\">\n                需要重启 Cursor 才能生效\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"restartNowBtn\">立即重启</button>\n                <button class=\"modal-btn secondary\" id=\"restartLaterBtn\">稍后</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 激活码过期弹窗 -->\n    <div class=\"modal-overlay\" id=\"expiredModal\">\n        <div class=\"modal-content\">\n            <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>\n            <div class=\"modal-title\">激活码已过期</div>\n            <div class=\"modal-message\">\n                您的激活码已过期，请续费后继续使用\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn single\" id=\"expiredModalClose\">我知道了</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 清理环境确认弹窗 -->\n    <div class=\"modal-overlay\" id=\"cleanEnvModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">⚠️</div>\n            <div class=\"modal-title\">清理 Cursor 环境</div>\n            <div class=\"modal-message\">\n                此操作会删除所有配置和登录信息<br>确定要继续吗？\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"cleanEnvConfirmBtn\">确定清理</button>\n                <button class=\"modal-btn secondary\" id=\"cleanEnvCancelBtn\">取消</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 换号确认弹窗 -->\n    <div class=\"modal-overlay\" id=\"switchConfirmModal\">\n        <div class=\"modal-content\">\n            <div class=\"modal-icon warning\">💰</div>\n            <div class=\"modal-title\">账号未使用完</div>\n            <div class=\"modal-message\">\n                当前账号 <span id=\"switchConfirmEmail\" style=\"color:#4caf50;\"></span><br>\n                已用额度: <span id=\"switchConfirmCost\" style=\"color:#ff9800;font-weight:bold;\">$0.00</span> (不足 $10)<br><br>\n                确定要换号吗？\n            </div>\n            <div class=\"modal-buttons\">\n                <button class=\"modal-btn primary\" id=\"switchConfirmBtn\">确认换号</button>\n                <button class=\"modal-btn secondary\" id=\"switchCancelBtn\">取消</button>\n            </div>\n        </div>\n    </div>\n    \n    <!-- 离线状态提示 -->\n    <div class=\"offline-banner\" id=\"offlineBanner\">\n        <span class=\"offline-icon\">📡</span>\n        <div class=\"offline-text\">\n            <div class=\"offline-title\">网络连接失败</div>\n            <div class=\"offline-desc\">请检查网络后重试</div>\n        </div>\n        <button class=\"retry-btn\" id=\"retryConnectBtn\">重试</button>\n    </div>\n    \n    <!-- 软件授权 -->\n    <div class=\"section\">\n        <div class=\"section-title\">\n            <span class=\"icon\">🔐</span>\n            <span>软件授权</span>\n            <span class=\"status-badge\" id=\"authStatus\">未授权</span>\n        </div>\n        \n        <div class=\"input-group\">\n            <input type=\"text\" id=\"keyInput\" placeholder=\"请输入CDK激活码\">\n            <button class=\"btn btn-primary\" id=\"activateBtn\"><span class=\"btn-text\">激活</span></button>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">激活码</span>\n            <span class=\"info-value key-display\" id=\"keyDisplay\" title=\"点击复制\">尚未激活</span>\n        </div>\n        <div class=\"info-row\">\n            <span class=\"info-label\">到期时间</span>\n            <span class=\"info-value\" id=\"expireDate\">尚未激活</span>\n        </div>\n    </div>\n    \n    <!-- 账号数据 (已隐藏) -->\n    <div class=\"section\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\">👤</span>\n            <span>账号数据</span>\n            <span class=\"status-badge\" id=\"accountStatus\">未激活</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">CI积分余额</span>\n            <span class=\"info-value\">0 <button style=\"background:none;border:none;color:#007acc;cursor:pointer;\">🔄</button></span>\n        </div>\n        \n        <button class=\"btn btn-purple btn-block\" id=\"switchBtn\" disabled>换号</button>\n        <button class=\"btn btn-blue btn-block\" id=\"resetBtn\">重置机器码</button>\n        <button class=\"btn btn-blue btn-block\" id=\"disableUpdateBtn\">禁用自动更新</button>\n        <button class=\"btn btn-blue btn-block\" id=\"cleanEnvBtn\">清理Cursor环境</button>\n        <button class=\"btn btn-red btn-block\" id=\"disableBtn\">停用插件</button>\n    </div>\n    \n    <!-- 无感换号 -->\n    <div class=\"section\">\n        <div class=\"section-title\">\n            <span class=\"icon\">⚡</span>\n            <span>无感换号</span>\n            <span class=\"status-badge\" id=\"seamlessStatus\">未启用</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">积分</span>\n            <span class=\"info-value\" id=\"seamlessSwitchRemaining\">0</span>\n        </div>\n        \n        <div class=\"info-row\">\n            <span class=\"info-label\">当前账号</span>\n            <span class=\"info-value\" style=\"font-size:11px;\" id=\"seamlessCurrentAccount\">未分配</span>\n        </div>\n        \n        <div class=\"switch-container\" style=\"margin: 12px 0;\">\n            <span>免魔法模式</span>\n            <span class=\"pro-badge\">PRO</span>\n            <span style=\"margin-left: auto; color: #888; font-size: 11px;\"></span>\n            <label class=\"switch\">\n                <input type=\"checkbox\" id=\"seamlessProxySwitch\">\n                <span class=\"slider\"></span>\n            </label>\n        </div>\n        \n        <button class=\"btn btn-purple btn-block\" id=\"enableSeamlessBtn\" disabled><span class=\"btn-text\">启用无感换号</span></button>\n        <button class=\"btn btn-red btn-block\" id=\"seamlessResetMachineBtn\" style=\"display:none;\"><span class=\"btn-text\">重置机器码</span></button>\n        <button class=\"btn btn-red btn-block\" id=\"disableSeamlessBtn\" style=\"display:none;\"><span class=\"btn-text\">禁用无感换号</span></button>\n        <button class=\"btn btn-blue btn-block\" id=\"manualSwitchBtn\" style=\"display:none;\" disabled><span class=\"btn-text\">一键换号(扣1积分)</span></button>\n    </div>\n    \n    <!-- 账号用量 -->\n    <div class=\"section\" id=\"usageSection\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\">📊</span>\n            <span>账号用量</span>\n            <button class=\"btn\" style=\"margin-left:auto;padding:4px 8px;font-size:11px;background:#3c3c3c;\" id=\"refreshUsageBtn\">🔄</button>\n        </div>\n        \n        <div class=\"usage-row\">\n            <div class=\"usage-item\">\n                <span class=\"info-label\">会员类型</span>\n                <span class=\"info-value\" id=\"usageMemberType\">-</span>\n            </div>\n            <div class=\"usage-item\">\n                <span class=\"info-label\">试用剩余</span>\n                <span class=\"info-value\" id=\"usageTrialDays\">-</span>\n            </div>\n        </div>\n        <div class=\"usage-row\">\n            <div class=\"usage-item\">\n                <span class=\"info-label\">请求次数</span>\n                <span class=\"info-value\" id=\"usageRequestCount\">-</span>\n            </div>\n            <div class=\"usage-item\">\n                <span class=\"info-label\">已用额度</span>\n                <span class=\"info-value\" id=\"usageCostUSD\">-</span>\n            </div>\n        </div>\n        <p style=\"font-size:10px;color:#666;margin-top:8px;text-align:center;\" id=\"usageUpdateTime\">-</p>\n    </div>\n    \n    <!-- 公告 -->\n    <div class=\"section\" id=\"announcementSection\" style=\"display:none;\">\n        <div class=\"section-title\">\n            <span class=\"icon\" id=\"announcementIcon\">📢</span>\n            <span>公告</span>\n            <span class=\"announcement-badge\" id=\"announcementBadge\">info</span>\n        </div>\n        <div class=\"announcement-title\" id=\"announcementTitle\"></div>\n        <div class=\"announcement-content\" id=\"announcementContent\"></div>\n        <p style=\"font-size:10px;color:#666;margin-top:8px;text-align:right;\" id=\"announcementTime\"></p>\n    </div>\n    \n    <!-- 版本信息 -->\n    <div class=\"section\" id=\"versionSection\">\n        <div class=\"section-title\">\n            <span class=\"icon\">📦</span>\n            <span>版本信息</span>\n            <span class=\"status-badge\" id=\"versionStatus\" style=\"display:none;\">有更新</span>\n        </div>\n        <div class=\"info-row\">\n            <span class=\"info-label\">当前版本</span>\n            <span class=\"info-value\" id=\"currentVersion\">-</span>\n        </div>\n        <div class=\"info-row\" id=\"latestVersionRow\" style=\"display:none;\">\n            <span class=\"info-label\">最新版本</span>\n            <span class=\"info-value\" id=\"latestVersion\" style=\"color:#4caf50;\">-</span>\n        </div>\n        <p id=\"updateHint\" style=\"font-size:11px;color:#ff9800;margin-top:8px;display:none;\">\n            ⚠️ 发现新版本，请更新插件以获取最新功能\n        </p>\n    </div>\n    \n    <!-- 页脚 -->\n    <div class=\"footer\">\n        <div class=\"footer-row\">\n            <div class=\"auto-start\">\n                <span>自动启动</span>\n                <label class=\"switch switch-sm\">\n                    <input type=\"checkbox\" id=\"autoStartSwitch\" checked>\n                    <span class=\"slider\"></span>\n                </label>\n            </div>\n            <div class=\"cursor-version\">\n                <span>Cursor</span>\n                <span class=\"version-num\" id=\"cursorVersion\">0.0.0</span>\n            </div>\n        </div>\n        <div class=\"footer-row\" style=\"margin-top: 8px;\">\n            <div style=\"font-size: 10px; color: #666; word-break: break-all;\">\n                <span>路径: </span>\n                <span id=\"cursorPath\" style=\"color: #888;\">获取中...</span>\n            </div>\n        </div>\n    </div>\n    \n    <!-- Toast 通知 -->\n    <div class=\"toast-container\" id=\"toastContainer\">\n        <div class=\"toast\" id=\"toast\">\n            <span class=\"toast-icon\" id=\"toastIcon\">✅</span>\n            <span class=\"toast-message\" id=\"toastMessage\"></span>\n        </div>\n    </div>\n    \n    <script nonce=\"" + var794 + "\">\n        const vscode = acquireVsCodeApi();\n        \n        // 元素引用\n        const keyInput = document.getElementById('keyInput');\n        const activateBtn = document.getElementById('activateBtn');\n        const switchBtn = document.getElementById('switchBtn');\n        const resetBtn = document.getElementById('resetBtn');\n        const disableUpdateBtn = document.getElementById('disableUpdateBtn');\n        const cleanEnvBtn = document.getElementById('cleanEnvBtn');\n        const disableBtn = document.getElementById('disableBtn');\n        const authStatus = document.getElementById('authStatus');\n        const accountStatus = document.getElementById('accountStatus');\n        const keyDisplay = document.getElementById('keyDisplay');\n        const switchCount = document.getElementById('switchCount');\n        const expireDate = document.getElementById('expireDate');\n        const cursorVersion = document.getElementById('cursorVersion');\n        const cursorPath = document.getElementById('cursorPath');\n        \n        // 离线状态元素\n        const offlineBanner = document.getElementById('offlineBanner');\n        const retryConnectBtn = document.getElementById('retryConnectBtn');\n        \n        // 无感换号元素\n        const seamlessStatus = document.getElementById('seamlessStatus');\n        const seamlessProxySwitch = document.getElementById('seamlessProxySwitch');\n        const enableSeamlessBtn = document.getElementById('enableSeamlessBtn');\n        const disableSeamlessBtn = document.getElementById('disableSeamlessBtn');\n        const manualSwitchBtn = document.getElementById('manualSwitchBtn');\n        const seamlessResetMachineBtn = document.getElementById('seamlessResetMachineBtn');\n        const seamlessSwitchRemaining = document.getElementById('seamlessSwitchRemaining');\n        const seamlessCurrentAccount = document.getElementById('seamlessCurrentAccount');\n        \n        // 用量显示元素\n        const usageSection = document.getElementById('usageSection');\n        const refreshUsageBtn = document.getElementById('refreshUsageBtn');\n        const usageMemberType = document.getElementById('usageMemberType');\n        const usageTrialDays = document.getElementById('usageTrialDays');\n        const usageRequestCount = document.getElementById('usageRequestCount');\n        const usageCostUSD = document.getElementById('usageCostUSD');\n        const usageUpdateTime = document.getElementById('usageUpdateTime');\n        \n        // 公告元素\n        const announcementSection = document.getElementById('announcementSection');\n        const announcementIcon = document.getElementById('announcementIcon');\n        const announcementBadge = document.getElementById('announcementBadge');\n        const announcementTitle = document.getElementById('announcementTitle');\n        const announcementContent = document.getElementById('announcementContent');\n        const announcementTime = document.getElementById('announcementTime');\n        \n        // 版本元素\n        const versionSection = document.getElementById('versionSection');\n        const versionStatus = document.getElementById('versionStatus');\n        const currentVersionEl = document.getElementById('currentVersion');\n        const latestVersionEl = document.getElementById('latestVersion');\n        const latestVersionRow = document.getElementById('latestVersionRow');\n        const updateHint = document.getElementById('updateHint');\n        \n        // 顶部更新提醒条\n        const updateBanner = document.getElementById('updateBanner');\n        const updateBannerVersion = document.getElementById('updateBannerVersion');\n        const updateBannerClose = document.getElementById('updateBannerClose');\n        \n        // Toast 元素\n        const toast = document.getElementById('toast');\n        const toastIcon = document.getElementById('toastIcon');\n        const toastMessage = document.getElementById('toastMessage');\n        let toastTimer = null;\n        \n        // 显示 Toast 通知\n        function showToast(message, icon = '✅', duration = 10000) {\n            // 清除之前的定时器\n            if (toastTimer) {\n                clearTimeout(toastTimer);\n            }\n            \n            toastIcon.textContent = icon;\n            toastMessage.textContent = message;\n            toast.classList.add('show');\n            \n            // 设置自动隐藏\n            toastTimer = setTimeout(() => {\n                toast.classList.remove('show');\n            }, duration);\n        }\n        \n        // 禁用换号按钮并显示倒计时\n        let switchBtnCountdownTimer = null;\n        const originalSwitchBtnText = '一键换号(扣1积分)';\n        \n        function disableSwitchBtnWithCountdown(seconds) {\n            // 清除之前的定时器\n            if (switchBtnCountdownTimer) {\n                clearInterval(switchBtnCountdownTimer);\n            }\n            \n            let remaining = seconds;\n            manualSwitchBtn.disabled = true;\n            manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';\n            \n            switchBtnCountdownTimer = setInterval(() => {\n                remaining--;\n                if (remaining <= 0) {\n                    clearInterval(switchBtnCountdownTimer);\n                    switchBtnCountdownTimer = null;\n                    manualSwitchBtn.disabled = false;\n                    manualSwitchBtn.querySelector('.btn-text').textContent = originalSwitchBtnText;\n                } else {\n                    manualSwitchBtn.querySelector('.btn-text').textContent = remaining + '秒后可用';\n                }\n            }, 1000);\n        }\n        \n        // 弹窗元素\n        const adminModal = document.getElementById('adminModal');\n        const adminModalClose = document.getElementById('adminModalClose');\n        const resetPermissionModal = document.getElementById('resetPermissionModal');\n        const resetPermissionClose = document.getElementById('resetPermissionClose');\n        const restartModal = document.getElementById('restartModal');\n        const restartModalTitle = document.getElementById('restartModalTitle');\n        const restartNowBtn = document.getElementById('restartNowBtn');\n        const restartLaterBtn = document.getElementById('restartLaterBtn');\n        const expiredModal = document.getElementById('expiredModal');\n        const expiredModalClose = document.getElementById('expiredModalClose');\n        const cleanEnvModal = document.getElementById('cleanEnvModal');\n        const cleanEnvConfirmBtn = document.getElementById('cleanEnvConfirmBtn');\n        const cleanEnvCancelBtn = document.getElementById('cleanEnvCancelBtn');\n        \n        // 换号确认弹窗元素\n        const switchConfirmModal = document.getElementById('switchConfirmModal');\n        const switchConfirmEmail = document.getElementById('switchConfirmEmail');\n        const switchConfirmCost = document.getElementById('switchConfirmCost');\n        const switchConfirmBtn = document.getElementById('switchConfirmBtn');\n        const switchCancelBtn = document.getElementById('switchCancelBtn');\n        \n        // 显示管理员权限弹窗\n        function showAdminModal() {\n            adminModal.classList.add('show');\n        }\n        \n        // 显示重置机器码权限提示弹窗\n        function showAdminPermissionModal() {\n            resetPermissionModal.classList.add('show');\n        }\n        \n        // 重置机器码权限弹窗 - 关闭按钮\n        resetPermissionClose.addEventListener('click', () => {\n            resetPermissionModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭权限提示弹窗\n        resetPermissionModal.addEventListener('click', (e) => {\n            if (e.target === resetPermissionModal) {\n                resetPermissionModal.classList.remove('show');\n            }\n        });\n        \n        // 显示重启提示弹窗\n        let restartModalAction = 'reload'; // 'reload' 或 'close'\n        \n        function showRestartModal(title, action = 'reload') {\n            restartModalTitle.textContent = title || '操作成功';\n            restartModalAction = action;\n            // 根据操作类型更新按钮文字\n            restartNowBtn.textContent = action === 'close' ? '立即关闭 Cursor' : '立即重启';\n            restartModal.classList.add('show');\n        }\n        \n        // 显示过期弹窗\n        function showExpiredModal() {\n            expiredModal.classList.add('show');\n        }\n        \n        // 关闭管理员弹窗\n        adminModalClose.addEventListener('click', () => {\n            adminModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭管理员弹窗\n        adminModal.addEventListener('click', (e) => {\n            if (e.target === adminModal) {\n                adminModal.classList.remove('show');\n            }\n        });\n        \n        // 立即重启/关闭按钮\n        restartNowBtn.addEventListener('click', () => {\n            restartModal.classList.remove('show');\n            if (restartModalAction === 'close') {\n                // 完全关闭 Cursor\n                vscode.postMessage({ type: 'closeCursor' });\n            } else {\n                // 重新加载窗口\n            vscode.postMessage({ type: 'reloadWindow' });\n            }\n        });\n        \n        // 稍后手动按钮\n        restartLaterBtn.addEventListener('click', () => {\n            restartModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭重启弹窗\n        restartModal.addEventListener('click', (e) => {\n            if (e.target === restartModal) {\n                restartModal.classList.remove('show');\n            }\n        });\n        \n        // 关闭过期弹窗\n        expiredModalClose.addEventListener('click', () => {\n            expiredModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭过期弹窗\n        expiredModal.addEventListener('click', (e) => {\n            if (e.target === expiredModal) {\n                expiredModal.classList.remove('show');\n            }\n        });\n        \n        // 当前账号邮箱（用于查询用量）\n        let currentAccountEmail = '';\n        let usageRefreshInterval = null;\n        // 存储完整激活码（用于复制）\n        let fullActivationKey = '';\n        // 当前剩余换号次数\n        let currentSwitchRemaining = 0;\n        // 当前到期时间\n        let currentExpireDate = '';\n        \n        // 检查卡密是否已过期\n        function isKeyExpired() {\n            if (!currentExpireDate) return true;\n            try {\n                const expireTime = new Date(currentExpireDate).getTime();\n                return Date.now() > expireTime;\n            } catch {\n                return true;\n            }\n        }\n        \n        // 格式化到期时间为北京时间\n        function formatExpireDate(dateStr) {\n            if (!dateStr) return '';\n            try {\n                // 后端返回的时间没有时区标识，假设是 UTC 时间\n                // 将空格替换为T，并添加Z表示UTC\n                let utcStr = dateStr;\n                if (!dateStr.includes('T') && !dateStr.includes('Z') && !dateStr.includes('+')) {\n                    utcStr = dateStr.replace(' ', 'T') + 'Z';\n                }\n                const date = new Date(utcStr);\n                \n                // 使用中国时区格式化（UTC+8）\n                return date.toLocaleString('zh-CN', {\n                    timeZone: 'Asia/Shanghai',\n                    year: 'numeric',\n                    month: '2-digit',\n                    day: '2-digit',\n                    hour: '2-digit',\n                    minute: '2-digit',\n                    second: '2-digit',\n                    hour12: false\n                });\n            } catch {\n                return dateStr;  // 格式化失败返回原始值\n            }\n        }\n        \n        // 隐藏激活码后几位\n        function maskKey(key) {\n            if (!key || key.length <= 8) return key;\n            return key.substring(0, key.length - 4) + '****';\n        }\n        \n        // 点击激活码复制\n        keyDisplay.addEventListener('click', () => {\n            if (!fullActivationKey) return;\n            navigator.clipboard.writeText(fullActivationKey).then(() => {\n                keyDisplay.classList.add('copied');\n                const originalText = keyDisplay.textContent;\n                keyDisplay.textContent = '已复制!';\n                setTimeout(() => {\n                    keyDisplay.textContent = maskKey(fullActivationKey);\n                    keyDisplay.classList.remove('copied');\n                }, 1000);\n            }).catch(() => {\n                // 降级方案\n                const textarea = document.createElement('textarea');\n                textarea.value = fullActivationKey;\n                document.body.appendChild(textarea);\n                textarea.select();\n                document.execCommand('copy');\n                document.body.removeChild(textarea);\n                keyDisplay.classList.add('copied');\n                keyDisplay.textContent = '已复制!';\n                setTimeout(() => {\n                    keyDisplay.textContent = maskKey(fullActivationKey);\n                    keyDisplay.classList.remove('copied');\n                }, 1000);\n            });\n        });\n        \n        // Loading 状态控制\n        function setButtonLoading(btn, loading) {\n            if (loading) {\n                btn.classList.add('loading');\n                btn.disabled = true;\n            } else {\n                btn.classList.remove('loading');\n                // 注意：某些按钮可能需要保持禁用状态，由调用方控制\n            }\n        }\n        \n        function setRefreshLoading(btn, loading) {\n            if (loading) {\n                btn.classList.add('loading');\n            } else {\n                btn.classList.remove('loading');\n            }\n        }\n        \n        // 获取初始状态\n        vscode.postMessage({ type: 'getState' });\n        vscode.postMessage({ type: 'getSeamlessStatus' });\n        vscode.postMessage({ type: 'getUserSwitchStatus' });\n        vscode.postMessage({ type: 'getProxyStatus' });\n        vscode.postMessage({ type: 'getAnnouncement' });\n        vscode.postMessage({ type: 'checkVersion' });\n        vscode.postMessage({ type: 'getCursorRunningPath' });\n        \n        // 激活按钮\n        activateBtn.addEventListener('click', () => {\n            const key = keyInput.value.trim();\n            if (!key) {\n                return;\n            }\n            setButtonLoading(activateBtn, true);\n            vscode.postMessage({ type: 'activate', key });\n        });\n        \n        // 换号按钮\n        switchBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'switch' });\n        });\n        \n        // 重置机器码按钮\n        resetBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'resetMachineId' });\n        });\n        \n        // 禁用自动更新按钮\n        disableUpdateBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'disableUpdate' });\n        });\n        \n        // 清理Cursor环境按钮 - 显示确认弹窗\n        cleanEnvBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.add('show');\n        });\n        \n        // 确认清理\n        cleanEnvConfirmBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.remove('show');\n            vscode.postMessage({ type: 'cleanEnv' });\n        });\n        \n        // 取消清理\n        cleanEnvCancelBtn.addEventListener('click', () => {\n            cleanEnvModal.classList.remove('show');\n        });\n        \n        // 点击遮罩关闭清理弹窗\n        cleanEnvModal.addEventListener('click', (e) => {\n            if (e.target === cleanEnvModal) {\n                cleanEnvModal.classList.remove('show');\n            }\n        });\n        \n        // 停用按钮\n        disableBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'disable' });\n        });\n        \n        // 关闭更新提醒条\n        updateBannerClose.addEventListener('click', () => {\n            updateBanner.classList.remove('show');\n        });\n        \n        // 免魔法开关\n        seamlessProxySwitch.addEventListener('change', (e) => {\n            const wantEnabled = e.target.checked;\n            \n            // 如果要开启免魔法，检查卡密是否过期（只要没过期就可以用，不管换号次数）\n            if (wantEnabled && isKeyExpired()) {\n                e.target.checked = false;\n                showToast('授权码已过期，无法开启免魔法', '⚠️', 3000);\n                return;\n            }\n            \n            vscode.postMessage({ \n                type: 'toggleProxy', \n                enabled: wantEnabled,\n                url: ''\n            });\n        });\n        \n        // 无感换号 - 启用按钮\n        enableSeamlessBtn.addEventListener('click', () => {\n            setButtonLoading(enableSeamlessBtn, true);\n            vscode.postMessage({ type: 'injectSeamless' });\n        });\n        \n        // 无感换号 - 禁用按钮\n        disableSeamlessBtn.addEventListener('click', () => {\n            setButtonLoading(disableSeamlessBtn, true);\n            vscode.postMessage({ type: 'restoreSeamless' });\n        });\n        \n        // 无感换号 - 手动换号按钮（先检查用量）\n        manualSwitchBtn.addEventListener('click', () => {\n            setButtonLoading(manualSwitchBtn, true);\n            // 传递当前显示的账号邮箱\n            vscode.postMessage({ type: 'checkUsageBeforeSwitch', email: currentAccountEmail });\n        });\n        \n        // 换号确认弹窗 - 确认按钮\n        switchConfirmBtn.addEventListener('click', () => {\n            switchConfirmModal.classList.remove('show');\n            setButtonLoading(manualSwitchBtn, true);\n            vscode.postMessage({ type: 'confirmSwitch' });\n        });\n        \n        // 换号确认弹窗 - 取消按钮\n        switchCancelBtn.addEventListener('click', () => {\n            switchConfirmModal.classList.remove('show');\n            setButtonLoading(manualSwitchBtn, false);\n            manualSwitchBtn.disabled = false;\n        });\n        \n        // 换号确认弹窗 - 点击遮罩关闭\n        switchConfirmModal.addEventListener('click', (e) => {\n            if (e.target === switchConfirmModal) {\n                switchConfirmModal.classList.remove('show');\n                setButtonLoading(manualSwitchBtn, false);\n                manualSwitchBtn.disabled = false;\n            }\n        });\n        \n        // 无感换号区域 - 重置机器码按钮\n        seamlessResetMachineBtn.addEventListener('click', () => {\n            vscode.postMessage({ type: 'resetMachineId' });\n        });\n        \n        // 刷新用量按钮\n        refreshUsageBtn.addEventListener('click', () => {\n            if (currentAccountEmail) {\n                setRefreshLoading(refreshUsageBtn, true);\n                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });\n            }\n        });\n        \n        // 刷新用量函数\n        function refreshUsage() {\n            if (currentAccountEmail) {\n                vscode.postMessage({ type: 'getAccountUsage', email: currentAccountEmail });\n            }\n        }\n        \n        // 启动用量定时刷新 (每分钟一次)\n        function startUsageRefresh() {\n            if (usageRefreshInterval) {\n                clearInterval(usageRefreshInterval);\n            }\n            // 立即刷新一次\n            refreshUsage();\n            // 每60秒刷新一次\n            usageRefreshInterval = setInterval(refreshUsage, 60000);\n        }\n        \n        // 停止用量刷新\n        function stopUsageRefresh() {\n            if (usageRefreshInterval) {\n                clearInterval(usageRefreshInterval);\n                usageRefreshInterval = null;\n            }\n        }\n        \n        // 更新用量显示\n        function updateUsageDisplay(data) {\n            if (!data) return;\n            \n            const subscription = data.subscription || {};\n            const usage = data.usage || {};\n            \n            // 会员类型\n            const memberTypeMap = {\n                'free_trial': '免费试用',\n                'pro': 'Pro会员',\n                'free': '免费版',\n                'business': '商业版'\n            };\n            usageMemberType.textContent = memberTypeMap[subscription.membershipType] || subscription.membershipType || '-';\n            \n            // 试用剩余天数\n            if (subscription.daysRemainingOnTrial !== undefined && subscription.daysRemainingOnTrial !== null) {\n                usageTrialDays.textContent = subscription.daysRemainingOnTrial + ' 天';\n                usageTrialDays.style.color = subscription.daysRemainingOnTrial <= 3 ? '#f87171' : '#4ade80';\n            } else {\n                usageTrialDays.textContent = '-';\n                usageTrialDays.style.color = '#fff';\n            }\n            \n            // 请求次数\n            usageRequestCount.textContent = (usage.totalUsageCount || 0) + ' 次';\n            \n            // 已用额度\n            const costUSD = usage.totalCostUSD || 0;\n            usageCostUSD.textContent = '$' + costUSD.toFixed(2);\n            usageCostUSD.style.color = costUSD > 5 ? '#f87171' : (costUSD > 2 ? '#fbbf24' : '#4ade80');\n            \n            // 更新时间\n            usageUpdateTime.textContent = '更新于 ' + new Date().toLocaleTimeString();\n        }\n        \n        // 解析公告内容中的链接 {文字URL}\n        function parseAnnouncementContent(content) {\n            if (!content) return '';\n            \n            // 转义 HTML 特殊字符\n            let escaped = content\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;')\n                .replace(/\"/g, '&quot;');\n            \n            // 匹配 {文字https://...} 或 {文字http://...} 格式\n            const linkRegex = /\\{([^}]+?)(https?:\\/\\/[^}]+)\\}/g;\n            \n            escaped = escaped.replace(linkRegex, function(match, text, url) {\n                return '<a href=\"' + url + '\" class=\"announcement-link\" target=\"_blank\">' + text + '</a>';\n            });\n            \n            // 将换行符转换为 <br>\n            escaped = escaped.replace(/\\n/g, '<br>');\n            \n            return escaped;\n        }\n        \n        // 更新公告显示\n        function updateAnnouncementDisplay(data) {\n            if (!data || !data.is_active) {\n                announcementSection.style.display = 'none';\n                return;\n            }\n            \n            // 显示公告区域\n            announcementSection.style.display = 'block';\n            \n            // 设置图标和类型徽章\n            const typeConfig = {\n                'info': { icon: '📢', text: '通知', class: 'info' },\n                'warning': { icon: '⚠️', text: '警告', class: 'warning' },\n                'error': { icon: '🚨', text: '重要', class: 'error' },\n                'success': { icon: '✅', text: '好消息', class: 'success' }\n            };\n            \n            const config = typeConfig[data.type] || typeConfig.info;\n            announcementIcon.textContent = config.icon;\n            announcementBadge.textContent = config.text;\n            announcementBadge.className = 'announcement-badge ' + config.class;\n            \n            // 设置标题和内容（解析链接）\n            announcementTitle.textContent = data.title || '';\n            announcementContent.innerHTML = parseAnnouncementContent(data.content || '');\n            \n            // 设置时间\n            if (data.created_at) {\n                const date = new Date(data.created_at);\n                announcementTime.textContent = date.toLocaleDateString('zh-CN', {\n                    year: 'numeric',\n                    month: '2-digit',\n                    day: '2-digit',\n                    hour: '2-digit',\n                    minute: '2-digit'\n                });\n            } else {\n                announcementTime.textContent = '';\n            }\n        }\n        \n        // 处理来自扩展的消息\n        window.addEventListener('message', event => {\n            const message = event.data;\n            \n            switch (message.type) {\n                case 'state':\n                    updateUI(message);\n                    break;\n                case 'activated':\n                    setButtonLoading(activateBtn, false);\n                    activateBtn.disabled = false;\n                    if (message.success) {\n                        // 调试日志\n                        console.log('[CursorPro] 前端收到激活成功消息:', message);\n                        \n                        authStatus.textContent = '已授权';\n                        authStatus.className = 'status-badge active';\n                        accountStatus.textContent = '已激活';\n                        accountStatus.className = 'status-badge active';\n                        switchBtn.disabled = false;\n                        // 更新激活码显示（使用后端返回的 key）\n                        fullActivationKey = message.key || keyInput.value;\n                        keyDisplay.textContent = maskKey(fullActivationKey);\n                        // 更新到期时间\n                        console.log('[CursorPro] 更新到期时间:', message.expireDate);\n                        currentExpireDate = message.expireDate || '';\n                        expireDate.textContent = formatExpireDate(currentExpireDate) || '未知';\n                        // 更新换号次数\n                        if (message.switchRemaining !== undefined) {\n                            currentSwitchRemaining = message.switchRemaining;\n                            switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                        }\n                        // 清空输入框\n                        keyInput.value = '';\n                        showToast('授权码激活成功！', '✅', 10000);\n                    } else {\n                        showToast(message.error || '激活失败', '❌', 10000);\n                    }\n                    break;\n                case 'switched':\n                    if (message.success) {\n                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                        showToast('换号成功: ' + (message.email || ''), '✅', 10000);\n                    } else {\n                        showToast(message.error || '换号失败', '❌', 10000);\n                    }\n                    break;\n                case 'reset':\n                    authStatus.textContent = '未授权';\n                    authStatus.className = 'status-badge inactive';\n                    accountStatus.textContent = '未激活';\n                    accountStatus.className = 'status-badge inactive';\n                    switchBtn.disabled = true;\n                    keyInput.value = '';\n                    fullActivationKey = '';\n                    keyDisplay.textContent = '尚未激活';\n                    expireDate.textContent = '尚未激活';\n                    break;\n                \n                // 激活码状态检查结果\n                case 'keyStatusChecked':\n                    if (message.valid) {\n                        // 激活码有效，更新显示\n                        currentExpireDate = message.expireDate || '';\n                        currentSwitchRemaining = message.switchRemaining || 0;\n                        expireDate.textContent = formatExpireDate(currentExpireDate);\n                        switchCount.textContent = message.switchRemaining + '/' + (message.switchLimit || 100);\n                    } else if (message.expired) {\n                        // 激活码已过期，显示提示并重置状态\n                        currentExpireDate = '';\n                        currentSwitchRemaining = 0;\n                        authStatus.textContent = '已过期';\n                        authStatus.className = 'status-badge inactive';\n                        authStatus.style.background = '#6e3232';\n                        authStatus.style.color = '#ff6b6b';\n                        expireDate.textContent = '已过期';\n                        expireDate.style.color = '#f87171';\n                        switchBtn.disabled = true;\n                        enableSeamlessBtn.disabled = true;\n                        // 如果免魔法已开启，自动关闭\n                        if (seamlessProxySwitch.checked) {\n                            seamlessProxySwitch.checked = false;\n                            vscode.postMessage({ type: 'toggleProxy', enabled: false, url: '' });\n                        }\n                        // 显示过期弹窗\n                        showExpiredModal();\n                    }\n                    break;\n                \n                // 用户换号状态\n                case 'userSwitchStatus':\n                    const remaining = message.switchRemaining || 0;\n                    const canSwitch = remaining > 0;\n                    \n                    // 更新全局变量\n                    currentSwitchRemaining = remaining;\n                    \n                    seamlessSwitchRemaining.textContent = remaining.toString();\n                    seamlessSwitchRemaining.style.color = canSwitch ? '#4ade80' : '#f87171';\n                    \n                    if (message.lockedAccount) {\n                        seamlessCurrentAccount.textContent = message.lockedAccount.email;\n                        \n                        // 设置当前账号邮箱并启动用量刷新\n                        if (message.lockedAccount.email && message.lockedAccount.email !== currentAccountEmail) {\n                            currentAccountEmail = message.lockedAccount.email;\n                            usageSection.style.display = 'block';\n                            startUsageRefresh();\n                        }\n                    } else {\n                        seamlessCurrentAccount.textContent = '未分配';\n                        \n                        // 没有锁定账号时隐藏用量区域\n                        currentAccountEmail = '';\n                        usageSection.style.display = 'none';\n                        stopUsageRefresh();\n                    }\n                    \n                    // 根据剩余次数控制手动换号按钮状态\n                    if (!canSwitch) {\n                        manualSwitchBtn.disabled = true;\n                    }\n                    // 启用无感换号按钮不受积分限制，只有过期才禁用\n                    enableSeamlessBtn.disabled = isKeyExpired();\n                    \n                    // 如果无感换号已启用，显示手动换号按钮和重置机器码按钮\n                    if (message.seamlessEnabled && canSwitch) {\n                        manualSwitchBtn.style.display = 'block';\n                        manualSwitchBtn.disabled = false;\n                        setButtonLoading(manualSwitchBtn, false);\n                        seamlessResetMachineBtn.style.display = 'block';\n                    }\n                    break;\n                \n                // 账号用量\n                case 'accountUsage':\n                    setRefreshLoading(refreshUsageBtn, false);\n                    if (message.success && message.data) {\n                        updateUsageDisplay(message.data);\n                    } else {\n                        usageUpdateTime.textContent = '获取失败: ' + (message.error || '未知错误');\n                        usageUpdateTime.style.color = '#f87171';\n                    }\n                    break;\n                \n                // 无感换号状态\n                case 'seamlessStatus':\n                    if (message.is_injected) {\n                        seamlessStatus.textContent = '已启用';\n                        seamlessStatus.className = 'status-badge active';\n                        enableSeamlessBtn.style.display = 'none';\n                        disableSeamlessBtn.style.display = 'block';\n                        disableSeamlessBtn.disabled = false;\n                        setButtonLoading(disableSeamlessBtn, false);\n                        manualSwitchBtn.style.display = 'block';\n                        manualSwitchBtn.disabled = false;\n                        setButtonLoading(manualSwitchBtn, false);\n                        seamlessResetMachineBtn.style.display = 'block';\n                    } else {\n                        seamlessStatus.textContent = '未启用';\n                        seamlessStatus.className = 'status-badge inactive';\n                        enableSeamlessBtn.style.display = 'block';\n                        setButtonLoading(enableSeamlessBtn, false);\n                        // 启用按钮不受积分限制，只有过期才禁用\n                        enableSeamlessBtn.disabled = isKeyExpired();\n                        disableSeamlessBtn.style.display = 'none';\n                        manualSwitchBtn.style.display = 'none';\n                        seamlessResetMachineBtn.style.display = 'none';\n                    }\n                    break;\n                \n                case 'seamlessInjected':\n                    setButtonLoading(enableSeamlessBtn, false);\n                    enableSeamlessBtn.disabled = false;\n                    if (message.success) {\n                        seamlessStatus.textContent = '已启用';\n                        seamlessStatus.className = 'status-badge active';\n                        enableSeamlessBtn.style.display = 'none';\n                        disableSeamlessBtn.style.display = 'block';\n                        manualSwitchBtn.style.display = 'block';\n                        seamlessResetMachineBtn.style.display = 'block';\n                        // 刷新用户状态\n                        vscode.postMessage({ type: 'getUserSwitchStatus' });\n                        // 显示重启提示弹窗\n                        if (message.needRestart) {\n                            showRestartModal(message.message || '无感换号已启用');\n                        }\n                    } else {\n                        // 如果是权限错误，显示自定义弹窗\n                        if (message.needAdmin) {\n                            // Mac/Linux 权限问题，显示详细提示\n                            var errorMsg = message.error || '没有写入权限';\n                            if (message.path) {\n                                errorMsg += '\\n路径: ' + message.path;\n                            }\n                            showToast(errorMsg, '🔐', 15000);\n                        } else {\n                            // 显示详细错误\n                            var detailMsg = message.error || '启用失败';\n                            if (message.details) {\n                                detailMsg += '\\n' + message.details;\n                            }\n                            showToast(detailMsg, '❌', 15000);\n                        }\n                    }\n                    break;\n                \n                case 'seamlessRestored':\n                    setButtonLoading(disableSeamlessBtn, false);\n                    disableSeamlessBtn.disabled = false;\n                    if (message.success) {\n                        seamlessStatus.textContent = '未启用';\n                        seamlessStatus.className = 'status-badge inactive';\n                        enableSeamlessBtn.style.display = 'block';\n                        disableSeamlessBtn.style.display = 'none';\n                        manualSwitchBtn.style.display = 'none';\n                        seamlessResetMachineBtn.style.display = 'none';\n                        // 显示重启提示弹窗\n                        if (message.needRestart) {\n                            showRestartModal(message.message || '无感换号已禁用');\n                        }\n                    } else {\n                        // 如果是权限错误，显示自定义弹窗\n                        if (message.needAdmin) {\n                            showAdminModal();\n                        } else {\n                            showToast(message.error || '禁用失败', '❌', 10000);\n                        }\n                    }\n                    break;\n                \n                // 用量检查结果\n                case 'usageCheckResult':\n                    if (message.success) {\n                        if (message.needConfirm) {\n                            // 需要确认，显示弹窗（按钮保持可用状态，等用户选择）\n                            setButtonLoading(manualSwitchBtn, false);\n                            manualSwitchBtn.disabled = false;\n                            switchConfirmEmail.textContent = message.email || '';\n                            switchConfirmCost.textContent = '$' + (message.costUSD || '0.00');\n                            switchConfirmModal.classList.add('show');\n                        } else {\n                            // 不需要确认，直接换号\n                            vscode.postMessage({ type: 'confirmSwitch' });\n                        }\n                    } else {\n                        setButtonLoading(manualSwitchBtn, false);\n                        manualSwitchBtn.disabled = false;\n                        showToast(message.error || '检查失败', '❌', 5000);\n                    }\n                    break;\n                \n                case 'manualSeamlessSwitched':\n                    setButtonLoading(manualSwitchBtn, false);\n                    if (message.success) {\n                        seamlessSwitchRemaining.textContent = (message.switchRemaining || 0).toString();\n                        seamlessCurrentAccount.textContent = message.email || '未知';\n                        // 显示 Toast 通知，10秒后消失\n                        showToast('已切换到: ' + (message.email || '新账号') + '，约10秒内自动生效', '✅', 10000);\n                        // 刷新状态\n                        vscode.postMessage({ type: 'getUserSwitchStatus' });\n                        // 禁用按钮10秒，显示倒计时\n                        disableSwitchBtnWithCountdown(10);\n                    } else {\n                        manualSwitchBtn.disabled = false;\n                        showToast(message.error || '换号失败', '❌', 5000);\n                    }\n                    break;\n                \n                case 'proxyStatus':\n                    // 设置免魔法开关状态\n                    seamlessProxySwitch.checked = message.enabled;\n                    break;\n                \n                // 公告\n                case 'announcement':\n                    if (message.success && message.data) {\n                        updateAnnouncementDisplay(message.data);\n                    } else {\n                        announcementSection.style.display = 'none';\n                    }\n                    break;\n                \n                // 版本检查\n                case 'versionCheck':\n                    currentVersionEl.textContent = message.currentVersion || '-';\n                    if (message.success && message.hasUpdate) {\n                        // 有更新\n                        latestVersionEl.textContent = message.latestVersion;\n                        latestVersionRow.style.display = 'flex';\n                        versionStatus.style.display = 'inline-block';\n                        versionStatus.style.background = '#ff9800';\n                        updateHint.style.display = 'block';\n                        \n                        // 显示顶部更新提醒条\n                        updateBannerVersion.textContent = 'v' + message.latestVersion;\n                        updateBanner.classList.add('show');\n                    } else if (message.success) {\n                        // 已是最新版\n                        versionStatus.textContent = '最新';\n                        versionStatus.style.display = 'inline-block';\n                        versionStatus.style.background = '#4caf50';\n                        latestVersionRow.style.display = 'none';\n                        updateHint.style.display = 'none';\n                        updateBanner.classList.remove('show');\n                    }\n                    break;\n                \n                // Cursor 运行路径\n                case 'cursorRunningPath':\n                    if (message.path) {\n                        const pathText = message.path + (message.packageExists ? ' ✓' : ' ✗');\n                        cursorPath.textContent = pathText;\n                        cursorPath.style.color = message.packageExists ? '#4ade80' : '#f87171';\n                        // 同时更新版本号\n                        if (message.cursorVersion) {\n                            cursorVersion.textContent = message.cursorVersion;\n                        }\n                    } else {\n                        cursorPath.textContent = '未找到';\n                        cursorPath.style.color = '#f87171';\n                    }\n                    break;\n                \n                // 管理员权限不足提示\n                case 'adminPermissionRequired':\n                    showAdminPermissionModal();\n                    break;\n                \n                // 机器码重置\n                case 'machineIdReset':\n                    if (message.success && message.needRestart) {\n                        // 机器码重置需要完全关闭 Cursor，不是 reload\n                        showRestartModal(message.message || '机器码重置成功', 'close');\n                    }\n                    break;\n                \n                // 通用 Toast 消息\n                case 'showToast':\n                    showToast(message.message || '', message.icon || '📢', 10000);\n                    break;\n                \n                // 网络状态\n                case 'networkStatus':\n                    updateOfflineStatus(!message.online);\n                    break;\n            }\n        });\n        \n        // 离线状态显示/隐藏\n        let wasOffline = false; // 跟踪之前是否离线\n        function updateOfflineStatus(isOffline) {\n            if (isOffline) {\n                offlineBanner.classList.add('show');\n                wasOffline = true;\n            } else {\n                offlineBanner.classList.remove('show');\n                // 只有从离线恢复到在线时才刷新状态\n                if (wasOffline) {\n                    wasOffline = false;\n                    vscode.postMessage({ type: 'getState' });\n                    vscode.postMessage({ type: 'getUserSwitchStatus' });\n                }\n            }\n        }\n        \n        // 重试连接按钮\n        retryConnectBtn.addEventListener('click', async () => {\n            retryConnectBtn.classList.add('loading');\n            retryConnectBtn.textContent = '连接中...';\n            \n            // 发起真正的网络请求来测试网络\n            vscode.postMessage({ type: 'retryConnect' });\n            \n            // 5秒后恢复按钮状态（给网络请求足够时间）\n            setTimeout(() => {\n                retryConnectBtn.classList.remove('loading');\n                retryConnectBtn.textContent = '重试';\n            }, 5000);\n        });\n        \n        function updateUI(state) {\n            if (state.isActivated) {\n                authStatus.textContent = '已授权';\n                authStatus.className = 'status-badge active';\n                accountStatus.textContent = '已激活';\n                accountStatus.className = 'status-badge active';\n                switchBtn.disabled = false;\n                fullActivationKey = state.key;\n                keyDisplay.textContent = maskKey(fullActivationKey);\n                // 更新到期时间\n                currentExpireDate = state.expireDate || '';\n                expireDate.textContent = formatExpireDate(currentExpireDate);\n                // 更新换号次数\n                if (state.switchRemaining !== undefined) {\n                    currentSwitchRemaining = state.switchRemaining;\n                    switchCount.textContent = state.switchRemaining + '/' + (state.switchLimit || 100);\n                }\n                // 启用无感换号按钮（只有过期才禁用）\n                enableSeamlessBtn.disabled = isKeyExpired();\n            }\n            cursorVersion.textContent = state.cursorVersion || '0.0.0';\n            \n            // 根据网络状态显示/隐藏离线提示\n            if (state.isOnline === false) {\n                offlineBanner.classList.add('show');\n                wasOffline = true;\n            } else if (state.isOnline === true) {\n                // 网络恢复，隐藏离线提示\n                offlineBanner.classList.remove('show');\n                wasOffline = false;\n            }\n        }\n    </script>\n</body>\n</html>";
  }
}
exports.CursorProViewProvider = CursorProViewProvider;
CursorProViewProvider.CURRENT_VERSION = '0.4.5';