| |
| |
| |
|
|
| import { proxyAwareFetch } from "../../utils/proxyFetch.js"; |
| import { U } from "./shared.js"; |
|
|
| |
| const GLM_QUOTA_URLS = { |
| international: U("glm").url, |
| china: U("glm-cn").url, |
| }; |
|
|
| |
| |
| const VERCEL_AI_GATEWAY_CREDITS_URL = U("vercel-ai-gateway").url; |
|
|
| |
| |
| |
| export async function getQwenUsage(accessToken, providerSpecificData) { |
| try { |
| const resourceUrl = providerSpecificData?.resourceUrl; |
| if (!resourceUrl) { |
| return { message: "Qwen connected. No resource URL available." }; |
| } |
|
|
| |
| return { message: "Qwen connected. Usage tracked per request." }; |
| } catch (error) { |
| return { message: "Unable to fetch Qwen usage." }; |
| } |
| } |
|
|
| |
| |
| |
| export async function getIflowUsage(accessToken) { |
| try { |
| |
| return { message: "iFlow connected. Usage tracked per request." }; |
| } catch (error) { |
| return { message: "Unable to fetch iFlow usage." }; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function getOllamaUsage(accessToken, providerSpecificData) { |
| try { |
| |
| |
| |
| const plan = providerSpecificData?.plan || "Free"; |
| return { |
| plan, |
| message: "Ollama Cloud uses a free tier with light usage limits (resets every 5h & 7d). For detailed usage tracking, visit ollama.com/settings/keys.", |
| quotas: [], |
| }; |
| } catch (error) { |
| return { message: "Unable to fetch Ollama Cloud usage." }; |
| } |
| } |
|
|
| |
| |
| |
| export async function getGlmUsage(apiKey, provider, proxyOptions = null) { |
| if (!apiKey) { |
| return { message: "GLM API key not available." }; |
| } |
|
|
| const region = provider === "glm-cn" ? "china" : "international"; |
| const quotaUrl = GLM_QUOTA_URLS[region]; |
|
|
| try { |
| const response = await proxyAwareFetch(quotaUrl, { |
| headers: { |
| Authorization: `Bearer ${apiKey}`, |
| Accept: "application/json", |
| }, |
| }, proxyOptions); |
|
|
| if (!response.ok) { |
| if (response.status === 401) { |
| return { message: "GLM API key invalid or expired." }; |
| } |
| return { message: `GLM quota API error (${response.status}).` }; |
| } |
|
|
| const json = await response.json(); |
| const data = json?.data && typeof json.data === "object" ? json.data : {}; |
| const limits = Array.isArray(data.limits) ? data.limits : []; |
| const quotas = {}; |
|
|
| for (const limit of limits) { |
| if (!limit || limit.type !== "TOKENS_LIMIT") continue; |
| const usedPercent = Number(limit.percentage) || 0; |
| const resetMs = Number(limit.nextResetTime) || 0; |
| const remaining = Math.max(0, 100 - usedPercent); |
|
|
| quotas["session"] = { |
| used: usedPercent, |
| total: 100, |
| remaining, |
| remainingPercentage: remaining, |
| resetAt: resetMs > 0 ? new Date(resetMs).toISOString() : null, |
| unlimited: false, |
| }; |
| } |
|
|
| const levelRaw = typeof data.level === "string" ? data.level : ""; |
| const plan = levelRaw |
| ? levelRaw.charAt(0).toUpperCase() + levelRaw.slice(1).toLowerCase() |
| : "Unknown"; |
|
|
| return { plan, quotas }; |
| } catch (error) { |
| return { message: `GLM error: ${error.message}` }; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export async function getVercelAiGatewayUsage(apiKey, proxyOptions = null) { |
| if (!apiKey) { |
| return { message: "Vercel AI Gateway API key not available." }; |
| } |
|
|
| try { |
| const response = await proxyAwareFetch(VERCEL_AI_GATEWAY_CREDITS_URL, { |
| method: "GET", |
| headers: { |
| Authorization: `Bearer ${apiKey}`, |
| Accept: "application/json", |
| }, |
| }, proxyOptions); |
|
|
| if (response.status === 401 || response.status === 403) { |
| return { message: "Vercel AI Gateway API key invalid or expired." }; |
| } |
|
|
| if (!response.ok) { |
| const errorText = await response.text().catch(() => ""); |
| const trimmed = errorText ? `: ${errorText.slice(0, 200)}` : ""; |
| return { message: `Vercel AI Gateway credits API error (${response.status})${trimmed}` }; |
| } |
|
|
| const data = await response.json(); |
|
|
| |
| const balance = Number(data?.balance) || 0; |
| const totalUsed = Number(data?.total_used) || 0; |
|
|
| |
| |
| const MONTHLY_CREDIT = 5; |
| const remainingPercentage = (balance / MONTHLY_CREDIT) * 100; |
|
|
| if (balance <= 0 && totalUsed <= 0) { |
| return { |
| plan: "Pay-as-you-go", |
| message: "Vercel AI Gateway connected. No credit allocation found (BYOK or unfunded account).", |
| quotas: {}, |
| }; |
| } |
|
|
| |
| |
| return { |
| plan: "Pay-as-you-go", |
| quotas: { |
| "Used (USD)": { |
| used: totalUsed, |
| total: 0, |
| remaining: 0, |
| remainingPercentage: 100, |
| unlimited: true, |
| }, |
| "Remaining (USD)": { |
| used: balance, |
| total: MONTHLY_CREDIT, |
| remaining: balance, |
| remainingPercentage, |
| unlimited: false, |
| }, |
| }, |
| }; |
| } catch (error) { |
| return { message: `Vercel AI Gateway error: ${error.message}` }; |
| } |
| } |
|
|
| export async function getQoderUsage(accessToken, proxyOptions = null) { |
| if (!accessToken) { |
| return { message: "Qoder usage unavailable: no access token" }; |
| } |
| try { |
| const response = await proxyAwareFetch( |
| U("qoder").url, |
| { |
| method: "GET", |
| headers: { |
| Authorization: `Bearer ${accessToken}`, |
| Accept: "application/json", |
| }, |
| }, |
| proxyOptions, |
| ); |
| if (!response.ok) { |
| return { message: `Qoder connected. Usage fetch returned ${response.status}.` }; |
| } |
| const body = await response.json().catch(() => null); |
| if (!body) { |
| return { message: "Qoder connected. Usage response was not JSON." }; |
| } |
| |
| |
| |
| const userQuota = body.userQuota || {}; |
| const orgQuota = body.orgResourcePackage || {}; |
| |
| |
| |
| const expiresAtMs = Number.isFinite(Number(body.expiresAt)) && Number(body.expiresAt) > 0 |
| ? Number(body.expiresAt) |
| : null; |
| const resetAt = expiresAtMs ? new Date(expiresAtMs).toISOString() : null; |
| const quotas = { |
| user: { |
| total: Number(userQuota.total) || 0, |
| used: Number(userQuota.used) || 0, |
| remaining: Number(userQuota.remaining) || 0, |
| unit: userQuota.unit || "credits", |
| resetAt, |
| }, |
| organization: { |
| total: Number(orgQuota.total) || 0, |
| used: Number(orgQuota.used) || 0, |
| remaining: Number(orgQuota.remaining) || 0, |
| unit: orgQuota.unit || "credits", |
| resetAt, |
| }, |
| }; |
| return { |
| quotas, |
| totalUsagePercentage: Number(body.totalUsagePercentage) || 0, |
| isQuotaExceeded: !!body.isQuotaExceeded, |
| expiresAt: expiresAtMs, |
| }; |
| } catch (error) { |
| return { message: `Qoder connected. Unable to fetch usage: ${error.message}` }; |
| } |
| } |
|
|