Files
cursornew2026/extension_clean/out/utils/account.js
ccdojox-crypto 73a71f198f 蜂鸟Pro v2.0.1 - 基础框架版本 (待完善)
## 当前状态
- 插件界面已完成重命名 (cursorpro → hummingbird)
- 双账号池 UI 已实现 (Auto/Pro 卡片)
- 后端已切换到 MySQL 数据库
- 添加了 Cursor 官方用量 API 文档

## 已知问题 (待修复)
1. 激活时检查账号导致无账号时激活失败
2. 未启用无感换号时不应获取账号
3. 账号用量模块不显示 (seamless 未启用时应隐藏)
4. 积分显示为 0 (后端未正确返回)
5. Auto/Pro 双密钥逻辑混乱,状态不同步
6. 账号添加后无自动分析功能

## 下一版本计划
- 重构数据模型,优化账号状态管理
- 实现 Cursor API 自动分析账号
- 修复激活流程,不依赖账号
- 启用无感时才分配账号
- 完善账号用量实时显示

## 文件说明
- docs/系统设计文档.md - 完整架构设计
- cursor 官方用量接口.md - Cursor API 文档
- 参考计费/ - Vibeviewer 开源项目参考

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:21:52 +08:00

214 lines
7.9 KiB
JavaScript

