ModelSelector.tsx105 lines · main
1import { Check, ChevronsUpDown } from 'lucide-react'
2import { useRouter } from 'next/router'
3import { useState } from 'react'
4import {
5 Badge,
6 Button,
7 Command,
8 CommandGroup,
9 CommandItem,
10 CommandList,
11 Popover,
12 PopoverContent,
13 PopoverTrigger,
14 Tooltip,
15 TooltipContent,
16 TooltipTrigger,
17} from 'ui'
18
19import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
20import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
21import { ASSISTANT_MODELS, isAdvanceOnlyModelId } from '@/lib/ai/model.utils'
22import type { AssistantModelId } from '@/lib/ai/model.utils'
23
24interface ModelSelectorProps {
25 selectedModel: AssistantModelId
26 onSelectModel: (model: AssistantModelId) => void
27}
28
29export const ModelSelector = ({ selectedModel, onSelectModel }: ModelSelectorProps) => {
30 const router = useRouter()
31 const { data: organization } = useSelectedOrganizationQuery()
32 const { hasAccess: hasAccessToAdvanceModel, isLoading: isLoadingEntitlements } =
33 useCheckEntitlements('assistant.advance_model')
34
35 const [open, setOpen] = useState(false)
36
37 const slug = organization?.slug ?? '_'
38
39 const upgradeHref = `/org/${slug}/billing?panel=subscriptionPlan&source=ai-assistant-model`
40
41 const handleSelectModel = (modelId: AssistantModelId) => {
42 if (isLoadingEntitlements && isAdvanceOnlyModelId(modelId)) {
43 return
44 }
45 if (isAdvanceOnlyModelId(modelId) && !hasAccessToAdvanceModel) {
46 setOpen(false)
47 void router.push(upgradeHref)
48 return
49 }
50
51 onSelectModel(modelId)
52 setOpen(false)
53 }
54
55 return (
56 <Popover open={open} onOpenChange={setOpen}>
57 <PopoverTrigger asChild>
58 <Button
59 type="default"
60 className="text-foreground-light"
61 iconRight={<ChevronsUpDown strokeWidth={1} size={12} />}
62 >
63 {selectedModel}
64 </Button>
65 </PopoverTrigger>
66 <PopoverContent className="p-0 w-44" align="start" side="top">
67 <Command>
68 <CommandList>
69 <CommandGroup>
70 {ASSISTANT_MODELS.map((m) => (
71 <CommandItem
72 key={m.id}
73 value={m.id}
74 disabled={isLoadingEntitlements && isAdvanceOnlyModelId(m.id)}
75 onSelect={() => handleSelectModel(m.id)}
76 className="flex justify-between"
77 >
78 <span>{m.id}</span>
79 {isAdvanceOnlyModelId(m.id) &&
80 !hasAccessToAdvanceModel &&
81 !isLoadingEntitlements ? (
82 <Tooltip>
83 <TooltipTrigger asChild>
84 <div>
85 <Badge role="button" variant="warning">
86 Upgrade
87 </Badge>
88 </div>
89 </TooltipTrigger>
90 <TooltipContent side="right">
91 {m.id} is available on Pro plans and above
92 </TooltipContent>
93 </Tooltip>
94 ) : (
95 selectedModel === m.id && <Check className="h-3.5 w-3.5" />
96 )}
97 </CommandItem>
98 ))}
99 </CommandGroup>
100 </CommandList>
101 </Command>
102 </PopoverContent>
103 </Popover>
104 )
105}