4307 lines
315 KiB
JavaScript
4307 lines
315 KiB
JavaScript
'use strict';
|
||
var __createBinding = this && this["__createBinding"] || (Object["create"] ? function (_0x426d51, _0x1fa101, _0xd56cbf, _0x584cf0) {
|
||
const _0x72e54d = {
|
||
'uKmJw': function (_0xdd80ed, _0x4bf4c4) {
|
||
return _0xdd80ed === _0x4bf4c4;
|
||
},
|
||
'TAoYL': function (_0x3d6ea4, _0x2c5cdc) {
|
||
return _0x3d6ea4 in _0x2c5cdc;
|
||
},
|
||
'aPyeo': "get"
|
||
};
|
||
if (_0x72e54d["uKmJw"](_0x584cf0, undefined)) {
|
||
_0x584cf0 = _0xd56cbf;
|
||
}
|
||
var _0x1907da = Object.getOwnPropertyDescriptor(_0x1fa101, _0xd56cbf);
|
||
if (!_0x1907da || (_0x72e54d.aPyeo in _0x1907da ? !_0x1fa101.__esModule : _0x1907da["writable"] || _0x1907da.configurable)) {
|
||
_0x1907da = {
|
||
'enumerable': true,
|
||
'get': function () {
|
||
return _0x1fa101[_0xd56cbf];
|
||
}
|
||
};
|
||
}
|
||
Object["defineProperty"](_0x426d51, _0x584cf0, _0x1907da);
|
||
} : function (_0x5f91d1, _0x9a02cb, _0x4b8c9f, _0x19d088) {
|
||
const _0x5f3f4d = {
|
||
'SeNEr': function (_0x5d446f, _0x23305b) {
|
||
return _0x5d446f === _0x23305b;
|
||
}
|
||
};
|
||
if (_0x5f3f4d["SeNEr"](_0x19d088, undefined)) {
|
||
_0x19d088 = _0x4b8c9f;
|
||
}
|
||
_0x5f91d1[_0x19d088] = _0x9a02cb[_0x4b8c9f];
|
||
});
|
||
var __setModuleDefault = this && this["__setModuleDefault"] || (Object["create"] ? function (_0x345a43, _0x11ae4c) {
|
||
const _0x4f212a = {
|
||
'FTXnn': "default"
|
||
};
|
||
Object["defineProperty"](_0x345a43, _0x4f212a.FTXnn, {
|
||
'enumerable': true,
|
||
'value': _0x11ae4c
|
||
});
|
||
} : function (_0x1d7e4a, _0x48365a) {
|
||
const _0x3780d5 = {
|
||
'kZOut': "default"
|
||
};
|
||
_0x1d7e4a[_0x3780d5["kZOut"]] = _0x48365a;
|
||
});
|
||
var __importStar = this && this.__importStar || function () {
|
||
const _0x4481b5 = {
|
||
'fsNNJ': function (_0x24a54e, _0x1bdb80) {
|
||
return _0x24a54e(_0x1bdb80);
|
||
},
|
||
'srHxh': '1|4|0|3|2',
|
||
'MoXZb': function (_0x3f36e7, _0x3a1c53) {
|
||
return _0x3f36e7 != _0x3a1c53;
|
||
},
|
||
'VqBsb': function (_0x32fe05, _0x1525ff) {
|
||
return _0x32fe05 < _0x1525ff;
|
||
},
|
||
'mymIw': function (_0x4a533c, _0x29a9b2) {
|
||
return _0x4a533c !== _0x29a9b2;
|
||
},
|
||
'zFOle': function (_0x3faee2, _0x31a6a7, _0x2bbca2, _0x53d668) {
|
||
return _0x3faee2(_0x31a6a7, _0x2bbca2, _0x53d668);
|
||
},
|
||
'zPdmk': function (_0x326a22, _0x578e64, _0x1ca450) {
|
||
return _0x326a22(_0x578e64, _0x1ca450);
|
||
}
|
||
};
|
||
var _0xb2a35b = function (_0x4d1aec) {
|
||
_0xb2a35b = Object["getOwnPropertyNames"] || function (_0x1a3c58) {
|
||
var _0x5ea703 = [];
|
||
for (var _0x185acc in _0x1a3c58) if (Object["prototype"]["hasOwnProperty"]["call"](_0x1a3c58, _0x185acc)) {
|
||
_0x5ea703[_0x5ea703["length"]] = _0x185acc;
|
||
}
|
||
return _0x5ea703;
|
||
};
|
||
return _0x4481b5["fsNNJ"](_0xb2a35b, _0x4d1aec);
|
||
};
|
||
return function (_0x31ac5f) {
|
||
const _0x3c765b = _0x4481b5["srHxh"]["split"]('|');
|
||
let _0x2fee3c = 0x0;
|
||
while (true) {
|
||
switch (_0x3c765b[_0x2fee3c++]) {
|
||
case '0':
|
||
if (_0x4481b5["MoXZb"](_0x31ac5f, null)) {
|
||
var _0x43241d = _0xb2a35b(_0x31ac5f);
|
||
for (var _0x27b692 = 0x0; _0x4481b5["VqBsb"](_0x27b692, _0x43241d["length"]); _0x27b692++) {
|
||
if (_0x4481b5["mymIw"](_0x43241d[_0x27b692], "default")) {
|
||
_0x4481b5["zFOle"](__createBinding, _0x23061d, _0x31ac5f, _0x43241d[_0x27b692]);
|
||
}
|
||
}
|
||
}
|
||
continue;
|
||
case '1':
|
||
if (_0x31ac5f && _0x31ac5f["__esModule"]) {
|
||
return _0x31ac5f;
|
||
}
|
||
continue;
|
||
case '2':
|
||
return _0x23061d;
|
||
case '3':
|
||
_0x4481b5["zPdmk"](__setModuleDefault, _0x23061d, _0x31ac5f);
|
||
continue;
|
||
case '4':
|
||
var _0x23061d = {};
|
||
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(_0x249e9c, _0x2abb89) {
|
||
const _0x22d112 = {
|
||
'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"] = _0x249e9c;
|
||
this["_context"] = _0x2abb89;
|
||
this._hostsPermissionGranted = false;
|
||
this.SNI_PROXY_IP = _0x22d112["NNvQE"];
|
||
this["CURSOR_DOMAINS"] = [_0x22d112.HENcW, _0x22d112["vVEYg"]];
|
||
this["HOSTS_MARKER_START"] = _0x22d112["xOuBX"];
|
||
this["HOSTS_MARKER_END"] = _0x22d112["gbbhA"];
|
||
this["_cachedCursorPath"] = null;
|
||
0x0;
|
||
this["_onlineStatusUnsubscribe"] = client_1["onOnlineStatusChange"](_0x11fa48 => {
|
||
this["_postMessage"]({
|
||
'type': _0x22d112["dJwJk"],
|
||
'online': _0x11fa48
|
||
});
|
||
});
|
||
}
|
||
["resolveWebviewView"](_0x3b70b5, _0x5282a8, _0x49a978) {
|
||
const _0x5b922e = {
|
||
'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"] = _0x3b70b5;
|
||
_0x3b70b5["webview"].options = {
|
||
'enableScripts': true,
|
||
'localResourceRoots': [this["_extensionUri"]]
|
||
};
|
||
_0x3b70b5["webview"]["html"] = this["_getHtmlContent"](_0x3b70b5["webview"]);
|
||
_0x3b70b5["webview"]["onDidReceiveMessage"](async _0x194d46 => {
|
||
const _0x275d91 = {
|
||
'WZyWQ': _0x5b922e["NRTxb"],
|
||
'ZXhkG': _0x5b922e["MCtQT"]
|
||
};
|
||
if (_0x5b922e["RCwUS"] !== _0x5b922e["gHWzN"]) {
|
||
switch (_0x194d46.type) {
|
||
case "activate":
|
||
await this._handleActivate(_0x194d46["key"]);
|
||
break;
|
||
case _0x5b922e["HxMUq"]:
|
||
await this["_handleSwitch"]();
|
||
break;
|
||
case "resetMachineId":
|
||
await this._handleResetMachineId();
|
||
break;
|
||
case _0x5b922e.mVWLv:
|
||
await this["_handleDisableUpdate"]();
|
||
break;
|
||
case _0x5b922e["kIVSE"]:
|
||
await this["_handleCleanEnv"]();
|
||
break;
|
||
case _0x5b922e["ayNzd"]:
|
||
await this._handleDisable();
|
||
break;
|
||
case _0x5b922e["XJsJS"]:
|
||
await this._handleToggleProxy(_0x194d46["enabled"], _0x194d46["url"]);
|
||
break;
|
||
case 'getProxyStatus':
|
||
await this["_handleGetProxyStatus"]();
|
||
break;
|
||
case _0x5b922e["TwlLk"]:
|
||
await this["_sendState"]();
|
||
break;
|
||
case "retryConnect":
|
||
await this["_handleRetryConnect"]();
|
||
break;
|
||
case _0x5b922e["Yecgn"]:
|
||
await this["_handleGetSeamlessStatus"]();
|
||
break;
|
||
case _0x5b922e.ekYOQ:
|
||
await this["_handleInjectSeamless"]();
|
||
break;
|
||
case "restoreSeamless":
|
||
await this._handleRestoreSeamless();
|
||
break;
|
||
case _0x5b922e["sJjTI"]:
|
||
await this["_handleToggleSeamless"](_0x194d46.enabled);
|
||
break;
|
||
case _0x5b922e["FtmLf"]:
|
||
await this["_handleGetUserSwitchStatus"]();
|
||
break;
|
||
case "manualSeamlessSwitch":
|
||
await this._handleManualSeamlessSwitch();
|
||
break;
|
||
case _0x5b922e.EflLA:
|
||
await this["_handleCheckUsageBeforeSwitch"](_0x194d46["email"]);
|
||
break;
|
||
case _0x5b922e["rXOaA"]:
|
||
await this["_handleManualSeamlessSwitch"]();
|
||
break;
|
||
case _0x5b922e.OkEoz:
|
||
await this._handleGetCursorPath();
|
||
break;
|
||
case 'getAccountUsage':
|
||
await this["_handleGetAccountUsage"](_0x194d46["email"]);
|
||
break;
|
||
case "getAnnouncement":
|
||
await this._handleGetAnnouncement();
|
||
break;
|
||
case _0x5b922e["ehEEN"]:
|
||
await this._handleCheckVersion();
|
||
break;
|
||
case _0x5b922e["myCHL"]:
|
||
await this["_handleGetCursorRunningPath"]();
|
||
break;
|
||
case _0x5b922e["KPDvL"]:
|
||
vscode["commands"].executeCommand(_0x5b922e["LHHus"]);
|
||
break;
|
||
case 'closeCursor':
|
||
0x0;
|
||
await account_1.closeCursor();
|
||
break;
|
||
}
|
||
} else {
|
||
const _0x282668 = _0x275d91["WZyWQ"];
|
||
this["_postMessage"]({
|
||
'type': _0x275d91["ZXhkG"],
|
||
'success': false,
|
||
'error': _0x282668,
|
||
'needAdmin': true
|
||
});
|
||
return;
|
||
}
|
||
});
|
||
this["_sendState"]();
|
||
this["_checkKeyStatus"]();
|
||
}
|
||
async ["_checkKeyStatus"]() {
|
||
const _0x4da3ff = {
|
||
'TLsxY': "utf-8",
|
||
'KqsKI': "cursorpro.key",
|
||
'OEKzo': function (_0x3f2189, _0x48838e) {
|
||
return _0x3f2189 !== _0x48838e;
|
||
},
|
||
'krxOp': "FAZar",
|
||
'lSeSm': "QlWcq",
|
||
'ubmNf': function (_0x29914e, _0x4e5d68) {
|
||
return _0x29914e === _0x4e5d68;
|
||
},
|
||
'yoPVW': 'EtMGw',
|
||
'UGSnZ': 'DVTND',
|
||
'jEejJ': 'cursorpro.expireDate',
|
||
'lpyMQ': 'cursorpro.switchRemaining',
|
||
'Auayd': "cursorpro.switchLimit",
|
||
'sbaFL': "keyStatusChecked",
|
||
'dyUVf': "激活码已过期或无效"
|
||
};
|
||
const _0x844666 = this["_context"]["globalState"].get(_0x4da3ff["KqsKI"]);
|
||
if (!_0x844666) {
|
||
if (_0x4da3ff["OEKzo"]('NCQkd', _0x4da3ff["krxOp"])) {
|
||
return;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': "accountUsage",
|
||
'success': false,
|
||
'error': "未提供账号邮箱"
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
try {
|
||
if (_0x4da3ff["lSeSm"] !== 'QlWcq') {
|
||
_0x24f700["writeFileSync"](_0x5ce57d, _0x2697d5, _0x4da3ff["TLsxY"]);
|
||
} else {
|
||
0x0;
|
||
const _0x439524 = await client_1.verifyKey(_0x844666);
|
||
if (_0x439524["success"] && _0x439524.valid) {
|
||
if (_0x4da3ff["ubmNf"](_0x4da3ff["yoPVW"], _0x4da3ff["UGSnZ"])) {
|
||
const _0x3a2e35 = _0x45d671["readFileSync"](_0x1f88e9, _0x4da3ff["TLsxY"]);
|
||
_0x2710ef = this["_checkInjected"](_0x3a2e35);
|
||
} else {
|
||
await this._context.globalState["update"](_0x4da3ff["jEejJ"], _0x439524["expire_date"]);
|
||
await this._context["globalState"]["update"](_0x4da3ff["lpyMQ"], _0x439524["switch_remaining"]);
|
||
await this._context["globalState"]["update"](_0x4da3ff["Auayd"], _0x439524["switch_limit"]);
|
||
this["_postMessage"]({
|
||
'type': _0x4da3ff["sbaFL"],
|
||
'valid': true,
|
||
'expireDate': _0x439524["expire_date"],
|
||
'switchRemaining': _0x439524["switch_remaining"],
|
||
'switchLimit': _0x439524["switch_limit"]
|
||
});
|
||
}
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x4da3ff["sbaFL"],
|
||
'valid': false,
|
||
'expired': true,
|
||
'error': _0x439524["error"] || _0x4da3ff["dyUVf"]
|
||
});
|
||
}
|
||
}
|
||
} catch (_0xe8e14c) {
|
||
console.error("[CursorPro] 检查激活码状态失败:", _0xe8e14c);
|
||
}
|
||
}
|
||
async ["_handleActivate"](_0x1c33b1) {
|
||
const _0x83ba47 = {
|
||
'cduDC': "utf-8",
|
||
'dWzRy': function (_0x2eb04a, _0x1a63c1) {
|
||
return _0x2eb04a(_0x1a63c1);
|
||
},
|
||
'yiKQp': "vscode",
|
||
'loOtc': "[CursorPro] 使用 VS Code API 获取版本:",
|
||
'fCoyb': function (_0x39f2f1, _0x5bc57a) {
|
||
return _0x39f2f1 === _0x5bc57a;
|
||
},
|
||
'hneyF': "ZPKij",
|
||
'MeNSD': "无感换号已启用,请先禁用后再更换授权码",
|
||
'jfGyX': function (_0x341f1e, _0x13166d) {
|
||
return _0x341f1e === _0x13166d;
|
||
},
|
||
'vAxgQ': 'ZyMNB',
|
||
'IStwX': "activated",
|
||
'RiXWk': "cursorpro.expireDate",
|
||
'tkwFD': "cursorpro.key",
|
||
'oRfTW': "cursorpro.switchLimit",
|
||
'lnDvM': "aVnan",
|
||
'bgJHu': "SOGed",
|
||
'lRVPz': "授权码无效",
|
||
'mbyBU': "连接服务器失败"
|
||
};
|
||
try {
|
||
const _0x3b1ee2 = await this["_isSeamlessInjected"]();
|
||
if (_0x3b1ee2) {
|
||
if (_0x83ba47["fCoyb"](_0x83ba47["hneyF"], "ZPKij")) {
|
||
this._postMessage({
|
||
'type': "activated",
|
||
'success': false,
|
||
'error': _0x83ba47.MeNSD
|
||
});
|
||
return;
|
||
} else {
|
||
const _0x5234a5 = this._getHostsPath();
|
||
if (_0x58e3ff["existsSync"](_0x5234a5)) {
|
||
return _0x490712["readFileSync"](_0x5234a5, _0x83ba47["cduDC"]);
|
||
}
|
||
}
|
||
}
|
||
this._cleanProxySettings();
|
||
0x0;
|
||
const _0x48d007 = await client_1["verifyKey"](_0x1c33b1);
|
||
if (_0x48d007["success"] && _0x48d007.valid) {
|
||
if (_0x83ba47["jfGyX"]('ZyMNB', _0x83ba47["vAxgQ"])) {
|
||
console.log("[CursorPro] 激活成功,后端返回:", {
|
||
'expire_date': _0x48d007["expire_date"],
|
||
'switch_remaining': _0x48d007["switch_remaining"],
|
||
'switch_limit': _0x48d007["switch_limit"]
|
||
});
|
||
await this["_context"].globalState["update"](_0x83ba47.tkwFD, _0x1c33b1);
|
||
await this._context["globalState"]["update"](_0x83ba47["RiXWk"], _0x48d007.expire_date);
|
||
await this["_context"]["globalState"]["update"]("cursorpro.switchRemaining", _0x48d007.switch_remaining);
|
||
await this._context["globalState"]["update"](_0x83ba47["oRfTW"], _0x48d007["switch_limit"]);
|
||
this["_postMessage"]({
|
||
'type': _0x83ba47["IStwX"],
|
||
'success': true,
|
||
'key': _0x1c33b1,
|
||
'expireDate': _0x48d007.expire_date,
|
||
'switchRemaining': _0x48d007["switch_remaining"],
|
||
'switchLimit': _0x48d007["switch_limit"]
|
||
});
|
||
0x0;
|
||
extension_1["showStatusBar"]();
|
||
await this._handleGetUserSwitchStatus();
|
||
} else {
|
||
_0x287901["warn"]("[CursorPro] 清理失败: " + _0x532653, _0x1db3e3);
|
||
}
|
||
} else {
|
||
if (_0x83ba47["lnDvM"] === _0x83ba47["bgJHu"]) {
|
||
const _0x1cf00a = _0x83ba47["dWzRy"](_0x931219, _0x83ba47["yiKQp"]);
|
||
if (_0x1cf00a["version"]) {
|
||
_0x4e3d1c["log"](_0x83ba47["loOtc"], _0x1cf00a.version);
|
||
return _0x1cf00a.version;
|
||
}
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x83ba47["IStwX"],
|
||
'success': false,
|
||
'error': _0x48d007["error"] || _0x83ba47["lRVPz"]
|
||
});
|
||
}
|
||
}
|
||
} catch (_0x40371b) {
|
||
this._postMessage({
|
||
'type': _0x83ba47["IStwX"],
|
||
'success': false,
|
||
'error': _0x83ba47["mbyBU"]
|
||
});
|
||
}
|
||
}
|
||
async ["_handleSwitch"]() {
|
||
const _0x3e408e = {
|
||
'QReae': "[CursorPro] WMIC 获取路径失败:",
|
||
'OVooV': "cursorpro.key",
|
||
'SpDeq': 'showToast',
|
||
'PTQOe': "请先激活授权码",
|
||
'YLEHJ': "cursorpro.switchRemaining",
|
||
'eBTDM': 'switched',
|
||
'kCeYh': "cursorpro.switchLimit",
|
||
'omFtC': "userSwitchStatus",
|
||
'XbTBi': function (_0x2bec63, _0x68602f) {
|
||
return _0x2bec63 > _0x68602f;
|
||
},
|
||
'pyrHY': function (_0x56ae50, _0xd521fd) {
|
||
return _0x56ae50 !== _0xd521fd;
|
||
},
|
||
'VqcBN': "kqrkg",
|
||
'bfgAG': "QcuMv"
|
||
};
|
||
const _0x11c87a = this["_context"]["globalState"]["get"](_0x3e408e["OVooV"]);
|
||
if (!_0x11c87a) {
|
||
this._postMessage({
|
||
'type': _0x3e408e["SpDeq"],
|
||
'message': _0x3e408e["PTQOe"],
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
0x0;
|
||
const _0xbe1a2d = await client_1["switchSeamlessToken"](_0x11c87a);
|
||
if (_0xbe1a2d["switched"]) {
|
||
await this["_context"]["globalState"].update(_0x3e408e["YLEHJ"], _0xbe1a2d["switchRemaining"]);
|
||
this._postMessage({
|
||
'type': _0x3e408e["eBTDM"],
|
||
'success': true,
|
||
'email': _0xbe1a2d["email"],
|
||
'switchRemaining': _0xbe1a2d["switchRemaining"],
|
||
'switchLimit': this["_context"]["globalState"].get(_0x3e408e["kCeYh"]) || 0x64
|
||
});
|
||
const _0x4b2796 = _0xbe1a2d.switchRemaining ?? 0x0;
|
||
this["_postMessage"]({
|
||
'type': _0x3e408e["omFtC"],
|
||
'switchRemaining': _0x4b2796,
|
||
'canSwitch': _0x4b2796 > 0x0,
|
||
'lockedAccount': _0xbe1a2d["email"] ? {
|
||
'email': _0xbe1a2d["email"]
|
||
} : null
|
||
});
|
||
} else if (_0x3e408e["pyrHY"]("yFoId", _0x3e408e.VqcBN)) {
|
||
this["_postMessage"]({
|
||
'type': _0x3e408e["eBTDM"],
|
||
'success': false,
|
||
'error': _0xbe1a2d["message"] || '换号失败'
|
||
});
|
||
} else {
|
||
_0x5b771a = _0x1474f8[0x1];
|
||
}
|
||
} catch (_0x41fa19) {
|
||
if (_0x3e408e["pyrHY"]("CyYkO", _0x3e408e["bfgAG"])) {
|
||
this["_postMessage"]({
|
||
'type': 'switched',
|
||
'success': false,
|
||
'error': "连接服务器失败"
|
||
});
|
||
} else {
|
||
_0xb585cb["log"](_0x3e408e.QReae, _0x5d81f0);
|
||
}
|
||
}
|
||
}
|
||
async ["_writeAccountToLocal"](_0x51678f) {
|
||
const _0x5df214 = {
|
||
'jAygU': function (_0x1a9516, _0x14e09c) {
|
||
return _0x1a9516 === _0x14e09c;
|
||
},
|
||
'lWsen': "Contents",
|
||
'ujkvI': "app",
|
||
'nHvFA': 'out',
|
||
'WYIiR': "workbench",
|
||
'HukDC': "workbench.desktop.main.js",
|
||
'lAqMN': function (_0x4621bc, _0x5e828f) {
|
||
return _0x4621bc === _0x5e828f;
|
||
},
|
||
'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 (_0x2c52bd, _0x27885e) {
|
||
return _0x2c52bd === _0x27885e;
|
||
},
|
||
'GXvhF': "hdUrt",
|
||
'tFDff': "Cursor",
|
||
'IFUbF': 'User',
|
||
'RqMFq': "globalStorage",
|
||
'tSjWJ': "state.vscdb",
|
||
'WnTYM': "machineid",
|
||
'ByhnO': "cursorAuth/accessToken",
|
||
'MPCdN': "cursorAuth/refreshToken",
|
||
'hrJHc': function (_0x223704, _0xb12866) {
|
||
return _0x223704 === _0xb12866;
|
||
},
|
||
'atmmx': "rmAmZ",
|
||
'qyuJo': "cursorAuth/cachedEmail",
|
||
'iOndu': "pAlKG",
|
||
'tfSWx': "cursorAuth/stripeMembershipType",
|
||
'UnRdA': function (_0x17b49d, _0x28b8c0) {
|
||
return _0x17b49d !== _0x28b8c0;
|
||
},
|
||
'FNcgD': "ptOKi",
|
||
'JVIPE': 'yLQZc',
|
||
'btARC': "cursorAuth/cachedSignUpType",
|
||
'pTffC': "eNCnU",
|
||
'taMeX': "storage.serviceMachineId",
|
||
'QhViN': function (_0x3ede25, _0x102e15) {
|
||
return _0x3ede25 === _0x102e15;
|
||
},
|
||
'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 (_0x4acd6e, _0x4cbd0e) {
|
||
return _0x4acd6e(_0x4cbd0e);
|
||
},
|
||
'dxmvV': "[CursorPro] 注册表写入失败(可能需要管理员权限):"
|
||
};
|
||
try {
|
||
if ("MClbP" === _0x5df214["GXvhF"]) {
|
||
let _0x9583b2;
|
||
if (_0x5df214["jAygU"](_0x48f1cd, "darwin")) {
|
||
_0x9583b2 = _0x3e2a77.join(this["_cachedCursorPath"], _0x5df214["lWsen"], 'Resources', _0x5df214["ujkvI"], _0x5df214["nHvFA"], 'vs', _0x5df214["WYIiR"], _0x5df214["HukDC"]);
|
||
} else {
|
||
_0x9583b2 = _0x4e0cd1.join(this["_cachedCursorPath"], "resources", _0x5df214["ujkvI"], _0x5df214["nHvFA"], 'vs', _0x5df214["WYIiR"], _0x5df214["HukDC"]);
|
||
}
|
||
if (_0x240b48["existsSync"](_0x9583b2)) {
|
||
return _0x9583b2;
|
||
}
|
||
} else {
|
||
const _0x33651c = process["env"]["APPDATA"] || '';
|
||
const _0x97018c = path["join"](_0x33651c, _0x5df214["tFDff"], _0x5df214["IFUbF"], _0x5df214.RqMFq, _0x5df214["tSjWJ"]);
|
||
const _0x155e62 = path["join"](_0x33651c, "Cursor", _0x5df214["IFUbF"], _0x5df214.RqMFq, 'storage.json');
|
||
const _0x392e23 = path["join"](_0x33651c, _0x5df214["tFDff"], _0x5df214.WnTYM);
|
||
if (fs["existsSync"](_0x97018c)) {
|
||
const _0x37f13d = [];
|
||
if (_0x51678f["accessToken"]) {
|
||
_0x37f13d["push"]([_0x5df214["ByhnO"], _0x51678f.accessToken]);
|
||
}
|
||
if (_0x51678f["refreshToken"]) {
|
||
_0x37f13d["push"]([_0x5df214["MPCdN"], _0x51678f["refreshToken"]]);
|
||
}
|
||
if (_0x51678f.email) {
|
||
if (_0x5df214["atmmx"] === 'mIiuu') {
|
||
_0xfb725b = _0x1931cc["dirname"](_0x2dba3b["trim"]());
|
||
} else {
|
||
_0x37f13d["push"]([_0x5df214.qyuJo, _0x51678f["email"]]);
|
||
}
|
||
}
|
||
if (_0x51678f["membership_type"]) {
|
||
if ('vhcuB' === _0x5df214["iOndu"]) {
|
||
const _0x637d29 = _0x1172a0["platform"];
|
||
let _0x5a842b = '没有写入权限';
|
||
if (_0x5df214["lAqMN"](_0x637d29, _0x5df214.uJtvK)) {
|
||
_0x5a842b = _0x5df214.klERN;
|
||
} else if (_0x5df214["lAqMN"](_0x637d29, _0x5df214["qVIKa"])) {
|
||
_0x5a842b = _0x5df214["uJMyy"];
|
||
}
|
||
this._postMessage({
|
||
'type': 'seamlessInjected',
|
||
'success': false,
|
||
'error': _0x5a842b,
|
||
'needAdmin': true,
|
||
'path': _0x24be1d
|
||
});
|
||
return;
|
||
} else {
|
||
_0x37f13d["push"]([_0x5df214.tfSWx, _0x51678f.membership_type]);
|
||
}
|
||
}
|
||
if (_0x51678f["sign_up_type"]) {
|
||
if (_0x5df214["UnRdA"](_0x5df214["FNcgD"], 'yLQZc')) {
|
||
_0x37f13d["push"]([_0x5df214["btARC"], _0x51678f["sign_up_type"]]);
|
||
} else {
|
||
_0x433bcf = _0x2003b8.dirname(_0x43cf7e);
|
||
}
|
||
}
|
||
if (_0x51678f["serviceMachineId"]) {
|
||
if ('fYfXI' !== _0x5df214["pTffC"]) {
|
||
_0x37f13d.push([_0x5df214["taMeX"], _0x51678f["serviceMachineId"]]);
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x5df214["oogyg"],
|
||
'success': true,
|
||
'needConfirm': true,
|
||
'costUSD': _0x2db93a["toFixed"](0x2),
|
||
'email': _0x28077f
|
||
});
|
||
}
|
||
}
|
||
0x0;
|
||
await sqlite_1["sqliteSetBatch"](_0x97018c, _0x37f13d);
|
||
console["log"]("[CursorPro] SQLite 数据库已更新");
|
||
}
|
||
if (fs["existsSync"](_0x155e62)) {
|
||
if (_0x5df214["QhViN"](_0x5df214["IenCN"], "nqqWG")) {
|
||
const _0xc468de = _0x12337e.message || _0x352413["error"] || _0x5df214.UUaYi;
|
||
this["_postMessage"]({
|
||
'type': _0x5df214.NEcQR,
|
||
'success': false,
|
||
'error': _0xc468de
|
||
});
|
||
} else {
|
||
const _0x589109 = JSON.parse(fs.readFileSync(_0x155e62, 'utf-8'));
|
||
if (_0x51678f.machineId) {
|
||
_0x589109[_0x5df214["ktByd"]] = _0x51678f["machineId"];
|
||
}
|
||
if (_0x51678f["macMachineId"]) {
|
||
_0x589109['telemetry.macMachineId'] = _0x51678f["macMachineId"];
|
||
}
|
||
if (_0x51678f["devDeviceId"]) {
|
||
_0x589109["telemetry.devDeviceId"] = _0x51678f.devDeviceId;
|
||
}
|
||
if (_0x51678f["sqmId"]) {
|
||
if (_0x5df214.hYviy === _0x5df214["ltTAn"]) {
|
||
this._postMessage({
|
||
'type': _0x5df214["BPXIz"],
|
||
'success': false,
|
||
'error': "修改 hosts 文件失败,请确保有管理员权限"
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x5df214.pgeAO,
|
||
'message': "需要管理员权限修改 hosts 文件",
|
||
'icon': '⚠️'
|
||
});
|
||
} else {
|
||
_0x589109["telemetry.sqmId"] = _0x51678f["sqmId"];
|
||
}
|
||
}
|
||
fs["writeFileSync"](_0x155e62, JSON.stringify(_0x589109, null, 0x4));
|
||
console["log"](_0x5df214["WtTZw"]);
|
||
}
|
||
}
|
||
if (_0x51678f.machineId) {
|
||
fs["writeFileSync"](_0x392e23, _0x51678f["machineId"]);
|
||
console["log"](_0x5df214["bohEI"]);
|
||
}
|
||
if (_0x51678f["registryGuid"] && process.platform === _0x5df214["tqMKz"]) {
|
||
if (_0x5df214["KhYFK"] === _0x5df214["KhYFK"]) {
|
||
try {
|
||
const _0x256ef2 = 'reg add "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid /t REG_SZ /d "' + _0x51678f.registryGuid + '" /f';
|
||
await execAsync(_0x256ef2);
|
||
console.log("[CursorPro] 注册表 MachineGuid 已更新");
|
||
} catch (_0x5c0e6a) {
|
||
console.warn(_0x5df214["dxmvV"], _0x5c0e6a);
|
||
}
|
||
} else {
|
||
_0x1b21f9 = _0x5df214["uJMyy"];
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
} catch (_0x4bd56d) {
|
||
console.error("[CursorPro] 写入本地失败:", _0x4bd56d);
|
||
vscode["window"].showErrorMessage("写入失败: " + _0x4bd56d);
|
||
return false;
|
||
}
|
||
}
|
||
async ["_handleReset"]() {
|
||
const _0x178daf = {
|
||
'SWWgG': '4|0|3|5|2|1',
|
||
'uEcXh': 'reset',
|
||
'eMKRt': 'cursorpro.switchRemaining',
|
||
'FOwUP': "cursorpro.key"
|
||
};
|
||
const _0x46dec9 = '4|0|3|5|2|1'["split"]('|');
|
||
let _0x51aa2c = 0x0;
|
||
while (true) {
|
||
switch (_0x46dec9[_0x51aa2c++]) {
|
||
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(_0x178daf["eMKRt"], undefined);
|
||
continue;
|
||
case '4':
|
||
await this["_context"]["globalState"]["update"](_0x178daf["FOwUP"], undefined);
|
||
continue;
|
||
case '5':
|
||
0x0;
|
||
extension_1["hideStatusBar"]();
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
async ._handleDisable() {
|
||
await this._handleReset();
|
||
vscode.window["showInformationMessage"]("插件已停用");
|
||
}
|
||
async ._checkAdminPrivilege() {
|
||
const _0x53e404 = {
|
||
'fAfUV': "Resources",
|
||
'Llgfj': function (_0x2ea46e, _0x597079) {
|
||
return _0x2ea46e !== _0x597079;
|
||
},
|
||
'pImJb': function (_0x3e6e32, _0x3b5f4c) {
|
||
return _0x3e6e32(_0x3b5f4c);
|
||
},
|
||
'wncyL': "net session 2>nul"
|
||
};
|
||
if (process.platform !== "win32") {
|
||
if ("FIUZS" === 'FIUZS') {
|
||
return true;
|
||
} else {
|
||
_0x2739b0 = _0x1385f5["join"](_0x2a3737, 'Contents', _0x53e404["fAfUV"], 'app', "package.json");
|
||
}
|
||
}
|
||
try {
|
||
await _0x53e404["pImJb"](execAsync, 'reg query "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid 2>nul');
|
||
const _0x41176e = await execAsync(_0x53e404["wncyL"])["catch"](() => ({
|
||
'stdout': '',
|
||
'stderr': 'error'
|
||
}));
|
||
return !_0x41176e.stderr;
|
||
} catch (_0x6d5696) {
|
||
return false;
|
||
}
|
||
}
|
||
async ["_handleResetMachineId"]() {
|
||
const _0x3dfa6c = {
|
||
'lElIk': function (_0x3fa0c5, _0x578287) {
|
||
return _0x3fa0c5 === _0x578287;
|
||
},
|
||
'yJQQD': "darwin",
|
||
'oTJSZ': 'Contents',
|
||
'sJMHZ': 'Resources',
|
||
'tIdJk': "app",
|
||
'rNqfB': "workbench",
|
||
'PaBhO': "workbench.desktop.main.js",
|
||
'cDXTK': "out",
|
||
'mseLD': function (_0x1a7b0a, _0x4298ee) {
|
||
return _0x1a7b0a(_0x4298ee);
|
||
},
|
||
'GpfdI': function (_0x561ce3, _0xd12af6) {
|
||
return _0x561ce3 != _0xd12af6;
|
||
},
|
||
'jGfgE': function (_0x4a5a60, _0x3f3e51) {
|
||
return _0x4a5a60 !== _0x3f3e51;
|
||
},
|
||
'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 (_0xa487f2, _0x46d29e) {
|
||
return _0xa487f2 === _0x46d29e;
|
||
},
|
||
'hazjj': "OKDBI",
|
||
'sltuA': "[CursorPro] storage.json 更新失败:",
|
||
'kdlCx': "storage.json",
|
||
'yAadA': "AGUOM",
|
||
'dVXng': function (_0x52e3f9, _0x1824a1) {
|
||
return _0x52e3f9 > _0x1824a1;
|
||
},
|
||
'jVCTI': function (_0x36b294, _0x50a679) {
|
||
return _0x36b294 !== _0x50a679;
|
||
},
|
||
'NgEqy': "XygLc",
|
||
'JHBVl': "[CursorPro] machineid 文件已更新",
|
||
'ihOph': "machineid",
|
||
'CUSOw': function (_0x5dca29, _0x1c0e29) {
|
||
return _0x5dca29 > _0x1c0e29;
|
||
},
|
||
'DXmLl': 'UbSjF',
|
||
'XMamy': function (_0x56b6ca, _0x4d16fd) {
|
||
return _0x56b6ca !== _0x4d16fd;
|
||
},
|
||
'TStTT': "SxHmQ",
|
||
'xXEyx': function (_0x41e747, _0x456d1f) {
|
||
return _0x41e747 !== _0x456d1f;
|
||
},
|
||
'iiJFH': 'edqsV',
|
||
'dLXnX': function (_0x626dd4, _0x4c0c64) {
|
||
return _0x626dd4 === _0x4c0c64;
|
||
},
|
||
'IMEYC': function (_0x2f404e, _0x1aec5f) {
|
||
return _0x2f404e === _0x1aec5f;
|
||
},
|
||
'aYwpG': "EvLtz",
|
||
'EdOfO': "[CursorPro] SQLite 更新失败:",
|
||
'wSpvM': "win32",
|
||
'hhSrG': function (_0x247938, _0x48462e) {
|
||
return _0x247938 === _0x48462e;
|
||
},
|
||
'DAvAD': "uxdjv",
|
||
'BkSzQ': "qWEGL",
|
||
'WYomd': "[CursorPro] 注册表 MachineGuid 已更新",
|
||
'ZaPkC': function (_0x59cb29, _0x513094) {
|
||
return _0x59cb29 >= _0x513094;
|
||
},
|
||
'fVMJA': 'machineIdReset',
|
||
'HiGXJ': "机器码重置成功",
|
||
'SEsMN': function (_0x34e2fe, _0x135030) {
|
||
return _0x34e2fe === _0x135030;
|
||
},
|
||
'dGXfv': "gGIGL",
|
||
'pKuzu': function (_0x3f0c5f, _0xdc4a4f) {
|
||
return _0x3f0c5f !== _0xdc4a4f;
|
||
},
|
||
'YfRLt': "KokEE"
|
||
};
|
||
try {
|
||
const _0x5ca938 = process["platform"];
|
||
if (_0x3dfa6c["lElIk"](_0x5ca938, 'win32')) {
|
||
const _0x2196c3 = await this._checkAdminPrivilege();
|
||
if (!_0x2196c3) {
|
||
this["_postMessage"]({
|
||
'type': _0x3dfa6c["BmSwh"]
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
0x0;
|
||
const _0x5e7765 = account_1["getCursorPaths"]();
|
||
const {
|
||
dbPath: _0x4aa0cd,
|
||
storagePath: _0x4a28ca,
|
||
machineidPath: _0x2ec82c
|
||
} = _0x5e7765;
|
||
const _0x2aee57 = _0x3dfa6c["mseLD"](require, _0x3dfa6c["DUzlm"]);
|
||
const _0x13d6be = _0x2aee57["randomBytes"](0x20).toString(_0x3dfa6c.iOJby);
|
||
const _0x4520aa = _0x2aee57.randomBytes(0x20).toString(_0x3dfa6c["iOJby"]);
|
||
const _0x5c9a5c = _0x2aee57["randomUUID"]();
|
||
const _0x295e98 = '{' + _0x2aee57["randomUUID"]()["toUpperCase"]() + '}';
|
||
let _0x42a386 = 0x0;
|
||
let _0x410d72 = [];
|
||
if (fs["existsSync"](_0x4a28ca)) {
|
||
if (_0x3dfa6c["SizrD"] !== "EIFLO") {
|
||
let _0x2d68ba;
|
||
if (_0x3dfa6c["lElIk"](_0x1eaffe, _0x3dfa6c["yJQQD"])) {
|
||
_0x2d68ba = _0x5e5bb2["join"](_0xae64c7, 'Contents', _0x3dfa6c["sJMHZ"], _0x3dfa6c["tIdJk"], "out", 'vs', _0x3dfa6c.rNqfB, _0x3dfa6c["PaBhO"]);
|
||
} else {
|
||
_0x2d68ba = _0x2996fd["join"](_0x5b8900, "resources", "app", _0x3dfa6c["cDXTK"], 'vs', _0x3dfa6c["rNqfB"], _0x3dfa6c.PaBhO);
|
||
}
|
||
if (_0xdd2a05.existsSync(_0x2d68ba)) {
|
||
return _0x2d68ba;
|
||
}
|
||
} else {
|
||
let _0x32a80e = 0x3;
|
||
while (_0x32a80e > 0x0) {
|
||
try {
|
||
const _0x34dbe5 = JSON["parse"](fs.readFileSync(_0x4a28ca, _0x3dfa6c["kVXre"]));
|
||
_0x34dbe5["telemetry.machineId"] = _0x13d6be;
|
||
_0x34dbe5[_0x3dfa6c["OoOvL"]] = _0x4520aa;
|
||
_0x34dbe5[_0x3dfa6c["NrAHw"]] = _0x5c9a5c;
|
||
_0x34dbe5["telemetry.sqmId"] = _0x295e98;
|
||
fs.writeFileSync(_0x4a28ca, JSON["stringify"](_0x34dbe5, null, 0x4));
|
||
console["log"](_0x3dfa6c.DYlNA);
|
||
_0x42a386++;
|
||
break;
|
||
} catch (_0x408e1a) {
|
||
_0x32a80e--;
|
||
if (_0x32a80e === 0x0) {
|
||
if (_0x3dfa6c["oWHkO"]("VbcUu", _0x3dfa6c["hazjj"])) {
|
||
_0x5162ea.rmSync(_0x9608e0, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x12202b++;
|
||
_0x22902f.log("[CursorPro] 已清理: " + _0x566ae7);
|
||
} else {
|
||
console["warn"](_0x3dfa6c["sltuA"], _0x408e1a["message"]);
|
||
_0x410d72["push"](_0x3dfa6c.kdlCx);
|
||
}
|
||
} else {
|
||
await new Promise(_0x1fb805 => setTimeout(_0x1fb805, 0x64));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
{
|
||
if (_0x3dfa6c["oWHkO"](_0x3dfa6c.yAadA, "omtSK")) {
|
||
var _0x2a4a6e = [];
|
||
for (var _0x3716c4 in _0x3f83c7) if (_0x2daf25["prototype"]["hasOwnProperty"]["call"](_0x1170bb, _0x3716c4)) {
|
||
_0x2a4a6e[_0x2a4a6e.length] = _0x3716c4;
|
||
}
|
||
return _0x2a4a6e;
|
||
} else {
|
||
let _0x3e6f5a = 0x3;
|
||
while (_0x3e6f5a > 0x0) {
|
||
try {
|
||
const _0x91b94a = path.dirname(_0x2ec82c);
|
||
if (!fs["existsSync"](_0x91b94a)) {
|
||
if (_0x3dfa6c["jVCTI"]('UjEXX', _0x3dfa6c.NgEqy)) {
|
||
fs["mkdirSync"](_0x91b94a, {
|
||
'recursive': true
|
||
});
|
||
} else {
|
||
return _0x5ad776;
|
||
}
|
||
}
|
||
fs["writeFileSync"](_0x2ec82c, _0x13d6be);
|
||
console["log"](_0x3dfa6c["JHBVl"]);
|
||
_0x42a386++;
|
||
break;
|
||
} catch (_0x15034e) {
|
||
_0x3e6f5a--;
|
||
if (_0x3e6f5a === 0x0) {
|
||
console["warn"]("[CursorPro] machineid 更新失败:", _0x15034e["message"]);
|
||
_0x410d72.push(_0x3dfa6c["ihOph"]);
|
||
} else {
|
||
await new Promise(_0x128d98 => setTimeout(_0x128d98, 0x64));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (fs["existsSync"](_0x4aa0cd)) {
|
||
let _0x46b5f7 = 0x3;
|
||
while (_0x3dfa6c["CUSOw"](_0x46b5f7, 0x0)) {
|
||
if ("UbSjF" === _0x3dfa6c["DXmLl"]) {
|
||
try {
|
||
if ("EvWMl" !== _0x3dfa6c["TStTT"]) {
|
||
const _0x49da25 = _0x2aee57.randomUUID();
|
||
0x0;
|
||
const _0x44bd41 = await sqlite_1.sqliteSetBatch(_0x4aa0cd, [['storage.serviceMachineId', _0x49da25]]);
|
||
if (_0x44bd41) {
|
||
console["log"]("[CursorPro] SQLite 数据库已更新");
|
||
_0x42a386++;
|
||
break;
|
||
} else {
|
||
if ('edqsV' !== "edqsV") {
|
||
const _0x480394 = {
|
||
'JDiGp': function (_0x296746, _0xe4a731) {
|
||
return _0x3dfa6c["GpfdI"](_0x296746, _0xe4a731);
|
||
},
|
||
'UJfLB': function (_0x5d0056, _0x5c568b) {
|
||
return _0x3dfa6c["jGfgE"](_0x5d0056, _0x5c568b);
|
||
},
|
||
'YIhbu': _0x3dfa6c["SKKxx"],
|
||
'hQSHL': function (_0x2ecb26, _0x249a15, _0x4919c7, _0x430d9c) {
|
||
return _0x2ecb26(_0x249a15, _0x4919c7, _0x430d9c);
|
||
},
|
||
'iFgQw': function (_0x3a1ffc, _0x7ebf92, _0x57e599) {
|
||
return _0x3a1ffc(_0x7ebf92, _0x57e599);
|
||
}
|
||
};
|
||
var _0x4b98ab = function (_0x111b39) {
|
||
_0x4b98ab = _0x2160f7.getOwnPropertyNames || function (_0x130daa) {
|
||
var _0x41f8fb = [];
|
||
for (var _0x670bc2 in _0x130daa) if (_0x75a24e.prototype["hasOwnProperty"]["call"](_0x130daa, _0x670bc2)) {
|
||
_0x41f8fb[_0x41f8fb["length"]] = _0x670bc2;
|
||
}
|
||
return _0x41f8fb;
|
||
};
|
||
return _0x3dfa6c["mseLD"](_0x4b98ab, _0x111b39);
|
||
};
|
||
return function (_0x20bb6b) {
|
||
if (_0x20bb6b && _0x20bb6b["__esModule"]) {
|
||
return _0x20bb6b;
|
||
}
|
||
var _0x2c00be = {};
|
||
if (_0x480394["JDiGp"](_0x20bb6b, null)) {
|
||
var _0x11069f = _0x4b98ab(_0x20bb6b);
|
||
for (var _0x2599df = 0x0; _0x2599df < _0x11069f["length"]; _0x2599df++) {
|
||
if (_0x3dfa6c["jGfgE"](_0x11069f[_0x2599df], _0x480394["YIhbu"])) {
|
||
_0x480394["hQSHL"](_0x674927, _0x2c00be, _0x20bb6b, _0x11069f[_0x2599df]);
|
||
}
|
||
}
|
||
}
|
||
_0x480394["iFgQw"](_0x240286, _0x2c00be, _0x20bb6b);
|
||
return _0x2c00be;
|
||
};
|
||
} else {
|
||
throw new Error("sqliteSetBatch 返回 false");
|
||
}
|
||
}
|
||
} else {
|
||
throw new _0x1a22ee("sqliteSetBatch 返回 false");
|
||
}
|
||
} catch (_0xfa28ae) {
|
||
_0x46b5f7--;
|
||
if (_0x3dfa6c["dLXnX"](_0x46b5f7, 0x0)) {
|
||
if (_0x3dfa6c["IMEYC"]('pUuQI', _0x3dfa6c["aYwpG"])) {
|
||
_0x964a59["error"](_0x3dfa6c["WWGrA"], _0x9baa98);
|
||
this["_postMessage"]({
|
||
'type': 'networkStatus',
|
||
'online': false
|
||
});
|
||
} else {
|
||
console["warn"](_0x3dfa6c["EdOfO"], _0xfa28ae["message"]);
|
||
_0x410d72["push"]("SQLite");
|
||
}
|
||
} else {
|
||
await new Promise(_0x1eb4ea => setTimeout(_0x1eb4ea, 0x1f4));
|
||
}
|
||
}
|
||
} else {
|
||
_0x38b61c = _0xf3fbd6["trim"]();
|
||
}
|
||
}
|
||
}
|
||
if (_0x5ca938 === _0x3dfa6c.wSpvM) {
|
||
if (_0x3dfa6c["DAvAD"] === 'uxdjv') {
|
||
const _0xc2bf8b = _0x2aee57["randomUUID"]();
|
||
try {
|
||
if (_0x3dfa6c["jVCTI"](_0x3dfa6c.BkSzQ, "lGcMr")) {
|
||
await execAsync('reg add "HKLM\SOFTWARE\Microsoft\Cryptography" /v MachineGuid /t REG_SZ /d "' + _0xc2bf8b + '" /f');
|
||
console.log(_0x3dfa6c["WYomd"]);
|
||
_0x42a386++;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x3dfa6c["VmkCj"],
|
||
'success': false,
|
||
'error': _0x29f22d["error"] || _0x3dfa6c["qukOr"]
|
||
});
|
||
return;
|
||
}
|
||
} catch (_0x2a0e47) {
|
||
console.warn("[CursorPro] 注册表更新失败(需要管理员权限),已跳过");
|
||
_0x410d72["push"]("注册表");
|
||
}
|
||
} else {
|
||
_0x45c2d2 = _0x2be321["getOwnPropertyNames"] || function (_0x5aff3b) {
|
||
var _0x2ac6fe = [];
|
||
for (var _0x56e238 in _0x5aff3b) if (_0x17dada["prototype"]["hasOwnProperty"]["call"](_0x5aff3b, _0x56e238)) {
|
||
_0x2ac6fe[_0x2ac6fe.length] = _0x56e238;
|
||
}
|
||
return _0x2ac6fe;
|
||
};
|
||
return _0x6e782f(_0x5c5de0);
|
||
}
|
||
}
|
||
if (_0x3dfa6c["ZaPkC"](_0x42a386, 0x2)) {
|
||
this["_postMessage"]({
|
||
'type': _0x3dfa6c["fVMJA"],
|
||
'success': true,
|
||
'needRestart': true,
|
||
'message': _0x3dfa6c["dVXng"](_0x410d72["length"], 0x0) ? "机器码重置成功(" + _0x410d72["join"](", ") + " 更新失败,不影响使用)" : _0x3dfa6c["HiGXJ"]
|
||
});
|
||
} else if ("uIJXM" === _0x3dfa6c["dGXfv"]) {
|
||
_0xb3a25e["log"]("[CursorPro] 尝试路径失败:", _0x35bfac, _0x26703c);
|
||
} else {
|
||
this._postMessage({
|
||
'type': "showToast",
|
||
'message': "重置部分失败: " + _0x410d72["join"](", ") + "。请先完全关闭 Cursor 再试",
|
||
'icon': '⚠️'
|
||
});
|
||
}
|
||
} catch (_0x2bd1a8) {
|
||
if ("KokEE" !== _0x3dfa6c.YfRLt) {
|
||
_0x2757ce["log"](_0x3dfa6c["nczgV"]);
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': "showToast",
|
||
'message': "重置机器码失败: " + _0x2bd1a8,
|
||
'icon': '❌'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
._generateRandomMAC() {
|
||
const _0x351246 = {
|
||
'gsyrk': function (_0x2456e7, _0x15dd24) {
|
||
return _0x2456e7(_0x15dd24);
|
||
},
|
||
'lYDrY': 'crypto',
|
||
'RmNIb': function (_0x562f1e, _0xc0a2a9) {
|
||
return _0x562f1e & _0xc0a2a9;
|
||
},
|
||
'WCBzn': function (_0x233015, _0x3ca3bf) {
|
||
return _0x233015 | _0x3ca3bf;
|
||
}
|
||
};
|
||
const _0x539ee8 = _0x351246["gsyrk"](require, _0x351246["lYDrY"]);
|
||
const _0x58dc79 = _0x539ee8["randomBytes"](0x6);
|
||
_0x58dc79[0x0] = _0x351246["RmNIb"](_0x351246["WCBzn"](_0x58dc79[0x0], 0x2), 0xfe);
|
||
return Array.from(_0x58dc79).map(_0x2d538f => _0x2d538f["toString"](0x10)["padStart"](0x2, '0'))["join"](':');
|
||
}
|
||
async ._handleDisableUpdate() {
|
||
const _0xcdd27f = {
|
||
'SlsxX': function (_0x2f9c04, _0x4c19d7) {
|
||
return _0x2f9c04 + _0x4c19d7;
|
||
},
|
||
'obUIO': "cursor-updater",
|
||
'MTNiO': function (_0x2e30f3, _0x4ab64b) {
|
||
return _0x2e30f3 !== _0x4ab64b;
|
||
},
|
||
'Bhmmc': 'Fkark',
|
||
'WHolg': "IvZQp",
|
||
'vJjHJ': 'showToast',
|
||
'KkOxm': "已禁用 Cursor 自动更新"
|
||
};
|
||
try {
|
||
const _0x24fe79 = process["env"]["LOCALAPPDATA"] || '';
|
||
const _0xac3e10 = path["join"](_0x24fe79, _0xcdd27f["obUIO"]);
|
||
if (fs["existsSync"](_0xac3e10)) {
|
||
if (_0xcdd27f["MTNiO"](_0xcdd27f["Bhmmc"], _0xcdd27f["Bhmmc"])) {
|
||
return false;
|
||
} else if (fs.statSync(_0xac3e10).isDirectory()) {
|
||
if (_0xcdd27f["MTNiO"](_0xcdd27f.WHolg, "IvZQp")) {
|
||
_0x5481a7 = _0x5e122b.substring(0x0, _0x4f63e3) + _0x214640["substring"](_0xcdd27f["SlsxX"](_0x5cc883, 0x7));
|
||
} else {
|
||
fs["rmSync"](_0xac3e10, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
}
|
||
} else {
|
||
fs["unlinkSync"](_0xac3e10);
|
||
}
|
||
}
|
||
fs["writeFileSync"](_0xac3e10, '');
|
||
this["_postMessage"]({
|
||
'type': 'showToast',
|
||
'message': _0xcdd27f["KkOxm"],
|
||
'icon': '✅'
|
||
});
|
||
} catch (_0x387797) {
|
||
this._postMessage({
|
||
'type': _0xcdd27f["vJjHJ"],
|
||
'message': "禁用自动更新失败: " + _0x387797,
|
||
'icon': '❌'
|
||
});
|
||
}
|
||
}
|
||
async ["_handleCleanEnv"]() {
|
||
const _0x5d7007 = {
|
||
'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 (_0x449fed, _0x1e0222) {
|
||
return _0x449fed === _0x1e0222;
|
||
},
|
||
'pYIFs': function (_0x3cef7a, _0x51f2f4) {
|
||
return _0x3cef7a in _0x51f2f4;
|
||
},
|
||
'JBwTr': 'get',
|
||
'koIoR': function (_0x43e103, _0x5178fd) {
|
||
return _0x43e103 === _0x5178fd;
|
||
},
|
||
'PGlXD': "win32",
|
||
'GTTuL': function (_0x5b1681, _0x264692) {
|
||
return _0x5b1681 === _0x264692;
|
||
},
|
||
'Psmij': "rhIFB",
|
||
'gYxAu': 'xYuSE',
|
||
'MuQDV': function (_0x4cb02b, _0x14cda9) {
|
||
return _0x4cb02b(_0x14cda9);
|
||
},
|
||
'IKcBt': "pkill -f Cursor",
|
||
'RPLYj': function (_0x1c7600, _0xe03586) {
|
||
return _0x1c7600 === _0xe03586;
|
||
},
|
||
'MGVKs': function (_0x4fe688, _0x467499) {
|
||
return _0x4fe688 !== _0x467499;
|
||
},
|
||
'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"] === _0x5d7007.PGlXD) {
|
||
await execAsync("taskkill /F /IM Cursor.exe")["catch"](() => {});
|
||
} else if (_0x5d7007["Psmij"] === _0x5d7007["gYxAu"]) {
|
||
this._postMessage({
|
||
'type': "showToast",
|
||
'message': "禁用自动更新失败: " + _0xaf40e5,
|
||
'icon': '❌'
|
||
});
|
||
} else {
|
||
await _0x5d7007["MuQDV"](execAsync, _0x5d7007["IKcBt"]).catch(() => {});
|
||
}
|
||
await new Promise(_0x30bca7 => setTimeout(_0x30bca7, 0x7d0));
|
||
const _0x27dda7 = process.env["APPDATA"] || '';
|
||
const _0x2dfaf0 = process["env"].LOCALAPPDATA || '';
|
||
const _0x2bcaef = process["env"].HOME || process.env["USERPROFILE"] || '';
|
||
let _0x1e982b = 0x0;
|
||
if (process.platform === _0x5d7007["PGlXD"]) {
|
||
if (_0x5d7007["MGVKs"]('OMLAe', _0x5d7007["ryaos"])) {
|
||
const _0x680500 = [path.join(_0x27dda7, _0x5d7007["voPhc"]), path["join"](_0x2dfaf0, _0x5d7007["voPhc"]), path["join"](_0x2dfaf0, _0x5d7007.lXGbz), path["join"](_0x2bcaef, _0x5d7007["xKriv"])];
|
||
for (const _0x395cca of _0x680500) {
|
||
if (_0x5d7007["ZoVAa"] !== "CTJTi") {
|
||
this._postMessage({
|
||
'type': 'userSwitchStatus',
|
||
'valid': false,
|
||
'switchRemaining': 0x0,
|
||
'canSwitch': false,
|
||
'error': '获取状态失败'
|
||
});
|
||
} else {
|
||
try {
|
||
if (fs["existsSync"](_0x395cca)) {
|
||
if (_0x5d7007["aPXBq"](_0x5d7007["MCBOh"], _0x5d7007["pGLVT"])) {
|
||
this["_postMessage"]({
|
||
'type': _0x5d7007["QgDaW"],
|
||
'online': _0x1e9bca
|
||
});
|
||
} else {
|
||
fs["rmSync"](_0x395cca, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x1e982b++;
|
||
console["log"]("[CursorPro] 已清理: " + _0x395cca);
|
||
}
|
||
}
|
||
} catch (_0x47ea0c) {
|
||
console["warn"]("[CursorPro] 清理失败: " + _0x395cca, _0x47ea0c);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
_0x305e73["log"](_0x5d7007["rCPOJ"]);
|
||
}
|
||
} else {
|
||
if (process["platform"] === _0x5d7007["OUBfk"]) {
|
||
const _0x173109 = [path["join"](_0x2bcaef, "Library", "Application Support", _0x5d7007["voPhc"]), path["join"](_0x2bcaef, "Library", _0x5d7007["FYnvF"], _0x5d7007["voPhc"]), path["join"](_0x2bcaef, _0x5d7007.uIkRt, _0x5d7007["tQzIF"], _0x5d7007.voPhc), path.join(_0x2bcaef, 'Library', "Application Support", 'Caches', _0x5d7007.lXGbz), path["join"](_0x2bcaef, _0x5d7007["xKriv"])];
|
||
for (const _0x151011 of _0x173109) {
|
||
if ("ZwnwK" === "juOiE") {
|
||
const _0x4223b9 = _0x6afa13["readFileSync"](_0x263f1d, 'utf-8');
|
||
const _0x4ffeb2 = _0x2673e3["parse"](_0x4223b9);
|
||
if (_0x4ffeb2["version"]) {
|
||
_0x4e128b["log"](_0x5d7007["FZidX"], _0x4ffeb2["version"], _0x5d7007["nLBbF"], _0x3afc55);
|
||
return _0x4ffeb2["version"];
|
||
}
|
||
} else {
|
||
try {
|
||
if (fs["existsSync"](_0x151011)) {
|
||
if (_0x5d7007["HlGXa"] !== _0x5d7007["EtSsM"]) {
|
||
fs["rmSync"](_0x151011, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x1e982b++;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x5d7007["tRjSQ"],
|
||
'success': false,
|
||
'error': _0x1b6792.error || _0x5d7007["BlfQc"]
|
||
});
|
||
}
|
||
}
|
||
} catch (_0x52cb05) {
|
||
if (_0x5d7007.FNyIR !== _0x5d7007["WPZrs"]) {
|
||
console["warn"]("[CursorPro] 清理失败: " + _0x151011, _0x52cb05);
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x5d7007["JlTFY"],
|
||
'success': false,
|
||
'error': _0xd37ccd["error"] || _0x5d7007["cqICS"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
const _0x305f11 = [path["join"](_0x2bcaef, ".config", _0x5d7007["voPhc"]), path.join(_0x2bcaef, _0x5d7007["jyFFs"], _0x5d7007["voPhc"]), path["join"](_0x2bcaef, _0x5d7007["hMrGj"], _0x5d7007.ISlsh, _0x5d7007.voPhc), path["join"](_0x2bcaef, _0x5d7007.xKriv)];
|
||
for (const _0x5bbdfa of _0x305f11) {
|
||
if ('lkchx' !== _0x5d7007["yteSk"]) {
|
||
_0x17a266["error"](_0x5d7007["JPunF"]);
|
||
_0xc8224e["error"](_0x5d7007["KMKzx"], _0x45b7c8);
|
||
_0x557053["error"](_0x5d7007["xFYQT"], _0x27fd6a.length);
|
||
_0x3c4a59["error"](_0x5d7007.hxRZC, _0x23fb79);
|
||
const _0x1c19d0 = _0x54cc25["includes"]('_showNotification');
|
||
const _0x605a0e = _0x4b5d6c["includes"]("getItems()");
|
||
_0x24e1b7.error("[CursorPro] 包含 _showNotification:", _0x1c19d0);
|
||
_0x16679d["error"]("[CursorPro] 包含 getItems():", _0x605a0e);
|
||
this["_postMessage"]({
|
||
'type': _0x5d7007["IjZFI"],
|
||
'success': false,
|
||
'error': _0x5d7007["JiWRI"],
|
||
'details': "路径: " + _0x8d33d3
|
||
});
|
||
return;
|
||
} else {
|
||
try {
|
||
if (fs.existsSync(_0x5bbdfa)) {
|
||
fs.rmSync(_0x5bbdfa, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x1e982b++;
|
||
}
|
||
} catch (_0x3fff64) {
|
||
if ('SPIaC' === _0x5d7007["Prgty"]) {
|
||
console["warn"]("[CursorPro] 清理失败: " + _0x5bbdfa, _0x3fff64);
|
||
} else {
|
||
if (_0x5a8ee0 === _0x67147f) {
|
||
_0x11f2b9 = _0x3ddb74;
|
||
}
|
||
var _0x5443a8 = _0x3e5510["getOwnPropertyDescriptor"](_0xf4f8d, _0x23f58b);
|
||
if (!_0x5443a8 || (_0x5d7007["pYIFs"]('get', _0x5443a8) ? !_0x30ad0e["__esModule"] : _0x5443a8["writable"] || _0x5443a8["configurable"])) {
|
||
_0x5443a8 = {
|
||
'enumerable': true,
|
||
'get': function () {
|
||
return _0x3769fc[_0x59f7bf];
|
||
}
|
||
};
|
||
}
|
||
_0xdc785.defineProperty(_0x25dfad, _0x4b142f, _0x5443a8);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
vscode["window"]["showInformationMessage"]("✅ Cursor 环境清理完成!已清理 " + _0x1e982b + " 个目录。请重新启动 Cursor。");
|
||
} catch (_0x559de5) {
|
||
if (_0x5d7007["WVkud"] !== _0x5d7007["okltc"]) {
|
||
vscode["window"].showErrorMessage("清理失败: " + _0x559de5);
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
._cleanProxySettings() {
|
||
const _0x476eaf = {
|
||
'rbZoX': "/etc/hosts",
|
||
'eHWqT': function (_0x4595b3, _0x51481f) {
|
||
return _0x4595b3 > _0x51481f;
|
||
},
|
||
'UIOhf': 'versionCheck',
|
||
'jYVrR': "app",
|
||
'vgDUh': "package.json",
|
||
'rqoZM': '连接服务器失败',
|
||
'PbRuC': 'uJNLm',
|
||
'ctBOw': function (_0x3ad726, _0x1a1bc9) {
|
||
return _0x3ad726 === _0x1a1bc9;
|
||
},
|
||
'YNRuA': function (_0x374e35, _0x5f2806) {
|
||
return _0x374e35 !== _0x5f2806;
|
||
},
|
||
'AcPSo': "Cursor",
|
||
'XeYdv': 'User',
|
||
'sRZng': "darwin",
|
||
'EYltU': 'Library',
|
||
'cngrf': "Application Support",
|
||
'bQVqg': "settings.json",
|
||
'lMMGf': "UAknb",
|
||
'eEioj': ".config",
|
||
'aTJcA': "TSToT",
|
||
'YGjhE': function (_0xb1f254, _0x285077) {
|
||
return _0xb1f254 in _0x285077;
|
||
},
|
||
'TTFqW': "tQfhG",
|
||
'dtgRq': 'xvUoy',
|
||
'KqxTd': "utf-8",
|
||
'ANrMY': "[CursorPro] 清理 settings.json 代理配置失败:"
|
||
};
|
||
try {
|
||
if (_0x476eaf["PbRuC"] === _0x476eaf["PbRuC"]) {
|
||
const _0x232e3c = process["platform"];
|
||
const _0x35e9f7 = process["env"]["HOME"] || process.env["USERPROFILE"] || '';
|
||
let _0x50dd63;
|
||
if (_0x476eaf["ctBOw"](_0x232e3c, "win32")) {
|
||
if (_0x476eaf["YNRuA"]("xHyzt", "xHyzt")) {
|
||
return _0x476eaf["rbZoX"];
|
||
} else {
|
||
const _0x3f558b = process.env["APPDATA"] || '';
|
||
_0x50dd63 = path.join(_0x3f558b, _0x476eaf["AcPSo"], _0x476eaf["XeYdv"], "settings.json");
|
||
}
|
||
} else {
|
||
if (_0x232e3c === _0x476eaf["sRZng"]) {
|
||
_0x50dd63 = path["join"](_0x35e9f7, _0x476eaf["EYltU"], _0x476eaf["cngrf"], _0x476eaf["AcPSo"], 'User', _0x476eaf["bQVqg"]);
|
||
} else {
|
||
if (_0x476eaf["ctBOw"](_0x476eaf["lMMGf"], 'UAknb')) {
|
||
_0x50dd63 = path["join"](_0x35e9f7, _0x476eaf["eEioj"], _0x476eaf["AcPSo"], _0x476eaf["XeYdv"], _0x476eaf["bQVqg"]);
|
||
} else {
|
||
const _0x13402f = _0xb498dc["version"];
|
||
const _0x50bf1b = _0x227cb4.CURRENT_VERSION;
|
||
const _0x310335 = _0x476eaf["eHWqT"](this["_compareVersions"](_0x13402f, _0x50bf1b), 0x0);
|
||
this["_postMessage"]({
|
||
'type': _0x476eaf["UIOhf"],
|
||
'success': true,
|
||
'currentVersion': _0x50bf1b,
|
||
'latestVersion': _0x13402f,
|
||
'hasUpdate': _0x310335
|
||
});
|
||
}
|
||
}
|
||
}
|
||
if (!fs.existsSync(_0x50dd63)) {
|
||
return;
|
||
}
|
||
const _0x3b1f5e = fs["readFileSync"](_0x50dd63, 'utf-8');
|
||
let _0x2d1395;
|
||
try {
|
||
_0x2d1395 = JSON.parse(_0x3b1f5e);
|
||
} catch {
|
||
if (_0x476eaf.aTJcA === _0x476eaf.aTJcA) {
|
||
return;
|
||
} else {
|
||
_0x374c70 = _0xf2eaf5.join(_0x313a74, "resources", _0x476eaf["jYVrR"], _0x476eaf.vgDUh);
|
||
}
|
||
}
|
||
const _0x312520 = ["http.proxy", "http.proxyStrictSSL", "http.proxySupport", "cursor.general.disableHttp2", "http.noProxy"];
|
||
let _0x163e93 = false;
|
||
for (const _0x2ee1a1 of _0x312520) {
|
||
if (_0x2ee1a1 in _0x2d1395) {
|
||
_0x163e93 = true;
|
||
delete _0x2d1395[_0x2ee1a1];
|
||
}
|
||
}
|
||
if (_0x163e93) {
|
||
if (_0x476eaf["TTFqW"] !== 'xvUoy') {
|
||
fs["writeFileSync"](_0x50dd63, JSON["stringify"](_0x2d1395, null, 0x4), _0x476eaf["KqxTd"]);
|
||
console["log"]("[CursorPro] 已清理 settings.json 中的旧代理配置");
|
||
} else {
|
||
_0x54658c = _0x115a6a[0x1]["trim"]();
|
||
}
|
||
}
|
||
} else {
|
||
const _0x75d65c = _0x5b4ad7?.["message"] || '连接服务器失败';
|
||
this["_postMessage"]({
|
||
'type': "manualSeamlessSwitched",
|
||
'success': false,
|
||
'error': _0x75d65c
|
||
});
|
||
}
|
||
} catch (_0xaf9b9c) {
|
||
console["warn"](_0x476eaf.ANrMY, _0xaf9b9c);
|
||
}
|
||
}
|
||
["_getHostsPath"]() {
|
||
const _0x1afd5f = {
|
||
'IIhaI': "win32",
|
||
'rhwiN': "C:\\Windows\\System32\\drivers\\etc\\hosts",
|
||
'WCHqe': '/etc/hosts'
|
||
};
|
||
return process.platform === _0x1afd5f["IIhaI"] ? _0x1afd5f["rhwiN"] : '/etc/hosts';
|
||
}
|
||
._readHostsFile() {
|
||
const _0x2eb328 = {
|
||
'wAevF': "[CursorPro] 写入本地失败:",
|
||
'sUhUV': function (_0x5ed9b2, _0x485978) {
|
||
return _0x5ed9b2 !== _0x485978;
|
||
},
|
||
'hsoXL': 'SLTdx',
|
||
'XvGHn': 'utf-8',
|
||
'LHIiR': "[CursorPro] Read hosts error:"
|
||
};
|
||
try {
|
||
if (_0x2eb328["sUhUV"]('SLTdx', _0x2eb328["hsoXL"])) {
|
||
_0x154660["error"](_0x2eb328["wAevF"], _0x1f3d21);
|
||
_0x12820c.window["showErrorMessage"]("写入失败: " + _0x430c52);
|
||
return false;
|
||
} else {
|
||
const _0x49f82f = this["_getHostsPath"]();
|
||
if (fs["existsSync"](_0x49f82f)) {
|
||
return fs.readFileSync(_0x49f82f, _0x2eb328["XvGHn"]);
|
||
}
|
||
}
|
||
} catch (_0x280006) {
|
||
console["error"](_0x2eb328["LHIiR"], _0x280006);
|
||
}
|
||
return '';
|
||
}
|
||
["_hasHostsConfig"]() {
|
||
const _0x18cd4d = this["_readHostsFile"]();
|
||
return _0x18cd4d["includes"](this["HOSTS_MARKER_START"]);
|
||
}
|
||
async ._grantHostsWritePermission() {
|
||
const _0x32c62b = {
|
||
'vkbEE': "seamlessStatus",
|
||
'seTZS': '检测状态失败',
|
||
'hKgsG': function (_0x4a5bc9, _0x2bfac2) {
|
||
return _0x4a5bc9 !== _0x2bfac2;
|
||
},
|
||
'ScmlY': "win32",
|
||
'HqZOI': "ffBKI",
|
||
'Qwoeu': function (_0x36c14a, _0x3b36cd) {
|
||
return _0x36c14a(_0x3b36cd);
|
||
},
|
||
'mzHlg': "[CursorPro] Hosts file permission granted to user:",
|
||
'wVYbp': "[CursorPro] Grant hosts permission error:"
|
||
};
|
||
if (_0x32c62b["hKgsG"](process["platform"], _0x32c62b["ScmlY"])) {
|
||
return false;
|
||
}
|
||
try {
|
||
if (_0x32c62b["HqZOI"] === _0x32c62b["HqZOI"]) {
|
||
const _0x4dd7b0 = this._getHostsPath();
|
||
const _0x52e208 = process["env"].USERNAME || '';
|
||
if (!_0x52e208) {
|
||
return false;
|
||
}
|
||
const _0xb2d318 = _0x4dd7b0["replace"](/\\/g, "\\\\");
|
||
const _0x1a66f9 = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command icacls \\\"" + _0xb2d318 + '\" /grant ' + _0x52e208 + ":M' -Verb RunAs -Wait\"";
|
||
await _0x32c62b["Qwoeu"](execAsync, _0x1a66f9);
|
||
this["_hostsPermissionGranted"] = true;
|
||
console["log"](_0x32c62b["mzHlg"], _0x52e208);
|
||
return true;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x32c62b.vkbEE,
|
||
'is_injected': false,
|
||
'error': _0x32c62b["seTZS"]
|
||
});
|
||
}
|
||
} catch (_0x32d96e) {
|
||
console["error"](_0x32c62b["wVYbp"], _0x32d96e);
|
||
return false;
|
||
}
|
||
}
|
||
async ["_writeHostsFile"](_0x5922a3) {
|
||
const _0x499688 = {
|
||
'xBPFl': "usageCheckResult",
|
||
'JhZQT': "未激活授权码",
|
||
'iNsae': 'cursorAuth/cachedSignUpType',
|
||
'AmHRk': "cursorAuth/stripeMembershipType",
|
||
'FOcWe': function (_0x5324f3, _0x2a612f) {
|
||
return _0x5324f3 === _0x2a612f;
|
||
},
|
||
'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 (_0x12ee8c, _0x39fa65) {
|
||
return _0x12ee8c !== _0x39fa65;
|
||
},
|
||
'OaUGz': "XVhkW",
|
||
'ofVDg': "kizvY",
|
||
'NrWkg': function (_0x3a76ad, _0x4ab4f9) {
|
||
return _0x3a76ad(_0x4ab4f9);
|
||
},
|
||
'sPvNi': "ipconfig /flushdns",
|
||
'iDcQt': function (_0x54a20c, _0x2484fe) {
|
||
return _0x54a20c === _0x2484fe;
|
||
},
|
||
'HLfqb': "darwin",
|
||
'vgoUd': "/tmp/hosts_cursor_temp",
|
||
'HGnBv': function (_0x134b08, _0x2d8a5b) {
|
||
return _0x134b08(_0x2d8a5b);
|
||
},
|
||
'jDqga': 'BDewf',
|
||
'txnlf': "[CursorPro] Write hosts error:"
|
||
};
|
||
const _0x2983c4 = this["_getHostsPath"]();
|
||
try {
|
||
if (_0x499688["FOcWe"](process.platform, _0x499688.KudFK)) {
|
||
let _0x27620a = false;
|
||
try {
|
||
if (_0x499688["Vogwl"] !== _0x499688["Vogwl"]) {
|
||
_0x3ec235 = _0x26751d["dirname"](_0x1b0534["trim"]());
|
||
} else {
|
||
fs["writeFileSync"](_0x2983c4, _0x5922a3, _0x499688["JcomX"]);
|
||
_0x27620a = true;
|
||
}
|
||
} catch (_0x2a820d) {
|
||
console["log"](_0x499688["ERSCs"]);
|
||
}
|
||
if (!_0x27620a) {
|
||
if (!this._hostsPermissionGranted) {
|
||
const _0x1cf639 = await this["_grantHostsWritePermission"]();
|
||
if (_0x1cf639) {
|
||
if (_0x499688["oXrgE"] === _0x499688["YmFQv"]) {
|
||
this._postMessage({
|
||
'type': _0x499688.xBPFl,
|
||
'success': false,
|
||
'error': _0x499688["JhZQT"]
|
||
});
|
||
return;
|
||
} else {
|
||
try {
|
||
fs["writeFileSync"](_0x2983c4, _0x5922a3, _0x499688["JcomX"]);
|
||
_0x27620a = true;
|
||
} catch (_0x22fb5c) {
|
||
console["log"]("[CursorPro] Write still failed after permission grant");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (!_0x27620a) {
|
||
const _0x1e3a86 = path["join"](process["env"]["TEMP"] || '', _0x499688.CGqqu);
|
||
fs["writeFileSync"](_0x1e3a86, _0x5922a3, _0x499688["JcomX"]);
|
||
const _0x2cf526 = _0x1e3a86["replace"](/\\/g, "\\\\");
|
||
const _0x456ea4 = _0x2983c4["replace"](/\\/g, "\\\\");
|
||
const _0x2a923f = "powershell -WindowStyle Hidden -Command \"Start-Process powershell -ArgumentList '-WindowStyle Hidden -Command Copy-Item -Path \\\"" + _0x2cf526 + '\" -Destination \"' + _0x456ea4 + "\\\" -Force' -Verb RunAs -Wait\"";
|
||
await execAsync(_0x2a923f);
|
||
try {
|
||
if (_0x499688["OaUGz"] !== _0x499688["ofVDg"]) {
|
||
fs["unlinkSync"](_0x1e3a86);
|
||
} else {
|
||
_0x23b2c1["push"]([_0x499688["iNsae"], _0x2e0cc7.sign_up_type]);
|
||
}
|
||
} catch {}
|
||
}
|
||
try {
|
||
await _0x499688["NrWkg"](execAsync, _0x499688["sPvNi"]);
|
||
console["log"]("[CursorPro] Windows DNS 缓存已刷新");
|
||
} catch (_0x460c7f) {
|
||
console.warn("[CursorPro] Windows DNS 刷新失败:", _0x460c7f);
|
||
}
|
||
} else {
|
||
if (_0x499688["iDcQt"](process["platform"], _0x499688.HLfqb)) {
|
||
const _0x24a472 = _0x499688["vgoUd"];
|
||
fs["writeFileSync"](_0x24a472, _0x5922a3, _0x499688["JcomX"]);
|
||
const _0x22f069 = "do shell script \"cp '" + _0x24a472 + "' '" + _0x2983c4 + "' && rm '" + _0x24a472 + "' && dscacheutil -flushcache && killall -HUP mDNSResponder\" with administrator privileges";
|
||
await _0x499688["HGnBv"](execAsync, 'osascript -e "' + _0x22f069.replace(/"/g, "\\\"") + "\"");
|
||
} else {
|
||
fs["writeFileSync"](_0x2983c4, _0x5922a3, _0x499688["JcomX"]);
|
||
}
|
||
}
|
||
return true;
|
||
} catch (_0x4e285f) {
|
||
console["error"](_0x499688["txnlf"], _0x4e285f);
|
||
return false;
|
||
}
|
||
}
|
||
async ["_handleToggleProxy"](_0x45fe86, _0x2bcba7) {
|
||
const _0x55a623 = {
|
||
'ejdVR': "[CursorPro] 检测无感换号状态失败:",
|
||
'PEste': function (_0x53a002, _0x4c22fe) {
|
||
return _0x53a002 === _0x4c22fe;
|
||
},
|
||
'hgedP': "win32",
|
||
'qGQVl': "[CursorPro] macOS 获取进程路径失败:",
|
||
'uJGtI': function (_0x48017f, _0x5c2c7c) {
|
||
return _0x48017f !== _0x5c2c7c;
|
||
},
|
||
'JOyUC': "owyly",
|
||
'abtRx': "JZnQC",
|
||
'bPNQC': "cursorpro.key",
|
||
'XKRmO': 'cursorpro.expireDate',
|
||
'lrUSI': "proxyUpdated",
|
||
'wngsU': '请先激活授权码',
|
||
'bNcBC': 'showToast',
|
||
'wbUaU': "nMubd",
|
||
'qvcRi': function (_0x6220c6, _0x46b6bf) {
|
||
return _0x6220c6 > _0x46b6bf;
|
||
},
|
||
'rBQDv': "授权码已过期,无法开启免魔法",
|
||
'RrtRU': function (_0x572eb6, _0x46c0a4) {
|
||
return _0x572eb6 !== _0x46c0a4;
|
||
},
|
||
'PoFgx': "BHFHl",
|
||
'xXref': function (_0x1b909c, _0x5c9bad) {
|
||
return _0x1b909c + _0x5c9bad;
|
||
},
|
||
'HwXSS': function (_0x576fb0, _0x41a4c1) {
|
||
return _0x576fb0 !== _0x41a4c1;
|
||
},
|
||
'LwgUG': "ejFIc",
|
||
'yTNgQ': "QrGmP",
|
||
'rATBP': "免魔法已关闭",
|
||
'jtzgG': "修改 hosts 文件失败,请确保有管理员权限",
|
||
'SfnWE': '更新配置失败'
|
||
};
|
||
try {
|
||
if ("JCMUi" === "JCMUi") {
|
||
if (_0x45fe86) {
|
||
if (_0x55a623["uJGtI"](_0x55a623.JOyUC, _0x55a623["abtRx"])) {
|
||
const _0x2e87c9 = this["_context"]["globalState"]["get"](_0x55a623["bPNQC"]);
|
||
const _0x4818f7 = this._context.globalState.get('cursorpro.expireDate');
|
||
if (!_0x2e87c9) {
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["lrUSI"],
|
||
'success': false,
|
||
'error': _0x55a623["wngsU"]
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["bNcBC"],
|
||
'message': '请先激活授权码',
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
if (_0x4818f7) {
|
||
if (_0x55a623["wbUaU"] === _0x55a623.wbUaU) {
|
||
const _0x13c1c7 = new Date(_0x4818f7)["getTime"]();
|
||
if (_0x55a623["qvcRi"](Date["now"](), _0x13c1c7)) {
|
||
this._postMessage({
|
||
'type': _0x55a623["lrUSI"],
|
||
'success': false,
|
||
'error': _0x55a623.rBQDv
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["bNcBC"],
|
||
'message': _0x55a623["rBQDv"],
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
} else {
|
||
_0xdb849d["error"]("[CursorPro] 检测无感换号状态失败:", _0x27cca9);
|
||
return false;
|
||
}
|
||
}
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
this["_cleanProxySettings"]();
|
||
let _0x41dcbc = this["_readHostsFile"]();
|
||
const _0x8cbdf8 = _0x41dcbc["indexOf"](this["HOSTS_MARKER_START"]);
|
||
const _0x5529db = _0x41dcbc["indexOf"](this.HOSTS_MARKER_END);
|
||
if (_0x55a623["uJGtI"](_0x8cbdf8, -0x1) && _0x5529db !== -0x1) {
|
||
if (_0x55a623["PoFgx"] !== 'jcvMA') {
|
||
_0x41dcbc = _0x41dcbc.substring(0x0, _0x8cbdf8) + _0x41dcbc["substring"](_0x55a623["xXref"](_0x5529db, this.HOSTS_MARKER_END["length"]));
|
||
} else {
|
||
return _0x55a623["PEste"](_0x52d6bb["platform"], _0x55a623.hgedP) ? "C:\\Windows\\System32\\drivers\\etc\\hosts" : "/etc/hosts";
|
||
}
|
||
}
|
||
_0x41dcbc = _0x41dcbc["replace"](/\n{3,}/g, "\n\n")["trim"]();
|
||
if (_0x45fe86) {
|
||
const _0x3c2da2 = this.CURSOR_DOMAINS.map(_0x2b32f6 => this.SNI_PROXY_IP + " " + _0x2b32f6)["join"]("\n");
|
||
const _0x12c61b = "\n\n" + this.HOSTS_MARKER_START + "\n" + _0x3c2da2 + "\n" + this["HOSTS_MARKER_END"] + "\n";
|
||
_0x41dcbc += _0x12c61b;
|
||
}
|
||
const _0x5b508c = await this._writeHostsFile(_0x41dcbc);
|
||
if (_0x5b508c) {
|
||
if (_0x55a623.LwgUG !== _0x55a623["yTNgQ"]) {
|
||
0x0;
|
||
await client_1["updateProxyConfig"](_0x45fe86, this["SNI_PROXY_IP"]);
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["lrUSI"],
|
||
'success': true,
|
||
'enabled': _0x45fe86,
|
||
'url': this.SNI_PROXY_IP
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["bNcBC"],
|
||
'message': _0x45fe86 ? "免魔法已开启" : _0x55a623["rATBP"],
|
||
'icon': '✅'
|
||
});
|
||
} else {
|
||
_0x5dcacb.log("[CursorPro] 快捷方式解析获取路径失败");
|
||
}
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': "proxyUpdated",
|
||
'success': false,
|
||
'error': _0x55a623["jtzgG"]
|
||
});
|
||
this._postMessage({
|
||
'type': "showToast",
|
||
'message': "需要管理员权限修改 hosts 文件",
|
||
'icon': '⚠️'
|
||
});
|
||
}
|
||
} else {
|
||
_0x2faaed["warn"](_0x55a623["qGQVl"], _0x591cf9);
|
||
}
|
||
} catch (_0x15bb87) {
|
||
console["error"]("[CursorPro] Toggle proxy error:", _0x15bb87);
|
||
this["_postMessage"]({
|
||
'type': _0x55a623["lrUSI"],
|
||
'success': false,
|
||
'error': _0x55a623["SfnWE"]
|
||
});
|
||
}
|
||
}
|
||
async ["_handleGetProxyStatus"]() {
|
||
const _0x2c5a98 = {
|
||
'fZAIy': "[CursorPro] Get proxy status error:",
|
||
'wipaS': "proxyStatus"
|
||
};
|
||
try {
|
||
const _0x45986e = this["_hasHostsConfig"]();
|
||
this._postMessage({
|
||
'type': "proxyStatus",
|
||
'enabled': _0x45986e,
|
||
'url': _0x45986e ? this.SNI_PROXY_IP : ''
|
||
});
|
||
} catch (_0x590417) {
|
||
console.error(_0x2c5a98["fZAIy"], _0x590417);
|
||
this._postMessage({
|
||
'type': _0x2c5a98["wipaS"],
|
||
'enabled': false,
|
||
'url': ''
|
||
});
|
||
}
|
||
}
|
||
async ["_handleGetSeamlessStatus"]() {
|
||
const _0x5ae0f5 = {
|
||
'KFUBS': 'seamlessStatus',
|
||
'rCNDh': '未找到'
|
||
};
|
||
try {
|
||
const _0x95ad53 = await this["_getWorkbenchPathAsync"]();
|
||
let _0x571ba2 = false;
|
||
if (_0x95ad53 && fs.existsSync(_0x95ad53)) {
|
||
const _0x16bc8d = fs["readFileSync"](_0x95ad53, 'utf-8');
|
||
_0x571ba2 = this["_checkInjected"](_0x16bc8d);
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x5ae0f5["KFUBS"],
|
||
'is_injected': _0x571ba2,
|
||
'workbench_path': _0x95ad53 || '未找到'
|
||
});
|
||
} catch (_0x4253d3) {
|
||
this["_postMessage"]({
|
||
'type': "seamlessStatus",
|
||
'is_injected': false,
|
||
'error': "检测状态失败"
|
||
});
|
||
}
|
||
}
|
||
async ._getCursorInstallPath() {
|
||
const _0x56e2a7 = {
|
||
'Dikkd': "showToast",
|
||
'jsXpS': "请先激活授权码",
|
||
'YOVDn': "更新配置失败",
|
||
'iTlfT': "[CursorPro] 创建备份文件",
|
||
'yLNTm': 'resources',
|
||
'GeHhf': 'app',
|
||
'CXUfC': "package.json",
|
||
'UtnZu': "[CursorPro] 读取账号失败:",
|
||
'gnUSM': "[CursorPro] 写入文件失败:",
|
||
'bYxaW': function (_0x423a3a, _0x5db055) {
|
||
return _0x423a3a === _0x5db055;
|
||
},
|
||
'EgKGn': "EPERM",
|
||
'EAHLk': function (_0x337fa2, _0x2cea6d) {
|
||
return _0x337fa2 === _0x2cea6d;
|
||
},
|
||
'WjWcW': "EACCES",
|
||
'MQZgl': "EROFS",
|
||
'oengj': function (_0x277036, _0x403852) {
|
||
return _0x277036 === _0x403852;
|
||
},
|
||
'Aarxw': 'darwin',
|
||
'DJbBl': "没有写入权限,请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
|
||
'aREDm': "seamlessInjected",
|
||
'iIXMD': "usageCheckResult",
|
||
'BDJnl': function (_0x1e4a2f, _0x534c0a) {
|
||
return _0x1e4a2f(_0x534c0a);
|
||
},
|
||
'DtDgA': function (_0x29bc62, _0x322a2b) {
|
||
return _0x29bc62 < _0x322a2b;
|
||
},
|
||
'mmvWR': "[CursorPro] SQLite 更新失败:",
|
||
'oaRrk': "SQLite",
|
||
'CTVdA': function (_0x74a645, _0x1120bf) {
|
||
return _0x74a645 * _0x1120bf;
|
||
},
|
||
'Uuffn': 'userSwitchStatus',
|
||
'rBiqx': "未激活授权码",
|
||
'rQFft': "cursorPath",
|
||
'RnudW': "[CursorPro] 使用用户配置的 Cursor 路径:",
|
||
'PVaIE': "win32",
|
||
'XfqQZ': function (_0x9c7d0d, _0x5e3a66) {
|
||
return _0x9c7d0d(_0x5e3a66);
|
||
},
|
||
'DeasY': function (_0x4abb75, _0x582177) {
|
||
return _0x4abb75 !== _0x582177;
|
||
},
|
||
'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 (_0x124977, _0x7c188e) {
|
||
return _0x124977 !== _0x7c188e;
|
||
},
|
||
'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 (_0x20ef8a, _0x2ae693) {
|
||
return _0x20ef8a(_0x2ae693);
|
||
},
|
||
'ZzzNm': "reg query \"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\" /s /f \"Cursor\" 2>nul | findstr \"InstallLocation\"",
|
||
'nbZaF': function (_0x1cbd3c, _0x4a6cb7) {
|
||
return _0x1cbd3c === _0x4a6cb7;
|
||
},
|
||
'wbtDv': "vnDbD",
|
||
'cNdLq': 'xFoOA',
|
||
'FZvwj': 'OHDPB',
|
||
'UneuY': 'Microsoft',
|
||
'qsIby': "Windows",
|
||
'EHZof': 'Cursor.lnk',
|
||
'jjkbK': "C:\\ProgramData",
|
||
'BtFbH': "Start Menu",
|
||
'JdBJc': function (_0x28f75d, _0x183780) {
|
||
return _0x28f75d(_0x183780);
|
||
},
|
||
'jsxnQ': function (_0x136514, _0x280034) {
|
||
return _0x136514 === _0x280034;
|
||
},
|
||
'qBUXV': "[CursorPro] 快捷方式解析获取路径失败",
|
||
'exySU': "vhjCP",
|
||
'TGkVo': function (_0x23968b, _0x7071) {
|
||
return _0x23968b !== _0x7071;
|
||
},
|
||
'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 (_0x28fb08, _0xcbe128) {
|
||
return _0x28fb08 !== _0xcbe128;
|
||
},
|
||
'HILVh': "iDOKM",
|
||
'smRnq': "EZQju",
|
||
'goLBO': function (_0x534585, _0x3cba48) {
|
||
return _0x534585(_0x3cba48);
|
||
},
|
||
'PfsJK': function (_0x1edda8, _0x24c322) {
|
||
return _0x1edda8 !== _0x24c322;
|
||
},
|
||
'SZhcT': "kFqGj",
|
||
'NkvWo': "AvPWh",
|
||
'fIoaQ': function (_0x241ec0, _0x2ed30c) {
|
||
return _0x241ec0 === _0x2ed30c;
|
||
},
|
||
'AEQys': "DLzJi",
|
||
'DMxiK': "fmKaB",
|
||
'KCchE': "ps -eo comm,args | grep -i \"[C]ursor\" | grep -v \"grep\" | head -1",
|
||
'oSNCM': "[CursorPro] macOS 获取进程路径失败:",
|
||
'vFKuA': function (_0x3f2aba, _0x3b57d7) {
|
||
return _0x3f2aba !== _0x3b57d7;
|
||
},
|
||
'BzqQS': "LPxcr",
|
||
'Iiavz': function (_0x518563, _0x266c3c) {
|
||
return _0x518563(_0x266c3c);
|
||
},
|
||
'DTxsT': "mdfind \"kMDItemCFBundleIdentifier == 'com.todesktop.*cursor*'\" 2>/dev/null | head -1",
|
||
'Duhra': '/Applications/Cursor.app',
|
||
'TWejg': function (_0x5bd29f, _0x55a6c4) {
|
||
return _0x5bd29f(_0x55a6c4);
|
||
},
|
||
'hHnTm': function (_0x24d237, _0x40656e) {
|
||
return _0x24d237(_0x40656e);
|
||
},
|
||
'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 _0x39cd5d = vscode["workspace"]["getConfiguration"]("cursorpro");
|
||
const _0x3bf8b8 = _0x39cd5d["get"](_0x56e2a7.rQFft);
|
||
if (_0x3bf8b8 && fs["existsSync"](_0x3bf8b8)) {
|
||
console["log"](_0x56e2a7["RnudW"], _0x3bf8b8);
|
||
this._cachedCursorPath = _0x3bf8b8;
|
||
return _0x3bf8b8;
|
||
}
|
||
const _0x51335c = process["platform"];
|
||
let _0x36d8e8 = null;
|
||
try {
|
||
if (_0x51335c === _0x56e2a7.PVaIE) {
|
||
try {
|
||
const {
|
||
stdout: _0x446f65
|
||
} = await execAsync("wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul");
|
||
if (_0x446f65) {
|
||
if (_0x56e2a7["DeasY"](_0x56e2a7["AsIZj"], _0x56e2a7["AsIZj"])) {
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7["Dikkd"],
|
||
'message': _0x56e2a7.jsXpS,
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
} else {
|
||
const _0x19ca83 = _0x446f65["match"](/ExecutablePath=(.+)/);
|
||
if (_0x19ca83 && _0x19ca83[0x1]) {
|
||
if (_0x56e2a7["nqiCC"] === "qzRkG") {
|
||
this._postMessage({
|
||
'type': "showToast",
|
||
'message': "重置机器码失败: " + _0x51bc1d,
|
||
'icon': '❌'
|
||
});
|
||
} else {
|
||
const _0x27a427 = _0x19ca83[0x1]["trim"]();
|
||
_0x36d8e8 = path["dirname"](_0x27a427);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x4c944d) {
|
||
console["log"](_0x56e2a7.QVuwP);
|
||
}
|
||
if (!_0x36d8e8) {
|
||
if ('YbsJH' !== _0x56e2a7["jErMS"]) {
|
||
try {
|
||
const {
|
||
stdout: _0x2ac2d3
|
||
} = await _0x56e2a7["BDJnl"](execAsync, _0x56e2a7.NyxMG);
|
||
if (_0x2ac2d3 && _0x2ac2d3["trim"]()) {
|
||
_0x36d8e8 = path["dirname"](_0x2ac2d3["trim"]());
|
||
}
|
||
} catch (_0x387539) {
|
||
if (_0x56e2a7["wEuDv"](_0x56e2a7.XOHNV, "idSrD")) {
|
||
console.log(_0x56e2a7["TGItL"]);
|
||
} else if (_0x36e365["includes"](_0x216fbb.scode)) {
|
||
_0x51a668 = _0x5d60b0["replace"](_0x562774["scode"], _0x1ac061["replacement"]);
|
||
_0x15853d["push"](_0x1d4997["name"]);
|
||
} else {
|
||
_0x41fc0e["push"](_0x551686["name"]);
|
||
}
|
||
}
|
||
} else {
|
||
_0x86b57c = _0xcd7e5a["dirname"](_0x337963);
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
try {
|
||
const {
|
||
stdout: _0x1bbadc
|
||
} = await execAsync(_0x56e2a7["thwli"]);
|
||
if (_0x1bbadc && _0x1bbadc.trim()) {
|
||
const _0x53b6fb = _0x1bbadc.match(/InstallLocation\s+REG_SZ\s+(.+)/);
|
||
if (_0x53b6fb && _0x53b6fb[0x1] && fs["existsSync"](_0x53b6fb[0x1]["trim"]())) {
|
||
if (_0x56e2a7["VMcWU"] !== _0x56e2a7.QxSsa) {
|
||
_0x36d8e8 = _0x53b6fb[0x1]["trim"]();
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': "proxyUpdated",
|
||
'success': false,
|
||
'error': _0x56e2a7["jsXpS"]
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7["Dikkd"],
|
||
'message': _0x56e2a7["jsXpS"],
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x4253cf) {
|
||
if (_0x56e2a7["dCyzn"] !== _0x56e2a7["fdUBf"]) {
|
||
console.log(_0x56e2a7.PIiyE);
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': 'seamlessConfigUpdated',
|
||
'success': false,
|
||
'error': _0x56e2a7["YOVDn"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
try {
|
||
const {
|
||
stdout: _0xf5d246
|
||
} = await execAsync(_0x56e2a7["ZzzNm"]);
|
||
if (_0xf5d246 && _0xf5d246.trim()) {
|
||
const _0x3c2cd7 = _0xf5d246["match"](/InstallLocation\s+REG_SZ\s+(.+)/);
|
||
if (_0x3c2cd7 && _0x3c2cd7[0x1] && fs.existsSync(_0x3c2cd7[0x1].trim())) {
|
||
if (_0x56e2a7["nbZaF"](_0x56e2a7["wbtDv"], _0x56e2a7["cNdLq"])) {
|
||
_0x371f53 = _0x3146b2["replace"](_0x262100["scode"], _0x35b030["replacement"]);
|
||
_0x2f13c6.push(_0x495b54.name);
|
||
} else {
|
||
_0x36d8e8 = _0x3c2cd7[0x1]["trim"]();
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x38448a) {
|
||
console["log"]("[CursorPro] 注册表方法2获取路径失败");
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
if (_0x56e2a7["FZvwj"] !== 'ASYNt') {
|
||
try {
|
||
const _0x4a36af = path["join"](process["env"]["APPDATA"] || '', _0x56e2a7["UneuY"], _0x56e2a7.qsIby, "Start Menu", 'Programs', _0x56e2a7["EHZof"]);
|
||
const _0x3876ac = path["join"](_0x56e2a7["jjkbK"], _0x56e2a7["UneuY"], 'Windows', _0x56e2a7["BtFbH"], "Programs", _0x56e2a7["EHZof"]);
|
||
for (const _0x20745d of [_0x4a36af, _0x3876ac]) {
|
||
if (fs["existsSync"](_0x20745d)) {
|
||
const {
|
||
stdout: _0x321537
|
||
} = await execAsync("powershell -Command \"(New-Object -ComObject WScript.Shell).CreateShortcut('" + _0x20745d["replace"](/'/g, "''") + "').TargetPath\"");
|
||
if (_0x321537 && _0x321537.trim() && fs.existsSync(_0x321537["trim"]())) {
|
||
if (_0x56e2a7["jsxnQ"]("EzvlI", "EzvlI")) {
|
||
_0x36d8e8 = path["dirname"](_0x321537["trim"]());
|
||
break;
|
||
} else {
|
||
_0x5839cf = ["/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js"];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x628be0) {
|
||
console["log"](_0x56e2a7["qBUXV"]);
|
||
}
|
||
} else {
|
||
const _0x41d381 = _0x1d7b98.match(/ExecutablePath=(.+)/);
|
||
if (_0x41d381 && _0x41d381[0x1]) {
|
||
const _0x311d7f = _0x41d381[0x1]["trim"]();
|
||
_0x7495 = _0x387799["dirname"](_0x311d7f);
|
||
}
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
if (_0x56e2a7["exySU"] === _0x56e2a7["exySU"]) {
|
||
try {
|
||
const {
|
||
stdout: _0x4d3618
|
||
} = await _0x56e2a7["JdBJc"](execAsync, "where cursor 2>nul");
|
||
if (_0x4d3618 && _0x4d3618["trim"]()) {
|
||
const _0x1e390f = _0x4d3618.trim()["split"]("\n");
|
||
for (const _0x4be01a of _0x1e390f) {
|
||
const _0x2817ed = _0x4be01a.trim();
|
||
if (_0x2817ed && fs.existsSync(_0x2817ed)) {
|
||
_0x36d8e8 = path["dirname"](_0x2817ed);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x2b8ad6) {
|
||
if ("BQAEU" !== _0x56e2a7["suGMP"]) {
|
||
_0x33db66["copyFileSync"](_0x51579c, _0x931655);
|
||
_0x261bd5["log"](_0x56e2a7["iTlfT"]);
|
||
} else {
|
||
console["log"](_0x56e2a7["UFTPT"]);
|
||
}
|
||
}
|
||
} else {
|
||
const _0x4c6948 = _0x4dafc4[0x1].trim();
|
||
_0x373919 = _0x57ec2c.dirname(_0x4c6948);
|
||
_0x543724 = _0x3fcb44["join"](_0x2ba35f, _0x56e2a7["yLNTm"], _0x56e2a7["GeHhf"], _0x56e2a7["CXUfC"]);
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
const _0x526dcd = process["env"].LOCALAPPDATA || '';
|
||
const _0x11abe2 = process["env"]["USERPROFILE"] || '';
|
||
const _0x5a2b8c = process["env"]["ProgramFiles"] || _0x56e2a7["DmbzX"];
|
||
const _0x53bae9 = process["env"][_0x56e2a7["pezWM"]] || "C:\\Program Files (x86)";
|
||
const _0x7ed789 = [path["join"](_0x526dcd, _0x56e2a7.siiYr, _0x56e2a7.qYQbK), path.join(_0x526dcd, _0x56e2a7["siiYr"], _0x56e2a7["IrvuT"]), path["join"](_0x11abe2, _0x56e2a7["GSVlF"], _0x56e2a7.MCVpB, _0x56e2a7.siiYr, _0x56e2a7.qYQbK), path.join(_0x5a2b8c, _0x56e2a7.qYQbK), path["join"](_0x53bae9, "Cursor"), path.join(_0x526dcd, _0x56e2a7["qYQbK"]), path["join"](_0x526dcd, _0x56e2a7["IrvuT"])];
|
||
for (const _0x5e748e of _0x7ed789) {
|
||
if (_0x56e2a7["EAHLk"]("mDWBe", _0x56e2a7["PDSZm"])) {
|
||
_0x4e428d.error(_0x56e2a7["UtnZu"], _0x4ee69e);
|
||
return [];
|
||
} else {
|
||
if (_0x5e748e && fs["existsSync"](_0x5e748e)) {
|
||
_0x36d8e8 = _0x5e748e;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (_0x51335c === _0x56e2a7["Aarxw"]) {
|
||
if (_0x56e2a7["EgLjx"](_0x56e2a7.HILVh, "mPbmb")) {
|
||
try {
|
||
if ("VYhDm" === _0x56e2a7["smRnq"]) {
|
||
_0x3f27c6.error(_0x56e2a7["gnUSM"], _0x16e0a9);
|
||
if (_0x56e2a7["bYxaW"](_0x3fa137["code"], _0x56e2a7["EgKGn"]) || _0x56e2a7["EAHLk"](_0x50c56a["code"], _0x56e2a7["WjWcW"]) || _0x2fdaaf.code === _0x56e2a7.MQZgl) {
|
||
const _0x2f5e07 = _0xf7d812["platform"];
|
||
let _0xee0d40 = "没有写入权限";
|
||
if (_0x56e2a7["oengj"](_0x2f5e07, 'darwin')) {
|
||
_0xee0d40 = _0x56e2a7["DJbBl"];
|
||
} else if (_0x2f5e07 === "linux") {
|
||
_0xee0d40 = "没有写入权限,请使用 sudo 权限运行或修改文件权限";
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7["aREDm"],
|
||
'success': false,
|
||
'error': _0xee0d40,
|
||
'needAdmin': true,
|
||
'path': _0x4f0e82
|
||
});
|
||
return;
|
||
}
|
||
throw _0x47d908;
|
||
} else {
|
||
const {
|
||
stdout: _0x369a56
|
||
} = await _0x56e2a7["goLBO"](execAsync, "lsof -c Cursor 2>/dev/null | grep \"txt\" | grep -i \"Cursor.app\" | head -1 | awk '{print $9}'");
|
||
if (_0x369a56 && _0x369a56.trim()) {
|
||
if (_0x56e2a7.SZhcT !== _0x56e2a7["SZhcT"]) {
|
||
this["_postMessage"]({
|
||
'type': "usageCheckResult",
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
} else {
|
||
const _0x257e0d = _0x369a56.trim()["match"](/(.+\.app)/);
|
||
if (_0x257e0d) {
|
||
if (_0x56e2a7["bYxaW"](_0x56e2a7.NkvWo, 'hsffN')) {
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7["iIXMD"],
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
return;
|
||
} else {
|
||
_0x36d8e8 = _0x257e0d[0x1];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x1b82a1) {}
|
||
if (!_0x36d8e8) {
|
||
try {
|
||
if (_0x56e2a7["fIoaQ"](_0x56e2a7.AEQys, _0x56e2a7["DMxiK"])) {
|
||
const _0x3b6ec9 = _0x4396d5.data["usage"] || {};
|
||
const _0x318ca7 = _0x56e2a7["BDJnl"](_0x5a3f82, _0x3b6ec9["totalCostUSD"] || 0x0);
|
||
if (_0x56e2a7["DtDgA"](_0x318ca7, 0xa)) {
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7.iIXMD,
|
||
'success': true,
|
||
'needConfirm': true,
|
||
'costUSD': _0x318ca7.toFixed(0x2),
|
||
'email': _0x430d08
|
||
});
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x56e2a7["iIXMD"],
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
}
|
||
} else {
|
||
const {
|
||
stdout: _0x58b89f
|
||
} = await execAsync(_0x56e2a7["KCchE"]);
|
||
if (_0x58b89f && _0x58b89f.trim()) {
|
||
const _0x488389 = _0x58b89f["match"](/(\/.+\.app)/);
|
||
if (_0x488389) {
|
||
_0x36d8e8 = _0x488389[0x1];
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x58c36b) {
|
||
console.warn(_0x56e2a7["oSNCM"], _0x58c36b);
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
if (_0x56e2a7["vFKuA"]("LPxcr", _0x56e2a7["BzqQS"])) {
|
||
_0x178033.error("[CursorPro] Write hosts error:", _0x1a091f);
|
||
return false;
|
||
} else {
|
||
try {
|
||
const {
|
||
stdout: _0x45fa41
|
||
} = await execAsync(_0x56e2a7["DTxsT"]);
|
||
if (_0x45fa41 && _0x45fa41.trim() && fs.existsSync(_0x45fa41["trim"]())) {
|
||
_0x36d8e8 = _0x45fa41.trim();
|
||
}
|
||
} catch (_0x141dcf) {}
|
||
}
|
||
}
|
||
if (!_0x36d8e8 && fs["existsSync"]('/Applications/Cursor.app')) {
|
||
_0x36d8e8 = _0x56e2a7["Duhra"];
|
||
}
|
||
} else {
|
||
_0x221adf["warn"](_0x56e2a7["mmvWR"], _0x45ce1f.message);
|
||
_0x2ae3cb["push"](_0x56e2a7["oaRrk"]);
|
||
}
|
||
} else {
|
||
try {
|
||
const {
|
||
stdout: _0x11564d
|
||
} = await execAsync('pgrep -f "[c]ursor" | head -1');
|
||
const _0x5dd0f3 = _0x11564d && _0x11564d.trim();
|
||
if (_0x5dd0f3) {
|
||
const {
|
||
stdout: _0x447245
|
||
} = await _0x56e2a7["hHnTm"](execAsync, "readlink -f /proc/" + _0x5dd0f3 + "/exe 2>/dev/null");
|
||
if (_0x447245 && _0x447245["trim"]()) {
|
||
const _0x11b963 = _0x447245["trim"]();
|
||
_0x36d8e8 = path.dirname(_0x11b963);
|
||
if (_0x36d8e8["endsWith"](_0x56e2a7["ytsfa"])) {
|
||
_0x36d8e8 = path["dirname"](_0x36d8e8);
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x27a28d) {}
|
||
if (!_0x36d8e8) {
|
||
if ("BDrEe" !== _0x56e2a7["fYZrC"]) {
|
||
let _0x34acf5 = '';
|
||
const _0x3634b6 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||
for (let _0x1963ff = 0x0; _0x1963ff < 0x20; _0x1963ff++) {
|
||
_0x34acf5 += _0x3634b6.charAt(_0x5a7f9b["floor"](_0x142a7a["random"]() * _0x3634b6["length"]));
|
||
}
|
||
return _0x34acf5;
|
||
} else {
|
||
try {
|
||
const {
|
||
stdout: _0x400a70
|
||
} = await _0x56e2a7["BDJnl"](execAsync, _0x56e2a7["TLLsB"]);
|
||
if (_0x400a70 && _0x400a70.trim()) {
|
||
const _0x44bb60 = await execAsync('readlink -f "' + _0x400a70.trim() + '" 2>/dev/null');
|
||
if (_0x44bb60.stdout && _0x44bb60["stdout"].trim()) {
|
||
_0x36d8e8 = path["dirname"](_0x44bb60["stdout"].trim());
|
||
if (_0x36d8e8["endsWith"]('/bin')) {
|
||
if (_0x56e2a7["oengj"](_0x56e2a7.IGQIN, "ZRSMl")) {
|
||
this["_postMessage"]({
|
||
'type': 'userSwitchStatus',
|
||
'valid': false,
|
||
'switchRemaining': 0x0,
|
||
'canSwitch': false,
|
||
'error': _0x56e2a7["rBiqx"]
|
||
});
|
||
return;
|
||
} else {
|
||
_0x36d8e8 = path["dirname"](_0x36d8e8);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x1d7835) {
|
||
console["warn"](_0x56e2a7["rbFqJ"], _0x1d7835);
|
||
}
|
||
}
|
||
}
|
||
if (!_0x36d8e8) {
|
||
const _0x38357a = [_0x56e2a7["WgRyf"], _0x56e2a7["XOLnJ"], _0x56e2a7["fxGJt"], _0x56e2a7["lzEMa"], path["join"](process["env"]["HOME"] || '', ".local/share/cursor"), path.join(process["env"]["HOME"] || '', _0x56e2a7["gQXjY"])];
|
||
for (const _0x3a8856 of _0x38357a) {
|
||
if (fs.existsSync(_0x3a8856)) {
|
||
_0x36d8e8 = _0x3a8856;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x2440bb) {
|
||
console["error"](_0x56e2a7["EghBP"], _0x2440bb);
|
||
}
|
||
if (_0x36d8e8) {
|
||
this._cachedCursorPath = _0x36d8e8;
|
||
}
|
||
return _0x36d8e8;
|
||
}
|
||
._getWorkbenchPath() {
|
||
return this["_getWorkbenchPathSync"]();
|
||
}
|
||
._getWorkbenchPathSync() {
|
||
const _0x45dfd9 = {
|
||
'UfpAf': "storage.serviceMachineId",
|
||
'Anviz': "[CursorPro] machineid 更新失败:",
|
||
'VVCFs': "machineid",
|
||
'JyreV': function (_0x2669b9, _0x3af5b1) {
|
||
return _0x2669b9(_0x3af5b1);
|
||
},
|
||
'LuKVI': 'crypto',
|
||
'SWJRm': function (_0xc6cc6a, _0x1e79ba) {
|
||
return _0xc6cc6a & _0x1e79ba;
|
||
},
|
||
'FQssd': function (_0x36d4a3, _0x3f9411) {
|
||
return _0x36d4a3 !== _0x3f9411;
|
||
},
|
||
'eUATr': function (_0x5176f0, _0x2f72df) {
|
||
return _0x5176f0 === _0x2f72df;
|
||
},
|
||
'jTUqv': "darwin",
|
||
'VLslV': 'xuLZV',
|
||
'UWqNM': "app",
|
||
'sQFsh': "out",
|
||
'eRJjA': "workbench",
|
||
'gkqWe': "workbench.desktop.main.js",
|
||
'ZSOkm': function (_0x45c79f, _0x381d17) {
|
||
return _0x45c79f !== _0x381d17;
|
||
},
|
||
'SccyE': "kWVws",
|
||
'dVhNW': "resources",
|
||
'VfwmP': function (_0x239346, _0xe3f08f) {
|
||
return _0x239346 === _0xe3f08f;
|
||
},
|
||
'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 _0x476275 = process["platform"];
|
||
if (this._cachedCursorPath) {
|
||
if (_0x45dfd9["FQssd"]('zZyLK', "PQRiM")) {
|
||
let _0x3205e4;
|
||
if (_0x45dfd9["eUATr"](_0x476275, _0x45dfd9["jTUqv"])) {
|
||
if (_0x45dfd9["eUATr"]("xuLZV", 'xuLZV')) {
|
||
_0x3205e4 = path.join(this["_cachedCursorPath"], 'Contents', "Resources", _0x45dfd9["UWqNM"], _0x45dfd9["sQFsh"], 'vs', _0x45dfd9.eRJjA, _0x45dfd9["gkqWe"]);
|
||
} else {
|
||
_0x3e2976["push"]([_0x45dfd9["UfpAf"], _0x4568af["serviceMachineId"]]);
|
||
}
|
||
} else if (_0x45dfd9["ZSOkm"]("XbfIf", _0x45dfd9["SccyE"])) {
|
||
_0x3205e4 = path["join"](this["_cachedCursorPath"], _0x45dfd9.dVhNW, "app", _0x45dfd9["sQFsh"], 'vs', _0x45dfd9["eRJjA"], "workbench.desktop.main.js");
|
||
} else {
|
||
_0x575999["warn"](_0x45dfd9["Anviz"], _0x58392c.message);
|
||
_0x8af8ae["push"](_0x45dfd9["VVCFs"]);
|
||
}
|
||
if (fs.existsSync(_0x3205e4)) {
|
||
return _0x3205e4;
|
||
}
|
||
} else {
|
||
return [];
|
||
}
|
||
}
|
||
if (_0x45dfd9["eUATr"](_0x476275, 'win32')) {
|
||
return null;
|
||
}
|
||
let _0x5a8c19 = [];
|
||
if (_0x45dfd9["VfwmP"](_0x476275, _0x45dfd9.jTUqv)) {
|
||
_0x5a8c19 = [_0x45dfd9["NyLwi"]];
|
||
} else {
|
||
if ('DESET' !== _0x45dfd9["aJjyB"]) {
|
||
_0x5a8c19 = [_0x45dfd9["bWpPz"], '/usr/share/cursor/resources/app/out/vs/workbench/workbench.desktop.main.js'];
|
||
} else {
|
||
const _0x495a3b = _0x45dfd9["JyreV"](_0x32b48c, 'crypto');
|
||
const _0xfc487e = _0x495a3b["randomBytes"](0x6);
|
||
_0xfc487e[0x0] = _0x45dfd9["SWJRm"](_0xfc487e[0x0] | 0x2, 0xfe);
|
||
return _0x55363f["from"](_0xfc487e)["map"](_0x210fd8 => _0x210fd8.toString(0x10)["padStart"](0x2, '0'))["join"](':');
|
||
}
|
||
}
|
||
for (const _0x3c46cb of _0x5a8c19) {
|
||
if (fs["existsSync"](_0x3c46cb)) {
|
||
return _0x3c46cb;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
async ["_getWorkbenchPathAsync"]() {
|
||
const _0x333f76 = {
|
||
'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 (_0x175f78, _0x5a924f) {
|
||
return _0x175f78 === _0x5a924f;
|
||
},
|
||
'fYTsi': "EUUHA",
|
||
'idevD': "eXeOK",
|
||
'SJHtk': function (_0x48c702, _0x410996) {
|
||
return _0x48c702 === _0x410996;
|
||
},
|
||
'AJPrD': "darwin",
|
||
'qcilt': function (_0x48c64d, _0x367af2) {
|
||
return _0x48c64d === _0x367af2;
|
||
},
|
||
'yQEWX': "vUlDT",
|
||
'Knhyl': "Contents",
|
||
'NPYXr': "Resources",
|
||
'xDNVo': "out",
|
||
'Lnhsa': "workbench",
|
||
'ejmIv': "workbench.desktop.main.js",
|
||
'yfprZ': "dtGAS"
|
||
};
|
||
const _0x4a5df6 = process.platform;
|
||
const _0x1a6628 = await this["_getCursorInstallPath"]();
|
||
if (_0x1a6628) {
|
||
if (_0x333f76["ktVBs"](_0x333f76["fYTsi"], _0x333f76["idevD"])) {
|
||
const _0x56cab4 = _0x12c65b[0x1]["trim"]();
|
||
_0x13e8cf = _0x13c1c8["dirname"](_0x56cab4);
|
||
} else {
|
||
let _0x469a72;
|
||
if (_0x4a5df6 === _0x333f76["AJPrD"]) {
|
||
if (_0x333f76["qcilt"](_0x333f76["yQEWX"], _0x333f76.yQEWX)) {
|
||
_0x469a72 = path["join"](_0x1a6628, _0x333f76["Knhyl"], _0x333f76.NPYXr, _0x333f76["JBwsK"], _0x333f76["xDNVo"], 'vs', _0x333f76.Lnhsa, _0x333f76["ejmIv"]);
|
||
} else {
|
||
const _0x2ee571 = _0x2f3785["env"].LOCALAPPDATA || '';
|
||
const _0x5b8a61 = _0x36b6d4["env"]["USERPROFILE"] || '';
|
||
const _0x534e4d = _0x38e95c.env["ProgramFiles"] || _0x333f76["diJhY"];
|
||
const _0x5281b8 = _0x2279f9["env"][_0x333f76["BHmwx"]] || _0x333f76["xDKiN"];
|
||
_0x344063["push"](_0x3b35ac["join"](_0x2ee571, _0x333f76["aIUry"], _0x333f76.oemiO, _0x333f76.wNjLv, "app", _0x333f76["BzPhh"]), _0x1d0746["join"](_0x2ee571, _0x333f76["aIUry"], _0x333f76["dNHJx"], _0x333f76["wNjLv"], _0x333f76["JBwsK"], _0x333f76["BzPhh"]), _0x3cb2bc["join"](_0x5b8a61, _0x333f76["NoEGQ"], _0x333f76["GOKzJ"], _0x333f76["aIUry"], _0x333f76["oemiO"], "resources", _0x333f76.JBwsK, "package.json"), _0x2db72["join"](_0x534e4d, "Cursor", "resources", "app", _0x333f76.BzPhh), _0x118213["join"](_0x534e4d, _0x333f76.dNHJx, _0x333f76["wNjLv"], _0x333f76["JBwsK"], _0x333f76["BzPhh"]), _0x56d86f["join"](_0x5281b8, _0x333f76.oemiO, "resources", _0x333f76["JBwsK"], "package.json"));
|
||
}
|
||
} else {
|
||
_0x469a72 = path["join"](_0x1a6628, _0x333f76.wNjLv, _0x333f76.JBwsK, _0x333f76["xDNVo"], 'vs', _0x333f76["Lnhsa"], "workbench.desktop.main.js");
|
||
}
|
||
if (fs["existsSync"](_0x469a72)) {
|
||
if (_0x333f76.yfprZ === _0x333f76["yfprZ"]) {
|
||
return _0x469a72;
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x333f76["okosv"],
|
||
'success': false,
|
||
'currentVersion': _0x13b64d.CURRENT_VERSION,
|
||
'error': _0x1da786["message"] || "请求失败"
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return this._getWorkbenchPathSync();
|
||
}
|
||
["_checkInjected"](_0x7082c6) {
|
||
const _0x5ec24a = {
|
||
'WkvEt': "/*i0*/"
|
||
};
|
||
return _0x7082c6["includes"](_0x5ec24a.WkvEt) || _0x7082c6.includes('/*i1s*/');
|
||
}
|
||
async ["_isSeamlessInjected"]() {
|
||
const _0x29b677 = {
|
||
'gPIxP': "utf-8",
|
||
'ntlpp': "[CursorPro] 检测无感换号状态失败:"
|
||
};
|
||
try {
|
||
const _0x1a2041 = await this._getWorkbenchPathAsync();
|
||
if (_0x1a2041 && fs["existsSync"](_0x1a2041)) {
|
||
const _0x432d66 = fs["readFileSync"](_0x1a2041, _0x29b677["gPIxP"]);
|
||
return this["_checkInjected"](_0x432d66);
|
||
}
|
||
return false;
|
||
} catch (_0x337782) {
|
||
console.error(_0x29b677["ntlpp"], _0x337782);
|
||
return false;
|
||
}
|
||
}
|
||
._getInjectionConfig(_0x1083ec, _0x19a8d2) {
|
||
const _0x1829e6 = {
|
||
'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': _0x1829e6["FgaCg"],
|
||
'replacement': "_showNotification(){/*i0*/}_showNotificationOld(){",
|
||
'restore': {
|
||
'find': _0x1829e6["OHrmM"],
|
||
'replace_with': _0x1829e6["FgaCg"]
|
||
}
|
||
}, {
|
||
'name': "注入点1: 核心模块初始化",
|
||
'scode': _0x1829e6["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='" + _0x1083ec + "';window.__cpUserKey='" + _0x19a8d2 + "';window.__cpVersion=0;console.log('[CP] Initialized with key:','" + _0x19a8d2 + "'.substring(0,15)+'...')}})(this)/*i1e*/",
|
||
'restore': {
|
||
'find_start': _0x1829e6["MqHGw"],
|
||
'find_end': _0x1829e6["OSWSK"]
|
||
}
|
||
}, {
|
||
'name': _0x1829e6["QXMFr"],
|
||
'scode': _0x1829e6["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': _0x1829e6["hxXLs"]
|
||
}
|
||
}];
|
||
}
|
||
async ["_handleInjectSeamless"]() {
|
||
const _0x4fdfb6 = {
|
||
'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 (_0x5dd144, _0x2310ea) {
|
||
return _0x5dd144 !== _0x2310ea;
|
||
},
|
||
'mZDVz': 'reoBh',
|
||
'XlzQa': "seamlessInjected",
|
||
'RKaZM': "授权码无效",
|
||
'wFOsZ': function (_0x6d21a5, _0x3149e3) {
|
||
return _0x6d21a5 === _0x3149e3;
|
||
},
|
||
'uTxRa': "wecNx",
|
||
'NQBnu': "启用失败",
|
||
'QwROM': function (_0x43ac94, _0xa61565) {
|
||
return _0x43ac94 + _0xa61565;
|
||
},
|
||
'KPHtC': ".backup",
|
||
'BJIgK': "cursorpro.seamlessInjected",
|
||
'asGDz': function (_0x58de12, _0x3456ca) {
|
||
return _0x58de12 === _0x3456ca;
|
||
},
|
||
'AvMcE': "grpZy",
|
||
'NFNQK': "[CursorPro] 首次启用,从备份恢复干净的 workbench 文件",
|
||
'ApEZm': "[CursorPro] 备份恢复成功",
|
||
'WEdcP': function (_0x1e1572, _0x389e03) {
|
||
return _0x1e1572 === _0x389e03;
|
||
},
|
||
'NwiBk': "jYehy",
|
||
'fWqWm': "gRHmI",
|
||
'PuBtb': function (_0x29c277, _0x1a6e1f) {
|
||
return _0x29c277 === _0x1a6e1f;
|
||
},
|
||
'QPTVv': "[CursorPro] 注入失败,未找到任何注入点",
|
||
'bwZyq': "[CursorPro] 文件路径:",
|
||
'isjyP': "[CursorPro] 文件大小:",
|
||
'nGlvY': "_showNotification",
|
||
'eLVeH': "getItems()",
|
||
'JDsIJ': "[CursorPro] 包含 _showNotification:",
|
||
'Spptx': "[CursorPro] 包含 getItems():",
|
||
'OaqMs': "Cursor 版本不兼容,注入点未找到",
|
||
'CqvrX': function (_0x5599e0, _0x5736b6) {
|
||
return _0x5599e0 > _0x5736b6;
|
||
},
|
||
'tdJex': "[CursorPro] 未找到的注入点:",
|
||
'IsXFU': function (_0x32bf90, _0x554c91) {
|
||
return _0x32bf90 === _0x554c91;
|
||
},
|
||
'NpueJ': "txcqo",
|
||
'chYLS': "[CursorPro] 写入文件失败:",
|
||
'qFuwX': 'EACCES',
|
||
'jWyZD': "没有写入权限,请在终端执行: sudo chmod -R 777 /Applications/Cursor.app",
|
||
'nsFtB': function (_0x385d3c, _0x38d8b9) {
|
||
return _0x385d3c === _0x38d8b9;
|
||
},
|
||
'vryqQ': "linux",
|
||
'FiwIr': "gWxzY",
|
||
'NnBbT': "qchHx",
|
||
'kofbg': "没有写入权限,请使用 sudo 权限运行或修改文件权限",
|
||
'WedEJ': "无感换号已启用",
|
||
'jiObk': "nUNdq",
|
||
'chXsS': "[CursorPro] Inject error:",
|
||
'PfOPU': "EPERM",
|
||
'GZrDV': function (_0x122af4, _0x148522) {
|
||
return _0x122af4 === _0x148522;
|
||
},
|
||
'SUpCK': 'TKgrk',
|
||
'JOonS': "rIkKS",
|
||
'uvZZD': "没有写入权限"
|
||
};
|
||
try {
|
||
const _0x4a9f7b = this._context["globalState"].get("cursorpro.key");
|
||
if (!_0x4a9f7b) {
|
||
if (_0x4fdfb6["nmpHW"]("dlteM", 'reoBh')) {
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': "请先激活授权码"
|
||
});
|
||
return;
|
||
} else {
|
||
_0x548dfc.push(_0x3afbb1["join"](_0x180fb4, _0x4fdfb6["eAudc"], _0x4fdfb6["ZnFEJ"], _0x4fdfb6["QGTLQ"]));
|
||
}
|
||
}
|
||
0x0;
|
||
const _0x358ad2 = await client_1["getUserSwitchStatus"](_0x4a9f7b);
|
||
if (!_0x358ad2.valid) {
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0x358ad2["error"] || _0x4fdfb6["RKaZM"]
|
||
});
|
||
return;
|
||
}
|
||
const _0x1f82b7 = await this["_getWorkbenchPathAsync"]();
|
||
if (!_0x1f82b7) {
|
||
if (_0x4fdfb6["wFOsZ"](_0x4fdfb6["uTxRa"], _0x4fdfb6["uTxRa"])) {
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0x4fdfb6["NQBnu"]
|
||
});
|
||
return;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': 'keyStatusChecked',
|
||
'valid': false,
|
||
'expired': true,
|
||
'error': _0x2b03db["error"] || _0x4fdfb6["yDFID"]
|
||
});
|
||
}
|
||
}
|
||
const _0xcc733a = _0x4fdfb6["QwROM"](_0x1f82b7, _0x4fdfb6["KPHtC"]);
|
||
const _0x3dee3a = !this._context.globalState["get"](_0x4fdfb6["BJIgK"]);
|
||
if (_0x3dee3a && fs["existsSync"](_0xcc733a)) {
|
||
if (_0x4fdfb6["asGDz"]("xfseF", _0x4fdfb6["AvMcE"])) {
|
||
_0x41a723 = _0x4ad1c8;
|
||
if (_0x53f68b === _0x4fdfb6["XoRrm"]) {
|
||
_0x4d9364 = _0x1d4e3d["join"](_0xea2f6b, _0x4fdfb6.zcMpa, _0x4fdfb6["cTyAN"], _0x4fdfb6["ZnFEJ"], 'package.json');
|
||
} else {
|
||
_0x4ea91b = _0x247fd6.join(_0x348c77, _0x4fdfb6["eAudc"], _0x4fdfb6["ZnFEJ"], 'package.json');
|
||
}
|
||
_0x43e5e3.log(_0x4fdfb6.UNUES, _0x5e9043);
|
||
} else {
|
||
console.log(_0x4fdfb6["NFNQK"]);
|
||
try {
|
||
fs["copyFileSync"](_0xcc733a, _0x1f82b7);
|
||
console.log(_0x4fdfb6["ApEZm"]);
|
||
} catch (_0x35600a) {
|
||
console.error(_0x4fdfb6["gzoYo"], _0x35600a);
|
||
}
|
||
}
|
||
}
|
||
let _0x293b2f = fs["readFileSync"](_0x1f82b7, 'utf-8');
|
||
if (this._checkInjected(_0x293b2f)) {
|
||
this["_postMessage"]({
|
||
'type': "showToast",
|
||
'message': "已启用",
|
||
'icon': '✅'
|
||
});
|
||
return;
|
||
}
|
||
if (!fs["existsSync"](_0xcc733a)) {
|
||
fs["copyFileSync"](_0x1f82b7, _0xcc733a);
|
||
console["log"]("[CursorPro] 创建备份文件");
|
||
}
|
||
0x0;
|
||
const _0x4d5a34 = client_1.getApiUrl();
|
||
const _0x4868b5 = this._getInjectionConfig(_0x4d5a34, _0x4a9f7b);
|
||
const _0x576180 = [];
|
||
const _0x51a1cd = [];
|
||
for (const _0x334c21 of _0x4868b5) {
|
||
if (_0x4fdfb6["NwiBk"] === _0x4fdfb6["fWqWm"]) {
|
||
_0xf54d53 = _0x4fdfb6["IJzdz"];
|
||
} else if (_0x293b2f.includes(_0x334c21.scode)) {
|
||
_0x293b2f = _0x293b2f["replace"](_0x334c21["scode"], _0x334c21["replacement"]);
|
||
_0x576180.push(_0x334c21["name"]);
|
||
} else {
|
||
_0x51a1cd["push"](_0x334c21["name"]);
|
||
}
|
||
}
|
||
if (_0x4fdfb6["PuBtb"](_0x576180["length"], 0x0)) {
|
||
console["error"](_0x4fdfb6["QPTVv"]);
|
||
console.error(_0x4fdfb6["bwZyq"], _0x1f82b7);
|
||
console["error"](_0x4fdfb6["isjyP"], _0x293b2f["length"]);
|
||
console["error"]("[CursorPro] 未找到的注入点:", _0x51a1cd);
|
||
const _0x163732 = _0x293b2f["includes"](_0x4fdfb6["nGlvY"]);
|
||
const _0xaf63e8 = _0x293b2f["includes"](_0x4fdfb6["eLVeH"]);
|
||
console["error"](_0x4fdfb6["JDsIJ"], _0x163732);
|
||
console.error(_0x4fdfb6.Spptx, _0xaf63e8);
|
||
this._postMessage({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0x4fdfb6["OaqMs"],
|
||
'details': "路径: " + _0x1f82b7
|
||
});
|
||
return;
|
||
}
|
||
console["log"]("[CursorPro] 注入成功,应用的注入点:", _0x576180);
|
||
if (_0x4fdfb6["CqvrX"](_0x51a1cd["length"], 0x0)) {
|
||
console["warn"](_0x4fdfb6["tdJex"], _0x51a1cd);
|
||
}
|
||
try {
|
||
if (_0x4fdfb6["IsXFU"]("nYkuW", "oAKop")) {
|
||
_0x5d5216["warn"]("[CursorPro] 获取进程路径失败:", _0x5973ff);
|
||
} else {
|
||
fs["writeFileSync"](_0x1f82b7, _0x293b2f, "utf-8");
|
||
}
|
||
} catch (_0x3a91bb) {
|
||
if (_0x4fdfb6["nmpHW"]("txcqo", _0x4fdfb6["NpueJ"])) {
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["VGOST"],
|
||
'success': false,
|
||
'error': _0x4fdfb6["vySBX"]
|
||
});
|
||
return;
|
||
} else {
|
||
console["error"](_0x4fdfb6["chYLS"], _0x3a91bb);
|
||
if (_0x4fdfb6["IsXFU"](_0x3a91bb.code, "EPERM") || _0x4fdfb6["WEdcP"](_0x3a91bb["code"], _0x4fdfb6["qFuwX"]) || _0x3a91bb["code"] === "EROFS") {
|
||
const _0x24004b = process["platform"];
|
||
let _0xccdd73 = "没有写入权限";
|
||
if (_0x4fdfb6["WEdcP"](_0x24004b, _0x4fdfb6.XoRrm)) {
|
||
_0xccdd73 = _0x4fdfb6["jWyZD"];
|
||
} else if (_0x24004b === _0x4fdfb6["vryqQ"]) {
|
||
if (_0x4fdfb6["FiwIr"] === _0x4fdfb6["NnBbT"]) {
|
||
_0x21b463.error(_0x4fdfb6["OUNoh"], _0x3e51df);
|
||
} else {
|
||
_0xccdd73 = _0x4fdfb6["kofbg"];
|
||
}
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0xccdd73,
|
||
'needAdmin': true,
|
||
'path': _0x1f82b7
|
||
});
|
||
return;
|
||
}
|
||
throw _0x3a91bb;
|
||
}
|
||
}
|
||
await this._context["globalState"]["update"](_0x4fdfb6.BJIgK, true);
|
||
this["_postMessage"]({
|
||
'type': 'seamlessInjected',
|
||
'success': true,
|
||
'applied': _0x576180,
|
||
'needRestart': true,
|
||
'message': _0x4fdfb6["WedEJ"]
|
||
});
|
||
} catch (_0xc2dc2b) {
|
||
if (_0x4fdfb6["jiObk"] !== 'nUNdq') {
|
||
const _0x4ee293 = this["_readHostsFile"]();
|
||
return _0x4ee293["includes"](this.HOSTS_MARKER_START);
|
||
} else {
|
||
console.error(_0x4fdfb6.chXsS, _0xc2dc2b);
|
||
if (_0xc2dc2b["code"] === _0x4fdfb6["PfOPU"] || _0xc2dc2b["code"] === _0x4fdfb6["qFuwX"]) {
|
||
if (_0x4fdfb6["SUpCK"] === _0x4fdfb6.JOonS) {
|
||
_0x5ec281.error(_0x4fdfb6["gzoYo"], _0x36fa8d);
|
||
} else {
|
||
const _0x2429c3 = _0x4fdfb6["uvZZD"];
|
||
this._postMessage({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0x2429c3,
|
||
'needAdmin': true
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x4fdfb6["XlzQa"],
|
||
'success': false,
|
||
'error': _0xc2dc2b["message"] || '注入失败'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
async ["_handleRestoreSeamless"]() {
|
||
const _0x5d9144 = {
|
||
'fNFwN': function (_0x4677dc, _0x3f836a) {
|
||
return _0x4677dc === _0x3f836a;
|
||
},
|
||
'qzWvm': "gPXAj",
|
||
'iIeEk': "utf-8",
|
||
'hXGdP': "_showNotification(){/*i0*/}_showNotificationOld(){",
|
||
'TTVZf': "_showNotification(){",
|
||
'gtuTM': "/*i1e*/",
|
||
'GRbOi': function (_0x496f84, _0x59be80) {
|
||
return _0x496f84 !== _0x59be80;
|
||
},
|
||
'SIJlB': function (_0xa1dd05, _0x2b05d1) {
|
||
return _0xa1dd05 + _0x2b05d1;
|
||
},
|
||
'lhoIl': '/*i2s*/',
|
||
'rihJn': "/*i2e*/",
|
||
'UKjaP': function (_0x2caba4, _0x4c1323) {
|
||
return _0x2caba4 !== _0x4c1323;
|
||
},
|
||
'gfXYq': "kmqvv",
|
||
'oXUXx': function (_0x3c695c, _0x1ab82c) {
|
||
return _0x3c695c + _0x1ab82c;
|
||
},
|
||
'hFPNQ': function (_0x55b01d, _0x32e339) {
|
||
return _0x55b01d === _0x32e339;
|
||
},
|
||
'iKOOs': function (_0x2379b9, _0x2b53a3) {
|
||
return _0x2379b9 === _0x2b53a3;
|
||
},
|
||
'yKkFV': "uoVdW",
|
||
'uxIzt': "tzZLb",
|
||
'PVsoN': "没有写入权限",
|
||
'dzulQ': "seamlessRestored",
|
||
'wYcDp': "[CursorPro] Restore error:",
|
||
'yoKCW': "EPERM",
|
||
'dGgrN': function (_0x635b, _0x11e947) {
|
||
return _0x635b === _0x11e947;
|
||
},
|
||
'ybPXs': "EACCES"
|
||
};
|
||
try {
|
||
const _0x52b18d = await this._getWorkbenchPathAsync();
|
||
if (!_0x52b18d) {
|
||
if ("JnQIK" === _0x5d9144["qzWvm"]) {
|
||
return _0x1ef303;
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': "seamlessRestored",
|
||
'success': false,
|
||
'error': '未找到Cursor安装目录'
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
let _0x3f0257 = fs["readFileSync"](_0x52b18d, _0x5d9144.iIeEk);
|
||
if (!this["_checkInjected"](_0x3f0257)) {
|
||
return;
|
||
}
|
||
_0x3f0257 = _0x3f0257.replace(_0x5d9144["hXGdP"], _0x5d9144["TTVZf"]);
|
||
const _0x1b150c = _0x3f0257["indexOf"]("/*i1s*/");
|
||
const _0x1689e0 = _0x3f0257["indexOf"](_0x5d9144["gtuTM"]);
|
||
if (_0x1b150c !== -0x1 && _0x1689e0 !== -0x1) {
|
||
_0x3f0257 = _0x3f0257.substring(0x0, _0x1b150c) + _0x3f0257["substring"](_0x1689e0 + 0x7);
|
||
}
|
||
const _0x17d1df = _0x3f0257["indexOf"](_0x5d9144["lhoIl"]);
|
||
const _0x260da1 = _0x3f0257["indexOf"](_0x5d9144["rihJn"]);
|
||
if (_0x17d1df !== -0x1 && _0x260da1 !== -0x1) {
|
||
if (_0x5d9144["UKjaP"]('kmqvv', _0x5d9144["gfXYq"])) {
|
||
_0x1c40a3.unlinkSync(_0x4225bd);
|
||
} else {
|
||
_0x3f0257 = _0x5d9144["oXUXx"](_0x3f0257["substring"](0x0, _0x17d1df), _0x3f0257["substring"](_0x260da1 + 0x7));
|
||
}
|
||
}
|
||
try {
|
||
fs.writeFileSync(_0x52b18d, _0x3f0257, _0x5d9144.iIeEk);
|
||
} catch (_0x1ea8dd) {
|
||
if (_0x5d9144["hFPNQ"](_0x1ea8dd["code"], "EPERM") || _0x1ea8dd["code"] === "EACCES") {
|
||
if (_0x5d9144["iKOOs"](_0x5d9144["yKkFV"], _0x5d9144.uxIzt)) {
|
||
_0x2edff2 = _0x55fda2[0x1];
|
||
} else {
|
||
const _0x32b396 = _0x5d9144["PVsoN"];
|
||
this["_postMessage"]({
|
||
'type': _0x5d9144["dzulQ"],
|
||
'success': false,
|
||
'error': _0x32b396,
|
||
'needAdmin': true
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
throw _0x1ea8dd;
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x5d9144["dzulQ"],
|
||
'success': true,
|
||
'needRestart': true,
|
||
'message': "无感换号已禁用"
|
||
});
|
||
} catch (_0x5a1405) {
|
||
console["error"](_0x5d9144["wYcDp"], _0x5a1405);
|
||
if (_0x5a1405.code === _0x5d9144["yoKCW"] || _0x5d9144["dGgrN"](_0x5a1405.code, _0x5d9144["ybPXs"])) {
|
||
const _0x5de741 = "没有写入权限";
|
||
this._postMessage({
|
||
'type': _0x5d9144["dzulQ"],
|
||
'success': false,
|
||
'error': _0x5de741,
|
||
'needAdmin': true
|
||
});
|
||
return;
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x5d9144.dzulQ,
|
||
'success': false,
|
||
'error': _0x5a1405["message"] || '还原失败'
|
||
});
|
||
}
|
||
}
|
||
async ["_handleToggleSeamless"](_0x1772fb) {
|
||
const _0x595d47 = {
|
||
'uMKkd': "dSScr",
|
||
'puuTf': 'OoEdP',
|
||
'GMeLW': "seamlessConfigUpdated",
|
||
'xfsPC': function (_0x594de1, _0x4d93aa) {
|
||
return _0x594de1 === _0x4d93aa;
|
||
},
|
||
'gwHNY': "SZovO",
|
||
'DbkSk': "更新配置失败"
|
||
};
|
||
try {
|
||
if (_0x595d47["uMKkd"] === 'OoEdP') {
|
||
try {
|
||
if (_0x2c90c5["existsSync"](_0x4f880f)) {
|
||
_0x40d342.rmSync(_0x56e280, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x108655++;
|
||
}
|
||
} catch (_0x5f07e2) {
|
||
_0x49f06e["warn"]("[CursorPro] 清理失败: " + _0x860525, _0x5f07e2);
|
||
}
|
||
} else {
|
||
0x0;
|
||
await client_1["updateSeamlessConfig"]({
|
||
'enabled': _0x1772fb
|
||
});
|
||
this["_postMessage"]({
|
||
'type': _0x595d47["GMeLW"],
|
||
'success': true,
|
||
'enabled': _0x1772fb
|
||
});
|
||
}
|
||
} catch (_0x4b5076) {
|
||
if (_0x595d47["xfsPC"]("lzzwb", _0x595d47.gwHNY)) {
|
||
return this._getWorkbenchPathSync();
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x595d47.GMeLW,
|
||
'success': false,
|
||
'error': _0x595d47["DbkSk"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
async ._handleGetUserSwitchStatus() {
|
||
const _0x7a74ee = {
|
||
'iTdeY': "tFzAd",
|
||
'sJbdj': 'userSwitchStatus',
|
||
'Bzqze': 'TSpKd',
|
||
'HRNLC': function (_0xf71d5d, _0x1fbc3a) {
|
||
return _0xf71d5d !== _0x1fbc3a;
|
||
},
|
||
'BIPgO': "NMuKY",
|
||
'zFtlx': "获取状态失败"
|
||
};
|
||
try {
|
||
if (_0x7a74ee["iTdeY"] !== _0x7a74ee.iTdeY) {
|
||
_0x5ec7da["push"](["cursorAuth/cachedEmail", _0x4c815c["email"]]);
|
||
} else {
|
||
const _0x8fa174 = this["_context"]["globalState"].get('cursorpro.key');
|
||
if (!_0x8fa174) {
|
||
this._postMessage({
|
||
'type': _0x7a74ee["sJbdj"],
|
||
'valid': false,
|
||
'switchRemaining': 0x0,
|
||
'canSwitch': false,
|
||
'error': "未激活授权码"
|
||
});
|
||
return;
|
||
}
|
||
0x0;
|
||
const _0x55ca3b = await client_1["getUserSwitchStatus"](_0x8fa174);
|
||
let _0x1b9794 = false;
|
||
try {
|
||
if ('TSpKd' === "TSpKd") {
|
||
0x0;
|
||
const _0x3f529b = await client_1["getSeamlessStatus"]();
|
||
_0x1b9794 = _0x3f529b["is_injected"] || false;
|
||
} else {
|
||
_0x3d9b73["warn"]("[CursorPro] 清理失败: " + _0x151b0c, _0x57f0b8);
|
||
}
|
||
} catch (_0x12015a) {}
|
||
this._postMessage({
|
||
'type': 'userSwitchStatus',
|
||
..._0x55ca3b,
|
||
'seamlessEnabled': _0x1b9794
|
||
});
|
||
}
|
||
} catch (_0x831a4b) {
|
||
if ("ObXTw" !== _0x7a74ee["BIPgO"]) {
|
||
this._postMessage({
|
||
'type': "userSwitchStatus",
|
||
'valid': false,
|
||
'switchRemaining': 0x0,
|
||
'canSwitch': false,
|
||
'error': _0x7a74ee["zFtlx"]
|
||
});
|
||
} else {
|
||
const _0x2c52f0 = 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-" + _0x2c52f0 + "'; img-src " + _0x2ff1db["cspSource"] + " https: data:; font-src " + _0x1bed45["cspSource"] + "; worker-src 'none';\">\n <title>CursorPro</title>\n <script nonce=\"" + _0x2c52f0 + "\">\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=\"" + _0x2c52f0 + "\">\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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\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"](_0x1b796a) {
|
||
const _0x312bb1 = {
|
||
'kwSDs': "[CursorPro] Toggle proxy error:",
|
||
'cuNHx': "proxyUpdated",
|
||
'AlVbI': '更新配置失败',
|
||
'cBprM': "accountUsage",
|
||
'pLAQo': "未提供账号邮箱",
|
||
'XCtgT': function (_0x51bb3f, _0x5ae513) {
|
||
return _0x51bb3f(_0x5ae513);
|
||
},
|
||
'LcuLD': "获取用量失败",
|
||
'JvSqa': "NYkng",
|
||
'rptjh': "请求失败"
|
||
};
|
||
try {
|
||
if (!_0x1b796a) {
|
||
this._postMessage({
|
||
'type': _0x312bb1.cBprM,
|
||
'success': false,
|
||
'error': _0x312bb1["pLAQo"]
|
||
});
|
||
return;
|
||
}
|
||
0x0;
|
||
const _0x58b290 = client_1["getApiUrl"]() + "/api/cursor-accounts/query?email=" + _0x312bb1["XCtgT"](encodeURIComponent, _0x1b796a) + '&refresh=true';
|
||
const _0x507bbc = await _0x312bb1["XCtgT"](fetch, _0x58b290);
|
||
const _0x46ba2b = await _0x507bbc.json();
|
||
if (_0x46ba2b["success"] && _0x46ba2b["data"]) {
|
||
this["_postMessage"]({
|
||
'type': _0x312bb1["cBprM"],
|
||
'success': true,
|
||
'data': _0x46ba2b["data"]
|
||
});
|
||
const _0x4cf6e5 = _0x46ba2b["data"]["usage"] || {};
|
||
const _0x3d3ce3 = _0x4cf6e5["totalUsageCount"] || 0x0;
|
||
const _0x1f779f = _0x312bb1["XCtgT"](parseFloat, _0x4cf6e5["totalCostUSD"] || 0x0);
|
||
0x0;
|
||
extension_1["updateUsageStatusBar"](_0x3d3ce3, _0x1f779f);
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x312bb1.cBprM,
|
||
'success': false,
|
||
'error': _0x46ba2b["error"] || _0x312bb1["LcuLD"]
|
||
});
|
||
}
|
||
} catch (_0x3c8684) {
|
||
if (_0x312bb1["JvSqa"] !== 'NYkng') {
|
||
_0x496ef8["error"](_0x312bb1["kwSDs"], _0x4d4142);
|
||
this["_postMessage"]({
|
||
'type': _0x312bb1["cuNHx"],
|
||
'success': false,
|
||
'error': _0x312bb1["AlVbI"]
|
||
});
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x312bb1["cBprM"],
|
||
'success': false,
|
||
'error': _0x3c8684.message || _0x312bb1["rptjh"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
async ["_handleGetAnnouncement"]() {
|
||
const _0x507cc2 = {
|
||
'eXcSu': "cursorpro.key",
|
||
'wCuhU': "cursorpro.expireDate",
|
||
'tQyYP': '请先激活授权码',
|
||
'fEjcy': function (_0x14a329, _0x3ca24d) {
|
||
return _0x14a329 > _0x3ca24d;
|
||
},
|
||
'GLUmw': "proxyUpdated",
|
||
'Bjkrw': '授权码已过期,无法开启免魔法',
|
||
'trGXG': 'showToast',
|
||
'aCZjy': function (_0x85327, _0x557946) {
|
||
return _0x85327(_0x557946);
|
||
},
|
||
'aHNrz': 'announcement',
|
||
'PynOc': function (_0x4e3da2, _0x27c602) {
|
||
return _0x4e3da2 === _0x27c602;
|
||
},
|
||
'LjnPR': 'ysOwe',
|
||
'RdeWm': "获取公告失败",
|
||
'XcVTX': "请求失败"
|
||
};
|
||
try {
|
||
0x0;
|
||
const _0x2127d9 = client_1["getApiUrl"]() + "/api/announcements/latest";
|
||
const _0x59851a = await _0x507cc2["aCZjy"](fetch, _0x2127d9);
|
||
const _0x1529e0 = await _0x59851a.json();
|
||
if (_0x1529e0["success"] && _0x1529e0["data"]) {
|
||
this._postMessage({
|
||
'type': _0x507cc2["aHNrz"],
|
||
'success': true,
|
||
'data': _0x1529e0["data"]
|
||
});
|
||
} else {
|
||
if ('ysOwe' === _0x507cc2["LjnPR"]) {
|
||
this._postMessage({
|
||
'type': "announcement",
|
||
'success': false,
|
||
'error': _0x1529e0["error"] || _0x507cc2["RdeWm"]
|
||
});
|
||
} else {
|
||
const _0x2213b8 = this["_context"].globalState.get(_0x507cc2["eXcSu"]);
|
||
const _0x3fde55 = this["_context"]["globalState"]["get"](_0x507cc2["wCuhU"]);
|
||
if (!_0x2213b8) {
|
||
this["_postMessage"]({
|
||
'type': 'proxyUpdated',
|
||
'success': false,
|
||
'error': '请先激活授权码'
|
||
});
|
||
this["_postMessage"]({
|
||
'type': "showToast",
|
||
'message': _0x507cc2["tQyYP"],
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
if (_0x3fde55) {
|
||
const _0x88cb25 = new _0x3cd6be(_0x3fde55)["getTime"]();
|
||
if (_0x507cc2["fEjcy"](_0x4cae44["now"](), _0x88cb25)) {
|
||
this._postMessage({
|
||
'type': _0x507cc2.GLUmw,
|
||
'success': false,
|
||
'error': _0x507cc2["Bjkrw"]
|
||
});
|
||
this._postMessage({
|
||
'type': _0x507cc2["trGXG"],
|
||
'message': "授权码已过期,无法开启免魔法",
|
||
'icon': '⚠️'
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} catch (_0x2ebc04) {
|
||
this["_postMessage"]({
|
||
'type': _0x507cc2["aHNrz"],
|
||
'success': false,
|
||
'error': _0x2ebc04.message || _0x507cc2["XcVTX"]
|
||
});
|
||
}
|
||
}
|
||
async ["_handleCheckVersion"]() {
|
||
const _0x250fa3 = {
|
||
'HgWOc': "[CursorPro] 使用用户配置的 Cursor 路径:",
|
||
'QXFeq': function (_0x28c00c, _0x55597c) {
|
||
return _0x28c00c > _0x55597c;
|
||
},
|
||
'lYCxA': "versionCheck",
|
||
'QtoxZ': function (_0x5cd3f7, _0x1bb416) {
|
||
return _0x5cd3f7 === _0x1bb416;
|
||
},
|
||
'xqknY': "vUHCr",
|
||
'GbNrd': "请求失败"
|
||
};
|
||
try {
|
||
0x0;
|
||
const _0xcbd93e = await client_1["getLatestVersion"]();
|
||
if (_0xcbd93e.success && _0xcbd93e.version) {
|
||
const _0x59dc2f = _0xcbd93e["version"];
|
||
const _0x1a5d58 = CursorProViewProvider["CURRENT_VERSION"];
|
||
const _0x4acb32 = _0x250fa3["QXFeq"](this["_compareVersions"](_0x59dc2f, _0x1a5d58), 0x0);
|
||
this["_postMessage"]({
|
||
'type': _0x250fa3["lYCxA"],
|
||
'success': true,
|
||
'currentVersion': _0x1a5d58,
|
||
'latestVersion': _0x59dc2f,
|
||
'hasUpdate': _0x4acb32
|
||
});
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x250fa3["lYCxA"],
|
||
'success': false,
|
||
'currentVersion': CursorProViewProvider.CURRENT_VERSION,
|
||
'error': _0xcbd93e["error"] || "获取版本失败"
|
||
});
|
||
}
|
||
} catch (_0x5d97b6) {
|
||
if (_0x250fa3["QtoxZ"](_0x250fa3["xqknY"], "LOWQh")) {
|
||
_0x21c480["log"](_0x250fa3["HgWOc"], _0x41f567);
|
||
this["_cachedCursorPath"] = _0x3c3681;
|
||
return _0xb7920c;
|
||
} else {
|
||
this._postMessage({
|
||
'type': "versionCheck",
|
||
'success': false,
|
||
'currentVersion': CursorProViewProvider.CURRENT_VERSION,
|
||
'error': _0x5d97b6["message"] || _0x250fa3["GbNrd"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
["_compareVersions"](_0x2c35a0, _0x3e2c58) {
|
||
const _0x576d14 = {
|
||
'PMKNW': function (_0x2cee68, _0x17cabb) {
|
||
return _0x2cee68 < _0x17cabb;
|
||
},
|
||
'qyNxu': function (_0xbd034d, _0x5b41) {
|
||
return _0xbd034d > _0x5b41;
|
||
},
|
||
'HZvmu': function (_0x1f686e, _0x307d8c) {
|
||
return _0x1f686e < _0x307d8c;
|
||
}
|
||
};
|
||
const _0xbaec2f = _0x2c35a0["split"]('.')["map"](Number);
|
||
const _0x52cf6d = _0x3e2c58["split"]('.')["map"](Number);
|
||
const _0x23e911 = Math["max"](_0xbaec2f["length"], _0x52cf6d["length"]);
|
||
for (let _0x2d8ca5 = 0x0; _0x2d8ca5 < _0x23e911; _0x2d8ca5++) {
|
||
const _0x237a97 = _0xbaec2f[_0x2d8ca5] || 0x0;
|
||
const _0x266b01 = _0x52cf6d[_0x2d8ca5] || 0x0;
|
||
if (_0x576d14["qyNxu"](_0x237a97, _0x266b01)) {
|
||
return 0x1;
|
||
}
|
||
if (_0x237a97 < _0x266b01) {
|
||
return -0x1;
|
||
}
|
||
}
|
||
return 0x0;
|
||
}
|
||
async ["_handleGetCursorRunningPath"]() {
|
||
const _0x46ebbb = {
|
||
'SsULC': "[CursorPro] 使用 VS Code API 获取版本:",
|
||
'AwKfF': 'utf-8',
|
||
'zAvXx': "UBmxB",
|
||
'QhWXL': "未找到",
|
||
'bZBTW': 'cursorpro',
|
||
'vlHDb': 'cursorPath',
|
||
'ONVXL': function (_0x45b9b2, _0x3d0419) {
|
||
return _0x45b9b2 === _0x3d0419;
|
||
},
|
||
'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 (_0x3ac49f, _0x3550a9) {
|
||
return _0x3ac49f === _0x3550a9;
|
||
},
|
||
'rEwYQ': "snkgX",
|
||
'YxYZp': "BoVlO",
|
||
'Qvzam': function (_0x5c6915, _0xdddb6e) {
|
||
return _0x5c6915 === _0xdddb6e;
|
||
},
|
||
'FyfZA': function (_0x35b4f7, _0x394159) {
|
||
return _0x35b4f7 !== _0x394159;
|
||
},
|
||
'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" !== _0x46ebbb.zAvXx) {
|
||
return [{
|
||
'email': _0x7e9b73,
|
||
'access_token': _0x4f7a33,
|
||
'refresh_token': _0x32c653 || _0x23d4b2
|
||
}];
|
||
} else {
|
||
const _0x1b946c = process["platform"];
|
||
let _0x306e39 = _0x46ebbb.QhWXL;
|
||
let _0x260237 = '';
|
||
const _0x36a669 = vscode["workspace"]["getConfiguration"](_0x46ebbb["bZBTW"]);
|
||
const _0x49eda3 = _0x36a669["get"](_0x46ebbb["vlHDb"]);
|
||
if (_0x49eda3 && fs.existsSync(_0x49eda3)) {
|
||
_0x306e39 = _0x49eda3;
|
||
if (_0x1b946c === _0x46ebbb.JPYoo) {
|
||
_0x260237 = path["join"](_0x49eda3, _0x46ebbb["nEYhA"], _0x46ebbb["EbBLW"], _0x46ebbb["lMfdt"], _0x46ebbb["MFjtx"]);
|
||
} else {
|
||
_0x260237 = path["join"](_0x49eda3, "resources", _0x46ebbb.lMfdt, _0x46ebbb["MFjtx"]);
|
||
}
|
||
console.log(_0x46ebbb["NjVqB"], _0x49eda3);
|
||
} else {
|
||
if (_0x1b946c === _0x46ebbb.Wxyfp) {
|
||
try {
|
||
if (_0x46ebbb["JSWuW"] === "eKgQY") {
|
||
_0x2258e6 = true;
|
||
delete _0x2dff6a[_0x1d391b];
|
||
} else {
|
||
const {
|
||
stdout: _0x1a7f66
|
||
} = await execAsync(_0x46ebbb["ACRef"]);
|
||
const _0xa3209b = _0x1a7f66["match"](/ExecutablePath=(.+)/);
|
||
if (_0xa3209b && _0xa3209b[0x1]) {
|
||
const _0x5d0249 = _0xa3209b[0x1]["trim"]();
|
||
_0x306e39 = path.dirname(_0x5d0249);
|
||
_0x260237 = path["join"](_0x306e39, _0x46ebbb.ydRHF, _0x46ebbb.lMfdt, _0x46ebbb.MFjtx);
|
||
}
|
||
}
|
||
} catch (_0x48a57c) {
|
||
if (_0x46ebbb["rEwYQ"] === _0x46ebbb["YxYZp"]) {
|
||
_0x15013a["log"](_0x46ebbb["SsULC"], _0x3e70a4.version);
|
||
return _0x1800fc.version;
|
||
} else {
|
||
console.log("[CursorPro] WMIC 获取路径失败:", _0x48a57c);
|
||
}
|
||
}
|
||
if (_0x306e39 === _0x46ebbb["QhWXL"]) {
|
||
if (_0x46ebbb["FyfZA"]("DZGqD", _0x46ebbb["eCMQp"])) {
|
||
try {
|
||
const _0x378439 = this["_getHostsPath"]();
|
||
if (_0x1530ba["existsSync"](_0x378439)) {
|
||
return _0x4386be["readFileSync"](_0x378439, _0x46ebbb["AwKfF"]);
|
||
}
|
||
} catch (_0xba9c07) {
|
||
_0x79d384["error"]("[CursorPro] Read hosts error:", _0xba9c07);
|
||
}
|
||
return '';
|
||
} else {
|
||
const _0x17a391 = process["env"]["LOCALAPPDATA"] || '';
|
||
const _0x6b3334 = [path["join"](_0x17a391, _0x46ebbb["QKwAH"], 'cursor'), path["join"](_0x17a391, _0x46ebbb["eEobw"])];
|
||
for (const _0x516d23 of _0x6b3334) {
|
||
const _0x495418 = path["join"](_0x516d23, _0x46ebbb["ydRHF"], "app", _0x46ebbb["MFjtx"]);
|
||
if (fs.existsSync(_0x495418)) {
|
||
_0x306e39 = _0x516d23;
|
||
_0x260237 = _0x495418;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (_0x1b946c === "darwin") {
|
||
if (_0x46ebbb["Qvzam"](_0x46ebbb["aouCU"], _0x46ebbb["XXRrw"])) {
|
||
return null;
|
||
} else {
|
||
_0x306e39 = (await this["_getCursorInstallPath"]()) || _0x46ebbb["biXGl"];
|
||
_0x260237 = path["join"](_0x306e39, _0x46ebbb["nEYhA"], _0x46ebbb.EbBLW, 'app', _0x46ebbb.MFjtx);
|
||
}
|
||
} else {
|
||
const _0x1071f5 = process.env["HOME"] || '';
|
||
const _0x34c761 = [_0x46ebbb["ErbAO"], path.join(_0x1071f5, _0x46ebbb["vvvXG"], _0x46ebbb["kVBXU"], _0x46ebbb.eEobw)];
|
||
for (const _0x1aac5b of _0x34c761) {
|
||
if (fs.existsSync(_0x1aac5b)) {
|
||
_0x306e39 = _0x1aac5b;
|
||
_0x260237 = path["join"](_0x1aac5b, _0x46ebbb["ydRHF"], 'app', "package.json");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
const _0x3c9745 = _0x260237 && fs["existsSync"](_0x260237);
|
||
let _0xd636a6 = '';
|
||
if (_0x3c9745) {
|
||
try {
|
||
if (_0x46ebbb["sxYuF"] === _0x46ebbb["sYfMC"]) {
|
||
if (_0x343ee2["existsSync"](_0x44179b)) {
|
||
return _0x52b912;
|
||
}
|
||
} else {
|
||
const _0x4c9fc9 = fs.readFileSync(_0x260237, _0x46ebbb["AwKfF"]);
|
||
const _0x4056ed = JSON["parse"](_0x4c9fc9);
|
||
_0xd636a6 = _0x4056ed.version || '';
|
||
console["log"](_0x46ebbb["UFfHe"], _0xd636a6);
|
||
}
|
||
} catch (_0x15526b) {
|
||
console.log("[CursorPro] 读取 package.json 失败:", _0x15526b);
|
||
}
|
||
}
|
||
this._postMessage({
|
||
'type': 'cursorRunningPath',
|
||
'path': _0x306e39,
|
||
'packageJsonPath': _0x260237,
|
||
'packageExists': _0x3c9745,
|
||
'cursorVersion': _0xd636a6
|
||
});
|
||
}
|
||
} catch (_0x1da737) {
|
||
this._postMessage({
|
||
'type': _0x46ebbb["HLsOj"],
|
||
'path': "获取失败: " + (_0x1da737["message"] || _0x1da737),
|
||
'packageJsonPath': '',
|
||
'packageExists': false,
|
||
'cursorVersion': ''
|
||
});
|
||
}
|
||
}
|
||
async ["_handleCheckUsageBeforeSwitch"](_0x423ed0) {
|
||
const _0x46be7a = {
|
||
'sEVKj': "[CursorPro] PowerShell Get-Process 获取路径失败",
|
||
'kcIfn': "[CursorPro] Direct write failed, trying to grant permission",
|
||
'qVzhF': function (_0x1030be, _0x3ef0ad) {
|
||
return _0x1030be === _0x3ef0ad;
|
||
},
|
||
'NTZfw': "klkmy",
|
||
'LnwIK': 'usageCheckResult',
|
||
'yCHku': "未激活授权码",
|
||
'wnjiM': function (_0x5ba0af, _0x167687) {
|
||
return _0x5ba0af === _0x167687;
|
||
},
|
||
'FHkCa': "taehn",
|
||
'Elfrz': function (_0x4cea4c, _0x4a5432) {
|
||
return _0x4cea4c(_0x4a5432);
|
||
},
|
||
'uXXMl': function (_0x4a7089, _0x1a8977) {
|
||
return _0x4a7089(_0x1a8977);
|
||
},
|
||
'rMdug': "Drfmf",
|
||
'KaGPw': "lZGGL",
|
||
'DqgLz': function (_0x3614c7, _0x5a56ba) {
|
||
return _0x3614c7 < _0x5a56ba;
|
||
},
|
||
'nMItX': "aCFwf",
|
||
'YHdCp': 'MhURV',
|
||
'zYseP': function (_0x315829, _0x209dfd) {
|
||
return _0x315829 !== _0x209dfd;
|
||
},
|
||
'XaQBc': "PgKQl",
|
||
'PYWHP': 'hlMgj',
|
||
'EKVNJ': "zdYFk"
|
||
};
|
||
try {
|
||
if ('pydTE' !== _0x46be7a["NTZfw"]) {
|
||
const _0x265715 = this["_context"]["globalState"]["get"]("cursorpro.key");
|
||
if (!_0x265715) {
|
||
this["_postMessage"]({
|
||
'type': _0x46be7a["LnwIK"],
|
||
'success': false,
|
||
'error': _0x46be7a.yCHku
|
||
});
|
||
return;
|
||
}
|
||
if (!_0x423ed0) {
|
||
if (_0x46be7a["FHkCa"] === _0x46be7a["FHkCa"]) {
|
||
this["_postMessage"]({
|
||
'type': "usageCheckResult",
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
return;
|
||
} else {
|
||
_0x4ade37["window"].showErrorMessage("清理失败: " + _0x39dd6b);
|
||
}
|
||
}
|
||
0x0;
|
||
const _0xe4de04 = client_1["getApiUrl"]() + '/api/cursor-accounts/query?email=' + encodeURIComponent(_0x423ed0) + "&refresh=false";
|
||
const _0x4e6615 = await fetch(_0xe4de04);
|
||
const _0xa38d3b = await _0x4e6615.json();
|
||
if (_0xa38d3b["success"] && _0xa38d3b.data) {
|
||
if (_0x46be7a.rMdug !== _0x46be7a["KaGPw"]) {
|
||
const _0x1a9459 = _0xa38d3b["data"]["usage"] || {};
|
||
const _0x54f98 = parseFloat(_0x1a9459["totalCostUSD"] || 0x0);
|
||
if (_0x46be7a["DqgLz"](_0x54f98, 0xa)) {
|
||
if (_0x46be7a["wnjiM"](_0x46be7a["nMItX"], _0x46be7a["YHdCp"])) {
|
||
_0x36aa30["log"](_0x46be7a["sEVKj"]);
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x46be7a["LnwIK"],
|
||
'success': true,
|
||
'needConfirm': true,
|
||
'costUSD': _0x54f98.toFixed(0x2),
|
||
'email': _0x423ed0
|
||
});
|
||
}
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x46be7a["LnwIK"],
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
}
|
||
} else {
|
||
_0x11939f["rmSync"](_0x5a5124, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x5829eb++;
|
||
}
|
||
} else if (_0x46be7a["zYseP"]('GbpRm', _0x46be7a.XaQBc)) {
|
||
this["_postMessage"]({
|
||
'type': _0x46be7a["LnwIK"],
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
} else {
|
||
_0x34b65e["log"](_0x46be7a["kcIfn"]);
|
||
}
|
||
} else {
|
||
if (_0x46be7a["qVzhF"](_0x12d7bd, _0x4c400f)) {
|
||
_0x2cc937 = _0x34b272;
|
||
}
|
||
_0x370969[_0x2f7e57] = _0x496a29[_0x21aa14];
|
||
}
|
||
} catch (_0xc3e637) {
|
||
if (_0x46be7a["zYseP"](_0x46be7a["PYWHP"], _0x46be7a["EKVNJ"])) {
|
||
this["_postMessage"]({
|
||
'type': 'usageCheckResult',
|
||
'success': true,
|
||
'needConfirm': false
|
||
});
|
||
} else {
|
||
_0xd7775["push"](_0x5f24a2.name);
|
||
}
|
||
}
|
||
}
|
||
async ._handleManualSeamlessSwitch() {
|
||
const _0x239b7a = {
|
||
'BIFqO': "utf-8",
|
||
'BfPph': "[CursorPro] Linux 获取进程路径失败:",
|
||
'loKNV': 'cursorRunningPath',
|
||
'HrshN': function (_0x5b042b, _0x3fb2de) {
|
||
return _0x5b042b + _0x3fb2de;
|
||
},
|
||
'ByJnO': "获取失败: ",
|
||
'yJBIQ': 'exYVj',
|
||
'KvCvh': 'manualSeamlessSwitched',
|
||
'VLaZZ': "未激活授权码",
|
||
'tbDpF': function (_0x5a9370, _0x36f88c) {
|
||
return _0x5a9370 !== _0x36f88c;
|
||
},
|
||
'yPImL': 'ingEM',
|
||
'mlftM': function (_0x148013, _0x58777f) {
|
||
return _0x148013 !== _0x58777f;
|
||
},
|
||
'jnyry': "FYJZv",
|
||
'HxZxj': "换号失败",
|
||
'sLjSr': "连接服务器失败"
|
||
};
|
||
try {
|
||
if (_0x239b7a["yJBIQ"] === 'exYVj') {
|
||
const _0x204f37 = this["_context"]["globalState"]["get"]("cursorpro.key");
|
||
if (!_0x204f37) {
|
||
this["_postMessage"]({
|
||
'type': _0x239b7a["KvCvh"],
|
||
'success': false,
|
||
'error': _0x239b7a["VLaZZ"]
|
||
});
|
||
return;
|
||
}
|
||
0x0;
|
||
const _0x4d82f2 = await client_1["switchSeamlessToken"](_0x204f37);
|
||
if (_0x4d82f2["switched"]) {
|
||
if (_0x4d82f2["email"]) {
|
||
await this["_context"].globalState["update"]("cursorpro.seamlessCurrentAccount", _0x4d82f2["email"]);
|
||
}
|
||
this["_postMessage"]({
|
||
'type': _0x239b7a["KvCvh"],
|
||
'success': true,
|
||
'email': _0x4d82f2["email"],
|
||
'switchRemaining': _0x4d82f2.switchRemaining
|
||
});
|
||
} else {
|
||
if (_0x239b7a["mlftM"]("JYbEY", _0x239b7a["jnyry"])) {
|
||
const _0x1d8cc3 = _0x4d82f2["message"] || _0x4d82f2["error"] || _0x239b7a["HxZxj"];
|
||
this._postMessage({
|
||
'type': _0x239b7a["KvCvh"],
|
||
'success': false,
|
||
'error': _0x1d8cc3
|
||
});
|
||
} else {
|
||
_0x48d9fc.warn(_0x239b7a["BfPph"], _0x2600b5);
|
||
}
|
||
}
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': 'cursorRunningPath',
|
||
'path': _0x239b7a["HrshN"](_0x239b7a["ByJnO"], _0x2ae8a1["message"] || _0x13ffd1),
|
||
'packageJsonPath': '',
|
||
'packageExists': false,
|
||
'cursorVersion': ''
|
||
});
|
||
}
|
||
} catch (_0x56a0cb) {
|
||
const _0x38f43a = _0x56a0cb?..message || _0x239b7a["sLjSr"];
|
||
this._postMessage({
|
||
'type': _0x239b7a["KvCvh"],
|
||
'success': false,
|
||
'error': _0x38f43a
|
||
});
|
||
}
|
||
}
|
||
async ["_handleGetCursorPath"]() {
|
||
const _0x38acb3 = {
|
||
'tbZpe': function (_0x46700e, _0x216ec6) {
|
||
return _0x46700e === _0x216ec6;
|
||
},
|
||
'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 (_0x5469b9, _0x18421f) {
|
||
return _0x5469b9(_0x18421f);
|
||
},
|
||
'LurDi': "wmic process where \"name='Cursor.exe'\" get ExecutablePath /format:list 2>nul",
|
||
'VtoJO': 'hKLIf',
|
||
'KDsFj': function (_0x211f3c, _0x10fb3d) {
|
||
return _0x211f3c === _0x10fb3d;
|
||
},
|
||
'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 (_0x3b944e, _0x2c32f1) {
|
||
return _0x3b944e !== _0x2c32f1;
|
||
},
|
||
'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 (_0x273ac0, _0x5f39b) {
|
||
return _0x273ac0 !== _0x5f39b;
|
||
},
|
||
'EYQCn': "EvRNl",
|
||
'MiEkS': "cursorPath",
|
||
'HiXkV': function (_0xd0ebf9, _0x4cfcad) {
|
||
return _0xd0ebf9 || _0x4cfcad;
|
||
},
|
||
'hlIYy': 'ZzJmG',
|
||
'GONGu': '获取失败'
|
||
};
|
||
try {
|
||
const _0x2f8924 = process.platform;
|
||
let _0x46d162 = '';
|
||
let _0x3fe4eb = '';
|
||
if (_0x38acb3["tbZpe"](_0x2f8924, _0x38acb3.TFAWN)) {
|
||
try {
|
||
const {
|
||
stdout: _0x19a5fc
|
||
} = await _0x38acb3["VsfTO"](execAsync, _0x38acb3["LurDi"]);
|
||
const _0x1f42c2 = _0x19a5fc["match"](/ExecutablePath=(.+)/);
|
||
if (_0x1f42c2 && _0x1f42c2[0x1]) {
|
||
const _0x4dbd9f = _0x1f42c2[0x1]["trim"]();
|
||
_0x46d162 = path.dirname(_0x4dbd9f);
|
||
}
|
||
} catch (_0x1aba5f) {
|
||
if (_0x38acb3["VtoJO"] !== "hKLIf") {
|
||
if (_0x38acb3["tbZpe"](_0x763182["code"], _0x38acb3["pcUwb"]) || _0x38acb3["tbZpe"](_0x1d6dfe["code"], "EACCES")) {
|
||
const _0x5910ed = _0x38acb3["WPzlq"];
|
||
this["_postMessage"]({
|
||
'type': _0x38acb3["drojl"],
|
||
'success': false,
|
||
'error': _0x5910ed,
|
||
'needAdmin': true
|
||
});
|
||
return;
|
||
}
|
||
throw _0x25718f;
|
||
} else {
|
||
try {
|
||
if (_0x38acb3["KDsFj"](_0x38acb3["rLwGW"], _0x38acb3["rLwGW"])) {
|
||
const {
|
||
stdout: _0x54d048
|
||
} = await execAsync('powershell -Command "Get-Process Cursor -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Path"');
|
||
if (_0x54d048["trim"]()) {
|
||
if (_0x38acb3["ePJAJ"] !== _0x38acb3.WxyNi) {
|
||
_0x46d162 = path["dirname"](_0x54d048["trim"]());
|
||
} else {
|
||
this._postMessage({
|
||
'type': _0x38acb3["fTNeN"],
|
||
'success': false,
|
||
'error': '连接服务器失败'
|
||
});
|
||
}
|
||
}
|
||
} else {
|
||
_0x4bf468 = _0x1e8026["substring"](0x0, _0x40d01d) + _0x57a9ae["substring"](_0x17b950 + this.HOSTS_MARKER_END["length"]);
|
||
}
|
||
} catch (_0x215316) {
|
||
console.warn(_0x38acb3["lqoLD"], _0x215316);
|
||
}
|
||
}
|
||
}
|
||
const _0x268111 = process["env"]["APPDATA"] || '';
|
||
_0x3fe4eb = path["join"](_0x268111, _0x38acb3.oVgdC);
|
||
} else {
|
||
if (_0x2f8924 === "darwin") {
|
||
try {
|
||
const {
|
||
stdout: _0x4f065d
|
||
} = await _0x38acb3["VsfTO"](execAsync, _0x38acb3["USGWH"]);
|
||
if (_0x4f065d.trim()) {
|
||
const _0x5ebf8f = _0x4f065d["trim"]();
|
||
const _0x228acb = _0x5ebf8f.match(/(.+\.app)/);
|
||
if (_0x228acb) {
|
||
_0x46d162 = _0x228acb[0x1];
|
||
} else {
|
||
_0x46d162 = path.dirname(_0x5ebf8f);
|
||
}
|
||
}
|
||
} catch (_0x2b309c) {
|
||
console["warn"]("[CursorPro] 获取进程路径失败:", _0x2b309c);
|
||
}
|
||
const _0x6ea467 = process["env"].HOME || '';
|
||
_0x3fe4eb = path.join(_0x6ea467, 'Library', "Application Support", _0x38acb3.oVgdC);
|
||
} else {
|
||
try {
|
||
const {
|
||
stdout: _0x522bb9
|
||
} = await execAsync(_0x38acb3["gDuYC"]);
|
||
if (_0x522bb9["trim"]()) {
|
||
if (_0x38acb3["tbZpe"](_0x38acb3["bwLpU"], _0x38acb3["bwLpU"])) {
|
||
_0x46d162 = path.dirname(_0x522bb9["trim"]());
|
||
} else {
|
||
_0x3596e8 = _0x38acb3["TbbUg"];
|
||
}
|
||
}
|
||
} catch (_0x22983f) {
|
||
console["warn"](_0x38acb3["lqoLD"], _0x22983f);
|
||
}
|
||
const _0x456726 = process["env"].HOME || '';
|
||
_0x3fe4eb = path["join"](_0x456726, _0x38acb3["sWGNb"], _0x38acb3["oVgdC"]);
|
||
}
|
||
}
|
||
if (!_0x46d162) {
|
||
if ("dWdoR" === _0x38acb3["KbfNq"]) {
|
||
this["_postMessage"]({
|
||
'type': _0x38acb3["NwHIv"],
|
||
'success': false,
|
||
'error': _0x38acb3.jmXuW
|
||
});
|
||
return;
|
||
} else {
|
||
_0x46d162 = _0x38acb3["dALzw"];
|
||
}
|
||
}
|
||
let _0x121b7c = '';
|
||
if (_0x46d162 && !_0x46d162.includes(_0x38acb3["mOngd"])) {
|
||
if (_0x2f8924 === _0x38acb3["TFAWN"]) {
|
||
if (_0x38acb3["GdGfE"]('lPhmJ', "lPhmJ")) {
|
||
_0x1588d9["telemetry.devDeviceId"] = _0x11e099["devDeviceId"];
|
||
} else {
|
||
_0x121b7c = path["join"](_0x46d162, 'resources', _0x38acb3.vdFYP, 'out', 'vs', 'workbench', _0x38acb3["dEWjF"]);
|
||
}
|
||
} else {
|
||
if (_0x2f8924 === "darwin") {
|
||
if (_0x38acb3["KDsFj"]("RgvPD", _0x38acb3.AVeQH)) {
|
||
_0x121b7c = path["join"](_0x46d162, _0x38acb3.lEdrt, "Resources", _0x38acb3.vdFYP, _0x38acb3["UmBJK"], 'vs', _0x38acb3["NSGgG"], 'workbench.desktop.main.js');
|
||
} else {
|
||
_0x37d2a5["writeFileSync"](_0x3c282c, _0x4bc83c, 'utf-8');
|
||
_0x3e6238 = true;
|
||
}
|
||
} else {
|
||
if ("PYNDj" === _0x38acb3["mlBaX"]) {
|
||
this["_postMessage"]({
|
||
'type': "seamlessInjected",
|
||
'success': false,
|
||
'error': _0x38acb3["bpeCI"]
|
||
});
|
||
return;
|
||
} else {
|
||
_0x121b7c = path["join"](_0x46d162, _0x38acb3["xjVUo"], _0x38acb3["vdFYP"], _0x38acb3["UmBJK"], 'vs', "workbench", _0x38acb3["dEWjF"]);
|
||
}
|
||
}
|
||
}
|
||
if (!fs["existsSync"](_0x121b7c)) {
|
||
if (_0x38acb3["NFQWc"] !== _0x38acb3["IvxYw"]) {
|
||
_0x121b7c = (await this["_getWorkbenchPathAsync"]()) || _0x38acb3["UFtEi"];
|
||
} else {
|
||
const _0x984d92 = _0x84f583["match"](/InstallLocation\s+REG_SZ\s+(.+)/);
|
||
if (_0x984d92 && _0x984d92[0x1] && _0x529792["existsSync"](_0x984d92[0x1]["trim"]())) {
|
||
_0x36e7db = _0x984d92[0x1]["trim"]();
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (_0x38acb3["lWQvv"](_0x38acb3["EYQCn"], "npeOU")) {
|
||
_0x121b7c = (await this["_getWorkbenchPathAsync"]()) || "未找到";
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
const _0xbd859c = _0x46d162 && !_0x46d162["includes"](_0x38acb3["mOngd"]) ? fs.existsSync(_0x46d162) : false;
|
||
const _0x354cf1 = _0x3fe4eb ? fs["existsSync"](_0x3fe4eb) : false;
|
||
this["_postMessage"]({
|
||
'type': _0x38acb3["MiEkS"],
|
||
'cursorPath': _0xbd859c ? _0x46d162 : _0x38acb3["HiXkV"](_0x46d162, "未找到"),
|
||
'dataPath': _0x354cf1 ? _0x3fe4eb : _0x38acb3["UFtEi"],
|
||
'workbenchPath': _0x121b7c,
|
||
'platform': _0x2f8924
|
||
});
|
||
} catch (_0x5c0ff6) {
|
||
if (_0x38acb3["GdGfE"](_0x38acb3["hlIYy"], "GnlEK")) {
|
||
this["_postMessage"]({
|
||
'type': _0x38acb3.MiEkS,
|
||
'cursorPath': _0x38acb3["GONGu"],
|
||
'dataPath': '获取失败',
|
||
'workbenchPath': _0x38acb3["GONGu"],
|
||
'error': _0x5c0ff6["message"]
|
||
});
|
||
} else {
|
||
this["_view"]?..webview["postMessage"](_0x1b6a0f);
|
||
}
|
||
}
|
||
}
|
||
async ._loadAccountsFromDB() {
|
||
const _0xefdab9 = {
|
||
'oRodx': "[CursorPro] 找到 Cursor 版本:",
|
||
'pvPNp': "路径:",
|
||
'wjbSZ': "cursorAuth/accessToken",
|
||
'YZqNp': "cursorAuth/refreshToken",
|
||
'dbFLV': "cursorAuth/cachedEmail",
|
||
'zHYNu': function (_0x3aff44, _0x103caf) {
|
||
return _0x3aff44 && _0x103caf;
|
||
},
|
||
'rTrKG': function (_0x26321b, _0x5690c1) {
|
||
return _0x26321b || _0x5690c1;
|
||
}
|
||
};
|
||
try {
|
||
0x0;
|
||
const _0x3d6d98 = account_1["getCursorPaths"]();
|
||
const {
|
||
dbPath: _0x22a865
|
||
} = _0x3d6d98;
|
||
if (!fs["existsSync"](_0x22a865)) {
|
||
return 'OIoiO' === "YEFIo" ? (_0x4484c3.log(_0xefdab9["oRodx"], _0xa4ee3f["version"], _0xefdab9["pvPNp"], _0x4c184d), _0x4e0899["version"]) : [];
|
||
}
|
||
0x0;
|
||
const _0x483399 = await sqlite_1.sqliteGet(_0x22a865, _0xefdab9["wjbSZ"]);
|
||
0x0;
|
||
const _0x207002 = await sqlite_1["sqliteGet"](_0x22a865, _0xefdab9["YZqNp"]);
|
||
0x0;
|
||
const _0x1c5151 = await sqlite_1["sqliteGet"](_0x22a865, _0xefdab9["dbFLV"]);
|
||
if (_0xefdab9["zHYNu"](_0x483399, _0x1c5151)) {
|
||
return [{
|
||
'email': _0x1c5151,
|
||
'access_token': _0x483399,
|
||
'refresh_token': _0xefdab9["rTrKG"](_0x207002, _0x483399)
|
||
}];
|
||
}
|
||
return [];
|
||
} catch (_0x7a83d1) {
|
||
console.error("[CursorPro] 读取账号失败:", _0x7a83d1);
|
||
return [];
|
||
}
|
||
}
|
||
async ["_sendState"]() {
|
||
const _0xd6358c = {
|
||
'vIjoy': 'cursorpro.expireDate',
|
||
'PnvAx': 'cursorpro.switchRemaining',
|
||
'WEZcg': "cursorpro.switchLimit",
|
||
'MBSJn': "state",
|
||
'CNAgf': function (_0x34bf6b, _0x520b84) {
|
||
return _0x34bf6b || _0x520b84;
|
||
},
|
||
'dNuxR': function (_0x289948, _0x9f1b8e) {
|
||
return _0x289948 || _0x9f1b8e;
|
||
},
|
||
'tZHta': function (_0x216c5e, _0x1ac055) {
|
||
return _0x216c5e ?? _0x1ac055;
|
||
}
|
||
};
|
||
const _0x32793c = this["_context"]["globalState"]["get"]("cursorpro.key");
|
||
const _0x59a0ae = this["_context"].globalState["get"]('cursorpro.expireDate');
|
||
const _0x769674 = this["_context"]["globalState"]["get"](_0xd6358c["PnvAx"]);
|
||
const _0x340d3f = this["_context"]["globalState"]["get"](_0xd6358c["WEZcg"]);
|
||
const _0x440ba5 = await this["_getCursorVersion"]();
|
||
0x0;
|
||
const _0x5026a1 = client_1["getOnlineStatus"]();
|
||
this["_postMessage"]({
|
||
'type': _0xd6358c["MBSJn"],
|
||
'isActivated': !!_0x32793c,
|
||
'key': _0xd6358c["CNAgf"](_0x32793c, ''),
|
||
'expireDate': _0xd6358c["dNuxR"](_0x59a0ae, ''),
|
||
'switchRemaining': _0x769674 ?? 0x0,
|
||
'switchLimit': _0xd6358c["tZHta"](_0x340d3f, 0x64),
|
||
'cursorVersion': _0x440ba5,
|
||
'isOnline': _0x5026a1
|
||
});
|
||
}
|
||
async ["_handleRetryConnect"]() {
|
||
const _0x229eab = {
|
||
'rRAOR': function (_0x37df60, _0x561596) {
|
||
return _0x37df60 < _0x561596;
|
||
},
|
||
'dLQJl': function (_0x4e9578, _0x5e18f6) {
|
||
return _0x4e9578 < _0x5e18f6;
|
||
},
|
||
'vBOsW': 'cursorpro.key',
|
||
'NhGlq': function (_0x10685c, _0x39a256) {
|
||
return _0x10685c === _0x39a256;
|
||
},
|
||
'uUjDH': "NZAQL",
|
||
'PglaH': function (_0x2bd5d8, _0x594963) {
|
||
return _0x2bd5d8 !== _0x594963;
|
||
},
|
||
'zwtrx': "ANSiR",
|
||
'vNOCd': "PPUYG",
|
||
'vKktT': function (_0x1fc5b2, _0x4589aa, _0x33e731) {
|
||
return _0x1fc5b2(_0x4589aa, _0x33e731);
|
||
},
|
||
'ZQDbk': "networkStatus",
|
||
'FbRju': "[CursorPro] Retry connect failed:"
|
||
};
|
||
try {
|
||
const _0x38b05a = this["_context"]["globalState"]["get"](_0x229eab["vBOsW"]);
|
||
if (_0x38b05a) {
|
||
if (_0x229eab["NhGlq"](_0x229eab["uUjDH"], _0x229eab["uUjDH"])) {
|
||
0x0;
|
||
await client_1.verifyKey(_0x38b05a);
|
||
} else {
|
||
const _0x32a796 = _0x54cc32.split('.')["map"](_0x4b9729);
|
||
const _0x2142ee = _0x996c39["split"]('.')["map"](_0x1e92ec);
|
||
const _0xa1e4e2 = _0x523189["max"](_0x32a796["length"], _0x2142ee["length"]);
|
||
for (let _0x509f14 = 0x0; _0x229eab["rRAOR"](_0x509f14, _0xa1e4e2); _0x509f14++) {
|
||
const _0x563ae1 = _0x32a796[_0x509f14] || 0x0;
|
||
const _0x3a3596 = _0x2142ee[_0x509f14] || 0x0;
|
||
if (_0x563ae1 > _0x3a3596) {
|
||
return 0x1;
|
||
}
|
||
if (_0x229eab["dLQJl"](_0x563ae1, _0x3a3596)) {
|
||
return -0x1;
|
||
}
|
||
}
|
||
return 0x0;
|
||
}
|
||
} else {
|
||
if (_0x229eab["PglaH"](_0x229eab.zwtrx, _0x229eab["vNOCd"])) {
|
||
0x0;
|
||
const _0x4f7f5e = client_1["getApiUrl"]() + '/api/announcements/latest';
|
||
await _0x229eab["vKktT"](fetch, _0x4f7f5e, {
|
||
'method': 'GET'
|
||
});
|
||
} else {
|
||
_0x1df13e = _0x281b54[0x1].trim();
|
||
}
|
||
}
|
||
await this["_sendState"]();
|
||
this._postMessage({
|
||
'type': _0x229eab.ZQDbk,
|
||
'online': true
|
||
});
|
||
} catch (_0x46319e) {
|
||
console["error"](_0x229eab["FbRju"], _0x46319e);
|
||
this["_postMessage"]({
|
||
'type': "networkStatus",
|
||
'online': false
|
||
});
|
||
}
|
||
}
|
||
async ["_getCursorVersion"]() {
|
||
const _0x4f58a2 = {
|
||
'PTNWv': "[CursorPro] 首次启用,从备份恢复干净的 workbench 文件",
|
||
'wswmm': "[CursorPro] 备份恢复成功",
|
||
'QtJiM': "[CursorPro] 备份恢复失败:",
|
||
'Xqkdy': "cursorPath",
|
||
'ItKog': "获取失败",
|
||
'YSmFZ': function (_0x4ecad8, _0x2cb4f2) {
|
||
return _0x4ecad8 !== _0x2cb4f2;
|
||
},
|
||
'bglvq': 'LtYMm',
|
||
'YXUju': "FXgaA",
|
||
'vhvSM': function (_0xf9bd4a, _0x1405ae) {
|
||
return _0xf9bd4a === _0x1405ae;
|
||
},
|
||
'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 (_0xd9c47c, _0x4fb652) {
|
||
return _0xd9c47c(_0x4fb652);
|
||
},
|
||
'zEiiQ': "vscode",
|
||
'GjUNd': "[CursorPro] 使用 VS Code API 获取版本:",
|
||
'qlNII': "[CursorPro] 未找到 Cursor 版本,尝试的路径:",
|
||
'GOgfB': "[CursorPro] 获取 Cursor 版本失败:"
|
||
};
|
||
try {
|
||
const _0x574db7 = process["platform"];
|
||
const _0x369839 = [];
|
||
const _0x4065be = await this._getCursorInstallPath();
|
||
if (_0x4065be) {
|
||
if (_0x4f58a2["YSmFZ"](_0x4f58a2["bglvq"], _0x4f58a2.YXUju)) {
|
||
if (_0x4f58a2["vhvSM"](_0x574db7, "darwin")) {
|
||
_0x369839["push"](path.join(_0x4065be, _0x4f58a2.bBFPC, _0x4f58a2["gBPlE"], _0x4f58a2["bUMcY"], 'package.json'));
|
||
} else {
|
||
_0x369839["push"](path["join"](_0x4065be, "resources", 'app', _0x4f58a2.CaEkI));
|
||
}
|
||
} else {
|
||
_0x219157["rmSync"](_0x1a5f35, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
}
|
||
}
|
||
if (_0x4f58a2["vhvSM"](_0x574db7, "win32")) {
|
||
const _0x2ff2ee = process["env"].LOCALAPPDATA || '';
|
||
const _0x55e816 = process["env"]["USERPROFILE"] || '';
|
||
const _0x1f7bd3 = process["env"].ProgramFiles || "C:\\Program Files";
|
||
const _0x1defa4 = process["env"]['ProgramFiles(x86)'] || "C:\\Program Files (x86)";
|
||
_0x369839["push"](path["join"](_0x2ff2ee, _0x4f58a2["CfoeP"], _0x4f58a2["pwRyy"], _0x4f58a2.TosHP, "app", "package.json"), path["join"](_0x2ff2ee, _0x4f58a2.CfoeP, _0x4f58a2["LPmpS"], _0x4f58a2.TosHP, 'app', _0x4f58a2.CaEkI), path["join"](_0x55e816, _0x4f58a2["RYOAX"], _0x4f58a2["qCStx"], _0x4f58a2["CfoeP"], _0x4f58a2["pwRyy"], _0x4f58a2["TosHP"], _0x4f58a2["bUMcY"], _0x4f58a2["CaEkI"]), path["join"](_0x1f7bd3, _0x4f58a2.pwRyy, _0x4f58a2.TosHP, 'app', "package.json"), path["join"](_0x1f7bd3, _0x4f58a2["LPmpS"], "resources", _0x4f58a2["bUMcY"], _0x4f58a2["CaEkI"]), path["join"](_0x1defa4, "Cursor", _0x4f58a2.TosHP, _0x4f58a2["bUMcY"], _0x4f58a2["CaEkI"]));
|
||
} else {
|
||
if (_0x574db7 === _0x4f58a2["DEXlW"]) {
|
||
_0x369839.push(_0x4f58a2["VNwrn"]);
|
||
} else {
|
||
const _0x221758 = process.env.HOME || '';
|
||
_0x369839["push"](_0x4f58a2["fjFtX"], _0x4f58a2["jHXyq"], "/opt/cursor/resources/app/package.json", path["join"](_0x221758, _0x4f58a2.WWWWp, 'share', "cursor", _0x4f58a2["TosHP"], 'app', _0x4f58a2.CaEkI));
|
||
}
|
||
}
|
||
for (const _0x339dc7 of _0x369839) {
|
||
if (_0x4f58a2["YSmFZ"]("olTfK", _0x4f58a2["dUUUB"])) {
|
||
return;
|
||
} else {
|
||
try {
|
||
if (_0x4f58a2["JVRzx"] !== "eTsxR") {
|
||
if (fs.existsSync(_0x339dc7)) {
|
||
if (_0x4f58a2["YSmFZ"](_0x4f58a2["uGyrr"], _0x4f58a2.uGyrr)) {
|
||
_0x14c38f["log"](_0x4f58a2.PTNWv);
|
||
try {
|
||
_0x4ace07["copyFileSync"](_0x1facd8, _0xbb494e);
|
||
_0x2425e0["log"](_0x4f58a2["wswmm"]);
|
||
} catch (_0x5ee7d8) {
|
||
_0x18ad92["error"](_0x4f58a2["QtJiM"], _0x5ee7d8);
|
||
}
|
||
} else {
|
||
const _0x3621b8 = fs["readFileSync"](_0x339dc7, _0x4f58a2["RwEEN"]);
|
||
const _0x1f565f = JSON["parse"](_0x3621b8);
|
||
if (_0x1f565f["version"]) {
|
||
if (_0x4f58a2["YSmFZ"](_0x4f58a2["PKTCU"], _0x4f58a2["CRnub"])) {
|
||
console["log"]("[CursorPro] 找到 Cursor 版本:", _0x1f565f["version"], _0x4f58a2["ZQMXp"], _0x339dc7);
|
||
return _0x1f565f["version"];
|
||
} else {
|
||
this["_postMessage"]({
|
||
'type': _0x4f58a2["Xqkdy"],
|
||
'cursorPath': "获取失败",
|
||
'dataPath': _0x4f58a2["ItKog"],
|
||
'workbenchPath': _0x4f58a2["ItKog"],
|
||
'error': _0x130c99["message"]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else if (_0x1bada8.statSync(_0x1e9bf4)["isDirectory"]()) {
|
||
_0x56260a["rmSync"](_0x74e730, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
} else {
|
||
_0x309108["unlinkSync"](_0x19d74d);
|
||
}
|
||
} catch (_0x2af808) {
|
||
console["log"](_0x4f58a2["dEEFY"], _0x339dc7, _0x2af808);
|
||
}
|
||
}
|
||
}
|
||
try {
|
||
const _0xe1f1d3 = _0x4f58a2["opjtq"](require, _0x4f58a2["zEiiQ"]);
|
||
if (_0xe1f1d3.version) {
|
||
console["log"]("[CursorPro] 使用 VS Code API 获取版本:", _0xe1f1d3["version"]);
|
||
return _0xe1f1d3.version;
|
||
}
|
||
} catch (_0x35ddef) {}
|
||
console["log"](_0x4f58a2["qlNII"], _0x369839);
|
||
return '未知';
|
||
} catch (_0x311666) {
|
||
console.error(_0x4f58a2["GOgfB"], _0x311666);
|
||
return '未知';
|
||
}
|
||
}
|
||
._postMessage(_0x571950) {
|
||
this["_view"]?.["webview"]["postMessage"](_0x571950);
|
||
}
|
||
["_getNonce"]() {
|
||
const _0x323fa5 = {
|
||
'YiwNs': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
|
||
'FVmpm': function (_0x262e06, _0x566f52) {
|
||
return _0x262e06 < _0x566f52;
|
||
},
|
||
'XVmEg': function (_0x892c66, _0x1cd020) {
|
||
return _0x892c66 === _0x1cd020;
|
||
},
|
||
'gFjzo': 'UMZcN',
|
||
'RjXnp': function (_0xd635ba, _0x484045) {
|
||
return _0xd635ba * _0x484045;
|
||
}
|
||
};
|
||
let _0x14dd44 = '';
|
||
const _0x44199d = _0x323fa5["YiwNs"];
|
||
for (let _0x5ece7c = 0x0; _0x323fa5["FVmpm"](_0x5ece7c, 0x20); _0x5ece7c++) {
|
||
if (_0x323fa5["XVmEg"](_0x323fa5["gFjzo"], "UMZcN")) {
|
||
_0x14dd44 += _0x44199d["charAt"](Math["floor"](Math["random"]() * _0x44199d["length"]));
|
||
} else if (_0x56e4a8["existsSync"](_0x2ed688)) {
|
||
_0x2ab3fb["rmSync"](_0x258880, {
|
||
'recursive': true,
|
||
'force': true
|
||
});
|
||
_0x3de72a++;
|
||
_0x1d3455["log"]("[CursorPro] 已清理: " + _0x202472);
|
||
}
|
||
}
|
||
return _0x14dd44;
|
||
}
|
||
["_getHtmlContent"](_0x504c5f) {
|
||
const _0x1d6267 = 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-" + _0x1d6267 + "'; img-src " + _0x504c5f["cspSource"] + " https: data:; font-src " + _0x504c5f["cspSource"] + "; worker-src 'none';\">\n <title>CursorPro</title>\n <script nonce=\"" + _0x1d6267 + "\">\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=\"" + _0x1d6267 + "\">\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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\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'; |