diff --git a/app.js b/app.js
index 7b43c3b..a0b95e9 100644
--- a/app.js
+++ b/app.js
@@ -38,7 +38,6 @@ class CLIProxyManager {
if (savedTheme && ['light', 'dark'].includes(savedTheme)) {
this.currentTheme = savedTheme;
} else {
- // 根据系统偏好自动选择
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
this.currentTheme = 'dark';
} else {
@@ -586,6 +585,13 @@ class CLIProxyManager {
addOpenaiProvider.addEventListener('click', () => this.showAddOpenAIProviderModal());
}
+
+ // Gemini Web Token
+ const geminiWebTokenBtn = document.getElementById('gemini-web-token-btn');
+ if (geminiWebTokenBtn) {
+ geminiWebTokenBtn.addEventListener('click', () => this.saveGeminiWebTokenDirect());
+ }
+
// 认证文件管理
const uploadAuthFile = document.getElementById('upload-auth-file');
const deleteAllAuthFiles = document.getElementById('delete-all-auth-files');
@@ -726,8 +732,7 @@ class CLIProxyManager {
this.managementKey = savedKey;
}
- // 注意:不再处理DOM元素,因为认证配置已改为只读显示
- // DOM更新由updateConnectionInfo()方法处理
+
}
// API 请求方法
@@ -2187,6 +2192,241 @@ class CLIProxyManager {
}
}
+ // === OAuth 认证方法 ===
+
+ // 显示/隐藏 Gemini CLI 项目表单
+ showGeminiCliProjectForm() {
+ document.getElementById('gemini-cli-project-group').style.display = 'block';
+ }
+
+ hideGeminiCliProjectForm() {
+ document.getElementById('gemini-cli-project-group').style.display = 'none';
+ document.getElementById('gemini-cli-project-id').value = '';
+ }
+
+ // 开始 Anthropic (Claude) OAuth 认证
+ async startAnthropicAuth() {
+ try {
+ const response = await this.makeRequest('/anthropic-auth-url');
+ this.handleOAuthFlow(response.url, 'Anthropic (Claude)');
+ } catch (error) {
+ this.showNotification(`启动 Anthropic 认证失败: ${error.message}`, 'error');
+ }
+ }
+
+ // 开始 Codex OAuth 认证
+ async startCodexAuth() {
+ try {
+ const response = await this.makeRequest('/codex-auth-url');
+ this.handleOAuthFlow(response.url, 'Codex');
+ } catch (error) {
+ this.showNotification(`启动 Codex 认证失败: ${error.message}`, 'error');
+ }
+ }
+
+ // 开始 Gemini CLI OAuth 认证
+ async startGeminiCliAuth() {
+ try {
+ const projectId = document.getElementById('gemini-cli-project-id').value.trim();
+ let url = '/gemini-cli-auth-url';
+ if (projectId) {
+ url += `?project_id=${encodeURIComponent(projectId)}`;
+ }
+
+ const response = await this.makeRequest(url);
+ this.hideGeminiCliProjectForm();
+ this.handleOAuthFlow(response.url, 'Gemini CLI');
+ } catch (error) {
+ this.showNotification(`启动 Gemini CLI 认证失败: ${error.message}`, 'error');
+ }
+ }
+
+
+ // 处理 OAuth 流程
+ handleOAuthFlow(authUrl, providerName) {
+ // 从 URL 中提取 state 参数
+ const url = new URL(authUrl);
+ const state = url.searchParams.get('state');
+
+ // 显示 OAuth 状态模态框
+ this.showOAuthStatusModal(authUrl, providerName, state);
+ }
+
+ // 显示 OAuth 状态模态框
+ showOAuthStatusModal(authUrl, providerName, state) {
+ const modalBody = document.getElementById('modal-body');
+ modalBody.innerHTML = `
+
+
+
+
+
${i18n.t('auth_login.oauth_in_progress')}
+
${providerName} ${i18n.t('auth_login.oauth_open_browser')}
+
+
+ ${authUrl}
+
+
+
+
+
+
+
+
+ ${i18n.t('auth_login.oauth_waiting')}
+
+
+ `;
+
+ this.showModal();
+
+ // 如果有 state,开始轮询认证状态
+ if (state) {
+ this.pollOAuthStatus(state, providerName);
+ }
+ }
+
+ // 轮询 OAuth 认证状态
+ async pollOAuthStatus(state, providerName) {
+ const maxAttempts = 60; // 最多轮询 5 分钟(每 5 秒一次)
+ let attempts = 0;
+
+ const poll = async () => {
+ attempts++;
+
+ try {
+ const response = await this.makeRequest(`/get-auth-status?state=${encodeURIComponent(state)}`);
+
+ if (response.status === 'ok') {
+ // 认证成功
+ this.showOAuthSuccess(providerName);
+ this.loadAuthFiles(); // 刷新认证文件列表
+ return;
+ } else if (response.status === 'error') {
+ // 认证失败
+ this.showOAuthError(response.error || '认证失败');
+ return;
+ } else if (response.status === 'wait') {
+ // 继续等待
+ if (attempts < maxAttempts) {
+ setTimeout(poll, 5000); // 5 秒后重试
+ } else {
+ this.showOAuthError(i18n.t('auth_login.oauth_timeout'));
+ }
+ }
+ } catch (error) {
+ console.error('OAuth 状态轮询失败:', error);
+ if (attempts < maxAttempts) {
+ setTimeout(poll, 5000); // 5 秒后重试
+ } else {
+ this.showOAuthError(`${i18n.t('auth_login.oauth_failed')}: ${error.message}`);
+ }
+ }
+ };
+
+ // 开始轮询
+ setTimeout(poll, 2000); // 2 秒后开始第一次检查
+ }
+
+ // 显示 OAuth 认证成功
+ showOAuthSuccess(providerName) {
+ const modalBody = document.getElementById('modal-body');
+ modalBody.innerHTML = `
+
+
+
+
+
${i18n.t('auth_login.oauth_success')}
+
${providerName} 认证已完成!
+
+
+
+
+
+ `;
+ }
+
+ // 显示 OAuth 认证失败
+ showOAuthError(errorMessage) {
+ const modalBody = document.getElementById('modal-body');
+ modalBody.innerHTML = `
+
+
+
+
+
${i18n.t('auth_login.oauth_failed')}
+
${errorMessage}
+
+
+
+
+
+ `;
+ }
+
+ // 显示 Gemini Web Token 模态框
+ showGeminiWebTokenModal() {
+ const modalBody = document.getElementById('modal-body');
+ modalBody.innerHTML = `
+ ${i18n.t('auth_login.gemini_web_button')}
+
+ `;
+ this.showModal();
+ }
+
+ // 保存 Gemini Web Token
+ async saveGeminiWebToken() {
+ const secure1psid = document.getElementById('modal-secure-1psid').value.trim();
+ const secure1psidts = document.getElementById('modal-secure-1psidts').value.trim();
+
+ if (!secure1psid || !secure1psidts) {
+ this.showNotification('请填写完整的 Cookie 信息', 'error');
+ return;
+ }
+
+ try {
+ const response = await this.makeRequest('/gemini-web-token', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ secure_1psid: secure1psid,
+ secure_1psidts: secure1psidts
+ })
+ });
+
+ this.closeModal();
+ this.loadAuthFiles(); // 刷新认证文件列表
+ this.showNotification(`${i18n.t('auth_login.gemini_web_saved')}: ${response.file}`, 'success');
+ } catch (error) {
+ this.showNotification(`保存失败: ${error.message}`, 'error');
+ }
+ }
+
// 关闭模态框
closeModal() {
document.getElementById('modal').style.display = 'none';
diff --git a/i18n.js b/i18n.js
index 81746a1..b9ffa2d 100644
--- a/i18n.js
+++ b/i18n.js
@@ -182,9 +182,11 @@ const i18n = {
'ai_providers.openai_keys_count': '密钥数量',
'ai_providers.openai_models_count': '模型数量',
+
// 认证文件管理
'auth_files.title': '认证文件管理',
'auth_files.title_section': '认证文件',
+ 'auth_files.description': '这里管理 Qwen 和 Gemini 的认证配置文件。上传 JSON 格式的认证文件以启用相应的 AI 服务。',
'auth_files.upload_button': '上传文件',
'auth_files.delete_all_button': '删除全部',
'auth_files.empty_title': '暂无认证文件',
@@ -202,6 +204,16 @@ const i18n = {
'auth_files.delete_all_success': '成功删除',
'auth_files.files_count': '个文件',
+ // Gemini Web Token
+ 'auth_login.gemini_web_title': 'Gemini Web Token',
+ 'auth_login.gemini_web_button': '保存 Gemini Web Token',
+ 'auth_login.gemini_web_hint': '从浏览器开发者工具中获取 Gemini 网页版的 Cookie 值,用于直接认证访问 Gemini。',
+ 'auth_login.secure_1psid_label': '__Secure-1PSID Cookie:',
+ 'auth_login.secure_1psid_placeholder': '输入 __Secure-1PSID cookie 值',
+ 'auth_login.secure_1psidts_label': '__Secure-1PSIDTS Cookie:',
+ 'auth_login.secure_1psidts_placeholder': '输入 __Secure-1PSIDTS cookie 值',
+ 'auth_login.gemini_web_saved': 'Gemini Web Token 保存成功',
+
// 系统信息
'system_info.title': '系统信息',
'system_info.connection_status_title': '连接状态',
@@ -443,9 +455,11 @@ const i18n = {
'ai_providers.openai_keys_count': 'Keys Count',
'ai_providers.openai_models_count': 'Models Count',
+
// Auth files management
'auth_files.title': 'Auth Files Management',
'auth_files.title_section': 'Auth Files',
+ 'auth_files.description': 'Here you can manage authentication configuration files for Qwen and Gemini. Upload JSON format authentication files to enable the corresponding AI services.',
'auth_files.upload_button': 'Upload File',
'auth_files.delete_all_button': 'Delete All',
'auth_files.empty_title': 'No Auth Files',
@@ -463,6 +477,16 @@ const i18n = {
'auth_files.delete_all_success': 'Successfully deleted',
'auth_files.files_count': 'files',
+ // Gemini Web Token
+ 'auth_login.gemini_web_title': 'Gemini Web Token',
+ 'auth_login.gemini_web_button': 'Save Gemini Web Token',
+ 'auth_login.gemini_web_hint': 'Obtain the Cookie value of the Gemini web version from the browser\'s developer tools, used for direct authentication to access Gemini.',
+ 'auth_login.secure_1psid_label': '__Secure-1PSID Cookie:',
+ 'auth_login.secure_1psid_placeholder': 'Enter __Secure-1PSID cookie value',
+ 'auth_login.secure_1psidts_label': '__Secure-1PSIDTS Cookie:',
+ 'auth_login.secure_1psidts_placeholder': 'Enter __Secure-1PSIDTS cookie value',
+ 'auth_login.gemini_web_saved': 'Gemini Web Token saved successfully',
+
// System info
'system_info.title': 'System Information',
'system_info.connection_status_title': 'Connection Status',
diff --git a/index.html b/index.html
index d191c13..9521276 100644
--- a/index.html
+++ b/index.html
@@ -394,12 +394,45 @@
+
+
+
+
+
+
+
+ 从浏览器开发者工具中获取 Gemini 网页版的 Cookie 值,用于直接认证访问 Gemini。
+
+
+
+
+
+
+
+
+
+
+
认证文件管理
+
+
+
+ 这里管理 Qwen 和 Gemini 的认证配置文件。上传 JSON 格式的认证文件以启用相应的 AI 服务。
+
+
+
+
+