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:
Ali Shaikh
2026-09-17 20:06:19 +07:00
parent ef18175226
commit 3ac100d524
5 changed files with 20 additions and 8 deletions

View File

@@ -13,7 +13,7 @@ export default {
textIcon: "OC",
website: "https://opencode.ai/auth",
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",
},
},

View File

@@ -91,14 +91,15 @@ export async function getDeepseekUsage(apiKey = null, proxyOptions = null) {
const quotas = {};
for (const b of balances) {
const total = Math.max(0, b.totalBalance);
// Credit pot: show full remaining against current balance; never set absolute
// `remaining` — QuotaTable treats it as a 0100 percentage.
// Credit balance: show as "Credit: $X.XX USD" not a usage quota
quotas[`Balance (${b.currency})`] = {
used: 0,
total,
remainingPercentage: total > 0 ? 100 : 0,
resetAt: null,
unlimited: total > 0,
unlimited: false,
isCreditBalance: true,
currency: b.currency,
};
}

View File

@@ -151,7 +151,10 @@ export default function QuotaTable({
<div className="space-y-px">
{currentPageRows.map((quota) => {
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 resetDisplay = formatResetTimeDisplay(quota.resetAt);
// recurring defaults true: a missing flag means the quota
@@ -175,7 +178,7 @@ export default function QuotaTable({
{/* Progress + used/total */}
<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} ${
quota.remaining === 0 ? "border-black/10 dark:border-white/10" : "border-transparent"
}`}>
@@ -192,15 +195,19 @@ export default function QuotaTable({
title={
isUnlimited
? `${quota.used.toLocaleString()} used · Unlimited`
: isCreditBalance
? `Credit balance: ${quota.total.toFixed(2)} ${quota.currency || ""}`
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`
}
>
{isUnlimited
? `${quota.used.toLocaleString()} used · Unlimited`
: isCreditBalance
? `Credit: ${quota.total.toFixed(2)} ${quota.currency || ""}`
: `${quota.used.toLocaleString()} / ${quota.total > 0 ? quota.total.toLocaleString() : "∞"}`}
</span>
<span className={`font-medium ${isUnlimited ? "text-green-600 dark:text-green-400" : colors.text} shrink-0`}>
{isUnlimited ? "Unlimited" : `${quota.remaining}%`}
<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" : isCreditBalance ? "" : `${quota.remaining}%`}
</span>
</div>
</div>

View File

@@ -609,6 +609,8 @@ export function parseQuotaData(provider, data) {
total: quota.total || 0,
resetAt: quota.resetAt || null,
remainingPercentage: quota.remainingPercentage,
isCreditBalance: quota.isCreditBalance ?? true,
currency: quota.currency || (name.includes("(") ? name.slice(name.indexOf("(") + 1, name.indexOf(")")) : "USD"),
});
});
}

View File

@@ -80,6 +80,8 @@ describe("getUsageForProvider(deepseek)", () => {
used: 0,
total: 12.5,
remainingPercentage: 100,
isCreditBalance: true,
currency: "USD",
});
expect(usage.quotas["Balance (USD)"].remaining).toBeUndefined();
// Zero CNY still listed so user sees currency row