mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
d164191bd1
Codex OAuth (ChatGPT Plus/Pro) providers previously fell through to the
default UsageFooter branch and showed no quota at all, while Copilot and
official Codex providers already had a wham/usage-backed quota footer.
This wires up the same five-hour / seven-day tier badges for codex_oauth
provider cards by reusing the existing query_codex_quota function and
SubscriptionQuotaFooter rendering, parameterized to keep both the CLI
credential path ("codex") and the cc-switch managed OAuth path
("codex_oauth") working from a single source of truth.
- Parameterize services::subscription::query_codex_quota with tool_label
and expired_message; promote SubscriptionQuota constructors to
pub(crate). The CLI path keeps its existing "codex" label and the
"re-login with Codex CLI" message; the new path passes "codex_oauth"
and a cc-switch-specific re-login hint.
- Add a new get_codex_oauth_quota Tauri command in commands/codex_oauth.rs
that resolves the ChatGPT account (explicit binding > default account
> not_found), pulls a valid access_token from CodexOAuthManager
(auto-refresh handled), and delegates to query_codex_quota.
- Extract SubscriptionQuotaFooter's render body into a pure
SubscriptionQuotaView component (props: quota / loading / refetch /
appIdForExpiredHint / inline). The existing SubscriptionQuotaFooter
becomes a thin wrapper with identical props and behavior, so
CopilotQuotaFooter and the official Claude/Codex/Gemini paths are
untouched. This avoids duplicating ~280 lines of five-state rendering.
- Add CodexOauthQuotaFooter, a 38-line wrapper that calls the new
useCodexOauthQuota hook and forwards to SubscriptionQuotaView.
- ProviderCard inserts an isCodexOauth branch between isCopilot and
isOfficial, keyed off PROVIDER_TYPES.CODEX_OAUTH (newly added to
config/constants.ts to centralize the previously scattered string).
- Frontend hook caches per (codex_oauth, accountId) so multiple cards
bound to the same ChatGPT account share one fetch via react-query
dedup; cards bound to different accounts get independent fetches.
- No new i18n keys: existing subscription.fiveHour / sevenDay / expired /
refresh / queryFailed / expiredHint are reused.
59 lines
2.1 KiB
Rust
59 lines
2.1 KiB
Rust
//! Codex OAuth Tauri Commands
|
|
//!
|
|
//! 提供 OpenAI ChatGPT Plus/Pro OAuth 认证相关的 Tauri 命令。
|
|
//!
|
|
//! 大部分认证命令通过通用 `auth_*` 命令(参见 `commands::auth`)暴露给前端,
|
|
//! 此处定义 State wrapper 以及 Codex OAuth 专属的订阅额度查询命令。
|
|
|
|
use crate::proxy::providers::codex_oauth_auth::CodexOAuthManager;
|
|
use crate::services::subscription::{query_codex_quota, CredentialStatus, SubscriptionQuota};
|
|
use std::sync::Arc;
|
|
use tauri::State;
|
|
use tokio::sync::RwLock;
|
|
|
|
/// Codex OAuth 认证状态
|
|
pub struct CodexOAuthState(pub Arc<RwLock<CodexOAuthManager>>);
|
|
|
|
/// 查询 Codex OAuth (ChatGPT Plus/Pro) 订阅额度
|
|
///
|
|
/// - `account_id` 未指定时回退到 `CodexOAuthManager` 的默认账号
|
|
/// - 没有任何账号时返回 `not_found`,前端 `SubscriptionQuotaView` 会静默不渲染
|
|
/// - 复用 `services::subscription::query_codex_quota`,因此 wham/usage 端点协议
|
|
/// 与 Codex CLI 路径完全一致
|
|
#[tauri::command(rename_all = "camelCase")]
|
|
pub async fn get_codex_oauth_quota(
|
|
account_id: Option<String>,
|
|
state: State<'_, CodexOAuthState>,
|
|
) -> Result<SubscriptionQuota, String> {
|
|
let manager = state.0.read().await;
|
|
|
|
// 解析最终使用的账号 ID:显式 > 默认账号 > 无账号 (not_found)
|
|
let resolved = match account_id {
|
|
Some(id) => Some(id),
|
|
None => manager.default_account_id().await,
|
|
};
|
|
let Some(id) = resolved else {
|
|
return Ok(SubscriptionQuota::not_found("codex_oauth"));
|
|
};
|
|
|
|
// 获取(必要时自动刷新)access_token
|
|
let token = match manager.get_valid_token_for_account(&id).await {
|
|
Ok(t) => t,
|
|
Err(e) => {
|
|
return Ok(SubscriptionQuota::error(
|
|
"codex_oauth",
|
|
CredentialStatus::Expired,
|
|
format!("Codex OAuth token unavailable: {e}"),
|
|
));
|
|
}
|
|
};
|
|
|
|
Ok(query_codex_quota(
|
|
&token,
|
|
Some(&id),
|
|
"codex_oauth",
|
|
"Codex OAuth access token expired or rejected. Please re-login via cc-switch.",
|
|
)
|
|
.await)
|
|
}
|