'use strict'; // ============================================ // CursorPro Webview Provider - 反混淆版本 // ============================================ const vscode = require('vscode'); const client = require('../api/client'); const account = require('../utils/account'); const extension = require('../extension'); /** * CursorPro Webview Provider * 处理侧边栏 webview 的显示和交互 */ class CursorProProvider { constructor(extensionUri, context) { this._extensionUri = extensionUri; this._context = context; this._view = undefined; } /** * 解析 webview 视图 */ resolveWebviewView(webviewView, context, token) { this._view = webviewView; webviewView.webview.options = { enableScripts: true, localResourceRoots: [this._extensionUri] }; // 设置 HTML 内容 webviewView.webview.html = this._getHtmlContent(webviewView.webview); // 处理来自 webview 的消息 webviewView.webview.onDidReceiveMessage(async (message) => { await this._handleMessage(message); }); // 监听在线状态变化 client.onOnlineStatusChange((isOnline) => { this._postMessage({ type: 'onlineStatus', isOnline: isOnline }); }); } /** * 发送消息到 webview */ _postMessage(message) { if (this._view) { this._view.webview.postMessage(message); } } /** * 处理来自 webview 的消息 */ async _handleMessage(message) { const { type, data } = message; try { switch (type) { case 'verifyKey': await this._handleVerifyKey(data); break; case 'switchAccount': await this._handleSwitchAccount(data); break; case 'getSeamlessStatus': await this._handleGetSeamlessStatus(); break; case 'getSeamlessConfig': await this._handleGetSeamlessConfig(); break; case 'updateSeamlessConfig': await this._handleUpdateSeamlessConfig(data); break; case 'injectSeamless': await this._handleInjectSeamless(data); break; case 'restoreSeamless': await this._handleRestoreSeamless(); break; case 'getSeamlessAccounts': await this._handleGetSeamlessAccounts(); break; case 'syncSeamlessAccounts': await this._handleSyncSeamlessAccounts(data); break; case 'switchSeamlessToken': await this._handleSwitchSeamlessToken(data); break; case 'getProxyConfig': await this._handleGetProxyConfig(); break; case 'updateProxyConfig': await this._handleUpdateProxyConfig(data); break; case 'checkVersion': await this._handleCheckVersion(); break; case 'openExternal': vscode.env.openExternal(vscode.Uri.parse(data.url)); break; case 'showMessage': this._showMessage(data.messageType, data.message); break; case 'getStoredKey': await this._handleGetStoredKey(); break; case 'logout': await this._handleLogout(); break; default: console.warn('[CursorPro] 未知消息类型:', type); } } catch (error) { console.error('[CursorPro] 处理消息失败:', error); this._postMessage({ type: 'error', error: error.message || '操作失败' }); } } /** * 验证 Key */ async _handleVerifyKey(data) { const { key } = data; extension.log('开始验证 Key...'); const result = await client.verifyKey(key); if (result.success) { // 保存 key 到全局状态 await this._context.globalState.update('cursorpro.key', key); // 写入账号数据到本地 if (result.data) { const writeResult = await account.writeAccountToLocal(result.data); if (writeResult) { extension.showStatusBar(); extension.updateUsageStatusBar( result.data.requestCount || 0, result.data.usageAmount || 0 ); // 提示重启 await account.promptRestartCursor('账号切换成功,需要重启 Cursor 生效'); } } } this._postMessage({ type: 'verifyKeyResult', result: result }); } /** * 切换账号 */ async _handleSwitchAccount(data) { const { key } = data; extension.log('开始切换账号...'); const result = await client.switchAccount(key); if (result.success && result.data) { const writeResult = await account.writeAccountToLocal(result.data); if (writeResult) { extension.updateUsageStatusBar( result.data.requestCount || 0, result.data.usageAmount || 0 ); await account.promptRestartCursor('账号切换成功,需要重启 Cursor 生效'); } } this._postMessage({ type: 'switchAccountResult', result: result }); } /** * 获取无缝模式状态 */ async _handleGetSeamlessStatus() { const result = await client.getSeamlessStatus(); this._postMessage({ type: 'seamlessStatusResult', result: result }); } /** * 获取无缝配置 */ async _handleGetSeamlessConfig() { const result = await client.getSeamlessConfig(); this._postMessage({ type: 'seamlessConfigResult', result: result }); } /** * 更新无缝配置 */ async _handleUpdateSeamlessConfig(data) { const result = await client.updateSeamlessConfig(data); this._postMessage({ type: 'updateSeamlessConfigResult', result: result }); } /** * 注入无缝模式 */ async _handleInjectSeamless(data) { const { apiUrl, userKey } = data; const result = await client.injectSeamless(apiUrl, userKey); if (result.success && result.data) { const writeResult = await account.writeAccountToLocal(result.data); if (writeResult) { await account.promptRestartCursor('无缝模式注入成功,需要重启 Cursor 生效'); } } this._postMessage({ type: 'injectSeamlessResult', result: result }); } /** * 恢复无缝模式 */ async _handleRestoreSeamless() { const result = await client.restoreSeamless(); if (result.success) { await account.promptRestartCursor('已恢复默认设置,需要重启 Cursor 生效'); } this._postMessage({ type: 'restoreSeamlessResult', result: result }); } /** * 获取无缝账号列表 */ async _handleGetSeamlessAccounts() { const result = await client.getSeamlessAccounts(); this._postMessage({ type: 'seamlessAccountsResult', result: result }); } /** * 同步无缝账号 */ async _handleSyncSeamlessAccounts(data) { const result = await client.syncSeamlessAccounts(data.accounts); this._postMessage({ type: 'syncSeamlessAccountsResult', result: result }); } /** * 切换无缝 Token */ async _handleSwitchSeamlessToken(data) { const { userKey } = data; const result = await client.switchSeamlessToken(userKey); if (result.success && result.data) { const writeResult = await account.writeAccountToLocal(result.data); if (writeResult) { extension.updateUsageStatusBar( result.data.requestCount || 0, result.data.usageAmount || 0 ); await account.promptRestartCursor('Token 切换成功,需要重启 Cursor 生效'); } } this._postMessage({ type: 'switchSeamlessTokenResult', result: result }); } /** * 获取代理配置 */ async _handleGetProxyConfig() { const result = await client.getProxyConfig(); this._postMessage({ type: 'proxyConfigResult', result: result }); } /** * 更新代理配置 */ async _handleUpdateProxyConfig(data) { const { isEnabled, proxyUrl } = data; const result = await client.updateProxyConfig(isEnabled, proxyUrl); this._postMessage({ type: 'updateProxyConfigResult', result: result }); } /** * 检查版本 */ async _handleCheckVersion() { const result = await client.getLatestVersion(); this._postMessage({ type: 'versionResult', result: result }); } /** * 获取存储的 Key */ async _handleGetStoredKey() { const key = this._context.globalState.get('cursorpro.key'); this._postMessage({ type: 'storedKeyResult', key: key || null }); } /** * 登出 */ async _handleLogout() { await this._context.globalState.update('cursorpro.key', undefined); extension.hideStatusBar(); this._postMessage({ type: 'logoutResult', success: true }); } /** * 显示消息 */ _showMessage(messageType, message) { switch (messageType) { case 'info': vscode.window.showInformationMessage(message); break; case 'warning': vscode.window.showWarningMessage(message); break; case 'error': vscode.window.showErrorMessage(message); break; default: vscode.window.showInformationMessage(message); } } /** * 生成 Webview HTML 内容 */ _getHtmlContent(webview) { const styleUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, 'media', 'style.css') ); const scriptUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, 'media', 'main.js') ); const nonce = this._getNonce(); return `