When an assistant message sits status='streaming' with no token activity for 60+ seconds, the chat shows a banner above the input offering Retry or Discard. Both clear the stale row via a new backend endpoint POST /api/chats/:id/discard_stale that updates status='failed' and publishes chat_status='idle'. Closes the UX gap that caused the 2026-05-21 debugging spiral — slow streams and dead streams now look different to the user. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
35 lines
1.2 KiB
TypeScript
35 lines
1.2 KiB
TypeScript
interface Props {
|
|
onRetry: () => void;
|
|
onDiscard: () => void;
|
|
}
|
|
|
|
// v1.12.3: shown when an assistant message has been 'streaming' for 60+
|
|
// seconds without new tokens. Lives above ChatInput in ChatPane. Retry
|
|
// discards the stuck row then resends the last user message; Discard just
|
|
// clears the row and drops the dot to idle.
|
|
export function StaleStreamBanner({ onRetry, onDiscard }: Props) {
|
|
return (
|
|
<div className="border border-amber-500/30 bg-amber-500/5 rounded-md p-3 mb-2 mx-4 flex items-center justify-between gap-2">
|
|
<span className="text-sm text-muted-foreground">
|
|
Previous response didn't complete.
|
|
</span>
|
|
<div className="flex gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={onRetry}
|
|
className="text-xs px-2 py-1 rounded border border-border hover:bg-accent max-md:min-h-[44px] max-md:px-3"
|
|
>
|
|
Retry
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={onDiscard}
|
|
className="text-xs px-2 py-1 rounded border border-border hover:bg-accent max-md:min-h-[44px] max-md:px-3"
|
|
>
|
|
Discard
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|