fix: 密钥失效后自动清除并刷新UI
- _checkKeyStatus 清除无效密钥后重新调用 _sendState() 刷新面板 - 区分网络离线和后端明确返回无效,避免离线时误清密钥 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -186,6 +186,22 @@ class HummingbirdProViewProvider {
|
||||
this._sendState();
|
||||
this._checkKeyStatus();
|
||||
}
|
||||
/**
|
||||
* 获取当前激活的密钥(统一入口)
|
||||
* 优先返回当前选中号池的密钥,兼容旧版本的 hummingbird.key
|
||||
*/
|
||||
_getActiveKey() {
|
||||
const selectedPool = this._context.globalState.get("hummingbird.selectedPool") || "auto";
|
||||
const key = selectedPool === "pro"
|
||||
? this._context.globalState.get("hummingbird.proKey")
|
||||
: this._context.globalState.get("hummingbird.autoKey");
|
||||
|
||||
// 兼容旧版本:如果新字段没有值,回退到旧字段
|
||||
if (!key) {
|
||||
return this._context.globalState.get("hummingbird.key");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
async _checkKeyStatus() {
|
||||
// 检查 Auto 和 Pro 两个密钥的状态
|
||||
const autoKey = this._context.globalState.get("hummingbird.autoKey");
|
||||
@@ -205,6 +221,9 @@ class HummingbirdProViewProvider {
|
||||
try {
|
||||
const verifyResult = await client_1.verifyKey(autoKey);
|
||||
if (verifyResult.success && verifyResult.valid) {
|
||||
if (verifyResult.key && verifyResult.key !== autoKey) {
|
||||
await this._context.globalState.update("hummingbird.autoKey", verifyResult.key);
|
||||
}
|
||||
keyStatus.auto = {
|
||||
valid: true,
|
||||
expireDate: verifyResult.expire_date,
|
||||
@@ -212,8 +231,14 @@ class HummingbirdProViewProvider {
|
||||
mergedCount: verifyResult.merged_count || 0
|
||||
};
|
||||
await this._context.globalState.update("hummingbird.autoExpireDate", verifyResult.expire_date);
|
||||
} else {
|
||||
keyStatus.auto = { valid: false, error: verifyResult.error };
|
||||
} else if (!verifyResult.isOffline) {
|
||||
// 后端明确返回无效(非网络错误),自动清除本地 Auto 密钥
|
||||
console.warn("[蜂鸟Pro] Auto 密钥已失效,自动清除:", verifyResult.error);
|
||||
await this._context.globalState.update("hummingbird.autoKey", undefined);
|
||||
await this._context.globalState.update("hummingbird.autoExpireDate", undefined);
|
||||
await this._context.globalState.update("hummingbird.autoMergedCount", undefined);
|
||||
await this._context.globalState.update("hummingbird.key", undefined);
|
||||
keyStatus.auto = { valid: false, error: verifyResult.error, cleared: true };
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[蜂鸟Pro] 检查 Auto 密钥状态失败:", err);
|
||||
@@ -225,6 +250,9 @@ class HummingbirdProViewProvider {
|
||||
try {
|
||||
const verifyResult = await client_1.verifyKey(proKey);
|
||||
if (verifyResult.success && verifyResult.valid) {
|
||||
if (verifyResult.key && verifyResult.key !== proKey) {
|
||||
await this._context.globalState.update("hummingbird.proKey", verifyResult.key);
|
||||
}
|
||||
keyStatus.pro = {
|
||||
valid: true,
|
||||
quota: verifyResult.quota,
|
||||
@@ -234,19 +262,45 @@ class HummingbirdProViewProvider {
|
||||
};
|
||||
await this._context.globalState.update("hummingbird.proQuota", verifyResult.quota);
|
||||
await this._context.globalState.update("hummingbird.proQuotaUsed", verifyResult.quota_used);
|
||||
} else {
|
||||
keyStatus.pro = { valid: false, error: verifyResult.error };
|
||||
} else if (!verifyResult.isOffline) {
|
||||
// 后端明确返回无效(非网络错误),自动清除本地 Pro 密钥
|
||||
console.warn("[蜂鸟Pro] Pro 密钥已失效,自动清除:", verifyResult.error);
|
||||
await this._context.globalState.update("hummingbird.proKey", undefined);
|
||||
await this._context.globalState.update("hummingbird.proQuota", undefined);
|
||||
await this._context.globalState.update("hummingbird.proQuotaUsed", undefined);
|
||||
await this._context.globalState.update("hummingbird.proMergedCount", undefined);
|
||||
keyStatus.pro = { valid: false, error: verifyResult.error, cleared: true };
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("[蜂鸟Pro] 检查 Pro 密钥状态失败:", err);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有密钥被清除,同时清理无感换号状态
|
||||
if (keyStatus.auto?.cleared || keyStatus.pro?.cleared) {
|
||||
const remainingAuto = this._context.globalState.get("hummingbird.autoKey");
|
||||
const remainingPro = this._context.globalState.get("hummingbird.proKey");
|
||||
if (!remainingAuto && !remainingPro) {
|
||||
// 所有密钥都失效了,清理全部状态
|
||||
await this._context.globalState.update("hummingbird.selectedPool", undefined);
|
||||
await this._context.globalState.update("hummingbird.seamlessInjected", undefined);
|
||||
await this._context.globalState.update("hummingbird.seamlessCurrentAccount", undefined);
|
||||
await this._context.globalState.update("hummingbird.expireDate", undefined);
|
||||
await this._context.globalState.update("hummingbird.switchRemaining", undefined);
|
||||
extension_1.hideStatusBar();
|
||||
}
|
||||
}
|
||||
|
||||
this._postMessage({
|
||||
'type': "keyStatusChecked",
|
||||
'auto': keyStatus.auto,
|
||||
'pro': keyStatus.pro
|
||||
});
|
||||
|
||||
// 如果有密钥被清除,重新发送状态给面板刷新UI
|
||||
if (keyStatus.auto?.cleared || keyStatus.pro?.cleared) {
|
||||
await this._sendState();
|
||||
}
|
||||
}
|
||||
async _handleActivate(key) {
|
||||
try {
|
||||
@@ -262,8 +316,9 @@ class HummingbirdProViewProvider {
|
||||
this._cleanProxySettings();
|
||||
const verifyResult = await client_1.verifyKey(key);
|
||||
if (verifyResult.success && verifyResult.valid) {
|
||||
const membershipType = verifyResult.membership_type || 'free';
|
||||
const isAuto = membershipType === 'free';
|
||||
const membershipType = verifyResult.membership_type || 'auto';
|
||||
const isAuto = membershipType === 'auto' || membershipType === 'free';
|
||||
const activatedKey = verifyResult.key || key;
|
||||
|
||||
console.log("[蜂鸟Pro] 激活成功,类型:", membershipType, "后端返回:", {
|
||||
'expire_date': verifyResult.expire_date,
|
||||
@@ -274,20 +329,25 @@ class HummingbirdProViewProvider {
|
||||
|
||||
// 根据类型存储到不同字段
|
||||
if (isAuto) {
|
||||
await this._context.globalState.update("hummingbird.autoKey", key);
|
||||
await this._context.globalState.update("hummingbird.autoKey", activatedKey);
|
||||
await this._context.globalState.update("hummingbird.autoExpireDate", verifyResult.expire_date);
|
||||
await this._context.globalState.update("hummingbird.autoMergedCount", verifyResult.merged_count || 0);
|
||||
// 同步写回旧字段(兼容旧逻辑)
|
||||
await this._context.globalState.update("hummingbird.key", activatedKey);
|
||||
await this._context.globalState.update("hummingbird.expireDate", verifyResult.expire_date);
|
||||
} else {
|
||||
await this._context.globalState.update("hummingbird.proKey", key);
|
||||
await this._context.globalState.update("hummingbird.proKey", activatedKey);
|
||||
await this._context.globalState.update("hummingbird.proQuota", verifyResult.quota);
|
||||
await this._context.globalState.update("hummingbird.proQuotaUsed", verifyResult.quota_used || 0);
|
||||
await this._context.globalState.update("hummingbird.proMergedCount", verifyResult.merged_count || 0);
|
||||
// 同步写回旧字段(兼容旧逻辑)
|
||||
await this._context.globalState.update("hummingbird.key", activatedKey);
|
||||
}
|
||||
|
||||
this._postMessage({
|
||||
'type': "activated",
|
||||
'success': true,
|
||||
'key': key,
|
||||
'key': activatedKey,
|
||||
'membershipType': membershipType,
|
||||
'expireDate': verifyResult.expire_date,
|
||||
'quota': verifyResult.quota,
|
||||
@@ -332,6 +392,15 @@ class HummingbirdProViewProvider {
|
||||
const switchResult = await client_1.switchSeamlessToken(savedKey);
|
||||
if (switchResult.switched) {
|
||||
await this._context.globalState.update("hummingbird.switchRemaining", switchResult.switchRemaining);
|
||||
// 写入新 token 到本地 Cursor 存储
|
||||
if (switchResult.data) {
|
||||
try {
|
||||
await this._writeAccountToLocal(switchResult.data);
|
||||
console.log("[蜂鸟Pro] 换号成功,已写入新 token");
|
||||
} catch (writeErr) {
|
||||
console.error("[蜂鸟Pro] 写入 token 失败:", writeErr);
|
||||
}
|
||||
}
|
||||
this._postMessage({
|
||||
'type': "switched",
|
||||
'success': true,
|
||||
@@ -365,10 +434,10 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
async _writeAccountToLocal(accountData) {
|
||||
try {
|
||||
const condition = process.env.APPDATA || '';
|
||||
const joinedPath = path.join(condition, "Cursor", "User", "globalStorage", "state.vscdb");
|
||||
const joinedPath1 = path.join(condition, "Cursor", "User", "globalStorage", 'storage.json');
|
||||
const joinedPath2 = path.join(condition, "Cursor", "machineid");
|
||||
const cursorPaths = account_1.getCursorPaths();
|
||||
const joinedPath = cursorPaths.dbPath;
|
||||
const joinedPath1 = cursorPaths.storagePath;
|
||||
const joinedPath2 = cursorPaths.machineidPath;
|
||||
if (fs.existsSync(joinedPath)) {
|
||||
const items = [];
|
||||
if (accountData.accessToken) {
|
||||
@@ -377,6 +446,9 @@ class HummingbirdProViewProvider {
|
||||
if (accountData.refreshToken) {
|
||||
items.push(["cursorAuth/refreshToken", accountData.refreshToken]);
|
||||
}
|
||||
if (accountData.workosSessionToken) {
|
||||
items.push(["cursorAuth/WorkosCursorSessionToken", accountData.workosSessionToken]);
|
||||
}
|
||||
if (accountData.email) {
|
||||
items.push(["cursorAuth/cachedEmail", accountData.email]);
|
||||
}
|
||||
@@ -433,6 +505,17 @@ class HummingbirdProViewProvider {
|
||||
await this._context.globalState.update("hummingbird.key", undefined);
|
||||
await this._context.globalState.update("hummingbird.expireDate", undefined);
|
||||
await this._context.globalState.update("hummingbird.switchRemaining", undefined);
|
||||
// 清理双池相关状态
|
||||
await this._context.globalState.update("hummingbird.autoKey", undefined);
|
||||
await this._context.globalState.update("hummingbird.proKey", undefined);
|
||||
await this._context.globalState.update("hummingbird.autoExpireDate", undefined);
|
||||
await this._context.globalState.update("hummingbird.proQuota", undefined);
|
||||
await this._context.globalState.update("hummingbird.proQuotaUsed", undefined);
|
||||
await this._context.globalState.update("hummingbird.proMergedCount", undefined);
|
||||
await this._context.globalState.update("hummingbird.autoMergedCount", undefined);
|
||||
await this._context.globalState.update("hummingbird.selectedPool", undefined);
|
||||
await this._context.globalState.update("hummingbird.seamlessInjected", undefined);
|
||||
await this._context.globalState.update("hummingbird.seamlessCurrentAccount", undefined);
|
||||
extension_1.hideStatusBar();
|
||||
this._postMessage({
|
||||
'type': 'reset',
|
||||
@@ -473,9 +556,9 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
const hostLine = account_1.getCursorPaths();
|
||||
const {
|
||||
dbPath: charIdx,
|
||||
storagePath: lineItem,
|
||||
machineidPath: lineIdx
|
||||
dbPath: dbPath,
|
||||
storagePath: storagePath,
|
||||
machineidPath: machineidPath
|
||||
} = hostLine;
|
||||
const module = require("crypto");
|
||||
const str = module.randomBytes(32).toString("hex");
|
||||
@@ -484,16 +567,16 @@ class HummingbirdProViewProvider {
|
||||
const result = '{' + module.randomUUID().toUpperCase() + '}';
|
||||
let count = 0;
|
||||
let items = [];
|
||||
if (fs.existsSync(lineItem)) {
|
||||
if (fs.existsSync(storagePath)) {
|
||||
let num = 3;
|
||||
while (num > 0) {
|
||||
try {
|
||||
const parsed = JSON.parse(fs.readFileSync(lineItem, "utf-8"));
|
||||
const parsed = JSON.parse(fs.readFileSync(storagePath, "utf-8"));
|
||||
parsed["telemetry.machineId"] = str;
|
||||
parsed["telemetry.macMachineId"] = str1;
|
||||
parsed["telemetry.devDeviceId"] = proxyLine;
|
||||
parsed["telemetry.sqmId"] = result;
|
||||
fs.writeFileSync(lineItem, JSON.stringify(parsed, null, 4));
|
||||
fs.writeFileSync(storagePath, JSON.stringify(parsed, null, 4));
|
||||
console.log("[蜂鸟Pro] storage.json 已更新");
|
||||
count++;
|
||||
break;
|
||||
@@ -512,13 +595,13 @@ class HummingbirdProViewProvider {
|
||||
let num = 3;
|
||||
while (num > 0) {
|
||||
try {
|
||||
const dirPath = path.dirname(lineIdx);
|
||||
const dirPath = path.dirname(machineidPath);
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, {
|
||||
'recursive': true
|
||||
});
|
||||
}
|
||||
fs.writeFileSync(lineIdx, str);
|
||||
fs.writeFileSync(machineidPath, str);
|
||||
console.log("[蜂鸟Pro] machineid 文件已更新");
|
||||
count++;
|
||||
break;
|
||||
@@ -533,12 +616,12 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fs.existsSync(charIdx)) {
|
||||
if (fs.existsSync(dbPath)) {
|
||||
let num = 3;
|
||||
while (num > 0) {
|
||||
try {
|
||||
const proxyEntry = module.randomUUID();
|
||||
const newHostsContent = await sqlite_1.sqliteSetBatch(charIdx, [['storage.serviceMachineId', proxyEntry]]);
|
||||
const newHostsContent = await sqlite_1.sqliteSetBatch(dbPath, [['storage.serviceMachineId', proxyEntry]]);
|
||||
if (newHostsContent) {
|
||||
console.log("[蜂鸟Pro] SQLite 数据库已更新");
|
||||
count++;
|
||||
@@ -787,7 +870,7 @@ class HummingbirdProViewProvider {
|
||||
if (lockedInfo) {
|
||||
try {
|
||||
fs.writeFileSync(content1, content, "utf-8");
|
||||
remainingCount = true;
|
||||
isFalse = true;
|
||||
} catch (writeErr2) {
|
||||
console.log("[蜂鸟Pro] Write still failed after permission grant");
|
||||
}
|
||||
@@ -815,8 +898,8 @@ class HummingbirdProViewProvider {
|
||||
if (process.platform === "darwin") {
|
||||
const pathStr = "/tmp/hosts_cursor_temp";
|
||||
fs.writeFileSync(pathStr, content, "utf-8");
|
||||
const content1 = "do shell script \"cp '" + pathStr + "' '" + content1 + "' && rm '" + pathStr + "' && dscacheutil -flushcache && killall -HUP mDNSResponder\" with administrator privileges";
|
||||
await execAsync('osascript -e "' + content1.replace(/"/g, "\\\"") + "\"");
|
||||
const osaCmd = "do shell script \"cp '" + pathStr + "' '" + content1 + "' && rm '" + pathStr + "' && dscacheutil -flushcache && killall -HUP mDNSResponder\" with administrator privileges";
|
||||
await execAsync('osascript -e "' + osaCmd.replace(/"/g, "\\\"") + "\"");
|
||||
} else {
|
||||
fs.writeFileSync(content1, content, "utf-8");
|
||||
}
|
||||
@@ -830,7 +913,7 @@ class HummingbirdProViewProvider {
|
||||
async _handleToggleProxy(enabled, silent) {
|
||||
try {
|
||||
if (enabled) {
|
||||
const savedKey = this._context.globalState.get("hummingbird.key");
|
||||
const savedKey = this._getActiveKey();
|
||||
const expireDate = this._context.globalState.get('hummingbird.expireDate');
|
||||
if (!savedKey) {
|
||||
this._postMessage({
|
||||
@@ -1012,7 +1095,7 @@ class HummingbirdProViewProvider {
|
||||
if (regOut2 && regOut2.trim()) {
|
||||
const matchResult = regOut2.match(/InstallLocation\s+REG_SZ\s+(.+)/);
|
||||
if (matchResult && matchResult[1] && fs.existsSync(matchResult[1].trim())) {
|
||||
cursorPath = matchResult[1].trim();
|
||||
result = matchResult[1].trim();
|
||||
}
|
||||
}
|
||||
} catch (e5) {
|
||||
@@ -1048,7 +1131,7 @@ class HummingbirdProViewProvider {
|
||||
for (const str of parts) {
|
||||
const trimmed = str.trim();
|
||||
if (trimmed && fs.existsSync(trimmed)) {
|
||||
cursorPath = path.dirname(trimmed);
|
||||
result = path.dirname(trimmed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1091,7 +1174,7 @@ class HummingbirdProViewProvider {
|
||||
if (fileItem && fileItem.trim()) {
|
||||
const matchResult = fileItem.match(/(\/.+\.app)/);
|
||||
if (matchResult) {
|
||||
cursorPath = matchResult[1];
|
||||
result = matchResult[1];
|
||||
}
|
||||
}
|
||||
} catch (findErr) {
|
||||
@@ -1123,7 +1206,7 @@ class HummingbirdProViewProvider {
|
||||
} = await execAsync("readlink -f /proc/" + condition + "/exe 2>/dev/null");
|
||||
if (subDir && subDir.trim()) {
|
||||
const trimmed = subDir.trim();
|
||||
cursorPath = path.dirname(trimmed);
|
||||
result = path.dirname(trimmed);
|
||||
if (result.endsWith("/bin")) {
|
||||
result = path.dirname(result);
|
||||
}
|
||||
@@ -1138,9 +1221,9 @@ class HummingbirdProViewProvider {
|
||||
if (subItem && subItem.trim()) {
|
||||
const execResult = await execAsync('readlink -f "' + subItem.trim() + '" 2>/dev/null');
|
||||
if (execResult.stdout && execResult.stdout.trim()) {
|
||||
cursorPath = path.dirname(execResult.stdout.trim());
|
||||
result = path.dirname(execResult.stdout.trim());
|
||||
if (result.endsWith('/bin')) {
|
||||
cursorPath = path.dirname(result);
|
||||
result = path.dirname(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1260,7 +1343,7 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
async _handleInjectSeamless() {
|
||||
try {
|
||||
const savedKey = this._context.globalState.get("hummingbird.key");
|
||||
const savedKey = this._getActiveKey();
|
||||
if (!savedKey) {
|
||||
this._postMessage({
|
||||
'type': "seamlessInjected",
|
||||
@@ -1269,15 +1352,35 @@ class HummingbirdProViewProvider {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const status = await client_1.getUserSwitchStatus(savedKey);
|
||||
if (!status.valid) {
|
||||
|
||||
// 1. 先调用后端启用无感换号(分配账号)
|
||||
const deviceId = client_1.getDeviceId();
|
||||
console.log("[蜂鸟Pro] 正在调用后端启用无感换号...");
|
||||
const enableResult = await client_1.enableSeamless(savedKey, deviceId);
|
||||
|
||||
if (!enableResult.success) {
|
||||
this._postMessage({
|
||||
'type': "seamlessInjected",
|
||||
'success': false,
|
||||
'error': status.error || "授权码无效"
|
||||
'error': enableResult.error || "启用无感换号失败"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 验证账号数据
|
||||
const accountData = enableResult.data?.account;
|
||||
if (!accountData || !(accountData.token || accountData.access_token)) {
|
||||
this._postMessage({
|
||||
'type': "seamlessInjected",
|
||||
'success': false,
|
||||
'error': "后端未返回账号信息"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[蜂鸟Pro] 后端分配账号成功:", accountData.email);
|
||||
|
||||
// 3. 获取 workbench 路径并进行本地文件注入
|
||||
const workbenchPath = await this._getWorkbenchPathAsync();
|
||||
if (!workbenchPath) {
|
||||
this._postMessage({
|
||||
@@ -1368,12 +1471,33 @@ class HummingbirdProViewProvider {
|
||||
throw writeErr;
|
||||
}
|
||||
await this._context.globalState.update("hummingbird.seamlessInjected", true);
|
||||
|
||||
// 4. 注入成功后,将后端分配的账号信息写入 Cursor
|
||||
console.log("[蜂鸟Pro] 正在写入账号信息到 Cursor...");
|
||||
try {
|
||||
await this._writeAccountToLocal({
|
||||
accessToken: accountData.access_token || accountData.token,
|
||||
refreshToken: accountData.refresh_token,
|
||||
workosSessionToken: accountData.workos_session_token,
|
||||
email: accountData.email,
|
||||
membership_type: accountData.membership_type
|
||||
});
|
||||
console.log("[蜂鸟Pro] 账号信息写入成功");
|
||||
} catch (writeAccountErr) {
|
||||
console.error("[蜂鸟Pro] 写入账号信息失败:", writeAccountErr);
|
||||
// 写入失败不阻塞整个流程,因为注入已经成功
|
||||
}
|
||||
|
||||
this._postMessage({
|
||||
'type': 'seamlessInjected',
|
||||
'success': true,
|
||||
'applied': items,
|
||||
'needRestart': true,
|
||||
'message': "无感换号已启用"
|
||||
'message': "无感换号已启用",
|
||||
'account': {
|
||||
email: accountData.email,
|
||||
membership_type: accountData.membership_type
|
||||
}
|
||||
});
|
||||
} catch (appDir) {
|
||||
console.error("[蜂鸟Pro] Inject error:", appDir);
|
||||
@@ -1435,6 +1559,17 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
throw writeErr;
|
||||
}
|
||||
|
||||
// 通知后端释放锁定的账号
|
||||
try {
|
||||
const savedKey = this._context.globalState.get("hummingbird.key");
|
||||
if (savedKey) {
|
||||
await client_1.disableSeamless(savedKey);
|
||||
}
|
||||
} catch (disableErr) {
|
||||
console.warn("[蜂鸟Pro] 通知后端禁用无感换号失败:", disableErr);
|
||||
}
|
||||
|
||||
this._postMessage({
|
||||
'type': "seamlessRestored",
|
||||
'success': true,
|
||||
@@ -1480,7 +1615,7 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
async _handleGetUserSwitchStatus() {
|
||||
try {
|
||||
const savedKey = this._context.globalState.get('hummingbird.key');
|
||||
const savedKey = this._getActiveKey();
|
||||
if (!savedKey) {
|
||||
this._postMessage({
|
||||
'type': "userSwitchStatus",
|
||||
@@ -1713,7 +1848,7 @@ class HummingbirdProViewProvider {
|
||||
}
|
||||
async _handleCheckUsageBeforeSwitch(silent) {
|
||||
try {
|
||||
const savedKey = this._context.globalState.get("hummingbird.key");
|
||||
const savedKey = this._getActiveKey();
|
||||
if (!savedKey) {
|
||||
this._postMessage({
|
||||
'type': "usageCheckResult",
|
||||
@@ -2129,4 +2264,4 @@ class HummingbirdProViewProvider {
|
||||
// 以下为占位注释,保持文件结构不变
|
||||
|
||||
exports.HummingbirdProViewProvider = HummingbirdProViewProvider;
|
||||
HummingbirdProViewProvider.CURRENT_VERSION = '2.0.0';
|
||||
HummingbirdProViewProvider.CURRENT_VERSION = '2.1.0';
|
||||
|
||||
Reference in New Issue
Block a user