mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-07-09 17:19:15 +00:00
fix(overview): pin number grouping to en-US so output is locale-independent
`codeburn overview` formatted token/call/session counts with a bare `toLocaleString()`, which groups digits according to the host's locale. On an Indian-locale machine (en-IN) a value like 2,002,000,000 renders as 2,00,20,00,000, so the rendered summary — and its snapshot test — differed by machine. (formatCost already avoided this via an explicit thousands regex.) Pin `formatTokens` to 'en-US' and route the remaining count columns through a new `formatCount` helper that does the same, so the overview output is byte-identical everywhere. Verify: `npm test -- overview` (previously failed on non-US locales; the "thousands separators" case now passes regardless of $LANG / ICU default).
This commit is contained in:
parent
8e55b5ff55
commit
4e6e02d08d
1 changed files with 13 additions and 6 deletions
|
|
@ -14,7 +14,14 @@ function formatCost(usd: number): string {
|
|||
return baseCost(usd).replace(/(\d)(?=(\d{3})+(\.|$))/g, '$1,')
|
||||
}
|
||||
function formatTokens(n: number): string {
|
||||
return Math.round(n).toLocaleString()
|
||||
// Pin the locale so grouping is deterministic regardless of the host's
|
||||
// locale (e.g. en-IN groups as 2,00,20,00,000 instead of 2,002,000,000).
|
||||
return Math.round(n).toLocaleString('en-US')
|
||||
}
|
||||
// Integer counts (calls, sessions, turns, tool uses) — same locale pin so the
|
||||
// overview output is byte-identical across machines.
|
||||
function formatCount(n: number): string {
|
||||
return n.toLocaleString('en-US')
|
||||
}
|
||||
function isAbsoluteProjectPath(path: string): boolean {
|
||||
return path.startsWith('/') || path.startsWith('\\') || /^[a-zA-Z]:[/\\]/.test(path)
|
||||
|
|
@ -150,7 +157,7 @@ export function renderOverview(
|
|||
const kv = (k: string, v: string): string => ' ' + c.dim(k.padEnd(11)) + v
|
||||
out.push(kv('Cost', c.bold(formatCost(cost))))
|
||||
out.push(kv('Tokens', formatTokens(totalTokens) + c.dim(' (breakdown below)')))
|
||||
out.push(kv('Calls', calls.toLocaleString() + c.dim(' sessions ') + sessions.toLocaleString()))
|
||||
out.push(kv('Calls', formatCount(calls) + c.dim(' sessions ') + formatCount(sessions)))
|
||||
out.push(kv('Cache hit', `${cacheHit.toFixed(1)}%`))
|
||||
if (savings > 0) out.push(kv('Savings', formatCost(savings) + c.dim(' (local models)')))
|
||||
out.push('')
|
||||
|
|
@ -191,7 +198,7 @@ export function renderOverview(
|
|||
out.push(heading('Top models'))
|
||||
out.push(renderTable(c,
|
||||
[{ header: 'Model' }, { header: 'Cost', right: true }, { header: 'Calls', right: true }, { header: 'Tokens', right: true }],
|
||||
modelRows.map(([m, v]) => [getShortModelName(m), formatCost(v.cost), v.calls.toLocaleString(), formatTokens(v.tokens)]),
|
||||
modelRows.map(([m, v]) => [getShortModelName(m), formatCost(v.cost), formatCount(v.calls), formatTokens(v.tokens)]),
|
||||
))
|
||||
out.push('')
|
||||
}
|
||||
|
|
@ -213,7 +220,7 @@ export function renderOverview(
|
|||
out.push(heading('Top projects'))
|
||||
out.push(renderTable(c,
|
||||
[{ header: 'Project' }, { header: 'Cost', right: true }, { header: 'Sessions', right: true }],
|
||||
projRows.map(([name, v]) => [name, formatCost(v.cost), v.sessions.toLocaleString()]),
|
||||
projRows.map(([name, v]) => [name, formatCost(v.cost), formatCount(v.sessions)]),
|
||||
))
|
||||
out.push('')
|
||||
}
|
||||
|
|
@ -235,7 +242,7 @@ export function renderOverview(
|
|||
out.push(heading('By activity'))
|
||||
out.push(renderTable(c,
|
||||
[{ header: 'Activity' }, { header: 'Cost', right: true }, { header: 'Turns', right: true }],
|
||||
catRows.map(([cat, v]) => [CATEGORY_LABELS[cat as TaskCategory] ?? cat, formatCost(v.cost), v.turns.toLocaleString()]),
|
||||
catRows.map(([cat, v]) => [CATEGORY_LABELS[cat as TaskCategory] ?? cat, formatCost(v.cost), formatCount(v.turns)]),
|
||||
))
|
||||
out.push('')
|
||||
}
|
||||
|
|
@ -246,7 +253,7 @@ export function renderOverview(
|
|||
out.push(heading('Tools'))
|
||||
out.push(renderTable(c,
|
||||
[{ header: 'Tool' }, { header: 'Calls', right: true }],
|
||||
toolRows.map(([t, n]) => [t, n.toLocaleString()]),
|
||||
toolRows.map(([t, n]) => [t, formatCount(n)]),
|
||||
))
|
||||
out.push('')
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue