fix(desktop): wallet balance follows actual recharge currency - #7790
fix(desktop): wallet balance follows actual recharge currency#7790clearnature wants to merge 3 commits into
Conversation
Problem: balance display followed the UI language guess (zh→CNY, en→USD), which is wrong for overseas Chinese users who recharge USD but use a zh UI. Also, picking CNY/USD in Settings did not refresh the status-bar balance. Fix: - Balance.PrimaryCurrency(): return the largest reported balance's currency (DeepSeek returns one Info per currency; the largest is what the user actually recharged). - BalanceForTab: when desktop currency is auto, display follows PrimaryCurrency instead of the language guess. Explicit currency still wins. - applyDeepSeekOfficialDefaultPricingWithOverride: match provider-wide 'price' against p.ModelList() so deepseek-responses (models list + price fallback, empty p.Model) also gets converted to the selected CNY/USD table. - useController: refresh the wallet readout on model-catalog-changed, which SettingsPanel dispatches after applying currency/model changes. Tests: TestPrimaryCurrencyFollowsLargestBalance, TestApplyDeepSeekOfficialPricingOverridesProviderWidePrice.
There was a problem hiding this comment.
Pull request overview
This PR fixes desktop wallet balance and pricing-currency behavior so the displayed wallet currency follows the user’s actual recharge currency (when desktop currency is set to auto), and so changing CNY/USD in Settings refreshes the status-bar wallet readout and correctly converts DeepSeek official default pricing even when a provider uses a model list with a provider-wide price fallback.
Changes:
- Add
Balance.PrimaryCurrency()to select the currency associated with the largest reported balance entry. - Update desktop balance display logic to prefer the actual recharge currency when desktop currency is auto, and refresh the balance readout when Settings applies model/currency changes.
- Fix DeepSeek official pricing override logic to also apply to provider-wide
pricefallbacks when using amodelslist; add regression tests.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/config/pricing.go | Adjust DeepSeek official pricing override to handle provider-wide price when models list is used. |
| internal/config/backfill_test.go | Add regression test ensuring provider-wide DeepSeek pricing gets overridden to selected currency table. |
| internal/billing/balance.go | Add PrimaryCurrency() to infer display currency from the largest reported balance. |
| internal/billing/balance_test.go | Add test coverage for PrimaryCurrency() selection behavior. |
| desktop/app.go | Prefer actual recharge currency for balance display when desktop currency is auto. |
| desktop/frontend/src/lib/useController.ts | Refresh wallet balance readout when Settings dispatches the model-catalog-changed event. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ide, single config load for balance Copilot review esengine#7790 findings: 1. Provider-wide price override only checked models[0]; a multi-model entry whose first model is not a recognized official pricing model kept the wrong currency table. Now scans the whole resolved model list and overrides when ANY model matches the known official defaults. 2. BalanceForTab loaded the desktop user config twice (balanceDisplayCurrency + DesktopCurrency check) — extra disk/stat + TOML parse on every balance refresh, and the override depended on a second load succeeding. Load once and pass the config+err into balanceDisplayCurrency.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Suppressed comments (1)
desktop/app.go:6758
erris reused for the config-load call after it already held the balance-fetch error earlier in this function. Reassigning the sameerrname for an unrelated operation is easy to misread and makes future edits riskier (e.g., accidentally checking the wrong error). Use a distinct name likecfgErrand pass that through.
cfg, _, err := a.loadDesktopUserConfigForView()
currency := a.balanceDisplayCurrency(cfg, err)
if actual := b.PrimaryCurrency(); actual != "" {
if err == nil && cfg != nil && cfg.DesktopCurrency() == "" {
currency = actual
Summary
Wallet balance display followed the UI language guess (zh→CNY, en→USD),
which is wrong for overseas Chinese users who recharge USD but use a zh
interface. Also, picking CNY/USD in Settings did not refresh the
status-bar balance readout.
Changes
Balance.PrimaryCurrency()(internal/billing/balance.go)Returns the largest reported balance's currency. DeepSeek returns one
Info per currency; the largest balance is the one the user actually
recharged, so display should follow it rather than a language guess.
BalanceForTab(desktop/app.go)When desktop currency is auto (no explicit choice), display follows
PrimaryCurrency()instead of the UI-language guess. An explicitCNY/USD choice in Settings still wins.
applyDeepSeekOfficialDefaultPricingWithOverride(
internal/config/pricing.go)Match provider-wide
priceagainstp.ModelList()sodeepseek-responses(models list + provider-wide price fallback, emptyp.Model) also gets converted to the selected CNY/USD table. Beforethis, a USD default stayed in dollars even with
[desktop] currency = CNY.useController.ts(desktop frontend)Refresh the wallet readout on
reasonix:model-catalog-changed, whichSettingsPanel dispatches after applying currency/model changes. Before
this, picking CNY/USD in Settings did not update the status bar.
Verification
go test ./internal/billing/ ./internal/config/- all passTestPrimaryCurrencyFollowsLargestBalance,TestApplyDeepSeekOfficialPricingOverridesProviderWidePricetsc --noEmit- cleanCache-impact: low - config/billing/desktop display only; no provider wire
or system-prompt changes.
Cache-guard: go test ./internal/billing/ ./internal/config/ -count=1
Documentation-impact: none - internal display logic, no user-facing docs.
System-prompt-review: none - no system-prompt or boot surface changes.