mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-02 19:00:49 +08:00
feat(antigravity): implement Antigravity OAuth integration with UI elements and functionality
This commit is contained in:
16
app.js
16
app.js
@@ -221,6 +221,7 @@ class CLIProxyManager {
|
||||
const cardText = card.textContent || '';
|
||||
if (cardText.includes('Codex OAuth') ||
|
||||
cardText.includes('Anthropic OAuth') ||
|
||||
cardText.includes('Antigravity OAuth') ||
|
||||
cardText.includes('Gemini CLI OAuth') ||
|
||||
cardText.includes('Qwen OAuth') ||
|
||||
cardText.includes('iFlow OAuth')) {
|
||||
@@ -430,6 +431,21 @@ class CLIProxyManager {
|
||||
anthropicCopyLink.addEventListener('click', () => this.copyAnthropicLink());
|
||||
}
|
||||
|
||||
// Antigravity OAuth
|
||||
const antigravityOauthBtn = document.getElementById('antigravity-oauth-btn');
|
||||
const antigravityOpenLink = document.getElementById('antigravity-open-link');
|
||||
const antigravityCopyLink = document.getElementById('antigravity-copy-link');
|
||||
|
||||
if (antigravityOauthBtn) {
|
||||
antigravityOauthBtn.addEventListener('click', () => this.startAntigravityOAuth());
|
||||
}
|
||||
if (antigravityOpenLink) {
|
||||
antigravityOpenLink.addEventListener('click', () => this.openAntigravityLink());
|
||||
}
|
||||
if (antigravityCopyLink) {
|
||||
antigravityCopyLink.addEventListener('click', () => this.copyAntigravityLink());
|
||||
}
|
||||
|
||||
// Gemini CLI OAuth
|
||||
const geminiCliOauthBtn = document.getElementById('gemini-cli-oauth-btn');
|
||||
const geminiCliOpenLink = document.getElementById('gemini-cli-open-link');
|
||||
|
||||
26
i18n.js
26
i18n.js
@@ -333,6 +333,19 @@ const i18n = {
|
||||
'auth_login.anthropic_oauth_start_error': '启动 Anthropic OAuth 失败:',
|
||||
'auth_login.anthropic_oauth_polling_error': '检查认证状态失败:',
|
||||
|
||||
// Antigravity OAuth
|
||||
'auth_login.antigravity_oauth_title': 'Antigravity OAuth',
|
||||
'auth_login.antigravity_oauth_button': '开始 Antigravity 登录',
|
||||
'auth_login.antigravity_oauth_hint': '通过 OAuth 流程登录 Antigravity(Google 账号)服务,自动获取并保存认证文件。',
|
||||
'auth_login.antigravity_oauth_url_label': '授权链接:',
|
||||
'auth_login.antigravity_open_link': '打开链接',
|
||||
'auth_login.antigravity_copy_link': '复制链接',
|
||||
'auth_login.antigravity_oauth_status_waiting': '等待认证中...',
|
||||
'auth_login.antigravity_oauth_status_success': '认证成功!',
|
||||
'auth_login.antigravity_oauth_status_error': '认证失败:',
|
||||
'auth_login.antigravity_oauth_start_error': '启动 Antigravity OAuth 失败:',
|
||||
'auth_login.antigravity_oauth_polling_error': '检查认证状态失败:',
|
||||
|
||||
// Gemini CLI OAuth
|
||||
'auth_login.gemini_cli_oauth_title': 'Gemini CLI OAuth',
|
||||
'auth_login.gemini_cli_oauth_button': '开始 Gemini CLI 登录',
|
||||
@@ -854,6 +867,19 @@ const i18n = {
|
||||
'auth_login.anthropic_oauth_start_error': 'Failed to start Anthropic OAuth:',
|
||||
'auth_login.anthropic_oauth_polling_error': 'Failed to check authentication status:',
|
||||
|
||||
// Antigravity OAuth
|
||||
'auth_login.antigravity_oauth_title': 'Antigravity OAuth',
|
||||
'auth_login.antigravity_oauth_button': 'Start Antigravity Login',
|
||||
'auth_login.antigravity_oauth_hint': 'Login to Antigravity service (Google account) through OAuth flow, automatically obtain and save authentication files.',
|
||||
'auth_login.antigravity_oauth_url_label': 'Authorization URL:',
|
||||
'auth_login.antigravity_open_link': 'Open Link',
|
||||
'auth_login.antigravity_copy_link': 'Copy Link',
|
||||
'auth_login.antigravity_oauth_status_waiting': 'Waiting for authentication...',
|
||||
'auth_login.antigravity_oauth_status_success': 'Authentication successful!',
|
||||
'auth_login.antigravity_oauth_status_error': 'Authentication failed:',
|
||||
'auth_login.antigravity_oauth_start_error': 'Failed to start Antigravity OAuth:',
|
||||
'auth_login.antigravity_oauth_polling_error': 'Failed to check authentication status:',
|
||||
|
||||
// Gemini CLI OAuth
|
||||
'auth_login.gemini_cli_oauth_title': 'Gemini CLI OAuth',
|
||||
'auth_login.gemini_cli_oauth_button': 'Start Gemini CLI Login',
|
||||
|
||||
36
index.html
36
index.html
@@ -628,6 +628,42 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Antigravity OAuth -->
|
||||
<div class="card" id="antigravity-oauth-card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-rocket"></i> <span
|
||||
data-i18n="auth_login.antigravity_oauth_title">Antigravity OAuth</span></h3>
|
||||
<button id="antigravity-oauth-btn" class="btn btn-primary">
|
||||
<i class="fas fa-sign-in-alt"></i> <span
|
||||
data-i18n="auth_login.antigravity_oauth_button">开始 Antigravity 登录</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<p class="form-hint" style="margin-bottom: 20px;"
|
||||
data-i18n="auth_login.antigravity_oauth_hint">
|
||||
通过 OAuth 流程登录 Antigravity(Google 账号)服务,自动获取并保存认证文件。
|
||||
</p>
|
||||
<div id="antigravity-oauth-content" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label data-i18n="auth_login.antigravity_oauth_url_label">授权链接:</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="antigravity-oauth-url" readonly>
|
||||
<button id="antigravity-open-link" class="btn btn-primary">
|
||||
<i class="fas fa-external-link-alt"></i> <span
|
||||
data-i18n="auth_login.antigravity_open_link">打开链接</span>
|
||||
</button>
|
||||
<button id="antigravity-copy-link" class="btn btn-secondary">
|
||||
<i class="fas fa-copy"></i> <span
|
||||
data-i18n="auth_login.antigravity_copy_link">复制链接</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="antigravity-oauth-status" class="form-hint" style="margin-top: 10px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gemini CLI OAuth -->
|
||||
<div class="card" id="gemini-cli-oauth-card">
|
||||
<div class="card-header">
|
||||
|
||||
@@ -300,6 +300,135 @@ export const oauthModule = {
|
||||
}
|
||||
},
|
||||
|
||||
// ===== Antigravity OAuth 相关方法 =====
|
||||
|
||||
// 开始 Antigravity OAuth 流程
|
||||
async startAntigravityOAuth() {
|
||||
try {
|
||||
const response = await this.makeRequest('/antigravity-auth-url?is_webui=1');
|
||||
const authUrl = response.url;
|
||||
const state = response.state || this.extractStateFromUrl(authUrl);
|
||||
|
||||
// 显示授权链接
|
||||
const urlInput = document.getElementById('antigravity-oauth-url');
|
||||
const content = document.getElementById('antigravity-oauth-content');
|
||||
const status = document.getElementById('antigravity-oauth-status');
|
||||
|
||||
if (urlInput) {
|
||||
urlInput.value = authUrl;
|
||||
}
|
||||
if (content) {
|
||||
content.style.display = 'block';
|
||||
}
|
||||
if (status) {
|
||||
status.textContent = i18n.t('auth_login.antigravity_oauth_status_waiting');
|
||||
status.style.color = 'var(--warning-text)';
|
||||
}
|
||||
|
||||
// 开始轮询认证状态
|
||||
this.startAntigravityOAuthPolling(state);
|
||||
|
||||
} catch (error) {
|
||||
this.showNotification(`${i18n.t('auth_login.antigravity_oauth_start_error')} ${error.message}`, 'error');
|
||||
}
|
||||
},
|
||||
|
||||
// 打开 Antigravity 授权链接
|
||||
openAntigravityLink() {
|
||||
const urlInput = document.getElementById('antigravity-oauth-url');
|
||||
if (urlInput && urlInput.value) {
|
||||
window.open(urlInput.value, '_blank');
|
||||
}
|
||||
},
|
||||
|
||||
// 复制 Antigravity 授权链接
|
||||
async copyAntigravityLink() {
|
||||
const urlInput = document.getElementById('antigravity-oauth-url');
|
||||
if (urlInput && urlInput.value) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(urlInput.value);
|
||||
this.showNotification(i18n.t('notification.link_copied'), 'success');
|
||||
} catch (error) {
|
||||
urlInput.select();
|
||||
document.execCommand('copy');
|
||||
this.showNotification(i18n.t('notification.link_copied'), 'success');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 开始轮询 Antigravity OAuth 状态
|
||||
startAntigravityOAuthPolling(state) {
|
||||
if (!state) {
|
||||
this.showNotification(i18n.t('auth_login.missing_state'), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
const pollInterval = setInterval(async () => {
|
||||
try {
|
||||
const response = await this.makeRequest(`/get-auth-status?state=${encodeURIComponent(state)}`);
|
||||
const status = response.status;
|
||||
const statusElement = document.getElementById('antigravity-oauth-status');
|
||||
|
||||
if (status === 'ok') {
|
||||
clearInterval(pollInterval);
|
||||
this.resetAntigravityOAuthUI();
|
||||
this.showNotification(i18n.t('auth_login.antigravity_oauth_status_success'), 'success');
|
||||
this.loadAuthFiles();
|
||||
} else if (status === 'error') {
|
||||
clearInterval(pollInterval);
|
||||
const errorMessage = response.error || 'Unknown error';
|
||||
if (statusElement) {
|
||||
statusElement.textContent = `${i18n.t('auth_login.antigravity_oauth_status_error')} ${errorMessage}`;
|
||||
statusElement.style.color = 'var(--error-text)';
|
||||
}
|
||||
this.showNotification(`${i18n.t('auth_login.antigravity_oauth_status_error')} ${errorMessage}`, 'error');
|
||||
setTimeout(() => {
|
||||
this.resetAntigravityOAuthUI();
|
||||
}, 3000);
|
||||
} else if (status === 'wait') {
|
||||
if (statusElement) {
|
||||
statusElement.textContent = i18n.t('auth_login.antigravity_oauth_status_waiting');
|
||||
statusElement.style.color = 'var(--warning-text)';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(pollInterval);
|
||||
const statusElement = document.getElementById('antigravity-oauth-status');
|
||||
if (statusElement) {
|
||||
statusElement.textContent = `${i18n.t('auth_login.antigravity_oauth_polling_error')} ${error.message}`;
|
||||
statusElement.style.color = 'var(--error-text)';
|
||||
}
|
||||
this.showNotification(`${i18n.t('auth_login.antigravity_oauth_polling_error')} ${error.message}`, 'error');
|
||||
setTimeout(() => {
|
||||
this.resetAntigravityOAuthUI();
|
||||
}, 3000);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
clearInterval(pollInterval);
|
||||
}, 5 * 60 * 1000);
|
||||
},
|
||||
|
||||
// 重置 Antigravity OAuth UI 到初始状态
|
||||
resetAntigravityOAuthUI() {
|
||||
const urlInput = document.getElementById('antigravity-oauth-url');
|
||||
const content = document.getElementById('antigravity-oauth-content');
|
||||
const status = document.getElementById('antigravity-oauth-status');
|
||||
|
||||
if (urlInput) {
|
||||
urlInput.value = '';
|
||||
}
|
||||
if (content) {
|
||||
content.style.display = 'none';
|
||||
}
|
||||
if (status) {
|
||||
status.textContent = '';
|
||||
status.style.color = '';
|
||||
status.className = '';
|
||||
}
|
||||
},
|
||||
|
||||
// ===== Gemini CLI OAuth 相关方法 =====
|
||||
|
||||
// 开始 Gemini CLI OAuth 流程
|
||||
|
||||
@@ -109,6 +109,7 @@ export const REQUEST_TIMEOUT_MS = 30 * 1000;
|
||||
export const OAUTH_CARD_IDS = [
|
||||
'codex-oauth-card',
|
||||
'anthropic-oauth-card',
|
||||
'antigravity-oauth-card',
|
||||
'gemini-cli-oauth-card',
|
||||
'qwen-oauth-card',
|
||||
'iflow-oauth-card'
|
||||
@@ -120,6 +121,7 @@ export const OAUTH_CARD_IDS = [
|
||||
export const OAUTH_PROVIDERS = {
|
||||
CODEX: 'codex',
|
||||
ANTHROPIC: 'anthropic',
|
||||
ANTIGRAVITY: 'antigravity',
|
||||
GEMINI_CLI: 'gemini-cli',
|
||||
QWEN: 'qwen',
|
||||
IFLOW: 'iflow'
|
||||
|
||||
Reference in New Issue
Block a user