@lobehub/chat 0.123.0 → 0.123.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.123.1](https://github.com/lobehub/lobe-chat/compare/v0.123.0...v0.123.1)
6
+
7
+ <sup>Released on **2024-02-05**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Improve auth control of plugin gateways, update dockerfile.
12
+
13
+ #### 💄 Styles
14
+
15
+ - **misc**: Add gpt-4-all feature flag.
16
+
17
+ <br/>
18
+
19
+ <details>
20
+ <summary><kbd>Improvements and Fixes</kbd></summary>
21
+
22
+ #### What's fixed
23
+
24
+ - **misc**: Improve auth control of plugin gateways ([6354ad8](https://github.com/lobehub/lobe-chat/commit/6354ad8))
25
+ - **misc**: Update dockerfile ([e66aed3](https://github.com/lobehub/lobe-chat/commit/e66aed3))
26
+
27
+ #### Styles
28
+
29
+ - **misc**: Add gpt-4-all feature flag ([360b36c](https://github.com/lobehub/lobe-chat/commit/360b36c))
30
+
31
+ </details>
32
+
33
+ <div align="right">
34
+
35
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
36
+
37
+ </div>
38
+
5
39
  ## [Version 0.123.0](https://github.com/lobehub/lobe-chat/compare/v0.122.9...v0.123.0)
6
40
 
7
41
  <sup>Released on **2024-02-05**</sup>
package/Dockerfile CHANGED
@@ -57,7 +57,7 @@ ENV HOSTNAME "0.0.0.0"
57
57
  ENV PORT=3210
58
58
 
59
59
  # General Variables
60
- ENV ACCESS_CODE "lobe66"
60
+ ENV ACCESS_CODE ""
61
61
  ENV CUSTOM_MODELS ""
62
62
 
63
63
  # OpenAI
@@ -69,4 +69,10 @@ ENV USE_AZURE_OPENAI ""
69
69
  ENV AZURE_API_KEY ""
70
70
  ENV AZURE_API_VERSION ""
71
71
 
72
+ # Google
73
+ ENV GOOGLE_API_KEY ""
74
+
75
+ # Zhipu
76
+ ENV Zhipu_API_KEY ""
77
+
72
78
  CMD ["node", "server.js"]
package/README.md CHANGED
@@ -601,7 +601,7 @@ This project is [MIT](./LICENSE) licensed.
601
601
  [codespaces-link]: https://codespaces.new/lobehub/lobe-chat
602
602
  [codespaces-shield]: https://github.com/codespaces/badge.svg
603
603
  [deploy-button-image]: https://vercel.com/button
604
- [deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
604
+ [deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
605
605
  [deploy-on-sealos-button-image]: https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg
606
606
  [deploy-on-sealos-link]: https://cloud.sealos.io/?openapp=system-template%3FtemplateName%3Dlobe-chat
607
607
  [deploy-on-zeabur-button-image]: https://zeabur.com/button.svg
package/README.zh-CN.md CHANGED
@@ -617,7 +617,7 @@ This project is [MIT](./LICENSE) licensed.
617
617
  [codespaces-link]: https://codespaces.new/lobehub/lobe-chat
618
618
  [codespaces-shield]: https://github.com/codespaces/badge.svg
619
619
  [deploy-button-image]: https://vercel.com/button
620
- [deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
620
+ [deploy-link]: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat&env=OPENAI_API_KEY,ACCESS_CODE&envDescription=Find%20your%20OpenAI%20API%20Key%20by%20click%20the%20right%20Learn%20More%20button.%20%7C%20Access%20Code%20can%20protect%20your%20website&envLink=https%3A%2F%2Fplatform.openai.com%2Faccount%2Fapi-keys&project-name=lobe-chat&repository-name=lobe-chat
621
621
  [deploy-on-sealos-button-image]: https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg
622
622
  [deploy-on-sealos-link]: https://cloud.sealos.io/?openapp=system-template%3FtemplateName%3Dlobe-chat
623
623
  [deploy-on-zeabur-button-image]: https://zeabur.com/button.svg
@@ -47,7 +47,7 @@ $ docker run -d -p 3210:3210 \
47
47
  >
48
48
  > - The default mapped port is `3210`. Make sure it is not occupied or manually change the port mapping.
49
49
  > - Replace `sk-xxxx` in the above command with your own OpenAI API Key.
50
- > - The password set in the official Docker image is `lobe66` by default. Replace it with your own password to improve security.
50
+ > - The official Docker doesn't set password by default. Please add your own password to improve security.
51
51
  > - For a complete list of environment variables supported by LobeChat, please refer to the [Environment Variables](https://github.com/lobehub/lobe-chat/wiki/Environment-Variable.zh-CN) section.
52
52
 
53
53
  > \[!WARNING]
@@ -47,7 +47,7 @@ $ docker run -d -p 3210:3210 \
47
47
  >
48
48
  > - 默认映射端口为 `3210`, 请确保未被占用或手动更改端口映射
49
49
  > - 使用你的 OpenAI API Key 替换上述命令中的 `sk-xxxx`
50
- > - 官方 Docker 镜像中设定的密码默认为 `lobe66`,请将其替换为自己的密码以提升安全性
50
+ > - 官方 Docker 镜像中未设定密码,强烈建议添加密码以提升安全性,否则你可能会遇到 [My API Key was stolen!!!](https://github.com/lobehub/lobe-chat/issues/1123) 这样的情况
51
51
  > - LobeChat 支持的完整环境变量列表请参考 [环境变量](https://github.com/lobehub/lobe-chat/wiki/Environment-Variable.zh-CN) 部分
52
52
 
53
53
  > \[!WARNING]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.123.0",
3
+ "version": "0.123.1",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -84,7 +84,6 @@
84
84
  "@lobehub/tts": "latest",
85
85
  "@lobehub/ui": "latest",
86
86
  "@vercel/analytics": "^1",
87
- "ahooks": "3.7.8",
88
87
  "ai": "^2",
89
88
  "antd": "^5",
90
89
  "antd-style": "^3",
@@ -8,7 +8,10 @@ import { ChatErrorType, ErrorType } from '@/types/fetch';
8
8
  import { parserPluginSettings } from './settings';
9
9
 
10
10
  const checkAuth = (accessCode: string | null) => {
11
- const { ACCESS_CODES } = getServerConfig();
11
+ const { ACCESS_CODES, PLUGIN_SETTINGS } = getServerConfig();
12
+
13
+ // if there is no plugin settings, just skip the auth
14
+ if (!PLUGIN_SETTINGS) return { auth: true };
12
15
 
13
16
  // if accessCode doesn't exist
14
17
  if (!ACCESS_CODES.length) return { auth: true };
@@ -71,7 +71,7 @@ const Footer = memo<{ setExpand?: (expand: boolean) => void }>(({ setExpand }) =
71
71
  ]);
72
72
 
73
73
  const model = useSessionStore(agentSelectors.currentAgentModel);
74
- const canUpload = useGlobalStore(modelProviderSelectors.modelEnabledVision(model));
74
+ const canUpload = useGlobalStore(modelProviderSelectors.modelEnabledUpload(model));
75
75
 
76
76
  const sendMessage = useSendMessage();
77
77
 
@@ -94,6 +94,14 @@ const OpenAI: ModelProviderCard = {
94
94
  id: 'gpt-4-32k-0613',
95
95
  tokens: 32_768,
96
96
  },
97
+ {
98
+ files: true,
99
+ functionCall: true,
100
+ hidden: true,
101
+ id: 'gpt-4-all',
102
+ tokens: 32_768,
103
+ vision: true,
104
+ },
97
105
  ],
98
106
  enabled: true,
99
107
  id: 'openai',
@@ -19,11 +19,14 @@ const FileUpload = memo(() => {
19
19
  const upload = useFileStore((s) => s.uploadFile);
20
20
 
21
21
  const model = useSessionStore(agentSelectors.currentAgentModel);
22
- const canUpload = useGlobalStore(modelProviderSelectors.modelEnabledVision(model));
22
+ const [canUpload, enabledFiles] = useGlobalStore((s) => [
23
+ modelProviderSelectors.modelEnabledUpload(model)(s),
24
+ modelProviderSelectors.modelEnabledFiles(model)(s),
25
+ ]);
23
26
 
24
27
  return (
25
28
  <Upload
26
- accept="image/*"
29
+ accept={enabledFiles ? undefined : 'image/*'}
27
30
  beforeUpload={async (file) => {
28
31
  setLoading(true);
29
32
 
@@ -15,7 +15,7 @@ export const useChatInput = () => {
15
15
  const onSend = useSendMessage();
16
16
 
17
17
  const model = useSessionStore(agentSelectors.currentAgentModel);
18
- const canUpload = useGlobalStore(modelProviderSelectors.modelEnabledVision(model));
18
+ const canUpload = useGlobalStore(modelProviderSelectors.modelEnabledUpload(model));
19
19
 
20
20
  const [loading, value, onInput, onStop] = useChatStore((s) => [
21
21
  !!s.chatLoadingId,
@@ -138,9 +138,11 @@ class ChatService {
138
138
 
139
139
  if (imageList.length === 0) return m.content;
140
140
 
141
- const hasVision = modelProviderSelectors.modelEnabledVision(model)(useGlobalStore.getState());
141
+ const canUploadFile = modelProviderSelectors.modelEnabledUpload(model)(
142
+ useGlobalStore.getState(),
143
+ );
142
144
 
143
- if (!hasVision) {
145
+ if (!canUploadFile) {
144
146
  return m.content;
145
147
  }
146
148
 
@@ -30,235 +30,3 @@ exports[`modelProviderSelectors > CUSTOM_MODELS > custom deletion, addition, and
30
30
  },
31
31
  ]
32
32
  `;
33
-
34
- exports[`modelProviderSelectors > CUSTOM_MODELS > duplicate naming model 1`] = `
35
- [
36
- {
37
- "chatModels": [
38
- {
39
- "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务",
40
- "displayName": "GPT-3.5 Turbo",
41
- "functionCall": true,
42
- "id": "gpt-3.5-turbo",
43
- "tokens": 4096,
44
- },
45
- {
46
- "displayName": "GPT-3.5 Turbo (0125)",
47
- "functionCall": true,
48
- "id": "gpt-3.5-turbo-0125",
49
- "tokens": 16385,
50
- },
51
- {
52
- "displayName": "GPT-3.5 Turbo (1106)",
53
- "functionCall": true,
54
- "hidden": true,
55
- "id": "gpt-3.5-turbo-1106",
56
- "tokens": 16385,
57
- },
58
- {
59
- "hidden": true,
60
- "id": "gpt-3.5-turbo-instruct",
61
- "tokens": 4096,
62
- },
63
- {
64
- "hidden": true,
65
- "id": "gpt-3.5-turbo-16k",
66
- "tokens": 16385,
67
- },
68
- {
69
- "hidden": true,
70
- "id": "gpt-3.5-turbo-0613",
71
- "legacy": true,
72
- "tokens": 4096,
73
- },
74
- {
75
- "hidden": true,
76
- "id": "gpt-3.5-turbo-16k-0613",
77
- "legacy": true,
78
- "tokens": 4096,
79
- },
80
- {
81
- "displayName": "GPT-4 Turbo Preview",
82
- "functionCall": true,
83
- "id": "gpt-4-turbo-preview",
84
- "tokens": 128000,
85
- },
86
- {
87
- "displayName": "gpt-4-32k",
88
- "functionCall": true,
89
- "id": "gpt-4-0125-preview",
90
- "tokens": 128000,
91
- },
92
- {
93
- "description": "GPT-4 视觉预览版,支持视觉任务",
94
- "displayName": "GPT-4 Turbo Vision (Preview)",
95
- "id": "gpt-4-vision-preview",
96
- "tokens": 128000,
97
- "vision": true,
98
- },
99
- {
100
- "functionCall": true,
101
- "hidden": true,
102
- "id": "gpt-4-1106-preview",
103
- "tokens": 128000,
104
- },
105
- {
106
- "functionCall": true,
107
- "hidden": true,
108
- "id": "gpt-4",
109
- "tokens": 8192,
110
- },
111
- {
112
- "functionCall": true,
113
- "hidden": true,
114
- "id": "gpt-4-0613",
115
- "tokens": 8192,
116
- },
117
- {
118
- "functionCall": true,
119
- "hidden": true,
120
- "id": "gpt-4-32k",
121
- "tokens": 32768,
122
- },
123
- {
124
- "functionCall": true,
125
- "hidden": true,
126
- "id": "gpt-4-32k-0613",
127
- "tokens": 32768,
128
- },
129
- ],
130
- "enabled": true,
131
- "id": "openai",
132
- },
133
- ]
134
- `;
135
-
136
- exports[`modelProviderSelectors > CUSTOM_MODELS > only add the model 1`] = `
137
- [
138
- {
139
- "chatModels": [
140
- {
141
- "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务",
142
- "displayName": "GPT-3.5 Turbo",
143
- "functionCall": true,
144
- "id": "gpt-3.5-turbo",
145
- "tokens": 4096,
146
- },
147
- {
148
- "displayName": "GPT-3.5 Turbo (0125)",
149
- "functionCall": true,
150
- "id": "gpt-3.5-turbo-0125",
151
- "tokens": 16385,
152
- },
153
- {
154
- "displayName": "GPT-3.5 Turbo (1106)",
155
- "functionCall": true,
156
- "hidden": true,
157
- "id": "gpt-3.5-turbo-1106",
158
- "tokens": 16385,
159
- },
160
- {
161
- "hidden": true,
162
- "id": "gpt-3.5-turbo-instruct",
163
- "tokens": 4096,
164
- },
165
- {
166
- "hidden": true,
167
- "id": "gpt-3.5-turbo-16k",
168
- "tokens": 16385,
169
- },
170
- {
171
- "hidden": true,
172
- "id": "gpt-3.5-turbo-0613",
173
- "legacy": true,
174
- "tokens": 4096,
175
- },
176
- {
177
- "hidden": true,
178
- "id": "gpt-3.5-turbo-16k-0613",
179
- "legacy": true,
180
- "tokens": 4096,
181
- },
182
- {
183
- "displayName": "GPT-4 Turbo Preview",
184
- "functionCall": true,
185
- "id": "gpt-4-turbo-preview",
186
- "tokens": 128000,
187
- },
188
- {
189
- "displayName": "GPT-4 Turbo Preview (0125)",
190
- "functionCall": true,
191
- "id": "gpt-4-0125-preview",
192
- "tokens": 128000,
193
- },
194
- {
195
- "description": "GPT-4 视觉预览版,支持视觉任务",
196
- "displayName": "GPT-4 Turbo Vision (Preview)",
197
- "id": "gpt-4-vision-preview",
198
- "tokens": 128000,
199
- "vision": true,
200
- },
201
- {
202
- "functionCall": true,
203
- "hidden": true,
204
- "id": "gpt-4-1106-preview",
205
- "tokens": 128000,
206
- },
207
- {
208
- "functionCall": true,
209
- "hidden": true,
210
- "id": "gpt-4",
211
- "tokens": 8192,
212
- },
213
- {
214
- "functionCall": true,
215
- "hidden": true,
216
- "id": "gpt-4-0613",
217
- "tokens": 8192,
218
- },
219
- {
220
- "functionCall": true,
221
- "hidden": true,
222
- "id": "gpt-4-32k",
223
- "tokens": 32768,
224
- },
225
- {
226
- "functionCall": true,
227
- "hidden": true,
228
- "id": "gpt-4-32k-0613",
229
- "tokens": 32768,
230
- },
231
- {
232
- "displayName": "model1",
233
- "functionCall": true,
234
- "id": "model1",
235
- "isCustom": true,
236
- "vision": true,
237
- },
238
- {
239
- "displayName": "model2",
240
- "functionCall": true,
241
- "id": "model2",
242
- "isCustom": true,
243
- "vision": true,
244
- },
245
- {
246
- "displayName": "model3",
247
- "functionCall": true,
248
- "id": "model3",
249
- "isCustom": true,
250
- "vision": true,
251
- },
252
- {
253
- "displayName": "model4",
254
- "functionCall": true,
255
- "id": "model4",
256
- "isCustom": true,
257
- "vision": true,
258
- },
259
- ],
260
- "enabled": true,
261
- "id": "openai",
262
- },
263
- ]
264
- `;
@@ -37,7 +37,9 @@ describe('modelProviderSelectors', () => {
37
37
 
38
38
  const result = modelProviderSelectors.modelSelectList(s).filter((r) => r.enabled);
39
39
 
40
- expect(result).toMatchSnapshot();
40
+ expect(result[0].chatModels.find((s) => s.id === 'gpt-4-0125-preview')?.displayName).toEqual(
41
+ 'gpt-4-32k',
42
+ );
41
43
  });
42
44
 
43
45
  it('should delete model', () => {
@@ -47,99 +49,7 @@ describe('modelProviderSelectors', () => {
47
49
 
48
50
  const result = modelProviderSelectors.modelSelectList(s).filter((r) => r.enabled);
49
51
 
50
- expect(result).toEqual([
51
- {
52
- chatModels: [
53
- {
54
- description: 'GPT 3.5 Turbo,适用于各种文本生成和理解任务',
55
- displayName: 'GPT-3.5 Turbo',
56
- functionCall: true,
57
- id: 'gpt-3.5-turbo',
58
- tokens: 4096,
59
- },
60
- {
61
- displayName: 'GPT-3.5 Turbo (0125)',
62
- functionCall: true,
63
- id: 'gpt-3.5-turbo-0125',
64
- tokens: 16385,
65
- },
66
- {
67
- displayName: 'GPT-3.5 Turbo (1106)',
68
- functionCall: true,
69
- hidden: true,
70
- id: 'gpt-3.5-turbo-1106',
71
- tokens: 16385,
72
- },
73
- {
74
- hidden: true,
75
- id: 'gpt-3.5-turbo-instruct',
76
- tokens: 4096,
77
- },
78
- {
79
- hidden: true,
80
- id: 'gpt-3.5-turbo-16k',
81
- tokens: 16385,
82
- },
83
- {
84
- hidden: true,
85
- id: 'gpt-3.5-turbo-0613',
86
- legacy: true,
87
- tokens: 4096,
88
- },
89
- {
90
- hidden: true,
91
- id: 'gpt-3.5-turbo-16k-0613',
92
- legacy: true,
93
- tokens: 4096,
94
- },
95
- {
96
- displayName: 'GPT-4 Turbo Preview',
97
- functionCall: true,
98
- id: 'gpt-4-turbo-preview',
99
- tokens: 128000,
100
- },
101
- {
102
- displayName: 'GPT-4 Turbo Preview (0125)',
103
- functionCall: true,
104
- id: 'gpt-4-0125-preview',
105
- tokens: 128000,
106
- },
107
- {
108
- description: 'GPT-4 视觉预览版,支持视觉任务',
109
- displayName: 'GPT-4 Turbo Vision (Preview)',
110
- id: 'gpt-4-vision-preview',
111
- tokens: 128000,
112
- vision: true,
113
- },
114
- {
115
- functionCall: true,
116
- hidden: true,
117
- id: 'gpt-4-1106-preview',
118
- tokens: 128000,
119
- },
120
- {
121
- functionCall: true,
122
- hidden: true,
123
- id: 'gpt-4-0613',
124
- tokens: 8192,
125
- },
126
- {
127
- functionCall: true,
128
- hidden: true,
129
- id: 'gpt-4-32k',
130
- tokens: 32768,
131
- },
132
- {
133
- functionCall: true,
134
- hidden: true,
135
- id: 'gpt-4-32k-0613',
136
- tokens: 32768,
137
- },
138
- ],
139
- enabled: true,
140
- id: 'openai',
141
- },
142
- ]);
52
+ expect(result.find((r) => r.id === 'gpt-4')).toBeUndefined();
143
53
  });
144
54
 
145
55
  it('show the hidden model', () => {
@@ -177,7 +87,34 @@ describe('modelProviderSelectors', () => {
177
87
 
178
88
  const result = modelProviderSelectors.modelSelectList(s).filter((r) => r.enabled);
179
89
 
180
- expect(result).toMatchSnapshot();
90
+ expect(result[0].chatModels).toContainEqual({
91
+ displayName: 'model1',
92
+ functionCall: true,
93
+ id: 'model1',
94
+ isCustom: true,
95
+ vision: true,
96
+ });
97
+ expect(result[0].chatModels).toContainEqual({
98
+ displayName: 'model2',
99
+ functionCall: true,
100
+ id: 'model2',
101
+ isCustom: true,
102
+ vision: true,
103
+ });
104
+ expect(result[0].chatModels).toContainEqual({
105
+ displayName: 'model3',
106
+ functionCall: true,
107
+ id: 'model3',
108
+ isCustom: true,
109
+ vision: true,
110
+ });
111
+ expect(result[0].chatModels).toContainEqual({
112
+ displayName: 'model4',
113
+ functionCall: true,
114
+ id: 'model4',
115
+ isCustom: true,
116
+ vision: true,
117
+ });
181
118
  });
182
119
  });
183
120
 
@@ -206,7 +143,23 @@ describe('modelProviderSelectors', () => {
206
143
  });
207
144
  });
208
145
 
209
- describe('modelEnabledVision', () => {
146
+ describe('modelEnabledFiles', () => {
147
+ it('should return false if the model does not have file ability', () => {
148
+ const enabledFiles = modelProviderSelectors.modelEnabledFiles('gpt-4-vision-preview')(
149
+ useGlobalStore.getState(),
150
+ );
151
+ expect(enabledFiles).toBeFalsy();
152
+ });
153
+
154
+ it('should return true if the model has file ability', () => {
155
+ const enabledFiles = modelProviderSelectors.modelEnabledFiles('gpt-4-all')(
156
+ useGlobalStore.getState(),
157
+ );
158
+ expect(enabledFiles).toBeTruthy();
159
+ });
160
+ });
161
+
162
+ describe('modelHasMaxToken', () => {
210
163
  it('should return true if the model is in the list of models that show tokens', () => {
211
164
  const show = modelProviderSelectors.modelHasMaxToken('gpt-3.5-turbo')(
212
165
  useGlobalStore.getState(),
@@ -122,6 +122,11 @@ const modelEnabledFunctionCall = (id: string) => (s: GlobalStore) =>
122
122
  const modelEnabledVision = (id: string) => (s: GlobalStore) =>
123
123
  modelCardById(id)(s)?.vision || id.includes('vision');
124
124
 
125
+ const modelEnabledFiles = (id: string) => (s: GlobalStore) => modelCardById(id)(s)?.files;
126
+
127
+ const modelEnabledUpload = (id: string) => (s: GlobalStore) =>
128
+ modelEnabledVision(id)(s) || modelEnabledFiles(id)(s);
129
+
125
130
  const modelHasMaxToken = (id: string) => (s: GlobalStore) =>
126
131
  typeof modelCardById(id)(s)?.tokens !== 'undefined';
127
132
 
@@ -133,9 +138,13 @@ export const modelProviderSelectors = {
133
138
 
134
139
  modelCardById,
135
140
  modelMaxToken,
141
+ modelHasMaxToken,
142
+
136
143
  modelEnabledFunctionCall,
137
144
  modelEnabledVision,
138
- modelHasMaxToken,
145
+ modelEnabledFiles,
146
+ modelEnabledUpload,
147
+
139
148
  // OpenAI
140
149
  openAIConfig,
141
150
  openAIAPIKey,
package/src/types/llm.ts CHANGED
@@ -21,19 +21,26 @@ export interface ChatModelCard {
21
21
  description?: string;
22
22
  displayName?: string;
23
23
  /**
24
- * 是否支持 Function Call
24
+ * whether model supports file upload
25
+ */
26
+ files?: boolean;
27
+ /**
28
+ * whether model supports function call
25
29
  */
26
30
  functionCall?: boolean;
27
31
  hidden?: boolean;
28
32
  id: string;
29
33
  /**
30
- * user defined model
34
+ * whether model is custom
31
35
  */
32
36
  isCustom?: boolean;
37
+ /**
38
+ * whether model is legacy (deprecated but not removed yet)
39
+ */
33
40
  legacy?: boolean;
34
41
  tokens?: number;
35
42
  /**
36
- * 是否支持视觉识别
43
+ * whether model supports vision
37
44
  */
38
45
  vision?: boolean;
39
46
  }