mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-03 11:20:50 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a44257edda | ||
|
|
ebb80df24a |
@@ -18,7 +18,7 @@ import type {
|
|||||||
GeminiCliQuotaBucketState,
|
GeminiCliQuotaBucketState,
|
||||||
GeminiCliQuotaState
|
GeminiCliQuotaState
|
||||||
} from '@/types';
|
} from '@/types';
|
||||||
import { apiCallApi, getApiCallErrorMessage } from '@/services/api';
|
import { apiCallApi, authFilesApi, getApiCallErrorMessage } from '@/services/api';
|
||||||
import {
|
import {
|
||||||
ANTIGRAVITY_QUOTA_URLS,
|
ANTIGRAVITY_QUOTA_URLS,
|
||||||
ANTIGRAVITY_REQUEST_HEADERS,
|
ANTIGRAVITY_REQUEST_HEADERS,
|
||||||
@@ -55,6 +55,8 @@ type QuotaUpdater<T> = T | ((prev: T) => T);
|
|||||||
|
|
||||||
type QuotaType = 'antigravity' | 'codex' | 'gemini-cli';
|
type QuotaType = 'antigravity' | 'codex' | 'gemini-cli';
|
||||||
|
|
||||||
|
const DEFAULT_ANTIGRAVITY_PROJECT_ID = 'bamboo-precept-lgxtn';
|
||||||
|
|
||||||
export interface QuotaStore {
|
export interface QuotaStore {
|
||||||
antigravityQuota: Record<string, AntigravityQuotaState>;
|
antigravityQuota: Record<string, AntigravityQuotaState>;
|
||||||
codexQuota: Record<string, CodexQuotaState>;
|
codexQuota: Record<string, CodexQuotaState>;
|
||||||
@@ -82,6 +84,43 @@ export interface QuotaConfig<TState, TData> {
|
|||||||
renderQuotaItems: (quota: TState, t: TFunction, helpers: QuotaRenderHelpers) => ReactNode;
|
renderQuotaItems: (quota: TState, t: TFunction, helpers: QuotaRenderHelpers) => ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolveAntigravityProjectId = async (file: AuthFileItem): Promise<string> => {
|
||||||
|
try {
|
||||||
|
const text = await authFilesApi.downloadText(file.name);
|
||||||
|
const trimmed = text.trim();
|
||||||
|
if (!trimmed) return DEFAULT_ANTIGRAVITY_PROJECT_ID;
|
||||||
|
|
||||||
|
const parsed = JSON.parse(trimmed) as Record<string, unknown>;
|
||||||
|
const topLevel = normalizeStringValue(parsed.project_id ?? parsed.projectId);
|
||||||
|
if (topLevel) return topLevel;
|
||||||
|
|
||||||
|
const installed =
|
||||||
|
parsed.installed && typeof parsed.installed === 'object' && parsed.installed !== null
|
||||||
|
? (parsed.installed as Record<string, unknown>)
|
||||||
|
: null;
|
||||||
|
const installedProjectId = installed
|
||||||
|
? normalizeStringValue(installed.project_id ?? installed.projectId)
|
||||||
|
: null;
|
||||||
|
if (installedProjectId) return installedProjectId;
|
||||||
|
|
||||||
|
const web =
|
||||||
|
parsed.web && typeof parsed.web === 'object' && parsed.web !== null
|
||||||
|
? (parsed.web as Record<string, unknown>)
|
||||||
|
: null;
|
||||||
|
const webProjectId = web ? normalizeStringValue(web.project_id ?? web.projectId) : null;
|
||||||
|
if (webProjectId) return webProjectId;
|
||||||
|
} catch {
|
||||||
|
return DEFAULT_ANTIGRAVITY_PROJECT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_ANTIGRAVITY_PROJECT_ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isAntigravityUnknownFieldError = (message: string): boolean => {
|
||||||
|
const normalized = message.toLowerCase();
|
||||||
|
return normalized.includes('unknown name') && normalized.includes('cannot find field');
|
||||||
|
};
|
||||||
|
|
||||||
const fetchAntigravityQuota = async (
|
const fetchAntigravityQuota = async (
|
||||||
file: AuthFileItem,
|
file: AuthFileItem,
|
||||||
t: TFunction
|
t: TFunction
|
||||||
@@ -92,52 +131,64 @@ const fetchAntigravityQuota = async (
|
|||||||
throw new Error(t('antigravity_quota.missing_auth_index'));
|
throw new Error(t('antigravity_quota.missing_auth_index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const projectId = await resolveAntigravityProjectId(file);
|
||||||
|
const requestBodies = [JSON.stringify({ projectId }), JSON.stringify({ project: projectId })];
|
||||||
|
|
||||||
let lastError = '';
|
let lastError = '';
|
||||||
let lastStatus: number | undefined;
|
let lastStatus: number | undefined;
|
||||||
let priorityStatus: number | undefined;
|
let priorityStatus: number | undefined;
|
||||||
let hadSuccess = false;
|
let hadSuccess = false;
|
||||||
|
|
||||||
for (const url of ANTIGRAVITY_QUOTA_URLS) {
|
for (const url of ANTIGRAVITY_QUOTA_URLS) {
|
||||||
try {
|
for (let attempt = 0; attempt < requestBodies.length; attempt++) {
|
||||||
const result = await apiCallApi.request({
|
try {
|
||||||
authIndex,
|
const result = await apiCallApi.request({
|
||||||
method: 'POST',
|
authIndex,
|
||||||
url,
|
method: 'POST',
|
||||||
header: { ...ANTIGRAVITY_REQUEST_HEADERS },
|
url,
|
||||||
data: '{}'
|
header: { ...ANTIGRAVITY_REQUEST_HEADERS },
|
||||||
});
|
data: requestBodies[attempt]
|
||||||
|
});
|
||||||
|
|
||||||
if (result.statusCode < 200 || result.statusCode >= 300) {
|
if (result.statusCode < 200 || result.statusCode >= 300) {
|
||||||
lastError = getApiCallErrorMessage(result);
|
lastError = getApiCallErrorMessage(result);
|
||||||
lastStatus = result.statusCode;
|
lastStatus = result.statusCode;
|
||||||
if (result.statusCode === 403 || result.statusCode === 404) {
|
if (result.statusCode === 403 || result.statusCode === 404) {
|
||||||
priorityStatus ??= result.statusCode;
|
priorityStatus ??= result.statusCode;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
result.statusCode === 400 &&
|
||||||
|
isAntigravityUnknownFieldError(lastError) &&
|
||||||
|
attempt < requestBodies.length - 1
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hadSuccess = true;
|
hadSuccess = true;
|
||||||
const payload = parseAntigravityPayload(result.body ?? result.bodyText);
|
const payload = parseAntigravityPayload(result.body ?? result.bodyText);
|
||||||
const models = payload?.models;
|
const models = payload?.models;
|
||||||
if (!models || typeof models !== 'object' || Array.isArray(models)) {
|
if (!models || typeof models !== 'object' || Array.isArray(models)) {
|
||||||
lastError = t('antigravity_quota.empty_models');
|
lastError = t('antigravity_quota.empty_models');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = buildAntigravityQuotaGroups(models as AntigravityModelsPayload);
|
const groups = buildAntigravityQuotaGroups(models as AntigravityModelsPayload);
|
||||||
if (groups.length === 0) {
|
if (groups.length === 0) {
|
||||||
lastError = t('antigravity_quota.empty_models');
|
lastError = t('antigravity_quota.empty_models');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return groups;
|
return groups;
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
lastError = err instanceof Error ? err.message : t('common.unknown_error');
|
lastError = err instanceof Error ? err.message : t('common.unknown_error');
|
||||||
const status = getStatusFromError(err);
|
const status = getStatusFromError(err);
|
||||||
if (status) {
|
if (status) {
|
||||||
lastStatus = status;
|
lastStatus = status;
|
||||||
if (status === 403 || status === 404) {
|
if (status === 403 || status === 404) {
|
||||||
priorityStatus ??= status;
|
priorityStatus ??= status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,14 @@ export const authFilesApi = {
|
|||||||
|
|
||||||
deleteAll: () => apiClient.delete('/auth-files', { params: { all: true } }),
|
deleteAll: () => apiClient.delete('/auth-files', { params: { all: true } }),
|
||||||
|
|
||||||
|
downloadText: async (name: string): Promise<string> => {
|
||||||
|
const response = await apiClient.getRaw(`/auth-files/download?name=${encodeURIComponent(name)}`, {
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
const blob = response.data as Blob;
|
||||||
|
return blob.text();
|
||||||
|
},
|
||||||
|
|
||||||
// OAuth 排除模型
|
// OAuth 排除模型
|
||||||
async getOauthExcludedModels(): Promise<Record<string, string[]>> {
|
async getOauthExcludedModels(): Promise<Record<string, string[]>> {
|
||||||
const data = await apiClient.get('/oauth-excluded-models');
|
const data = await apiClient.get('/oauth-excluded-models');
|
||||||
|
|||||||
Reference in New Issue
Block a user