fix: /status shows incorrect context percentage — totalTokens clamped to contextTokens (#15114) (#15133)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: a489669fc7
Co-authored-by: echoVic <16428813+echoVic@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
青雲
2026-02-13 12:52:19 +08:00
committed by GitHub
parent b93ad2cd48
commit fd076eb43a
28 changed files with 361 additions and 53 deletions

View File

@@ -44,12 +44,13 @@ describe("persistSessionUsageUpdate", () => {
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
// totalTokens should reflect lastCallUsage (12_000 input), not accumulated (180_000)
expect(stored[sessionKey].totalTokens).toBe(12_000);
expect(stored[sessionKey].totalTokensFresh).toBe(true);
// inputTokens/outputTokens still reflect accumulated usage for cost tracking
expect(stored[sessionKey].inputTokens).toBe(180_000);
expect(stored[sessionKey].outputTokens).toBe(10_000);
});
it("falls back to accumulated usage for totalTokens when lastCallUsage not provided", async () => {
it("marks totalTokens as unknown when no fresh context snapshot is available", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-usage-"));
const storePath = path.join(tmp, "sessions.json");
const sessionKey = "main";
@@ -67,10 +68,34 @@ describe("persistSessionUsageUpdate", () => {
});
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
expect(stored[sessionKey].totalTokens).toBe(50_000);
expect(stored[sessionKey].totalTokens).toBeUndefined();
expect(stored[sessionKey].totalTokensFresh).toBe(false);
});
it("caps totalTokens at context window even with lastCallUsage", async () => {
it("uses promptTokens when available without lastCallUsage", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-usage-"));
const storePath = path.join(tmp, "sessions.json");
const sessionKey = "main";
await seedSessionStore({
storePath,
sessionKey,
entry: { sessionId: "s1", updatedAt: Date.now() },
});
await persistSessionUsageUpdate({
storePath,
sessionKey,
usage: { input: 50_000, output: 5_000, total: 55_000 },
promptTokens: 42_000,
contextTokensUsed: 200_000,
});
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
expect(stored[sessionKey].totalTokens).toBe(42_000);
expect(stored[sessionKey].totalTokensFresh).toBe(true);
});
it("keeps non-clamped lastCallUsage totalTokens when exceeding context window", async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-usage-"));
const storePath = path.join(tmp, "sessions.json");
const sessionKey = "main";
@@ -89,7 +114,7 @@ describe("persistSessionUsageUpdate", () => {
});
const stored = JSON.parse(await fs.readFile(storePath, "utf-8"));
// Capped at context window
expect(stored[sessionKey].totalTokens).toBe(200_000);
expect(stored[sessionKey].totalTokens).toBe(250_000);
expect(stored[sessionKey].totalTokensFresh).toBe(true);
});
});