Skip to content

feat(dashboard/chat): guide user to a new session on token/context limit (#6211)#6231

Merged
houko merged 4 commits into
mainfrom
feat/6211-token-limit-new-session
Jun 19, 2026
Merged

feat(dashboard/chat): guide user to a new session on token/context limit (#6211)#6231
houko merged 4 commits into
mainfrom
feat/6211-token-limit-new-session

Conversation

@houko

@houko houko commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What this does

Closes #6211 — when a conversation reaches the token / context-window limit, the dashboard now guides the user to start a new session instead of leaving a bare error bubble.

When the most recent agent-chat turn fails with a token / context-window or length / quota limit, the chat view renders an inline guidance banner with a one-click "Start a new session" action.
The action reuses the existing useCreateAgentSession mutation + handleNewSession flow (create session → navigate to it), so there is no new endpoint and no duplicated session-creation logic.

Investigation findings

  • The agent chat lives in crates/librefang-api/dashboard/src/pages/ChatPage.tsx.
    A failed send (HTTP ApiError or a WebSocket error event) is surfaced by attaching the error string to the assistant ChatMessage.error and rendering it as a red bubble — that error string is the only limit signal available on the chat surface in main.
  • There is no structured context-exhaustion signal in main: session types carry context_window_tokens, and models carry context_window, but there is no exceeded / limit_reached / usage-percentage field on the chat path. So a reliable detector has to read the error text rather than a backend flag.
  • useCreateAgentSession({ agentId, label? }) (in src/lib/mutations/agents.ts) already exists and already invalidates agentKeys.sessions / agentKeys.detail / sessionKeys.lists in its onSuccess; handleNewSession in ChatPage.tsx already wires it to a navigate. The banner reuses both as-is.
  • Channels have no conversation/chat surface in the dashboard (ChannelsPage.tsx + lib/queries/channels.ts are config / QR-login / topology only). The issue mentions channel conversations, but there is nothing to attach a banner to there, so this change is honestly scoped to the agent session chat view and that limitation is called out below.

The change (minimal + honest about limits)

  • isContextLimitError(text) — a small, case-insensitive heuristic over the error string, matching the phrases real providers and the kernel use for this class of failure (context window / max tokens / "too long" / "string too long" / quota / rate limit / 429, …).
    It is a frontend heuristic, not a fabricated backend field — a false positive only offers a new session, it never blocks the user.
  • LimitReachedBanner — guidance banner (styled like the existing CompactionSummaryBanner) with the one-click action, gated on the last message so it clears automatically as soon as the user sends again.
  • en / zh / uk locale strings (chat.limit_reached_*). The issue is in Chinese, so the zh copy mirrors the issue's wording.
  • ChatPage.limit.test.ts pins the classifier against real-world provider error strings.

No backend contract was invented. When #6215 (in-flight: context-usage indicator + quota-error classification) lands a structured signal, isContextLimitError can be swapped for it without touching the banner.

Relationship to #6215

#6215 (fix/quota-classify-and-context-usage) is related and possibly overlapping — it adds a context-window usage indicator and quota-error classification.
This PR is based on origin/main and does not depend on or duplicate it; it builds the smallest sensible guidance UI on what exists in main today.
If #6215 lands first, the maintainer can reconcile by feeding its structured signal into isContextLimitError (or replacing the heuristic outright).

Verification

All run from crates/librefang-api/dashboard with pnpm (the project's package manager):

  • pnpm install --frozen-lockfile — PASS (lockfile unchanged).
  • pnpm typecheck (tsc --noEmit) — PASS.
  • pnpm lint (eslint .) — PASS (0 errors; only pre-existing baseline warnings, none in the touched files).
  • pnpm test (vitest) — PASS, 83 files / 825 tests, including the new ChatPage.limit.test.ts and the locale-parity test.
  • pnpm build (vite) — PASS (built in ~0.7s; only the pre-existing chunk-size informational note).

Note: pnpm test:i18n-parity reports 6 pre-existing extra keys in uk.json (*_count_few / *_count_many plural forms for mcp / network / prompts); confirmed present on origin/main and unrelated to this change. The newly added chat.limit_reached_* keys are at full parity across en / zh / uk.

Scope / honest limitation

Closes #6211

Evan and others added 2 commits June 19, 2026 14:23
When the latest agent-chat turn fails with a token / context-window or
length / quota limit, the chat view now renders an inline guidance banner
with a one-click "Start a new session" action that reuses the existing
useCreateAgentSession mutation, instead of leaving only a raw error bubble.

Detection is a frontend heuristic over the daemon / provider error string
(isContextLimitError), because main carries no structured context-exhaustion
signal on the chat surface.
A structured signal can replace it later (related: in-flight #6215).

Scoped to the agent session chat view — channels are config-only surfaces in
the dashboard with no conversation UI.

Adds en/zh/uk locale strings and ChatPage.limit.test.ts.

Closes #6211

@houko houko left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One design concern in CONTEXT_LIMIT_PATTERNS worth the author weighing: "quota", "rate limit", "rate_limit", and "429" are rate-limit / quota signals, not context-exhaustion signals. A rate limit is a transient failure — the right advice is "wait a moment and retry", not "start a new session". Showing the "Start a new session" banner for a 429 response could actively mislead users into thinking their conversation history is the problem when it isn't.

The other patterns (context window, context length, max tokens, too long, etc.) are genuine length/capacity signals where a new session is the correct remedy. Suggest splitting the rate-limit family out — either drop them from this classifier, or handle them with a separate banner copy ("rate limit hit, try again shortly").


Generated by Claude Code

@github-actions github-actions Bot added area/docs Documentation and guides size/M 50-249 lines changed has-conflicts PR has merge conflicts that need resolution no-rust-required This task does not require Rust knowledge labels Jun 19, 2026
…classifier

The #6211 token/context-limit banner keys off the chat surface error string,
which on current main is the output of the kernel's `classify_streaming_error`
(#6215 merged).
Two cases were wrong against that output:

- False negative: the canonical context-overflow message is collapsed to
  "Context is full. Try /compact or /new.", which matched none of the phrase
  list, so the banner missed the exact case it exists for.
  Add "context is full".
- False positive with harmful advice: an internal usage/spending-budget cap is
  reported as "Usage budget reached ... not a full context window — /compact
  will NOT help ...".
  That string contains "context window" (inside a negation) and so fired the
  banner, telling the user to start a new session — which does nothing for a
  persisted budget window.
  Suppress the banner for usage-budget wording.

Add regression cases pinning both behaviours (they fail without the fix) and
refresh the CHANGELOG entry to reflect that #6215 has merged and only adds a
usage indicator, not a per-turn error classification.
@houko

houko commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Adversarial review pass — fixed two correctness bugs in isContextLimitError that surface now that #6215 merged and rewrote the chat-surface error strings via classify_streaming_error.

False negative: the canonical context-overflow message is collapsed to Context is full. Try /compact or /new., which matched none of the phrase list — so the banner missed the exact case it exists for. Added "context is full".

False positive (harmful advice): an internal usage / spending-budget cap is reported as Usage budget reached … not a full context window — /compact will NOT help …. That string contains context window (inside a negation) and fired the banner, telling the user to start a new session, which does nothing for a persisted budget window. Added a usage-budget suppression guard.

Added regression cases pinning both (they fail without the fix; ChatPage.limit.test.ts 14/14). Rebased onto the latest branch tip (4ee5ace) and kept the maintainer comment-trim style.

Verified: typecheck pass, lint 0 errors (85 pre-existing warnings), vitest 827/827, build pass. i18n-parity still reports the 6 pre-existing uk CLDR plural extras — confirmed present on the merge base, not introduced here.

@houko
houko enabled auto-merge (squash) June 19, 2026 07:28
@github-actions github-actions Bot added ready-for-review PR is ready for maintainer review and removed has-conflicts PR has merge conflicts that need resolution labels Jun 19, 2026
@houko
houko merged commit 35c5abc into main Jun 19, 2026
33 checks passed
@houko
houko deleted the feat/6211-token-limit-new-session branch June 19, 2026 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs Documentation and guides no-rust-required This task does not require Rust knowledge ready-for-review PR is ready for maintainer review size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

对话Token达到限制时引导开启新的会话

2 participants