Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions frontend/src/components/ComparisonChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,11 @@ export function ComparisonChart() {
{/* Header Row */}
<div
className="grid border-b border-[hsl(var(--marketing-card-border))]"
style={{
style={{
gridTemplateColumns: "minmax(200px, 1.5fr) repeat(6, minmax(80px, 1fr))"
}}
>
<div className="p-3 font-medium text-foreground bg-[hsl(var(--marketing-card-highlight))]/30 text-sm">

</div>
<div className="p-3 font-medium text-foreground bg-[hsl(var(--marketing-card-highlight))]/30 text-sm"></div>
{products.map((product) => (
<div
key={product.key}
Expand All @@ -197,7 +195,7 @@ export function ComparisonChart() {
className={`grid border-b border-[hsl(var(--marketing-card-border))] ${
index % 2 === 0 ? "bg-[hsl(var(--marketing-card-highlight))]/20" : ""
}`}
style={{
style={{
gridTemplateColumns: "minmax(200px, 1.5fr) repeat(6, minmax(80px, 1fr))"
}}
>
Expand Down
80 changes: 80 additions & 0 deletions frontend/src/components/ContextLimitDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { AlertCircle, MessageCircle } from "lucide-react";

interface ContextLimitDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
currentModel?: string;
hasDocument?: boolean;
}

export function ContextLimitDialog({
open,
onOpenChange,
currentModel,
hasDocument
}: ContextLimitDialogProps) {
const isGemma = currentModel?.includes("gemma");

return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<div className="flex items-center gap-3 mb-2">
<div className="p-2 rounded-lg bg-orange-500/10 text-orange-500">
<AlertCircle className="h-8 w-8" />
</div>
<DialogTitle>Message Too Large</DialogTitle>
</div>
<DialogDescription className="text-base">
Your message exceeds the context limit for the current model.
</DialogDescription>
</DialogHeader>

<div className="space-y-4 py-4">
<div className="space-y-3">
<p className="text-sm font-medium">Here's what you can try:</p>
<ul className="space-y-2 text-sm text-muted-foreground">
<li className="flex items-start gap-2">
<MessageCircle className="h-4 w-4 mt-0.5 shrink-0" />
<span>
<strong>Shorten your message</strong> - Try reducing the amount of text or content
</span>
</li>
{hasDocument && (
<li className="flex items-start gap-2">
<MessageCircle className="h-4 w-4 mt-0.5 shrink-0" />
<span>
<strong>Use a smaller document</strong> - Try uploading a shorter document or
extracting only the relevant sections
</span>
</li>
)}
{isGemma && (
<li className="flex items-start gap-2">
<MessageCircle className="h-4 w-4 mt-0.5 shrink-0" />
<span>
<strong>Switch to a model with more context</strong> - Try DeepSeek R1, Mistral,
or other models that support 128k tokens
</span>
</li>
)}
</ul>
</div>
</div>

<DialogFooter>
<Button onClick={() => onOpenChange(false)}>Got it</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
47 changes: 45 additions & 2 deletions frontend/src/components/UnifiedChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { useLocalState } from "@/state/useLocalState";
import { useOpenSecret } from "@opensecret/react";
import { UpgradePromptDialog } from "@/components/UpgradePromptDialog";
import { DocumentPlatformDialog } from "@/components/DocumentPlatformDialog";
import { ContextLimitDialog } from "@/components/ContextLimitDialog";
import { RecordingOverlay } from "@/components/RecordingOverlay";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { AlertCircle } from "lucide-react";
Expand Down Expand Up @@ -351,6 +352,7 @@ export function UnifiedChat() {
"image" | "document" | "voice" | "usage" | "tokens"
>("image");
const [documentPlatformDialogOpen, setDocumentPlatformDialogOpen] = useState(false);
const [contextLimitDialogOpen, setContextLimitDialogOpen] = useState(false);

// Audio recording states
const [isRecording, setIsRecording] = useState(false);
Expand Down Expand Up @@ -1525,16 +1527,49 @@ export function UnifiedChat() {
console.error("Failed to send message:", error);

// Handle usage limit errors with upsell dialogs
// The SDK throws errors with the message "Request failed with status 403: {json}"
// The SDK throws errors with the message "Request failed with status 403: {json}" or "Request failed with status 413: {json}"
// We need to parse this to extract the actual error details
let errorMessage = error instanceof Error ? error.message : "Something went wrong";

// Also check the cause property if it exists
const causeMessage = (error as Error & { cause?: { message?: string } })?.cause?.message;
if (causeMessage && causeMessage.includes("Request failed with status 403:")) {
if (causeMessage && causeMessage.includes("Request failed with status")) {
errorMessage = causeMessage;
}

// Check for 413 error (Message exceeds context limit)
let status413Error: { status: number; message: string } | null = null;
if (errorMessage.includes("Request failed with status 413:")) {
try {
// Extract the JSON part from the error message
const jsonMatch = errorMessage.match(/Request failed with status 413:\s*({.*})/);
if (jsonMatch && jsonMatch[1]) {
status413Error = JSON.parse(jsonMatch[1]);
}
} catch (parseError) {
console.error("Failed to parse 413 error:", parseError);
}
}

if (status413Error && status413Error.message === "Message exceeds context limit") {
// Remove the user message from history and restore input
setMessages((prev) => prev.filter((msg) => msg.id !== localMessageId));

// Restore the original input and attachments
if (!overrideInput) {
setInput(originalInput);
setDraftImages(originalImages);
setImageUrls(originalImageUrls);
setDocumentText(originalDocumentText);
setDocumentName(originalDocumentName);
}

Comment thread
AnthonyRonning marked this conversation as resolved.
// Show the context limit dialog
setContextLimitDialogOpen(true);
setError("Your message exceeds the context limit for this model.");
return; // Exit early, don't continue to other error handling
}
Comment thread
AnthonyRonning marked this conversation as resolved.

let status403Error: { status: number; message: string } | null = null;

// Check if this is a 403 error from the SDK
Expand Down Expand Up @@ -2235,6 +2270,14 @@ export function UnifiedChat() {
hasProAccess={canUseDocuments || false}
/>

{/* Context limit dialog for 413 errors */}
<ContextLimitDialog
open={contextLimitDialogOpen}
onOpenChange={setContextLimitDialogOpen}
currentModel={localState.model}
hasDocument={!!documentName}
/>

{/* Hidden file inputs - must be outside conditional rendering to work in both views */}
<input
type="file"
Expand Down
Loading