File size: 2,520 Bytes
973d6a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8451ad7
973d6a7
 
 
 
8451ad7
973d6a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { useState, useEffect, useRef } from 'react';
import { ChevronDown } from 'lucide-react';
import './ModelSelector.css';

interface ModelOption {
    id: string;
    label: string;
    provider: string;
}

interface ModelSelectorProps {
    send: (payload: Record<string, unknown>) => void;
}

export default function ModelSelector({ send }: ModelSelectorProps) {
    const [current, setCurrent] = useState('gpt-5.4');
    const [open, setOpen] = useState(false);
    const ref = useRef<HTMLDivElement>(null);

    const models: ModelOption[] = [
        { id: 'gpt-5.4', label: 'GPT-5.4', provider: 'openai' },
        { id: 'gpt-4.1', label: 'GPT-4.1', provider: 'openai' },
        { id: 'o3', label: 'o3', provider: 'openai' },
        { id: 'gemini-3.1-pro-preview', label: 'Gemini 3.1 Pro', provider: 'google' },
    ];

    // Close on click outside
    useEffect(() => {
        if (!open) return;
        const handleClick = (e: MouseEvent) => {
            if (ref.current && !ref.current.contains(e.target as Node)) {
                setOpen(false);
            }
        };
        document.addEventListener('mousedown', handleClick);
        return () => document.removeEventListener('mousedown', handleClick);
    }, [open]);

    const handleSelect = (modelId: string) => {
        setCurrent(modelId);
        setOpen(false);
        send({ type: 'set_provider', model: modelId });
    };

    const currentLabel = models.find(m => m.id === current)?.label ?? current;

    return (
        <div className="model-selector" ref={ref}>
            <button
                className="model-selector-btn"
                onClick={() => setOpen(v => !v)}
                title="Switch AI model"
            >
                <span className="model-label">{currentLabel}</span>
                <ChevronDown size={13} className={`chevron ${open ? 'open' : ''}`} />
            </button>
            {open && (
                <div className="model-dropdown">
                    {models.map(m => (
                        <button
                            key={m.id}
                            className={`model-option ${m.id === current ? 'active' : ''}`}
                            onClick={() => handleSelect(m.id)}
                        >
                            <span>{m.label}</span>
                            {m.id === current && <span className="check"></span>}
                        </button>
                    ))}
                </div>
            )}
        </div>
    );
}