fix(overview): group thousands in the integer part of costs only (#1714)

The comma-grouping regex in overview and devices also matched the fraction,
so $0.0028 rendered as $0.0,028. A lookbehind now skips digits after the
decimal point.
This commit is contained in:
Resham Joshi 2026-10-10 07:05:12 +02:00 • committed by GitHub
parent b62e4a30ee
commit 039a4e483e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 2 deletions

View file

@ -21,7 +21,7 @@ import { folderNameOriginKey, isTemporaryProjectPath, linkedOriginKey, originRep
// abbreviate; here we show full, comma-grouped numbers so the tables read like
// a precise statement. Aggregation uses raw numbers; these only affect render.
function formatCost(usd: number): string {
return baseCost(usd).replace(/(\d)(?=(\d{3})+(\.|$))/g, '$1,')
return baseCost(usd).replace(/(?<!\.\d*)(\d)(?=(\d{3})+(\.|$))/g, '$1,')
}
function formatDisplayCost(amount: number): string {
const { rate } = getCurrency()

View file

@ -208,7 +208,7 @@ export async function pullDevices(
// row. Tokens are shown as full, comma-grouped numbers.
export function renderDevices(results: DeviceUsage[]): string {
const n = (x: number): string => Math.round(x).toLocaleString()
const money = (x: number): string => formatCost(x).replace(/(\d)(?=(\d{3})+(\.|$))/g, '$1,')
const money = (x: number): string => formatCost(x).replace(/(?<!\.\d*)(\d)(?=(\d{3})+(\.|$))/g, '$1,')
const summary = summarizeDeviceUsage(results)
const rows = summary.perDevice.map((d) => ({
name: d.name + (d.local ? ' (this Mac)' : ''),

View file

@ -390,4 +390,15 @@ describe('renderOverview #1260 residuals', () => {
expect(top).toContain('$1.00')
expect(top).not.toContain('$11.00')
})
it('groups thousands in the integer part only', () => {
const render = (cost: number) => renderOverview([makeProject({
project: 'p', projectPath: '/Users/test/p', cost, calls: 1, model: 'claude-opus-4-8', provider: 'claude',
tokens: { input: 1, output: 1, cacheR: 0, cacheW: 0 },
})], { label: 'June 2026', color: false })
expect(render(0.0028)).toContain('$0.0028')
expect(render(0.0028)).not.toContain('$0.0,028')
expect(render(1234.5678)).toContain('$1,234.57')
expect(render(1234567)).toContain('$1,234,567.00')
})
})

View file

@ -255,4 +255,12 @@ describe('host device flow', () => {
expect(summary.perDevice[0]).toMatchObject({ cacheCreateTokens: 7, cacheReadTokens: 42 })
expect(summary.combined).toMatchObject({ cacheCreateTokens: 7, cacheReadTokens: 42 })
})
it('groups thousands in the integer part of costs only', () => {
const device = (id: string, cost: number): DeviceUsage => ({ id, name: id, local: id === 'a', payload: { current: { cost, calls: 1, sessions: 1, inputTokens: 1, outputTokens: 1 } } })
const text = renderDevices([device('a', 0.0028), device('b', 1234567)])
expect(text).toContain('$0.0028')
expect(text).not.toContain('$0.0,028')
expect(text).toContain('$1,234,567.00')
})
})