Add a desktop Direct-chat header indicator for estimated tokens used against the active model context window. - Estimate chat token usage client-side, including streaming text, and format compact counts. - Render the context-window badge only for non-mobile Direct-chat threads with known model context windows. - Cover desktop, mobile, floating-narrow, rooms, unknown-context, and streaming surfaces with tests. - Document the dashboard behavior and add a release changeset. Files changed: .changeset/fn-7141-chat-context-window.md | 7 + docs/dashboard-guide.md | 2 + packages/dashboard/app/components/ChatView.css | 22 +++ packages/dashboard/app/components/ChatView.tsx | 35 +++- .../__tests__/ChatView.context-window.test.tsx | 193 +++++++++++++++++++++ .../app/utils/__tests__/estimateChatTokens.test.ts | 34 ++++ packages/dashboard/app/utils/estimateChatTokens.ts | 29 ++++ packages/i18n/locales/en/app.json | 1 + 8 files changed, 322 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7141 Fusion-Task-Lineage: 3ede9af4-b8d6-4da6-996f-cd9277ef49ac Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { estimateChatTokens, formatTokenCount } from "../estimateChatTokens";
|
|
|
|
describe("estimateChatTokens", () => {
|
|
it("returns 0 for empty input", () => {
|
|
expect(estimateChatTokens([])).toBe(0);
|
|
});
|
|
|
|
it("sums multiple message contents with a four-character heuristic", () => {
|
|
expect(estimateChatTokens([{ content: "abcd" }, { content: "abcdefgh" }])).toBe(3);
|
|
});
|
|
|
|
it("includes streaming text in the estimate", () => {
|
|
expect(estimateChatTokens([{ content: "abcd" }], "abcdefgh")).toBe(3);
|
|
});
|
|
|
|
it("guards against null or undefined content", () => {
|
|
expect(estimateChatTokens([{ content: null }, {}, { content: "abcde" }])).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe("formatTokenCount", () => {
|
|
it("renders sub-1k counts without a suffix", () => {
|
|
expect(formatTokenCount(980)).toBe("980");
|
|
});
|
|
|
|
it("renders one-decimal compact thousands below 10k", () => {
|
|
expect(formatTokenCount(1234)).toBe("~1.2k");
|
|
});
|
|
|
|
it("rounds larger thousands without a decimal", () => {
|
|
expect(formatTokenCount(200_000)).toBe("200k");
|
|
});
|
|
});
|