feat(dashboard/chat): guide user to a new session on token/context limit (#6211)#6231
Conversation
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
…ssue refs from source
houko
left a comment
There was a problem hiding this comment.
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
…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.
|
Adversarial review pass — fixed two correctness bugs in False negative: the canonical context-overflow message is collapsed to False positive (harmful advice): an internal usage / spending-budget cap is reported as Added regression cases pinning both (they fail without the fix; Verified: typecheck pass, lint 0 errors (85 pre-existing warnings), vitest 827/827, build pass. i18n-parity still reports the 6 pre-existing |
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
useCreateAgentSessionmutation +handleNewSessionflow (create session → navigate to it), so there is no new endpoint and no duplicated session-creation logic.Investigation findings
crates/librefang-api/dashboard/src/pages/ChatPage.tsx.A failed send (HTTP
ApiErroror a WebSocketerrorevent) is surfaced by attaching the error string to the assistantChatMessage.errorand rendering it as a red bubble — that error string is the only limit signal available on the chat surface inmain.main: session types carrycontext_window_tokens, and models carrycontext_window, but there is noexceeded/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? })(insrc/lib/mutations/agents.ts) already exists and already invalidatesagentKeys.sessions/agentKeys.detail/sessionKeys.listsin itsonSuccess;handleNewSessioninChatPage.tsxalready wires it to a navigate. The banner reuses both as-is.ChannelsPage.tsx+lib/queries/channels.tsare 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 existingCompactionSummaryBanner) with the one-click action, gated on the last message so it clears automatically as soon as the user sends again.chat.limit_reached_*). The issue is in Chinese, so the zh copy mirrors the issue's wording.ChatPage.limit.test.tspins 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,
isContextLimitErrorcan 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/mainand does not depend on or duplicate it; it builds the smallest sensible guidance UI on what exists inmaintoday.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/dashboardwithpnpm(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 newChatPage.limit.test.tsand the locale-parity test.pnpm build(vite) — PASS (built in ~0.7s; only the pre-existing chunk-size informational note).Note:
pnpm test:i18n-parityreports 6 pre-existing extra keys inuk.json(*_count_few/*_count_manyplural forms for mcp / network / prompts); confirmed present onorigin/mainand unrelated to this change. The newly addedchat.limit_reached_*keys are at full parity across en / zh / uk.Scope / honest limitation
mainexposes no structured context-exhaustion signal on the chat path (see feat(api): context-window usage indicator + honest quota-error classification #6215).Closes #6211