Skip to content

fix(chat): refresh context ring after /compact - #2091

Open
xiaozou-second wants to merge 3 commits into
TencentCloud:developfrom
xiaozou-second:fix/context-ring-after-compact
Open

xiaozou-second wants to merge 3 commits into
TencentCloud:developfrom
xiaozou-second:fix/context-ring-after-compact

Conversation

@xiaozou-second

@xiaozou-second xiaozou-second commented Oct 15, 2026 •

Copy link
Copy Markdown

Summary

Fixes the context-window ring staying at 100% after /compact.

/compact shrinks the thread server-side without a model call, so the stream hint (usedTokens) never drops on its own — and the ring preferred that hint whenever it was non-zero. Now:

  • Each snapshot records the hint it was fetched against, and is authoritative only while the hint hasn't moved
  • Snapshots carry a request sequence number, so a slow response can't overwrite a newer one; thread switches invalidate in-flight requests
  • The ring refetches on the isStreaming true→false edge, and drops the cached snapshot if that refetch fails
  • ChatInputActionsRow forwards isStreaming (new optional prop, defaults to false)

Target branch

  • Base is develop

Type of change

  • Bug fix

Test plan

  • Added tests in dashboard/src/pages/Chat/components/ContextWindowRing.test.tsx:
    • drops to the snapshot when a turn ends with less context
    • a newer hint wins again after the snapshot
    • an older snapshot doesn't overwrite a newer one
    • refetches after a failed post-compaction refetch
  • make all passes locally
make all                                         # ruff / prettier / mypy clean
                                                 # pytest: 4602 passed, 210 skipped

Frontend — 17 passed, tsc and eslint clean:

vitest, tsc and eslint passing

cd dashboard
npx vitest run src/pages/Chat/components/ContextWindowRing.test.tsx \
               src/pages/Chat/components/ChatInputActionsRow.test.tsx --reporter=verbose
npx tsc --noEmit
npx eslint src/pages/Chat/components/ContextWindowRing.tsx \
           src/pages/Chat/components/ContextWindowRing.test.tsx \
           src/pages/Chat/components/ChatInputActionsRow.tsx

Checklist

  • Updated CHANGELOG.md
  • README / docs updated (not needed)

Issue

Closes #2071

/compact shrinks the thread server-side without a model call, so the
stream hint never drops on its own and the ring stayed at its
pre-compaction percentage.

- Record the hint each snapshot was fetched against; the snapshot is
  authoritative only while the hint has not moved.
- Sequence snapshots so a slow response cannot overwrite a newer one,
  and invalidate in-flight requests on thread switch.
- Refetch on the isStreaming true->false edge, dropping the cached
  snapshot if that refetch fails.
- Forward isStreaming from ChatInputActionsRow.
The ring memo read breakdownHintRef.current but only depended on
[breakdown, hintUsed, max]. Refs do not trigger recomputation, so after
a failed post-compaction refetch -- the one path that clears the hint
without touching state -- the memo kept serving the pre-compaction
value until something else re-rendered.

Hold the hint in state so the memo's inputs are complete, and make
isStreaming required so a future host that forgets it fails tsc
instead of silently never refetching.
@xiaozou-second

xiaozou-second commented Oct 16, 2026 •

Copy link
Copy Markdown
Author
86544fbe351641cac6ca24dc7783e99e 18afbd9235294c488cda423aafc52a8e

Resolve both-added prop conflicts in ChatInputActionsRow.tsx and
ContextWindowRing.tsx by keeping mine (isStreaming) and upstream's
(decisionSaved) side by side. Keep the hintMoved cache guard from
upstream alongside the local force alias.

Verified: vitest ContextWindowRing + ChatInputActionsRow 17 passed;
tsc --noEmit exit 0.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant