Align context usage display, refresh chat after compaction#66485
Align context usage display, refresh chat after compaction#664850riginal-claw wants to merge 1 commit intoopenclaw:mainfrom
Conversation
0riginal-claw
commented
Apr 14, 2026
- /status context % now uses canonical totalTokens when fresh (matches chat context notice)\n- Refresh chat history on compaction completion to reflect compacted transcript and cleared token counters\n\nFixes Context usage mismatch causes false 'context full' warnings; stale inputTokens after compaction #66483
…tion\n\n- /status percent now uses canonical totalTokens when fresh, matching chat context notice\n- Refresh chat history on compaction completion to clear stale pre-compaction tokens in UI\n\nFixes openclaw#66483
Greptile SummaryThis PR fixes two related display issues: the One minor inconsistency remains: the new Confidence Score: 5/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: 384-387
Comment:
**`totalTokensFresh === true` is stricter than `renderContextNotice`**
`renderContextNotice` (in `views/chat.ts:533`) hides only when `totalTokensFresh === false`; it still renders the bar when the flag is `undefined`. The new guard here requires `totalTokensFresh === true`, so when the field is absent (e.g. older session rows) `/status` silently drops the context line while the chat view still shows it. Using `!== false` would produce behaviour that actually matches the notice.
```suggestion
const pct =
(session.totalTokensFresh !== false && typeof session.totalTokens === "number" && ctx > 0)
? Math.round(Math.min((session.totalTokens / ctx) * 100, 100))
: null;
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: ui/src/ui/app-gateway.ts
Line: 445-457
Comment:
**`try/catch { // ignore }` is redundant here**
Every synchronous access inside the block is already guarded by optional chaining and explicit type-checks, so none of these lines can throw. The `void loadChatHistory(...)` call discards the promise, so any async rejection is already swallowed independently of the surrounding `try`. The catch block is dead code and the blanket suppression adds noise without protecting anything.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "UI: align context usage display with bac..." | Re-trigger Greptile |
| const pct = | ||
| (session.totalTokensFresh === true && typeof session.totalTokens === "number" && ctx > 0) | ||
| ? Math.round(Math.min((session.totalTokens / ctx) * 100, 100)) | ||
| : null; |
There was a problem hiding this comment.
totalTokensFresh === true is stricter than renderContextNotice
renderContextNotice (in views/chat.ts:533) hides only when totalTokensFresh === false; it still renders the bar when the flag is undefined. The new guard here requires totalTokensFresh === true, so when the field is absent (e.g. older session rows) /status silently drops the context line while the chat view still shows it. Using !== false would produce behaviour that actually matches the notice.
| const pct = | |
| (session.totalTokensFresh === true && typeof session.totalTokens === "number" && ctx > 0) | |
| ? Math.round(Math.min((session.totalTokens / ctx) * 100, 100)) | |
| : null; | |
| const pct = | |
| (session.totalTokensFresh !== false && typeof session.totalTokens === "number" && ctx > 0) | |
| ? Math.round(Math.min((session.totalTokens / ctx) * 100, 100)) | |
| : null; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/chat/slash-command-executor.ts
Line: 384-387
Comment:
**`totalTokensFresh === true` is stricter than `renderContextNotice`**
`renderContextNotice` (in `views/chat.ts:533`) hides only when `totalTokensFresh === false`; it still renders the bar when the flag is `undefined`. The new guard here requires `totalTokensFresh === true`, so when the field is absent (e.g. older session rows) `/status` silently drops the context line while the chat view still shows it. Using `!== false` would produce behaviour that actually matches the notice.
```suggestion
const pct =
(session.totalTokensFresh !== false && typeof session.totalTokens === "number" && ctx > 0)
? Math.round(Math.min((session.totalTokens / ctx) * 100, 100))
: null;
```
How can I resolve this? If you propose a fix, please make it concise.| try { | ||
| const data = (payload?.data ?? {}) as Record<string, unknown>; | ||
| const phase = typeof data.phase === "string" ? data.phase : ""; | ||
| const completed = data.completed === true; | ||
| const sessionKey = typeof payload?.sessionKey === "string" ? payload.sessionKey : undefined; | ||
| if (payload?.stream === "compaction" && phase === "end" && completed) { | ||
| if (!sessionKey || sessionKey === host.sessionKey) { | ||
| void loadChatHistory(host as unknown as ChatState); | ||
| } | ||
| } | ||
| } catch { | ||
| // ignore | ||
| } |
There was a problem hiding this comment.
try/catch { // ignore } is redundant here
Every synchronous access inside the block is already guarded by optional chaining and explicit type-checks, so none of these lines can throw. The void loadChatHistory(...) call discards the promise, so any async rejection is already swallowed independently of the surrounding try. The catch block is dead code and the blanket suppression adds noise without protecting anything.
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/app-gateway.ts
Line: 445-457
Comment:
**`try/catch { // ignore }` is redundant here**
Every synchronous access inside the block is already guarded by optional chaining and explicit type-checks, so none of these lines can throw. The `void loadChatHistory(...)` call discards the promise, so any async rejection is already swallowed independently of the surrounding `try`. The catch block is dead code and the blanket suppression adds noise without protecting anything.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9652519c38
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| (session.totalTokensFresh === true && typeof session.totalTokens === "number" && ctx > 0) | ||
| ? Math.round(Math.min((session.totalTokens / ctx) * 100, 100)) |
There was a problem hiding this comment.
Handle undefined totalTokensFresh as fresh in /usage
The new guard requires totalTokensFresh === true before showing context usage, but this codebase treats only an explicit false as stale (for example, resolveFreshSessionTotalTokens and chat context rendering both accept missing freshness as usable). With this change, sessions that have valid totalTokens but omit totalTokensFresh (older gateway payloads or compatibility-shaped rows) lose the context percentage line entirely, which regresses /usage output even when the data is otherwise fresh enough to display.
Useful? React with 👍 / 👎.
| if (!sessionKey || sessionKey === host.sessionKey) { | ||
| void loadChatHistory(host as unknown as ChatState); |
There was a problem hiding this comment.
Ignore sessionless compaction events from unrelated runs
This condition reloads chat history whenever a compaction-end event has no sessionKey, which means an unrelated sessionless compaction event can trigger loadChatHistory for the currently open chat. Because loadChatHistory clears streaming/tool state, that can interrupt an active conversation in the visible session even though the compaction belonged to another run.
Useful? React with 👍 / 👎.
|
Codex review: needs changes before merge. What this changes: The PR changes Control UI Required change before merge: This is a narrow Control UI repair with concrete failing review findings, clear files, and targeted validation; it does not require product or security approval first. Security review: Security review cleared: The PR only changes Control UI event handling and slash-command display code; it adds no dependencies, scripts, workflows, permissions, package-resolution changes, or secret-handling paths. Review findings:
Review detailsBest possible solution: Preserve current main’s Do we have a high-confidence way to reproduce the issue? Yes. A static event-path reproduction is clear: a session row with valid Is this the best way to solve the issue? No. The direction is useful, but the implementation should keep the shipped Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against a256745323ab. |