Skip to content

Commit 78f948f

Browse files
authored
fix(tui): show 0 not ? for fresh-session context tokens in footer (#94337)
Summary: - The PR extends TUI session info to carry `totalTokensFresh`, maps fresh missing totals to `0`, and adds a focused regression test for the footer merge path. - PR surface: Source +15, Tests +38. Total +53 across 4 files. - Reproducibility: yes. at source level: `chat.history` returns session info with `totalTokensFresh`, but curr ... `null` before footer formatting. I did not run local tests or a live TUI session in this read-only review. Automerge notes: - PR branch already contained follow-up commit before automerge: Merge branch 'main' into fix/followup-93798 Validation: - ClawSweeper review passed for head 43657b5. - Required merge gates passed before the squash merge. Prepared head SHA: 43657b5 Review: #94337 (comment) Co-authored-by: 杨浩宇0668001029 <yang.haoyu@xydigit.com> Co-authored-by: mushuiyu_xydt <yang.haoyu@xydigit.com>
1 parent 975340f commit 78f948f

4 files changed

Lines changed: 54 additions & 1 deletion

File tree

src/tui/tui-backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export type TuiSessionList = {
6262
| "inputTokens"
6363
| "outputTokens"
6464
| "totalTokens"
65+
| "totalTokensFresh"
6566
| "goal"
6667
| "modelProvider"
6768
| "displayName"

src/tui/tui-session-actions.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,44 @@ describe("tui session actions", () => {
495495
expect(listSessions).not.toHaveBeenCalled();
496496
});
497497

498+
it("renders a fresh session total as 0 (not '?') when totalTokensFresh is set", async () => {
499+
const listSessions = vi.fn().mockResolvedValue({ sessions: [] });
500+
const loadHistory = vi.fn().mockResolvedValue({
501+
sessionId: "session-fresh",
502+
sessionInfo: {
503+
key: "agent:main:fresh",
504+
sessionId: "session-fresh",
505+
model: "session-model",
506+
modelProvider: "openai",
507+
// The gateway strips the fresh 0 via resolvePositiveNumber but still
508+
// flags it fresh, so the footer must show 0 rather than "?". (#93798)
509+
totalTokensFresh: true,
510+
updatedAt: 60,
511+
},
512+
messages: [],
513+
});
514+
const state = createBaseState({
515+
historyLoaded: true,
516+
sessionInfo: {
517+
totalTokens: 3,
518+
updatedAt: 500,
519+
},
520+
});
521+
522+
const { setSession } = createTestSessionActions({
523+
client: {
524+
listSessions,
525+
loadHistory,
526+
} as unknown as TuiBackend,
527+
state,
528+
});
529+
530+
await setSession("agent:main:fresh");
531+
532+
expect(state.sessionInfo.totalTokens).toBe(0);
533+
expect(state.sessionInfo.totalTokensFresh).toBe(true);
534+
});
535+
498536
it("restores an in-flight run reported by chat.history on switch-back", async () => {
499537
const loadHistory = vi.fn().mockResolvedValue({
500538
sessionId: "session-bg",

src/tui/tui-session-actions.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,13 @@ export function createSessionActions(context: SessionActionContext) {
253253
}
254254
if (entry?.totalTokens !== undefined) {
255255
next.totalTokens = entry.totalTokens;
256+
next.totalTokensFresh = entry.totalTokensFresh === true;
257+
} else if (entry?.totalTokensFresh === true) {
258+
// Fresh session: the total is known to be 0. The gateway strips the 0 via
259+
// resolvePositiveNumber but still flags it fresh, so render 0 (not "?"),
260+
// mirroring the /status fix in #93798. See followup to #93771.
261+
next.totalTokens = 0;
262+
next.totalTokensFresh = true;
256263
}
257264
if (params.clearMissingUsage) {
258265
if (entry?.inputTokens === undefined) {
@@ -261,8 +268,9 @@ export function createSessionActions(context: SessionActionContext) {
261268
if (entry?.outputTokens === undefined) {
262269
next.outputTokens = null;
263270
}
264-
if (entry?.totalTokens === undefined) {
271+
if (entry?.totalTokens === undefined && entry?.totalTokensFresh !== true) {
265272
next.totalTokens = null;
273+
next.totalTokensFresh = undefined;
266274
}
267275
}
268276
if (hasEntryUpdate) {

src/tui/tui-types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ export type SessionInfo = {
8383
inputTokens?: number | null;
8484
outputTokens?: number | null;
8585
totalTokens?: number | null;
86+
/**
87+
* True when `totalTokens` is a known-fresh value (e.g. 0 on a brand-new
88+
* session) rather than an unknown/stale total. Lets the footer render `0`
89+
* instead of `?` for fresh sessions, mirroring the `/status` fix in #93798.
90+
*/
91+
totalTokensFresh?: boolean;
8692
goal?: SessionGoal;
8793
responseUsage?: ResponseUsageMode;
8894
updatedAt?: number | null;

0 commit comments

Comments
 (0)