import { useMemo } from 'react' import type { AgentState, ModelMode, PermissionMode } from '@/types/api' import { getContextBudgetTokens } from '@/chat/modelConfig' const PERMISSION_MODE_LABELS: Record = { default: 'Default', acceptEdits: 'Accept Edits', plan: 'Plan Mode', bypassPermissions: 'Bypass All' } // Vibing messages for thinking state const VIBING_MESSAGES = [ "Accomplishing", "Actioning", "Actualizing", "Baking", "Booping", "Brewing", "Calculating", "Cerebrating", "Channelling", "Churning", "Clauding", "Coalescing", "Cogitating", "Computing", "Combobulating", "Concocting", "Conjuring", "Considering", "Contemplating", "Cooking", "Crafting", "Creating", "Crunching", "Deciphering", "Deliberating", "Determining", "Discombobulating", "Divining", "Doing", "Effecting", "Elucidating", "Enchanting", "Envisioning", "Finagling", "Flibbertigibbeting", "Forging", "Forming", "Frolicking", "Generating", "Germinating", "Hatching", "Herding", "Honking", "Ideating", "Imagining", "Incubating", "Inferring", "Manifesting", "Marinating", "Meandering", "Moseying", "Mulling", "Mustering", "Musing", "Noodling", "Percolating", "Perusing", "Philosophising", "Pontificating", "Pondering", "Processing", "Puttering", "Puzzling", "Reticulating", "Ruminating", "Scheming", "Schlepping", "Shimmying", "Simmering", "Smooshing", "Spelunking", "Spinning", "Stewing", "Sussing", "Synthesizing", "Thinking", "Tinkering", "Transmuting", "Unfurling", "Unravelling", "Vibing", "Wandering", "Whirring", "Wibbling", "Wizarding", "Working", "Wrangling" ] function getConnectionStatus( active: boolean, thinking: boolean, agentState: AgentState | null | undefined ): { text: string; color: string; dotColor: string; isPulsing: boolean } { const hasPermissions = agentState?.requests && Object.keys(agentState.requests).length > 0 if (!active) { return { text: 'offline', color: 'text-[#999]', dotColor: 'bg-[#999]', isPulsing: false } } if (hasPermissions) { return { text: 'permission required', color: 'text-[#FF9500]', dotColor: 'bg-[#FF9500]', isPulsing: true } } if (thinking) { const vibingMessage = VIBING_MESSAGES[Math.floor(Math.random() * VIBING_MESSAGES.length)].toLowerCase() + '…' return { text: vibingMessage, color: 'text-[#007AFF]', dotColor: 'bg-[#007AFF]', isPulsing: true } } return { text: 'online', color: 'text-[#34C759]', dotColor: 'bg-[#34C759]', isPulsing: false } } function getContextWarning(contextSize: number, maxContextSize: number): { text: string; color: string } | null { const percentageUsed = (contextSize / maxContextSize) * 100 const percentageRemaining = Math.max(0, 100 - percentageUsed) if (percentageRemaining <= 5) { return { text: `${Math.round(percentageRemaining)}% left`, color: 'text-red-500' } } else if (percentageRemaining <= 10) { return { text: `${Math.round(percentageRemaining)}% left`, color: 'text-amber-500' } } else { return { text: `${Math.round(percentageRemaining)}% left`, color: 'text-[var(--app-hint)]' } } } export function StatusBar(props: { active: boolean thinking: boolean agentState: AgentState | null | undefined contextSize?: number modelMode?: ModelMode permissionMode?: PermissionMode }) { const connectionStatus = useMemo( () => getConnectionStatus(props.active, props.thinking, props.agentState), [props.active, props.thinking, props.agentState] ) const contextWarning = useMemo( () => { if (props.contextSize === undefined) return null const maxContextSize = getContextBudgetTokens(props.modelMode) if (!maxContextSize) return null return getContextWarning(props.contextSize, maxContextSize) }, [props.contextSize, props.modelMode] ) const permissionMode = props.permissionMode return (
{connectionStatus.text}
{contextWarning ? ( {contextWarning.text} ) : null}
{(permissionMode && permissionMode !== 'default') ? ( {PERMISSION_MODE_LABELS[permissionMode]} ) : null}
) }