Bumped tool limit and updated alerts (#2274)

This commit is contained in:
Zane
2025-04-21 18:25:39 -07:00
committed by GitHub
parent 80feb6da60
commit cb72617d5e
4 changed files with 54 additions and 36 deletions

View File

@@ -6,6 +6,7 @@ export enum AlertType {
export interface Alert { export interface Alert {
type: AlertType; type: AlertType;
message: string; message: string;
autoShow?: boolean;
action?: { action?: {
text: string; text: string;
onClick: () => void; onClick: () => void;

View File

@@ -1,13 +1,19 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import { Alert, AlertType } from './types'; import { Alert, AlertType } from './types';
interface AlertOptions {
type: AlertType;
message: string;
action?: {
text: string;
onClick: () => void;
};
autoShow?: boolean;
}
interface UseAlerts { interface UseAlerts {
alerts: Alert[]; alerts: Alert[];
addAlert: ( addAlert: (options: AlertOptions) => void;
type: AlertType,
message: string,
action?: { text: string; onClick: () => void }
) => void;
removeAlert: (index: number) => void; removeAlert: (index: number) => void;
clearAlerts: () => void; clearAlerts: () => void;
} }
@@ -15,12 +21,9 @@ interface UseAlerts {
export const useAlerts = (): UseAlerts => { export const useAlerts = (): UseAlerts => {
const [alerts, setAlerts] = useState<Alert[]>([]); const [alerts, setAlerts] = useState<Alert[]>([]);
const addAlert = useCallback( const addAlert = useCallback((options: AlertOptions) => {
(type: AlertType, message: string, action?: { text: string; onClick: () => void }) => { setAlerts((prev) => [...prev, options]);
setAlerts((prev) => [...prev, { type, message, action }]); }, []);
},
[]
);
const removeAlert = useCallback((index: number) => { const removeAlert = useCallback((index: number) => {
setAlerts((prev) => prev.filter((_, i) => i !== index)); setAlerts((prev) => prev.filter((_, i) => i !== index));

View File

@@ -11,11 +11,11 @@ import { settingsV2Enabled } from '../../flags';
import { BottomMenuModeSelection } from './BottomMenuModeSelection'; import { BottomMenuModeSelection } from './BottomMenuModeSelection';
import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar'; import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar';
import { useConfig } from '../ConfigContext'; import { useConfig } from '../ConfigContext';
import { getCurrentModelAndProvider } from '../settings_v2/models/index'; import { getCurrentModelAndProvider } from '../settings_v2/models';
const TOKEN_LIMIT_DEFAULT = 128000; // fallback for custom models that the backend doesn't know about const TOKEN_LIMIT_DEFAULT = 128000; // fallback for custom models that the backend doesn't know about
const TOKEN_WARNING_THRESHOLD = 0.8; // warning shows at 80% of the token limit const TOKEN_WARNING_THRESHOLD = 0.8; // warning shows at 80% of the token limit
const TOOLS_MAX_SUGGESTED = 25; // max number of tools before we show a warning const TOOLS_MAX_SUGGESTED = 60; // max number of tools before we show a warning
export default function BottomMenu({ export default function BottomMenu({
hasMessages, hasMessages,
@@ -73,28 +73,31 @@ export default function BottomMenu({
// Add token alerts if we have a token limit // Add token alerts if we have a token limit
if (tokenLimit && numTokens > 0) { if (tokenLimit && numTokens > 0) {
if (numTokens >= tokenLimit) { if (numTokens >= tokenLimit) {
addAlert( addAlert({
AlertType.Error, type: AlertType.Error,
`Token limit reached (${numTokens.toLocaleString()}/${tokenLimit.toLocaleString()})` message: `Token limit reached (${numTokens.toLocaleString()}/${tokenLimit.toLocaleString()}) \n Youve reached the models conversation limit. The session will be saved — copy anything important and start a new one to continue.`,
); autoShow: true, // Auto-show token limit errors
});
} else if (numTokens >= tokenLimit * TOKEN_WARNING_THRESHOLD) { } else if (numTokens >= tokenLimit * TOKEN_WARNING_THRESHOLD) {
addAlert( addAlert({
AlertType.Warning, type: AlertType.Warning,
`Approaching token limit (${numTokens.toLocaleString()}/${tokenLimit.toLocaleString()})` message: `Approaching token limit (${numTokens.toLocaleString()}/${tokenLimit.toLocaleString()}) \n Youre reaching the models conversation limit. The session will be saved — copy anything important and start a new one to continue.`,
); autoShow: true, // Auto-show token limit warnings
});
} }
} }
// Add tool count alert if we have the data // Add tool count alert if we have the data
if (toolCount !== null && toolCount > TOOLS_MAX_SUGGESTED) { if (toolCount !== null && toolCount > TOOLS_MAX_SUGGESTED) {
addAlert( addAlert({
AlertType.Warning, type: AlertType.Warning,
`Too many tools can degrade performance.\nTool count: ${toolCount} (recommend: ${TOOLS_MAX_SUGGESTED})`, message: `Too many tools can degrade performance.\nTool count: ${toolCount} (recommend: ${TOOLS_MAX_SUGGESTED})`,
{ action: {
text: 'View extensions', text: 'View extensions',
onClick: () => setView('settings'), onClick: () => setView('settings'),
} },
); autoShow: false, // Don't auto-show tool count warnings
});
} }
// We intentionally omit setView as it shouldn't trigger a re-render of alerts // We intentionally omit setView as it shouldn't trigger a re-render of alerts
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps

View File

@@ -1,5 +1,6 @@
import React, { useRef, useEffect, useCallback } from 'react'; import React, { useRef, useEffect, useCallback } from 'react';
import { IoIosCloseCircle, IoIosWarning } from 'react-icons/io'; import { FaCircle } from 'react-icons/fa';
import { IoIosCloseCircle } from 'react-icons/io';
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'; import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
import { cn } from '../../utils'; import { cn } from '../../utils';
import { Alert, AlertType } from '../alerts'; import { Alert, AlertType } from '../alerts';
@@ -37,16 +38,21 @@ export default function BottomMenuAlertPopover({ alerts }: AlertPopoverProps) {
useEffect(() => { useEffect(() => {
if (alerts.length === 0) return; if (alerts.length === 0) return;
// Compare current and previous alerts for any changes // Find new or changed alerts
const hasChanges = alerts.some((alert, index) => { const changedAlerts = alerts.filter((alert, index) => {
const prevAlert = previousAlertsRef.current[index]; const prevAlert = previousAlertsRef.current[index];
return !prevAlert || prevAlert.type !== alert.type || prevAlert.message !== alert.message; return !prevAlert || prevAlert.type !== alert.type || prevAlert.message !== alert.message;
}); });
previousAlertsRef.current = alerts; previousAlertsRef.current = alerts;
// Auto show the popover if there are new alerts // Only auto-show if any of the new/changed alerts have autoShow: true
if (!hasShownInitial || hasChanges) { const hasNewAutoShowAlert = changedAlerts.some((alert) => alert.autoShow === true);
// Auto show the popover only if:
// 1. There are new alerts that should auto-show AND
// 2. We haven't shown this specific alert before (tracked by hasShownInitial)
if (hasNewAutoShowAlert && !hasShownInitial) {
setIsOpen(true); setIsOpen(true);
setHasShownInitial(true); setHasShownInitial(true);
setWasAutoShown(true); setWasAutoShown(true);
@@ -83,18 +89,23 @@ export default function BottomMenuAlertPopover({ alerts }: AlertPopoverProps) {
if (alerts.length === 0) return null; if (alerts.length === 0) return null;
// Determine the icon to show based on the highest priority alert // Determine the icon and styling based on the alerts
const hasError = alerts.some((alert) => alert.type === AlertType.Error); const hasError = alerts.some((alert) => alert.type === AlertType.Error);
const TriggerIcon = hasError ? IoIosCloseCircle : IoIosWarning; const TriggerIcon = hasError ? IoIosCloseCircle : FaCircle;
const triggerColor = hasError ? 'text-[#d7040e]' : 'text-[#cc4b03]'; const triggerColor = hasError ? 'text-[#d7040e]' : 'text-[#cc4b03]';
// Different styling for error icon vs notification dot
const iconStyles = hasError
? 'h-5 w-5' // Keep error icon larger
: 'h-2.5 w-2.5'; // Smaller notification dot
return ( return (
<div ref={popoverRef}> <div ref={popoverRef}>
<Popover open={isOpen}> <Popover open={isOpen}>
<div className="relative"> <div className="relative">
<PopoverTrigger asChild> <PopoverTrigger asChild>
<div <div
className="cursor-pointer flex items-center" className="cursor-pointer flex items-center justify-center min-w-5 min-h-5 translate-y-[1px]"
onClick={() => { onClick={() => {
if (hideTimerRef.current) { if (hideTimerRef.current) {
clearTimeout(hideTimerRef.current); clearTimeout(hideTimerRef.current);
@@ -114,7 +125,7 @@ export default function BottomMenuAlertPopover({ alerts }: AlertPopoverProps) {
setIsHovered(false); setIsHovered(false);
}} }}
> >
<TriggerIcon className={cn('h-5 w-5', triggerColor)} /> <TriggerIcon className={cn(iconStyles, triggerColor)} />
</div> </div>
</PopoverTrigger> </PopoverTrigger>