fix(usage): improve DeepSeek credit balance display
Display DeepSeek prepaid balances as credit with currency instead of a 0/total quota bar, and mark balance items as isCreditBalance.
This commit is contained in:
@@ -13,7 +13,7 @@ export default {
|
|||||||
textIcon: "OC",
|
textIcon: "OC",
|
||||||
website: "https://opencode.ai/auth",
|
website: "https://opencode.ai/auth",
|
||||||
notice: {
|
notice: {
|
||||||
text: "OpenCode Go subscription: $5/mo (then 0/mo). Access to Kimi, GLM, Qwen, MiMo, MiniMax models.",
|
text: "OpenCode Go subscription: $5/mo (then 10/mo). Access to Kimi, GLM, Qwen, MiMo, MiniMax models.",
|
||||||
apiKeyUrl: "https://opencode.ai/auth",
|
apiKeyUrl: "https://opencode.ai/auth",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -91,14 +91,15 @@ export async function getDeepseekUsage(apiKey = null, proxyOptions = null) {
|
|||||||
const quotas = {};
|
const quotas = {};
|
||||||
for (const b of balances) {
|
for (const b of balances) {
|
||||||
const total = Math.max(0, b.totalBalance);
|
const total = Math.max(0, b.totalBalance);
|
||||||
// Credit pot: show full remaining against current balance; never set absolute
|
// Credit balance: show as "Credit: $X.XX USD" not a usage quota
|
||||||
// `remaining` — QuotaTable treats it as a 0–100 percentage.
|
|
||||||
quotas[`Balance (${b.currency})`] = {
|
quotas[`Balance (${b.currency})`] = {
|
||||||
used: 0,
|
used: 0,
|
||||||
total,
|
total,
|
||||||
remainingPercentage: total > 0 ? 100 : 0,
|
remainingPercentage: total > 0 ? 100 : 0,
|
||||||
resetAt: null,
|
resetAt: null,
|
||||||
unlimited: total > 0,
|
unlimited: false,
|
||||||
|
isCreditBalance: true,
|
||||||
|
currency: b.currency,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,10 @@ export default function QuotaTable({
|
|||||||
<div className="space-y-px">
|
<div className="space-y-px">
|
||||||
{currentPageRows.map((quota) => {
|
{currentPageRows.map((quota) => {
|
||||||
const isUnlimited = quota.unlimited === true;
|
const isUnlimited = quota.unlimited === true;
|
||||||
const colors = getColorClasses(quota.remaining);
|
const isCreditBalance = quota.isCreditBalance === true;
|
||||||
|
const colors = isCreditBalance
|
||||||
|
? { text: "text-blue-600 dark:text-blue-400", bg: "bg-blue-500", bgLight: "bg-blue-500/10", emoji: "💰" }
|
||||||
|
: getColorClasses(quota.remaining);
|
||||||
const countdown = formatResetTime(quota.resetAt);
|
const countdown = formatResetTime(quota.resetAt);
|
||||||
const resetDisplay = formatResetTimeDisplay(quota.resetAt);
|
const resetDisplay = formatResetTimeDisplay(quota.resetAt);
|
||||||
// recurring defaults true: a missing flag means the quota
|
// recurring defaults true: a missing flag means the quota
|
||||||
@@ -175,7 +178,7 @@ export default function QuotaTable({
|
|||||||
|
|
||||||
{/* Progress + used/total */}
|
{/* Progress + used/total */}
|
||||||
<div className={`min-w-0 flex-1 ${compact ? "space-y-1" : "space-y-1.5"}`}>
|
<div className={`min-w-0 flex-1 ${compact ? "space-y-1" : "space-y-1.5"}`}>
|
||||||
{!isUnlimited && (
|
{!isUnlimited && !isCreditBalance && (
|
||||||
<div className={`${compact ? "h-1" : "h-1.5"} rounded-full overflow-hidden border ${colors.bgLight} ${
|
<div className={`${compact ? "h-1" : "h-1.5"} rounded-full overflow-hidden border ${colors.bgLight} ${
|
||||||
quota.remaining === 0 ? "border-black/10 dark:border-white/10" : "border-transparent"
|
quota.remaining === 0 ? "border-black/10 dark:border-white/10" : "border-transparent"
|
||||||
}`}>
|
}`}>
|
||||||
@@ -192,15 +195,19 @@ export default function QuotaTable({
|
|||||||
title={
|
title={
|
||||||
isUnlimited
|
isUnlimited
|
||||||
? `${quota.used.toLocaleString()} used · Unlimited`
|
? `${quota.used.toLocaleString()} used · Unlimited`
|
||||||
|
: isCreditBalance
|
||||||
|
? `Credit balance: ${quota.total.toFixed(2)} ${quota.currency || ""}`
|
||||||
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`
|
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{isUnlimited
|
{isUnlimited
|
||||||
? `${quota.used.toLocaleString()} used · Unlimited`
|
? `${quota.used.toLocaleString()} used · Unlimited`
|
||||||
|
: isCreditBalance
|
||||||
|
? `Credit: ${quota.total.toFixed(2)} ${quota.currency || ""}`
|
||||||
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`}
|
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`}
|
||||||
</span>
|
</span>
|
||||||
<span className={`font-medium ${isUnlimited ? "text-green-600 dark:text-green-400" : colors.text} shrink-0`}>
|
<span className={`font-medium ${isUnlimited ? "text-green-600 dark:text-green-400" : isCreditBalance ? "text-blue-600 dark:text-blue-400" : colors.text} shrink-0`}>
|
||||||
{isUnlimited ? "Unlimited" : `${quota.remaining}%`}
|
{isUnlimited ? "Unlimited" : isCreditBalance ? "" : `${quota.remaining}%`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -609,6 +609,8 @@ export function parseQuotaData(provider, data) {
|
|||||||
total: quota.total || 0,
|
total: quota.total || 0,
|
||||||
resetAt: quota.resetAt || null,
|
resetAt: quota.resetAt || null,
|
||||||
remainingPercentage: quota.remainingPercentage,
|
remainingPercentage: quota.remainingPercentage,
|
||||||
|
isCreditBalance: quota.isCreditBalance ?? true,
|
||||||
|
currency: quota.currency || (name.includes("(") ? name.slice(name.indexOf("(") + 1, name.indexOf(")")) : "USD"),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ describe("getUsageForProvider(deepseek)", () => {
|
|||||||
used: 0,
|
used: 0,
|
||||||
total: 12.5,
|
total: 12.5,
|
||||||
remainingPercentage: 100,
|
remainingPercentage: 100,
|
||||||
|
isCreditBalance: true,
|
||||||
|
currency: "USD",
|
||||||
});
|
});
|
||||||
expect(usage.quotas["Balance (USD)"].remaining).toBeUndefined();
|
expect(usage.quotas["Balance (USD)"].remaining).toBeUndefined();
|
||||||
// Zero CNY still listed so user sees currency row
|
// Zero CNY still listed so user sees currency row
|
||||||
|
|||||||
Reference in New Issue
Block a user