
























@@ -109,6 +109,7 @@ describe("buildStatusMessage", () => {
109109inputTokens: 1200,
110110outputTokens: 800,
111111totalTokens: 16_000,
112+totalTokensFresh: true,
112113contextTokens: 32_000,
113114thinkingLevel: "low",
114115verboseLevel: "on",
@@ -221,6 +222,30 @@ describe("buildStatusMessage", () => {
221222expect(normalized).not.toContain("Context: 3.8m/1.0m");
222223});
223224225+it("preserves legacy unknown-freshness totalTokens as context usage", () => {
226+const text = buildStatusMessage({
227+agent: {
228+model: "anthropic/test:opus",
229+contextTokens: 1_000_000,
230+},
231+sessionEntry: {
232+sessionId: "abc",
233+updatedAt: 0,
234+totalTokens: 25_000,
235+contextTokens: 1_000_000,
236+},
237+sessionKey: "agent:main:main",
238+sessionScope: "per-sender",
239+queue: { mode: "collect", depth: 0 },
240+modelAuth: "api-key",
241+now: 10 * 60_000,
242+});
243+const normalized = normalizeTestText(text);
244+245+expect(normalized).toContain("Context: 25k/1.0m");
246+expect(normalized).not.toContain("Context: ?/1.0m");
247+});
248+224249it("uses estimated context budget status when fresh totalTokens are unavailable", () => {
225250const text = buildStatusMessage({
226251agent: {
@@ -856,6 +881,7 @@ describe("buildStatusMessage", () => {
856881channel: "discord",
857882groupId: "123",
858883totalTokens: 49_000,
884+totalTokensFresh: true,
859885contextTokens: 1_048_576,
860886},
861887sessionKey: "agent:main:main",
@@ -891,6 +917,7 @@ describe("buildStatusMessage", () => {
891917sessionId: "ctx1m",
892918updatedAt: 0,
893919totalTokens: 200_000,
920+totalTokensFresh: true,
894921},
895922sessionKey: "agent:main:main",
896923sessionScope: "per-sender",
@@ -909,6 +936,7 @@ describe("buildStatusMessage", () => {
909936sessionId: "opus47",
910937updatedAt: 0,
911938totalTokens: 200_000,
939+totalTokensFresh: true,
912940},
913941sessionKey: "agent:main:main",
914942sessionScope: "per-sender",
@@ -928,6 +956,7 @@ describe("buildStatusMessage", () => {
928956modelOverride: "small-model",
929957contextTokens: 4_096,
930958totalTokens: 1_024,
959+totalTokensFresh: true,
931960};
932961933962applyModelOverrideToSessionEntry({
@@ -981,6 +1010,7 @@ describe("buildStatusMessage", () => {
9811010fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
9821011fallbackNoticeReason: "model not allowed",
9831012totalTokens: 49_000,
1013+totalTokensFresh: true,
9841014contextTokens: 1_048_576,
9851015},
9861016sessionKey: "agent:main:main",
@@ -1113,6 +1143,7 @@ describe("buildStatusMessage", () => {
11131143fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
11141144fallbackNoticeReason: "model not allowed",
11151145totalTokens: 49_000,
1146+totalTokensFresh: true,
11161147contextTokens: 1_048_576,
11171148},
11181149sessionKey: "agent:main:main",
@@ -1157,6 +1188,7 @@ describe("buildStatusMessage", () => {
11571188fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
11581189fallbackNoticeReason: "model not allowed",
11591190totalTokens: 49_000,
1191+totalTokensFresh: true,
11601192contextTokens: 123_456,
11611193},
11621194sessionKey: "agent:main:main",
@@ -1203,6 +1235,7 @@ describe("buildStatusMessage", () => {
12031235fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
12041236fallbackNoticeReason: "model not allowed",
12051237totalTokens: 49_000,
1238+totalTokensFresh: true,
12061239},
12071240sessionKey: "agent:main:main",
12081241sessionScope: "per-sender",
@@ -1248,6 +1281,7 @@ describe("buildStatusMessage", () => {
12481281fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
12491282fallbackNoticeReason: "model not allowed",
12501283totalTokens: 49_000,
1284+totalTokensFresh: true,
12511285},
12521286sessionKey: "agent:main:main",
12531287sessionScope: "per-sender",
@@ -1292,6 +1326,7 @@ describe("buildStatusMessage", () => {
12921326fallbackNoticeActiveModel: "minimax-portal/MiniMax-M2.7",
12931327fallbackNoticeReason: "model not allowed",
12941328totalTokens: 49_000,
1329+totalTokensFresh: true,
12951330},
12961331sessionKey: "agent:main:main",
12971332sessionScope: "per-sender",
@@ -1333,6 +1368,7 @@ describe("buildStatusMessage", () => {
13331368fallbackNoticeActiveModel: "custom-runtime/unknown-fallback-model",
13341369fallbackNoticeReason: "model not allowed",
13351370totalTokens: 49_000,
1371+totalTokensFresh: true,
13361372contextTokens: 128_000,
13371373},
13381374sessionKey: "agent:main:main",
@@ -1981,6 +2017,54 @@ describe("buildStatusMessage", () => {
19812017);
19822018});
198320192020+it("does not let legacy cumulative session totals override fresh transcript context usage", async () => {
2021+await withTempHome(
2022+async (dir) => {
2023+const sessionId = "sess-legacy-cumulative-context";
2024+writeTranscriptUsageLog({
2025+ dir,
2026+agentId: "main",
2027+ sessionId,
2028+usage: {
2029+input: 10_000,
2030+output: 1_000,
2031+cacheRead: 26_000,
2032+cacheWrite: 0,
2033+totalTokens: 36_000,
2034+},
2035+});
2036+2037+const text = buildStatusMessage({
2038+agent: {
2039+model: "anthropic/claude-opus-4-6",
2040+contextTokens: 1_000_000,
2041+},
2042+sessionEntry: {
2043+ sessionId,
2044+updatedAt: 0,
2045+inputTokens: 16,
2046+outputTokens: 5_100,
2047+cacheRead: 2_300_000,
2048+cacheWrite: 11_000,
2049+totalTokens: 2_300_000,
2050+contextTokens: 1_000_000,
2051+},
2052+sessionKey: "agent:main:main",
2053+sessionScope: "per-sender",
2054+queue: { mode: "collect", depth: 0 },
2055+includeTranscriptUsage: true,
2056+modelAuth: "api-key",
2057+});
2058+const normalized = normalizeTestText(text);
2059+2060+expect(normalized).toContain("Cache: 100% hit · 2.3m cached, 11k new");
2061+expect(normalized).toContain("Context: 36k/1.0m (4%)");
2062+expect(normalized).not.toContain("Context: 2.3m/1.0m");
2063+},
2064+{ prefix: "openclaw-status-" },
2065+);
2066+});
2067+19842068it("reads transcript usage for non-default agents", async () => {
19852069await withTempHome(
19862070async (dir) => {
@@ -2237,6 +2321,7 @@ describe("buildStatusMessage", () => {
22372321sessionId: "sess-runtime-slash-id",
22382322updatedAt: 0,
22392323totalTokens: 1205,
2324+totalTokensFresh: true,
22402325model: "google/gemini-2.5-pro",
22412326},
22422327sessionKey: "agent:main:main",
@@ -2279,6 +2364,7 @@ describe("buildStatusMessage", () => {
22792364fallbackNoticeActiveModel: "fake-minimax/FakeMiniMax-M2.5",
22802365fallbackNoticeReason: "model not allowed",
22812366totalTokens: 49_000,
2367+totalTokensFresh: true,
22822368},
22832369sessionKey: "agent:main:main",
22842370sessionScope: "per-sender",
@@ -2314,6 +2400,7 @@ describe("buildStatusMessage", () => {
23142400updatedAt: 0,
23152401model: "openai/gpt-4o",
23162402totalTokens: 49_000,
2403+totalTokensFresh: true,
23172404},
23182405sessionKey: "agent:main:main",
23192406sessionScope: "per-sender",
@@ -2384,6 +2471,7 @@ describe("buildStatusMessage", () => {
23842471sessionId: "sess-anthropic-qualified-context",
23852472updatedAt: 0,
23862473totalTokens: 25_000,
2474+totalTokensFresh: true,
23872475},
23882476sessionKey: "agent:main:main",
23892477sessionScope: "per-sender",
@@ -2408,6 +2496,7 @@ describe("buildStatusMessage", () => {
24082496sessionId: "sess-openai-chatgpt-cap-context",
24092497updatedAt: 0,
24102498totalTokens: 25_000,
2499+totalTokensFresh: true,
24112500},
24122501sessionKey: "agent:main:main",
24132502sessionScope: "per-sender",
@@ -2432,6 +2521,7 @@ describe("buildStatusMessage", () => {
24322521sessionId: "sess-openai-chatgpt-runtime-cap-context",
24332522updatedAt: 0,
24342523totalTokens: 25_000,
2524+totalTokensFresh: true,
24352525},
24362526sessionKey: "agent:main:main",
24372527sessionScope: "per-sender",
@@ -2469,6 +2559,7 @@ describe("buildStatusMessage", () => {
24692559fallbackNoticeActiveModel: "custom-runtime/unknown-fallback-model",
24702560fallbackNoticeReason: "model not allowed",
24712561totalTokens: 49_000,
2562+totalTokensFresh: true,
24722563contextTokens: 128_000,
24732564},
24742565sessionKey: "agent:main:main",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。