mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
refactor(app): DRY pass — split large files, extract shared utils
S1: delete page.new.js (1724L abandoned) + remove dead getAntigravityProjectId
S2: split large files by natural seams
- usage.js → usage/{github,google,claude,codex,kiro,minimax,misc,shared}.js
- media-providers page → components/{Embedding,Tts,Generic,Stt}ExampleCard.js
- EndpointPageClient → endpointConstants.js + endpointPing.js + components/
- tokenRefresh.js → tokenRefresh/{dedup,providers}.js
- ProviderLimits/index.js: 16 pure fn + 9 constants → utils.js
- oauth/providers.js: 7 pure helpers → providerHelpers.js
S3: shared utils
- getModelKind(m, fallback) → shared/constants/models.js (replaces 20× m.kind||m.type)
- getStatusVariant → shared/utils/connectionStatus.js (dedup ConnectionRow/ConnectionsCard)
- sseChunk → open-sse/utils/sse.js (dedup grok-web/perplexity-web)
- fetchWithTimeout → usage/shared.js (replace 4× AbortController pattern in google.js)
fix: enableObservability2 field name in requestDetailsRepo
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Codex (OpenAI) usage handler
|
||||
*/
|
||||
|
||||
import { proxyAwareFetch } from "../../utils/proxyFetch.js";
|
||||
import { U, parseResetTime, toFiniteNumber } from "./shared.js";
|
||||
|
||||
// Codex (OpenAI) API config
|
||||
const CODEX_CONFIG = {
|
||||
usageUrl: U("codex").url,
|
||||
};
|
||||
|
||||
function getCodexRateLimitBody(snapshot) {
|
||||
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) return null;
|
||||
return snapshot.rate_limit && typeof snapshot.rate_limit === "object"
|
||||
? snapshot.rate_limit
|
||||
: snapshot;
|
||||
}
|
||||
|
||||
function formatCodexWindow(window) {
|
||||
const used = Math.max(0, Math.min(100, toFiniteNumber(window?.used_percent ?? window?.percent_used, 0)));
|
||||
return {
|
||||
used,
|
||||
total: 100,
|
||||
remaining: Math.max(0, 100 - used),
|
||||
resetAt: parseResetTime(window?.reset_at ?? window?.resets_at ?? window?.resetAt ?? null),
|
||||
unlimited: false,
|
||||
};
|
||||
}
|
||||
|
||||
function appendCodexQuotaWindows(quotas, prefix, snapshot) {
|
||||
const rateLimit = getCodexRateLimitBody(snapshot);
|
||||
if (!rateLimit) return false;
|
||||
|
||||
const primary = rateLimit.primary_window || rateLimit.primary || snapshot.primary_window || snapshot.primary;
|
||||
const secondary = rateLimit.secondary_window || rateLimit.secondary || snapshot.secondary_window || snapshot.secondary;
|
||||
let added = false;
|
||||
|
||||
if (primary) {
|
||||
quotas[prefix ? `${prefix}_session` : "session"] = formatCodexWindow(primary);
|
||||
added = true;
|
||||
}
|
||||
if (secondary) {
|
||||
quotas[prefix ? `${prefix}_weekly` : "weekly"] = formatCodexWindow(secondary);
|
||||
added = true;
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
function getCodexReviewRateLimit(data) {
|
||||
if (data.code_review_rate_limit || data.review_rate_limit) {
|
||||
return data.code_review_rate_limit || data.review_rate_limit;
|
||||
}
|
||||
|
||||
const byLimitId = data.rate_limits_by_limit_id;
|
||||
if (byLimitId && typeof byLimitId === "object" && !Array.isArray(byLimitId)) {
|
||||
return byLimitId.code_review || byLimitId.codex_review || byLimitId.review || null;
|
||||
}
|
||||
|
||||
const additional = Array.isArray(data.additional_rate_limits) ? data.additional_rate_limits : [];
|
||||
return additional.find((entry) => {
|
||||
const id = String(entry?.limit_name || entry?.metered_feature || entry?.id || "").toLowerCase();
|
||||
return id === "code_review" || id === "codex_review" || id === "review" || id.includes("review");
|
||||
}) || null;
|
||||
}
|
||||
|
||||
export async function getCodexUsage(accessToken, proxyOptions = null) {
|
||||
try {
|
||||
const response = await proxyAwareFetch(CODEX_CONFIG.usageUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": `Bearer ${accessToken}`,
|
||||
"Accept": "application/json",
|
||||
},
|
||||
}, proxyOptions);
|
||||
|
||||
if (!response.ok) {
|
||||
return { message: `Codex connected. Usage API temporarily unavailable (${response.status}).` };
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const normalRateLimit = data.rate_limit || data.rate_limits || data.rate_limits_by_limit_id?.codex || {};
|
||||
const reviewRateLimit = getCodexReviewRateLimit(data);
|
||||
const quotas = {};
|
||||
|
||||
appendCodexQuotaWindows(quotas, "", normalRateLimit);
|
||||
appendCodexQuotaWindows(quotas, "review", reviewRateLimit);
|
||||
|
||||
return {
|
||||
plan: data.plan_type || data.summary?.plan || "unknown",
|
||||
limitReached: getCodexRateLimitBody(normalRateLimit)?.limit_reached || false,
|
||||
reviewLimitReached: getCodexRateLimitBody(reviewRateLimit)?.limit_reached || false,
|
||||
quotas,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch Codex usage: ${error.message}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user