From 039a4e483eeeaf5d9a25e59bc60f6ea2baf1a52c Mon Sep 17 00:00:00 2001 From: Resham Joshi <65915470+iamtoruk@users.noreply.github.com> Date: Sat, 10 Oct 2026 07:05:12 +0200 Subject: [PATCH] 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. --- src/overview.ts | 2 +- src/sharing/host.ts | 2 +- tests/overview.test.ts | 11 +++++++++++ tests/sharing/host.test.ts | 8 ++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/overview.ts b/src/overview.ts index d88cc1f7..8e706e56 100644 --- a/src/overview.ts +++ b/src/overview.ts @@ -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(/(? 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(/(? ({ name: d.name + (d.local ? ' (this Mac)' : ''), diff --git a/tests/overview.test.ts b/tests/overview.test.ts index 331f398d..839d096c 100644 --- a/tests/overview.test.ts +++ b/tests/overview.test.ts @@ -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') + }) }) diff --git a/tests/sharing/host.test.ts b/tests/sharing/host.test.ts index 39db6883..42d288e0 100644 --- a/tests/sharing/host.test.ts +++ b/tests/sharing/host.test.ts @@ -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') + }) })