fix(ui): show current context tokens instead of cumulative in Control UI#48144
fix(ui): show current context tokens instead of cumulative in Control UI#48144imwyvern wants to merge 3 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes the Key changes:
Issue found:
Confidence Score: 2/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: ui/src/ui/chat/slash-command-executor.ts
Line: 306
Comment:
**`totalTokensFresh` missing from `GatewaySessionRow` type**
`session.totalTokensFresh` is accessed here, but `totalTokensFresh` is not declared in the `GatewaySessionRow` type in `ui/src/ui/types.ts`. TypeScript will reject this with _"Property 'totalTokensFresh' does not exist on type 'GatewaySessionRow'"_, causing compilation to fail.
The same problem surfaces in the test file at line 341, where `{ totalTokensFresh: false }` is passed as `Partial<GatewaySessionRow>` to the `row()` helper — TypeScript's excess-property check will also reject that.
`GatewaySessionRow` needs `totalTokensFresh?: boolean` added before this code can compile:
```
// ui/src/ui/types.ts (GatewaySessionRow)
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
+ totalTokensFresh?: boolean;
model?: string;
modelProvider?: string;
contextTokens?: number;
```
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: 5800b59 |
| const output = session.outputTokens ?? 0; | ||
| const total = session.totalTokens ?? input + output; | ||
| const total = | ||
| session.totalTokensFresh === false || !Number.isFinite(session.totalTokens) |
There was a problem hiding this comment.
totalTokensFresh missing from GatewaySessionRow type
session.totalTokensFresh is accessed here, but totalTokensFresh is not declared in the GatewaySessionRow type in ui/src/ui/types.ts. TypeScript will reject this with "Property 'totalTokensFresh' does not exist on type 'GatewaySessionRow'", causing compilation to fail.
The same problem surfaces in the test file at line 341, where { totalTokensFresh: false } is passed as Partial<GatewaySessionRow> to the row() helper — TypeScript's excess-property check will also reject that.
GatewaySessionRow needs totalTokensFresh?: boolean added before this code can compile:
// ui/src/ui/types.ts (GatewaySessionRow)
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
+ totalTokensFresh?: boolean;
model?: string;
modelProvider?: string;
contextTokens?: number;
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/chat/slash-command-executor.ts
Line: 306
Comment:
**`totalTokensFresh` missing from `GatewaySessionRow` type**
`session.totalTokensFresh` is accessed here, but `totalTokensFresh` is not declared in the `GatewaySessionRow` type in `ui/src/ui/types.ts`. TypeScript will reject this with _"Property 'totalTokensFresh' does not exist on type 'GatewaySessionRow'"_, causing compilation to fail.
The same problem surfaces in the test file at line 341, where `{ totalTokensFresh: false }` is passed as `Partial<GatewaySessionRow>` to the `row()` helper — TypeScript's excess-property check will also reject that.
`GatewaySessionRow` needs `totalTokensFresh?: boolean` added before this code can compile:
```
// ui/src/ui/types.ts (GatewaySessionRow)
inputTokens?: number;
outputTokens?: number;
totalTokens?: number;
+ totalTokensFresh?: boolean;
model?: string;
modelProvider?: string;
contextTokens?: number;
```
How can I resolve this? If you propose a fix, please make it concise.5d54bd3 to
11bb635
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11bb635411
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const total = | ||
| session.totalTokensFresh === false || !Number.isFinite(session.totalTokens) | ||
| ? null | ||
| : (session.totalTokens ?? null); |
There was a problem hiding this comment.
Keep reporting total usage when freshness is unknown
When totalTokensFresh is false we only know the context snapshot is stale, not that token usage is unavailable. persistSessionUsageUpdate still writes inputTokens/outputTokens in that case (src/auto-reply/reply/session-usage.ts:93-105), so providers or runs without lastCallUsage/promptTokens will now make /usage show Total: n/a even though the command can still compute the total-usage line from input + output as before. Hiding the context percentage makes sense here, but dropping the total-usage fallback regresses /usage for sessions that do not emit fresh prompt snapshots.
Useful? React with 👍 / 👎.
d68c0f2 to
57e4411
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57e4411514
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const total = Number.isFinite(session.totalTokens) ? (session.totalTokens ?? null) : null; | ||
| const totalTokensFresh = session.totalTokensFresh !== false; |
There was a problem hiding this comment.
Restore /usage fallback when stale totals are omitted
Fresh evidence: sessions.list strips stale or missing context snapshots before the Control UI sees them—listSessionsFromStore only exposes totalTokens when resolveFreshSessionTotalTokens(entry) succeeds, and src/gateway/session-utils.test.ts:800-838 asserts stale rows arrive as { totalTokens: undefined, totalTokensFresh: false }. In that normal provider path, this change still renders Total: n/a even though inputTokens and outputTokens are present, so /usage regresses for runs without a fresh snapshot. The old input + output fallback is still needed for the total line; only the context percentage should depend on totalTokensFresh.
Useful? React with 👍 / 👎.
57e4411 to
2c72a3f
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c72a3f494
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -302,15 +302,18 @@ async function executeUsage( | |||
| } | |||
| const input = session.inputTokens ?? 0; | |||
| const output = session.outputTokens ?? 0; | |||
| const total = session.totalTokens ?? input + output; | |||
| const total = Number.isFinite(session.totalTokens) ? (session.totalTokens ?? null) : null; | |||
There was a problem hiding this comment.
Keep the
/usage total line on cumulative tokens
session.totalTokens is not the session’s total usage; deriveSessionTotalTokens defines it as the prompt/context snapshot and explicitly excludes completion/output tokens (src/agents/usage.ts:173-180). Reusing it for the Total line means any session with non-zero output now underreports usage—for example, the transcript snapshot exercised in src/gateway/session-utils.fs.test.ts:693-697 has inputTokens: 1200, outputTokens: 300, but totalTokens: 1250, so this command would print Total: 1.25k even though the actual cumulative usage is 1.5k. We still need the old input + output total for the Total line and should reserve totalTokens for the context snapshot/percentage only.
Useful? React with 👍 / 👎.
2c72a3f to
48624b6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48624b6b54
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -1,3 +1,4 @@ | |||
| WARN Unsupported engine: wanted: {"node":">=22.16.0"} (current: {"node":"v20.11.0","pnpm":"10.23.0"}) | |||
There was a problem hiding this comment.
Remove the pnpm warning from the generated schema artifact
src/config/schema.ts:3 imports this file directly, so checking in the raw WARN Unsupported engine... line at the top corrupts the generated module and makes config-schema loads fail before any UI code runs. In practice this breaks any command or test path that imports the schema, because the file is no longer valid TypeScript/ESM source.
Useful? React with 👍 / 👎.
aedee3c to
159182a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 159182a45b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const total = Number.isFinite(session.totalTokens) ? (session.totalTokens ?? null) : null; | ||
| const totalTokensFresh = session.totalTokensFresh !== false; |
There was a problem hiding this comment.
Restore total-usage fallback when snapshot tokens are missing
sessions.list drops totalTokens whenever the prompt snapshot is stale or absent (resolveFreshSessionTotalTokens returns undefined when totalTokensFresh is false in src/config/sessions/types.ts), so this branch now sets total to null and /usage renders Total: n/a even when inputTokens and outputTokens are present. That regresses normal provider paths without a fresh context snapshot by hiding total usage entirely; the total line should still fall back to input + output (optionally marked approximate), while only the context-percentage line depends on fresh snapshot tokens.
Useful? React with 👍 / 👎.
159182a to
27bc496
Compare
27bc496 to
1838d20
Compare
1838d20 to
26e5115
Compare
26e5115 to
389ef43
Compare
2be88c7 to
592312a
Compare
592312a to
303a548
Compare
|
Follow-up complete on this branch:
|
92ff2b5 to
7e07932
Compare
7e07932 to
bceec12
Compare
bceec12 to
b1ec7c2
Compare
|
Closing this as implemented after Codex review. Current What I checked:
So I’m closing this as already implemented rather than keeping a duplicate issue open. Review notes: reviewed against 151befb90b90. |
Summary
Fixes #47885.
The Control UI
/usageslash-command displayed cumulative token counts instead of the current context snapshot, making context usage appear much higher than reality (e.g. 353k/200k at 100% vs TUI showing 95k/200k at 47%).Changes
ui/src/ui/chat/slash-command-executor.ts: Use the latest context-window snapshot (lastContextTokens) instead of the cumulativetotalTokensIn + totalTokensOut. When no snapshot is available, displayn/ainstead of a misleading cumulative figure.ui/src/ui/chat/slash-command-executor.node.test.ts: Added regression tests covering both fresh-snapshot and stale/missing-snapshot scenarios.Verification
PATH=/opt/homebrew/opt/node@22/bin:$PATH npx vitest run --config vitest.node.config.ts src/ui/chat/slash-command-executor.node.test.tsType