diff --git a/ui/src/components/profiles/editor/friendly-ui-section.tsx b/ui/src/components/profiles/editor/friendly-ui-section.tsx index 2c7e6c08..109a3231 100644 --- a/ui/src/components/profiles/editor/friendly-ui-section.tsx +++ b/ui/src/components/profiles/editor/friendly-ui-section.tsx @@ -1,16 +1,22 @@ /** * Friendly UI Section * Left column with environment variables and info tabs - * Enhanced with OpenRouter model picker when applicable + * Enhanced with OpenRouter-specific streamlined UI when applicable */ -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; import { EnvEditorSection } from './env-editor-section'; import { InfoSection } from './info-section'; import { OpenRouterModelPicker } from '@/components/profiles/openrouter-model-picker'; import { ModelTierMapping, type TierMapping } from '@/components/profiles/model-tier-mapping'; +import { Label } from '@/components/ui/label'; +import { MaskedInput } from '@/components/ui/masked-input'; +import { ChevronRight, Settings2 } from 'lucide-react'; import { isOpenRouterProfile, extractTierMapping, applyTierMapping } from './utils'; +import { toast } from 'sonner'; +import { cn } from '@/lib/utils'; import type { Settings, SettingsResponse } from './types'; interface FriendlyUISectionProps { @@ -46,9 +52,27 @@ export function FriendlyUISection({ // Memoize currentEnv for consistent reference const currentEnv = settingsEnv ?? {}; - // Handle model selection from OpenRouter picker + // Handle model selection from OpenRouter picker - applies to ALL tiers const handleModelChange = (modelId: string) => { - onEnvValueChange('ANTHROPIC_MODEL', modelId); + if (onEnvBulkChange) { + // Update all 4 model tiers at once + const newEnv = { + ...currentEnv, + ANTHROPIC_MODEL: modelId, + ANTHROPIC_DEFAULT_OPUS_MODEL: modelId, + ANTHROPIC_DEFAULT_SONNET_MODEL: modelId, + ANTHROPIC_DEFAULT_HAIKU_MODEL: modelId, + }; + onEnvBulkChange(newEnv); + } else { + // Fallback: update one by one + onEnvValueChange('ANTHROPIC_MODEL', modelId); + onEnvValueChange('ANTHROPIC_DEFAULT_OPUS_MODEL', modelId); + onEnvValueChange('ANTHROPIC_DEFAULT_SONNET_MODEL', modelId); + onEnvValueChange('ANTHROPIC_DEFAULT_HAIKU_MODEL', modelId); + } + // Show feedback toast + toast.success('Applied model to all tiers', { duration: 2000 }); }; // Handle tier mapping change @@ -71,13 +95,30 @@ export function FriendlyUISection({ } }; + // State for collapsible sections + const [showAllEnvVars, setShowAllEnvVars] = useState(false); + + // For OpenRouter: filter out model-related env vars from the main display + // These are managed by the model picker and tier mapping + const openRouterManagedKeys = new Set([ + 'ANTHROPIC_MODEL', + 'ANTHROPIC_DEFAULT_OPUS_MODEL', + 'ANTHROPIC_DEFAULT_SONNET_MODEL', + 'ANTHROPIC_DEFAULT_HAIKU_MODEL', + ]); + + // Count of hidden env vars for OpenRouter profiles + const hiddenEnvVarCount = isOpenRouter + ? Object.keys(currentEnv).filter((k) => openRouterManagedKeys.has(k)).length + : 0; + return ( -
+ Get your API key from{' '} + + openrouter.ai/keys + +
+