#21932: fix(tui): eliminate stale model indicator lag in TUI
size: S
Cluster:
Session Management Enhancements
## Summary
Fixes a TUI state race where `/model` updates could briefly revert in the footer indicator when an older `sessions.list` snapshot arrived after a successful patch.
## Expected vs Actual
- Expected: after `/model <value>`, the footer model indicator updates immediately and stays on the selected model.
- Actual: the footer could jump back to the previous model for 1-2 commands before catching up.
## Impact
- Prevents misleading model state in the TUI footer.
- Reduces operator confusion when quickly switching models during active sessions.
## Reproduction
1. Open `openclaw tui`.
2. Run `/model <new-model>` (for example a provider/model alias).
3. Observe footer model label right after command completion.
4. Before this fix, a stale refresh could revert the label temporarily.
## Issues
| ID | Issue | Severity | Status |
| --- | --- | --- | --- |
| PR-21932-BUG-01 | #21255 | medium | fixed |
## Fix Approach
- Track which session key last applied session info in `tui-session-actions`.
- Ignore older (`updatedAt`) refresh rows when they belong to the same session key as the most recent applied update.
- Keep cross-session behavior intact so switching to another session key still applies that session's data, even with older timestamps.
- Add regression tests for:
- stale same-session refresh not overriding a freshly patched model,
- session-key switch still applying the target session model.
## Testing Results
- `pnpm test src/tui/tui-session-actions.test.ts`
- Passed (`3 tests`)
- `pnpm exec oxfmt --check src/tui/tui-session-actions.ts src/tui/tui-session-actions.test.ts`
- Passed
- `pnpm tsgo`
- Passed
- `pnpm lint`
- Passed
## Notes
- Full `pnpm check` currently stops on a pre-existing formatting issue in `docs/style.css` unrelated to this change.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a race condition in the TUI where stale session refresh data could temporarily override freshly applied model changes. The fix introduces session-key tracking to distinguish between stale updates for the same session (which should be ignored) and updates for different sessions (which should always apply).
**Key changes:**
- Added `lastAppliedSessionKey` tracking variable to remember which session was last updated
- Modified `applySessionInfo` to accept a `sessionKey` parameter and compare it against the last applied session
- Stale updates (older `updatedAt` timestamps) are now ignored only when they belong to the same session as the most recent update
- Cross-session updates still apply regardless of timestamp to ensure switching sessions works correctly
- Removed the old `defaultsChanged` and `modelChanged` workarounds which were less precise
**Test coverage:**
- Added regression test confirming stale refresh data doesn't override a fresh model patch for the same session
- Added test confirming older timestamps are still applied when switching to a different session key
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with no identified risks
- The implementation is well-designed and solves the race condition cleanly. The logic is straightforward: track the last applied session key and ignore stale updates only when they're for the same session. The tests comprehensively cover both the fix scenario and the edge case of session switching. The removal of the old `defaultsChanged` and `modelChanged` checks simplifies the logic without losing functionality since `force: true` is used for intentional updates. All call sites have been properly updated to pass the new sessionKey parameter.
- No files require special attention
<sub>Last reviewed commit: 0944485</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#6750: fix(tui): show session model overrides in status bar
by ewijaya · 2026-02-02
87.0%
#21791: feat(TUI): show main agent model in status footer
by chansuke · 2026-02-20
84.4%
#8083: fix(tui): update model status immediately after /model command
by rohanjangala · 2026-02-03
84.0%
#11109: fix(tui): prefer config contextTokens over persisted session value
by marezgui · 2026-02-07
82.4%
#21615: fix(tui): preserve main session model during heartbeat model override
by lailoo · 2026-02-20
82.0%
#16478: fix(gateway): fall back to lookupContextTokens on model switch
by colddonkey · 2026-02-14
81.0%
#19087: fix(sessions): sync display fields on model switch
by Suksham-sharma · 2026-02-17
80.7%
#7794: fix(tui): refresh session info periodically to reflect config changes
by GuoxiangZu · 2026-02-03
79.9%
#16609: fix: resolve session store race condition and contextTokens updates
by battman21 · 2026-02-14
79.8%
#21847: fix(session): /new and /reset no longer carry over model overrides
by hydro13 · 2026-02-20
79.1%