'use strict';
// ============================================
// 蜂鸟Pro Account Utils - 反混淆版本
// ============================================
Object.defineProperty(exports, "__esModule", { value: true });
const vscode = require('vscode');
const path = require('path');
const fs = require('fs');
const child_process = require('child_process');
const util = require('util');
const sqlite_1 = require('./sqlite');
const execAsync = util.promisify(child_process.exec);
/**
* 获取 Cursor 相关路径
* @returns {{dbPath: string, storagePath: string, machineidPath: string}}
*/
function getCursorPaths() {
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
if (process.platform === 'win32') {
const appData = process.env.APPDATA || '';
return {
dbPath: path.join(appData, 'Cursor', 'User', 'globalStorage', 'state.vscdb'),
storagePath: path.join(appData, 'Cursor', 'User', 'globalStorage', 'storage.json'),
machineidPath: path.join(appData, 'Cursor', 'machineid')
};
} else if (process.platform === 'darwin') {
return {
dbPath: path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'state.vscdb'),
storagePath: path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'storage.json'),
machineidPath: path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'machineid')
};
} else {
// Linux
return {
dbPath: path.join(homeDir, '.config', 'Cursor', 'User', 'globalStorage', 'state.vscdb'),
storagePath: path.join(homeDir, '.config', 'Cursor', 'User', 'globalStorage', 'storage.json'),
machineidPath: path.join(homeDir, '.config', 'Cursor', 'machineid')
};
}
}
exports.getCursorPaths = getCursorPaths;
/**
* 将账号数据写入本地存储
* @param {Object} accountData - 账号数据
* @param {string} accountData.accessToken - 访问令牌
* @param {string} accountData.refreshToken - 刷新令牌
* @param {string} accountData.workosSessionToken - WorkOS 会话令牌
* @param {string} accountData.email - 邮箱
* @param {string} accountData.membership_type - 会员类型
* @param {string} accountData.machineId - 机器 ID
* @param {string} accountData.macMachineId - Mac 机器 ID
* @param {string} accountData.devDeviceId - 开发设备 ID
* @param {string} accountData.serviceMachineId - 服务机器 ID
* @returns {Promise<boolean>}
*/
async function writeAccountToLocal(accountData) {
try {
const cursorPaths = getCursorPaths();
const { dbPath, storagePath, machineidPath } = cursorPaths;
console.log('[蜂鸟Pro] 数据库路径:', dbPath);
console.log('[蜂鸟Pro] 数据库存在:', fs.existsSync(dbPath));
console.log('[蜂鸟Pro] 账号数据:', JSON.stringify({
hasAccessToken: !!accountData.accessToken,
hasRefreshToken: !!accountData.refreshToken,
hasWorkosToken: !!accountData.workosSessionToken,
email: accountData.email
}));
// 写入数据库
if (fs.existsSync(dbPath)) {
try {
const entries = [];
if (accountData.accessToken) {
entries.push(['cursorAuth/accessToken', accountData.accessToken]);
}
if (accountData.refreshToken) {
entries.push(['cursorAuth/refreshToken', accountData.refreshToken]);
}
if (accountData.workosSessionToken) {
entries.push(['cursorAuth/WorkosCursorSessionToken', accountData.workosSessionToken]);
}
if (accountData.email) {
entries.push(['cursorAuth/cachedEmail', accountData.email]);
}
if (accountData.membership_type) {
entries.push(['cursorAuth/stripeMembershipType', accountData.membership_type]);
}
if (accountData.devDeviceId) {
entries.push(['telemetry.devDeviceId', accountData.devDeviceId || 'default']);
}
if (accountData.serviceMachineId) {
entries.push(['serviceMachineId', accountData.serviceMachineId]);
}
console.log('[蜂鸟Pro] 准备写入', entries.length, '个字段');
const success = await sqlite_1.sqliteSetBatch(dbPath, entries);
if (!success) {
throw new Error('数据库写入失败');
}
console.log('[蜂鸟Pro] 已写入', entries.length, '个字段');
} catch (error) {
console.error('[蜂鸟Pro] 数据库写入错误:', error);
vscode.window.showErrorMessage('数据库写入失败: ' + error);
return false;
}
} else {
console.error('[蜂鸟Pro] 数据库文件不存在:', dbPath);
vscode.window.showErrorMessage('[蜂鸟Pro] 数据库文件不存在');
return false;
}
// 更新 storage.json
if (fs.existsSync(storagePath)) {
const storageData = JSON.parse(fs.readFileSync(storagePath, 'utf-8'));
if (accountData.machineId) {
storageData['telemetry.machineId'] = accountData.machineId;
}
if (accountData.macMachineId) {
storageData['telemetry.macMachineId'] = accountData.macMachineId;
}
if (accountData.devDeviceId) {
storageData['telemetry.devDeviceId'] = accountData.devDeviceId;
}
if (accountData.serviceMachineId) {
storageData['serviceMachineId'] = accountData.serviceMachineId;
}
fs.writeFileSync(storagePath, JSON.stringify(storageData, null, 4));
console.log('[蜂鸟Pro] storage.json 已更新');
}
// 更新 machineid 文件
if (accountData.machineId && machineidPath) {
const machineIdDir = path.dirname(machineidPath);
if (!fs.existsSync(machineIdDir)) {
fs.mkdirSync(machineIdDir, { recursive: true });
}
fs.writeFileSync(machineidPath, accountData.machineId);
console.log('[蜂鸟Pro] machineid 文件已更新');
}
// Windows: 更新注册表 (如果提供了 devDeviceId)
if (accountData.devDeviceId && process.platform === 'win32') {
try {
const regCommand = 'reg add "HKCU\\Software\\Cursor" /v devDeviceId /t REG_SZ /d "' + accountData.devDeviceId + '" /f';
await execAsync(regCommand);
console.log('[蜂鸟Pro] 注册表已更新');
} catch (error) {
console.warn('[蜂鸟Pro] 注册表写入失败(可能需要管理员权限):', error);
}
}
return true;
} catch (error) {
console.error('[蜂鸟Pro] writeAccountToLocal 错误:', error);
return false;
}
}
exports.writeAccountToLocal = writeAccountToLocal;
/**
* 关闭 Cursor 进程
*/
async function closeCursor() {
try {
if (process.platform === 'win32') {
await execAsync('taskkill /F /IM Cursor.exe').catch(() => {});
} else {
await execAsync('pkill -9 -f Cursor').catch(() => {});
}
} catch (error) {
console.warn('[蜂鸟Pro] 关闭 Cursor 失败:', error);
}
}
exports.closeCursor = closeCursor;
/**
* 提示重启 Cursor
* @param {string} message - 提示消息
*/
async function promptRestartCursor(message) {
const selection = await vscode.window.showInformationMessage(
message,
'立即重启',
'稍后'
);
if (selection === '立即重启') {
await closeCursor();
}
}
exports.promptRestartCursor = promptRestartCursor;