-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
/
index.tsx
122 lines (108 loc) · 3.46 KB
/
index.tsx
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { Icon } from '@lobehub/ui';
import { Dropdown } from 'antd';
import { createStyles } from 'antd-style';
import type { ItemType } from 'antd/es/menu/interface';
import { LucideArrowRight } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { PropsWithChildren, memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import { ModelItemRender, ProviderItemRender } from '@/components/ModelSelect';
import { isServerMode } from '@/const/version';
import { useEnabledChatModels } from '@/hooks/useEnabledChatModels';
import { useIsMobile } from '@/hooks/useIsMobile';
import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/slices/chat';
import { EnabledProviderWithModels } from '@/types/aiModel';
const useStyles = createStyles(({ css, prefixCls }) => ({
menu: css`
.${prefixCls}-dropdown-menu-item {
display: flex;
gap: 8px;
}
.${prefixCls}-dropdown-menu {
&-item-group-title {
padding-inline: 8px;
}
&-item-group-list {
margin: 0 !important;
}
}
`,
tag: css`
cursor: pointer;
`,
}));
const menuKey = (provider: string, model: string) => `${provider}-${model}`;
const ModelSwitchPanel = memo<PropsWithChildren>(({ children }) => {
const { t } = useTranslation('components');
const { styles, theme } = useStyles();
const [model, provider, updateAgentConfig] = useAgentStore((s) => [
agentSelectors.currentAgentModel(s),
agentSelectors.currentAgentModelProvider(s),
s.updateAgentConfig,
]);
const isMobile = useIsMobile();
const router = useRouter();
const enabledList = useEnabledChatModels();
const items = useMemo<ItemType[]>(() => {
const getModelItems = (provider: EnabledProviderWithModels) => {
const items = provider.children.map((model) => ({
key: menuKey(provider.id, model.id),
label: <ModelItemRender {...model} {...model.abilities} />,
onClick: () => {
updateAgentConfig({ model: model.id, provider: provider.id });
},
}));
// if there is empty items, add a placeholder guide
if (items.length === 0)
return [
{
key: 'empty',
label: (
<Flexbox gap={8} horizontal style={{ color: theme.colorTextTertiary }}>
{t('ModelSwitchPanel.emptyModel')}
<Icon icon={LucideArrowRight} />
</Flexbox>
),
onClick: () => {
router.push(!isServerMode ? '/settings/llm' : `/settings/provider/${provider.id}`);
},
},
];
return items;
};
// otherwise show with provider group
return enabledList.map((provider) => ({
children: getModelItems(provider),
key: provider.id,
label: (
<ProviderItemRender
logo={provider.logo}
name={provider.name}
provider={provider.id}
source={provider.source}
/>
),
type: 'group',
}));
}, [enabledList]);
return (
<Dropdown
menu={{
activeKey: menuKey(provider, model),
className: styles.menu,
items,
style: {
maxHeight: 500,
overflowY: 'scroll',
},
}}
placement={isMobile ? 'top' : 'topLeft'}
trigger={['click']}
>
<div className={styles.tag}>{children}</div>
</Dropdown>
);
});
export default ModelSwitchPanel;