fix(ui): show 1M context for million-token models (#120369)

* fix(ui): show 1M context for million-token models

* fix(deps): update nanoid security patch

* revert: drop obsolete nanoid lock refresh
This commit is contained in:
Peter Steinberger
2026-08-07 15:54:50 -07:00
committed by GitHub
parent 0f147d18d4
commit 47a3bf50ce
4 changed files with 27 additions and 3 deletions
+17
View File
@@ -7,6 +7,7 @@ import {
formatDateTimeMs,
formatDateMs,
formatCompactTokenCount,
formatContextTokenCapacity,
formatDurationCompact,
formatDurationHuman,
formatMs,
@@ -209,6 +210,7 @@ describe("formatCompactTokenCount", () => {
it("formats millions with one decimal, trimming a trailing .0", () => {
expect(formatCompactTokenCount(1_000_000)).toBe("1M");
expect(formatCompactTokenCount(1_050_000)).toBe("1.1M");
expect(formatCompactTokenCount(1_500_000)).toBe("1.5M");
});
@@ -235,6 +237,21 @@ describe("formatCompactTokenCount", () => {
});
});
describe("formatContextTokenCapacity", () => {
it("truncates million-scale capacity to at most one decimal", () => {
expect(formatContextTokenCapacity(1_000_000)).toBe("1M");
expect(formatContextTokenCapacity(1_050_000)).toBe("1M");
expect(formatContextTokenCapacity(1_100_000)).toBe("1.1M");
});
it("preserves shared compact formatting below one million", () => {
expect(formatContextTokenCapacity(999)).toBe("999");
expect(formatContextTokenCapacity(1_000)).toBe("1k");
expect(formatContextTokenCapacity(32_768)).toBe("32.8k");
expect(formatContextTokenCapacity(999_999)).toBe("1M");
});
});
describe("formatTokens", () => {
it("rolls a value that rounds up to 1000k over into the M branch", () => {
expect(formatTokens(999_500)).toBe("1.0M");
+7
View File
@@ -325,3 +325,10 @@ export function formatCompactTokenCount(
}
return String(tokens);
}
export function formatContextTokenCapacity(tokens: number): string {
if (tokens < 1_000_000) {
return formatCompactTokenCount(tokens);
}
return `${Math.floor(tokens / 100_000) / 10}M`;
}
+1 -1
View File
@@ -5106,7 +5106,7 @@ describe("chat model controls", () => {
);
expect(modelOption?.querySelector(".chat-controls__model-option-meta")?.textContent).toBe(
"1.1M context",
"1M context",
);
expect(modelOption?.closest("openclaw-tooltip")).toBeNull();
});
@@ -26,7 +26,7 @@ import {
formatThinkingOverrideLabel,
resolveChatThinkingSelectState,
} from "../../../lib/chat/thinking.ts";
import { formatCompactTokenCount } from "../../../lib/format.ts";
import { formatContextTokenCapacity } from "../../../lib/format.ts";
import { areUiSessionKeysEquivalent } from "../../../lib/sessions/session-key.ts";
import { moveChatModelProviderFocus, selectChatModelProvider } from "./chat-model-provider-menu.ts";
@@ -658,7 +658,7 @@ function renderChatModelReasoningSelect(params: {
const modelMeta = [
entry.contextWindow
? t("chat.modelControls.contextWindow", {
count: formatCompactTokenCount(entry.contextWindow),
count: formatContextTokenCapacity(entry.contextWindow),
})
: "",
entry.supportsTools === false ? t("chat.modelControls.chatOnly") : "",