feat: add Grok official subscription quota query

Add SuperGrok subscription usage display, following the existing
Claude Code / Codex official-subscription pattern (protocol ported
from steipete/CodexBar):

- New subscription_grok service: reads Grok CLI credentials from
  ~/.grok/auth.json, calls the grok.com GrokBuildBilling gRPC-web
  endpoint, and parses the response via heuristic protobuf scanning
  (used percent, reset time, zero-usage special case)
- Transient failures (network errors, HTTP 408, gRPC deadline/
  cancelled) propagate as Err so the frontend retries and keeps the
  last good value; auth failures map to Expired with a re-login hint
- Tier naming by reset distance: weekly limit, monthly, or a new
  "credits" tier (i18n added for zh/en/ja/zh-TW; tray shows "c")
- New get_xai_oauth_quota command: xai_oauth providers (managed
  SuperGrok OAuth accounts) query the same billing endpoint with
  their bound account token; ProviderCard auto-renders the quota
  footer for them and hides the usage-script entry, and the tray /
  usage-script path routes xai_oauth providers to the managed
  account instead of the host app's CLI credentials
- UsageScriptModal: drop the config-content heuristic for official
  detection; category === "official" is the single source of truth

Claude-Session: https://claude.ai/code/session_01LSNvhEfuoJHaQLZcYQgBU5
This commit is contained in:
Jason
2026-07-23 11:13:07 +08:00
parent a377d79303
commit 15d5dbe065
17 changed files with 1162 additions and 10 deletions
+2
View File
@@ -6,6 +6,8 @@ export const subscriptionApi = {
invoke("get_subscription_quota", { tool }),
getCodexOauthQuota: (accountId: string | null): Promise<SubscriptionQuota> =>
invoke("get_codex_oauth_quota", { accountId }),
getXaiOauthQuota: (accountId: string | null): Promise<SubscriptionQuota> =>
invoke("get_xai_oauth_quota", { accountId }),
getCodingPlanQuota: (
baseUrl: string,
apiKey: string,
+29 -1
View File
@@ -90,7 +90,8 @@ export function useSubscriptionQuota(
const query = useQuery({
queryKey: subscriptionKeys.quota(appId),
queryFn: () => subscriptionApi.getQuota(appId),
enabled: enabled && ["claude", "codex", "gemini"].includes(appId),
enabled:
enabled && ["claude", "codex", "gemini", "grokbuild"].includes(appId),
refetchInterval,
refetchIntervalInBackground: Boolean(refetchInterval),
refetchOnWindowFocus: Boolean(refetchInterval),
@@ -138,3 +139,30 @@ export function useCodexOauthQuota(
return useQuotaKeepLastGood(query, accountId ?? "default");
}
/**
* xAI OAuth (SuperGrok 反代) 订阅额度查询 hook
*
* 与 `useCodexOauthQuota` 平行:数据走 cc-switch 自管的 xAI OAuth token
* 而不是 Grok CLI 的 ~/.grok/auth.json;后端复用同一个 grok.com 账单端点,
* 因此与 Grok Build 分区的官方订阅显示同一份额度。
*/
export function useXaiOauthQuota(
meta: ProviderMeta | undefined,
options: UseCodexOauthQuotaOptions = {},
) {
const { enabled = true, autoQuery = false } = options;
const accountId = resolveManagedAccountId(meta, PROVIDER_TYPES.XAI_OAUTH);
const query = useQuery({
queryKey: ["xai_oauth", "quota", accountId ?? "default"],
queryFn: () => subscriptionApi.getXaiOauthQuota(accountId),
enabled,
refetchInterval: autoQuery ? REFETCH_INTERVAL : false,
refetchIntervalInBackground: autoQuery,
refetchOnWindowFocus: autoQuery,
staleTime: REFETCH_INTERVAL,
retry: 1,
});
return useQuotaKeepLastGood(query, accountId ?? "default");
}