In this article, we review a component BillingErrorAlert in Suna codebase. Suna is an open source generalist AI agent. We will look at:
Where this BillingErroAlert component is used?
BillingErrorAlert component
Where this BillingErrorAlert component is used?
This component is called at the end of the [threadId]/page.tsx component in the function, ThreadPage.
{/* Billing Alert for usage limit */} <BillingErrorAlert message={billingData.message} currentUsage={billingData.currentUsage} limit={billingData.limit} accountId={billingData.accountId} onDismiss={() => setShowBillingAlert(false)} isOpen={showBillingAlert} /> BillingErrorAlert component
Below code is picked from components/billing/usage-limit-alert.tsx
'use client'; import { AlertTriangle } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useRouter } from "next/navigation"; interface BillingErrorAlertProps { message?: string; currentUsage?: number; limit?: number; accountId?: string | null; onDismiss: () => void; isOpen: boolean; } export function BillingErrorAlert({ message, currentUsage, limit, accountId, onDismiss, isOpen }: BillingErrorAlertProps) { const router = useRouter(); if (!isOpen) return null; return ( <div className="fixed bottom-4 right-4 z-50"> <div className="bg-destructive/10 border border-destructive/20 rounded-lg p-4 shadow-lg max-w-md"> <div className="flex items-start gap-3"> <div className="flex-shrink-0"> <AlertTriangle className="h-5 w-5 text-destructive" /> </div> <div className="flex-1"> <h3 className="text-sm font-medium text-destructive mb-1">Usage Limit Reached</h3> <p className="text-sm text-muted-foreground mb-3">{message}</p> <div className="flex gap-2"> <Button variant="outline" size="sm" onClick={onDismiss} className="text-xs" > Dismiss </Button> <Button size="sm" onClick={() => router.push(`/settings/billing?accountId=${accountId}`)} className="text-xs" > Upgrade Plan </Button> </div> </div> </div> </div> </div> ); } setShowBillingAlert
This function decides if this BillingAlert should be rendered because of this check below in usage-limit-alert.tsx.
export function BillingErrorAlert({ message, currentUsage, limit, accountId, onDismiss, isOpen }: BillingErrorAlertProps) { const router = useRouter(); if (!isOpen) return null; isOpen prop is passed from file-viewer-modal
isOpen={showBillingAlert} From L618 to L634, you will see the below code snippet in [threadId]/page.tsx.
// Check if it's our custom BillingError (402) if (error instanceof BillingError) { console.log("Caught BillingError:", error.detail); // Extract billing details setBillingData({ // Note: currentUsage and limit might not be in the detail from the backend yet currentUsage: error.detail.currentUsage as number | undefined, limit: error.detail.limit as number | undefined, message: error.detail.message || 'Monthly usage limit reached. Please upgrade.', // Use message from error detail accountId: project?.account_id || null // Pass account ID }); setShowBillingAlert(true); // Remove the optimistic message since the agent couldn't start setMessages(prev => prev.filter(m => m.message_id !== optimisticUserMessage.message_id)); return; // Stop further execution in this case } About me:
Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.
Want me to review your codebase architecture? book a meeting — https://thinkthroo.com/consultation/codebase-architecture-review
Business enquiries — ramu@thinkthroo.com
My Github — https://github.com/ramu-narasinga
My website — https://ramunarasinga.com
My YouTube channel — https://www.youtube.com/@ramu-narasinga
Learning platform — https://thinkthroo.com
Codebase Architecture — https://app.thinkthroo.com/architecture
Best practices — https://app.thinkthroo.com/best-practices
Production-grade projects — https://app.thinkthroo.com/production-grade-projects


Top comments (0)