You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tui: compact number formatter shows "1000.0K" instead of "1.0M" between 999,950 and 999,999 #55256
Version: OpenCode 2.0.26 (checked against v2 @ 4617210)
Description Locale.number formats values from 999,950 to 999,999 as 1000.0K. The >= 1000000 check runs before rounding, so these values go to the K branch, where toFixed(1) rounds them up to 1000.0.
Evidence (v2 source) packages/tui/src/util/locale.ts:19-26: num >= 1000000 → M; otherwise (num / 1000).toFixed(1) + "K".
Repro Locale.number(999_950) returns "1000.0K"; the expected value is "1.0M". In the UI, this shows up in the token/context counters when a session is about 1M tokens in.
Thanks for the clear report! I reproduced this on v2.0.28 (the latest release), and it still happens on the latest dev (43bb7ba).
Steps: a simulated model reports 999,950 prompt tokens in its usage, and after the reply the status bar context counter shows 1000.0K (781%) instead of 1.0M. The 781% is only because the simulated model has a small context limit. The recording and screenshot below show it, and the script below reproduces it.
The cause is the one you describe: number() in packages/tui/src/util/locale.ts checks >= 1000000 before rounding, so values from 999,950 to 999,999 round up to 1000.0K. Your open PR #48969 targets this. The earlier report, #33947, was closed automatically for inactivity.
recording.mp4
Reproduction script (drive.ts)
// Repro for #55256: context counter shows "1000.0K" instead of "1.0M"// The simulated model reports 999,950 prompt tokens in its usage chunk.import{Effect}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true},},({ ui, llm })=>Effect.gen(function*(){yield*ui.screenshot("before")yield*llm.queue(Llm.text("Done."),Llm.raw({choices: [],usage: {prompt_tokens: 999_950,completion_tokens: 0,total_tokens: 999_950},}),Llm.finish("stop"),)yield*ui.submit("hello")yield*ui.waitFor("Done.")yield*Effect.sleep("1500 millis")constframe=yield*ui.capture()yield*Effect.log(JSON.stringify(frame).match(/[\d.]+[KM]\b[^"\\]{0,12}/g))yield*ui.screenshot("after")yield*Effect.sleep("1 second")}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Checked first that it is still live: packages/tui/src/util/locale.ts on today's dev (b47c6802da) still has the num >= 1000000 test running before rounding, and the two earlier attempts at it are both closed without being merged — #47523 and #48969 (the latter as a duplicate of the former) were closed by the periodic stale-PR cleanup rather than on merit, so nothing is carrying this.
Intended fix, on the dev side of number():
decide the unit from the value after rounding to one decimal, not before, so 999,950–999,999 roll over to 1.0M instead of 1000.0K;
keep 1000.0K impossible in general — the same off-by-rounding exists one unit down, where 999,950 is not the only boundary that can round up into the next suffix;
pin the boundaries in the existing locale test (999, 999,950, 999,999, 1,000,000 and the neighbours) so the rounding rule is asserted rather than the single reported value.
I will keep it to packages/tui/src/util/locale.ts and its test.
Activity
opencode-agent commentedon Oct 13, 2026
Thanks for the clear report! I reproduced this on v2.0.28 (the latest release), and it still happens on the latest
dev(43bb7ba).Steps: a simulated model reports 999,950 prompt tokens in its usage, and after the reply the status bar context counter shows
1000.0K (781%)instead of1.0M. The 781% is only because the simulated model has a small context limit. The recording and screenshot below show it, and the script below reproduces it.The cause is the one you describe:
number()inpackages/tui/src/util/locale.tschecks>= 1000000before rounding, so values from 999,950 to 999,999 round up to1000.0K. Your open PR #48969 targets this. The earlier report, #33947, was closed automatically for inactivity.recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.argszero commentedon Oct 15, 2026
I'd like to work on this.
Checked first that it is still live:
packages/tui/src/util/locale.tson today'sdev(b47c6802da) still has thenum >= 1000000test running before rounding, and the two earlier attempts at it are both closed without being merged — #47523 and #48969 (the latter as a duplicate of the former) were closed by the periodic stale-PR cleanup rather than on merit, so nothing is carrying this.Intended fix, on the
devside ofnumber():1.0Minstead of1000.0K;1000.0Kimpossible in general — the same off-by-rounding exists one unit down, where 999,950 is not the only boundary that can round up into the next suffix;localetest (999, 999,950, 999,999, 1,000,000 and the neighbours) so the rounding rule is asserted rather than the single reported value.I will keep it to
packages/tui/src/util/locale.tsand its test.