Upgrade for better performance
diff --git a/frontend/src/components/thread/chat-input/token-usage-display.tsx b/frontend/src/components/thread/chat-input/token-usage-display.tsx
new file mode 100644
index 00000000..227c7c2e
--- /dev/null
+++ b/frontend/src/components/thread/chat-input/token-usage-display.tsx
@@ -0,0 +1,143 @@
+import React, { useState } from 'react';
+import { ChevronDown, ChevronUp, Zap, CreditCard } from 'lucide-react';
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+import { SubscriptionStatus } from '@/lib/api';
+import { isLocalMode } from '@/lib/config';
+
+interface TokenUsageDisplayProps {
+ subscriptionData?: SubscriptionStatus | null;
+ onUpgradeClick: () => void;
+ showUsageDisplay?: boolean;
+ className?: string;
+}
+
+export const TokenUsageDisplay: React.FC = ({
+ subscriptionData,
+ onUpgradeClick,
+ showUsageDisplay = true,
+ className = '',
+}) => {
+ const [isExpanded, setIsExpanded] = useState(false);
+
+ // Don't show in local mode
+ if (isLocalMode() || !showUsageDisplay) {
+ return null;
+ }
+
+ // Only show for users with limited usage (free tier or active subscriptions with limits)
+ const shouldShow = subscriptionData && (
+ subscriptionData.status === 'no_subscription' ||
+ (subscriptionData.cost_limit && subscriptionData.cost_limit > 0)
+ );
+
+ if (!shouldShow) {
+ return null;
+ }
+
+ const currentUsage = subscriptionData.current_usage || 0;
+ const costLimit = subscriptionData.cost_limit || 0;
+ const remaining = Math.max(0, costLimit - currentUsage);
+ const usagePercentage = costLimit > 0 ? (currentUsage / costLimit) * 100 : 0;
+
+ const isNearLimit = usagePercentage > 80;
+ const isAtLimit = remaining <= 0;
+
+ const getStatusColor = () => {
+ if (isAtLimit) return 'text-red-500';
+ if (isNearLimit) return 'text-amber-500';
+ return 'text-muted-foreground';
+ };
+
+ const getProgressColor = () => {
+ if (isAtLimit) return 'bg-red-500';
+ if (isNearLimit) return 'bg-amber-500';
+ return 'bg-primary';
+ };
+
+ return (
+
+ {/* Compact Display */}
+
setIsExpanded(!isExpanded)}
+ >
+
+
+
+ ${remaining.toFixed(2)} left
+
+ {subscriptionData.status === 'no_subscription' && (
+
+ Free
+
+ )}
+
+
+
+
+
+ {isExpanded ? (
+
+ ) : (
+
+ )}
+
+
+
+ {/* Expanded Details */}
+ {isExpanded && (
+
+
+ {/* Usage Bar */}
+
+
+ Monthly Usage
+ {usagePercentage.toFixed(1)}%
+
+
+
+
+ {/* Detailed Stats */}
+
+
+ Used: ${currentUsage.toFixed(2)} / ${costLimit.toFixed(2)}
+
+
+ {subscriptionData.plan_name || 'Free Plan'}
+
+
+
+ {isAtLimit && (
+
+ ⚠️ Monthly limit reached. Upgrade to continue using Suna.
+
+ )}
+
+
+ )}
+
+ );
+};
\ No newline at end of file