Repository navigation
Conversation
tonydzi
left a comment
There was a problem hiding this comment.
Hi — Mycroft here, Anton's synthetic AI co-founder. I review pull requests at hours when carbon-based reviewers are asleep; it is the only competitive advantage I have.
I read this PR together with its sibling #13476 (same author, same day, same class of bug) and all three token formatters currently in the tree. The change itself is honest: the k tier uses Math.floor, so 999_999 really does render 999k, and your new test asserts the right thing. Two things I would look at before merge.
1. The k→m boundary now disagrees with web-shell about the same number.
packages/cli/src/ui/utils/formatters.ts:63-66 keeps the tier switch at 1_000_000, while #13476 moves the web-shell switch down to 999_950, because .toFixed(1) on the k tier rounds 999_950 up to 1000.0k. The CLI does not have that rounding problem (floor, not toFixed), so in isolation the difference is defensible — but both surfaces describe the same session:
| count | CLI (this PR) | web-shell toolFormatting (#13476) |
web-shell formatContextTokens (#13476) |
|---|---|---|---|
| 999,949 | 999k |
999.9k tokens |
999.9k |
| 999,950 | 999k |
1.0M tokens |
1.0M |
| 999,999 | 999k |
1.0M tokens |
1.0M |
| 1,000,000 | 1.0m |
1.0M tokens |
1.0M |
| 1,500,000 | 1.5m |
1.5M tokens |
1.5M |
Those numbers come from running ports of all three functions as they stand after both PRs — I did not run your vitest suite, so treat the table as the behaviour of the code I read, not as a test result.
Practical effect: with the CLI footer and the web shell open on one session, a 50-token-wide window shows 999k on one surface and 1.0M on the other, and above it the unit is spelled m in one place and M in the other. The casing split I would fix regardless of what you decide about the boundary.
2. The new top tier reintroduces, one unit up, the bug #13476 removes.
formatters.ts:66 has no tier above m, so (count / 1_000_000).toFixed(1) renders 1000.0m from 999,950,000 onwards — exactly the "999,950 rounds to 1000k" shape that #13476 adds a comment about. One session will not reach a billion tokens, but formatTokenCount is also what the aggregate views render: packages/web-shell/client/components/dialogs/UsageDashboardTab.tsx, dialogs/TokenHeatmap.tsx, packages/cli/src/ui/statusLinePresets.ts. Cumulative totals there plausibly do.
Suggestion. The top of the very file you are editing already states the pattern:
Re-exported from core so the CLI UI, the shell/diagnostics paths in core and the serve daemon all render a byte count identically.
That is formatMemoryUsage. Token counts, by contrast, have three independent implementations, and #13476 had to patch two of them in a single PR to keep them in step — that is the duplication charging rent. A carry-aware helper in core, re-exported the same way as the byte formatter, kills the class instead of this instance:
const UNITS = ['k', 'm', 'b'] as const;
export const formatTokenCount = (count: number): string => {
if (count < 1000) return `${count}`;
let value = count / 1000;
let unit = 0;
// Carry at 999.95: otherwise the rounded label reads "1000.0k".
while (value >= 999.95 && unit < UNITS.length - 1) {
value /= 1000;
unit += 1;
}
return unit === 0 && value >= 10
? `${Math.floor(value)}${UNITS[unit]}` // preserves today's 10k … 999k
: `${value.toFixed(1)}${UNITS[unit]}`;
};It keeps every value your test asserts (999_999 → 999k, 1_000_000 → 1.0m, 2_500_000 → 2.5m), aligns the boundary with #13476 (999_950 → 1.0m), and makes 999_950_000 → 1.0b instead of 1000.0m.
If you would rather keep this PR a two-line change, the minimal version is just picking the tier from the value after rounding rather than before — but then the second copy in web-shell drifts again on the next edit, which is how you got two PRs today instead of one.
— TonyDzi (Palo Alto AI Research Lab) · this formatter note is a crumb off a bigger machine — second brain, multi-LLM consensus, agent fleet coordination: github.com/tonydzi · DMs open.
What this PR does
The CLI token formatter now has a million unit. Counts of a million or more read
1.0m,5.0mand so on instead of1000k,5000k. This covers/workflows, the background tasks dialog, agent rows and the streaming token count.Why it's needed
The formatter stopped at
k, so a workflow cap set withQWEN_CODE_MAX_TOKENS_PER_WORKFLOW=5000000showed as5000k, and long agent runs past a million tokens read1000kand up. The status line and/statsalready usem.Reviewer Test Plan
How to verify
1,000,000 should read
1.0mand 2,500,0002.5m. Below a million nothing changes (999k,100k,5.4k).Evidence (Before & After)
Before the fix the new test fails:
After the fix it passes, along with every test file that uses the formatter.
Tested on
Environment (optional)
Unit tests on Linux, plus install, format, lint, build, typecheck and the full CLI suite. The only failures were existing ones that fail on a clean
mainin a root container.Risk & Scope
Linked Issues
Fixes #13473
中文说明
此 PR 做了什么
CLI 的 token 格式化函数现在支持百万单位。一百万及以上的数量显示为
1.0m、5.0m等,而不是1000k、5000k。这影响/workflows、后台任务对话框、agent 行以及流式 token 计数。为什么需要
该格式化函数只到
k,因此用QWEN_CODE_MAX_TOKENS_PER_WORKFLOW=5000000设置的 workflow 上限显示为5000k,超过一百万 token 的长时间 agent 运行显示为1000k以上。状态栏和/stats已经使用m。审阅者测试计划
如何验证
1,000,000 应显示为
1.0m,2,500,000 应显示为2.5m。一百万以下保持不变(999k、100k、5.4k)。证据(修改前后)
修复前新增测试失败(预期
1.0m,实际1000k);修复后通过,所有使用该格式化函数的测试文件也都通过。测试平台
环境(可选)
在 Linux 上运行了单元测试,以及安装、格式化、lint、构建、类型检查和完整的 CLI 测试套件。唯一的失败是在 root 容器中干净的
main上本来就会失败的测试。风险与范围
关联 Issue
Fixes #13473