@lobehub/chat 1.62.5 → 1.62.7

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/changelog/v1.json +18 -0
  5. package/docs/self-hosting/environment-variables/model-provider.mdx +17 -0
  6. package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +16 -0
  7. package/docs/self-hosting/platform/sealos.mdx +8 -8
  8. package/docs/self-hosting/platform/sealos.zh-CN.mdx +7 -7
  9. package/docs/self-hosting/server-database/sealos.mdx +84 -5
  10. package/docs/self-hosting/server-database/sealos.zh-CN.mdx +105 -5
  11. package/docs/self-hosting/start.zh-CN.mdx +2 -1
  12. package/locales/ar/plugin.json +4 -0
  13. package/locales/bg-BG/plugin.json +4 -0
  14. package/locales/de-DE/plugin.json +4 -0
  15. package/locales/en-US/plugin.json +4 -0
  16. package/locales/es-ES/plugin.json +4 -0
  17. package/locales/fa-IR/plugin.json +4 -0
  18. package/locales/fr-FR/plugin.json +4 -0
  19. package/locales/it-IT/plugin.json +4 -0
  20. package/locales/ja-JP/plugin.json +4 -0
  21. package/locales/ko-KR/plugin.json +4 -0
  22. package/locales/nl-NL/plugin.json +4 -0
  23. package/locales/pl-PL/plugin.json +4 -0
  24. package/locales/pt-BR/plugin.json +4 -0
  25. package/locales/ru-RU/plugin.json +4 -0
  26. package/locales/tr-TR/plugin.json +4 -0
  27. package/locales/vi-VN/plugin.json +4 -0
  28. package/locales/zh-CN/plugin.json +5 -1
  29. package/locales/zh-TW/plugin.json +4 -0
  30. package/package.json +1 -1
  31. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/index.tsx +1 -1
  32. package/src/config/aiModels/volcengine.ts +249 -2
  33. package/src/database/server/models/aiProvider.ts +22 -9
  34. package/src/database/server/models/topic.ts +2 -0
  35. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/Debug.tsx +43 -0
  36. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/Loader.tsx +58 -0
  37. package/src/features/Conversation/Messages/Assistant/Tool/Inspector/index.tsx +151 -0
  38. package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments.tsx +165 -0
  39. package/src/features/Conversation/Messages/Assistant/{ToolCallItem/Tool.tsx → Tool/Render/CustomRender.tsx} +34 -35
  40. package/src/features/Conversation/Messages/Assistant/Tool/Render/index.tsx +39 -0
  41. package/src/features/Conversation/Messages/Assistant/Tool/index.tsx +70 -0
  42. package/src/features/Conversation/Messages/Assistant/index.tsx +19 -27
  43. package/src/features/InitClientDB/PGliteIcon.tsx +2 -2
  44. package/src/features/PluginsUI/Render/index.tsx +2 -11
  45. package/src/locales/default/plugin.ts +4 -0
  46. package/src/styles/loading.ts +27 -0
  47. package/src/tools/dalle/Render/GalleyGrid.tsx +60 -0
  48. package/src/tools/dalle/Render/index.tsx +1 -1
  49. package/src/features/Conversation/Messages/Assistant/ToolCallItem/Inspector/index.tsx +0 -166
  50. package/src/features/Conversation/Messages/Assistant/ToolCallItem/Inspector/style.ts +0 -35
  51. package/src/features/Conversation/Messages/Assistant/ToolCallItem/index.tsx +0 -89
  52. package/src/features/Conversation/Messages/Assistant/ToolCallItem/style.ts +0 -35
  53. package/src/features/Conversation/Messages/components/Arguments.tsx +0 -22
  54. /package/src/features/Conversation/Messages/Assistant/{ToolCallItem → Tool}/Inspector/PluginResultJSON.tsx +0 -0
  55. /package/src/features/Conversation/Messages/Assistant/{ToolCallItem → Tool}/Inspector/Settings.tsx +0 -0
@@ -118,6 +118,10 @@
118
118
  "reinstallError": "插件 {{name}} 刷新失败",
119
119
  "urlError": "该链接没有返回 JSON 格式的内容, 请确保是有效的链接"
120
120
  },
121
+ "inspector": {
122
+ "args": "查看参数列表",
123
+ "pluginRender": "查看插件界面"
124
+ },
121
125
  "list": {
122
126
  "item": {
123
127
  "deprecated.title": "已删除",
@@ -163,4 +167,4 @@
163
167
  "title": "插件商店"
164
168
  },
165
169
  "unknownPlugin": "未知插件"
166
- }
170
+ }
@@ -118,6 +118,10 @@
118
118
  "reinstallError": "插件 {{name}} 刷新失敗",
119
119
  "urlError": "該連結沒有返回 JSON 格式的內容, 請確保是有效的連結"
120
120
  },
121
+ "inspector": {
122
+ "args": "查看參數列表",
123
+ "pluginRender": "查看插件介面"
124
+ },
121
125
  "list": {
122
126
  "item": {
123
127
  "deprecated.title": "已刪除",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.62.5",
3
+ "version": "1.62.7",
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",
@@ -14,10 +14,10 @@ const leftActions = [
14
14
  'model',
15
15
  'fileUpload',
16
16
  'knowledgeBase',
17
+ 'params',
17
18
  'history',
18
19
  'stt',
19
20
  'tools',
20
- 'params',
21
21
  'mainToken',
22
22
  ] as ActionKeys[];
23
23
 
@@ -1,28 +1,216 @@
1
1
  import { AIChatModelCard } from '@/types/aiModel';
2
2
 
3
+ // modelInfo https://www.volcengine.com/docs/82379/1330310
4
+ // pricing https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement
5
+
3
6
  const doubaoChatModels: AIChatModelCard[] = [
4
7
  {
5
8
  abilities: {
6
9
  reasoning: true,
7
10
  },
11
+ config: {
12
+ deploymentName: 'deepseek-r1-250120',
13
+ },
8
14
  contextWindowTokens: 65_536,
9
15
  description:
10
- '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 4k 上下文窗口的推理和精调。',
16
+ 'DeepSeek-R1 在后训练阶段大规模使用了强化学习技术,在仅有极少标注数据的情况下,极大提升了模型推理能力。在数学、代码、自然语言推理等任务上,性能比肩 OpenAI o1 正式版。',
11
17
  displayName: 'DeepSeek R1',
12
18
  enabled: true,
13
19
  id: 'deepseek-r1',
20
+ maxOutput: 8000,
21
+ pricing: {
22
+ currency: 'CNY',
23
+ input: 2, // 2.24 恢复原价 4, 16
24
+ output: 8,
25
+ },
26
+ type: 'chat',
27
+ },
28
+ {
29
+ abilities: {
30
+ reasoning: true,
31
+ },
32
+ config: {
33
+ deploymentName: 'deepseek-r1-distill-qwen-32b-250120',
34
+ },
35
+ contextWindowTokens: 32_768,
36
+ description:
37
+ 'DeepSeek-R1-Distill 模型是在开源模型的基础上通过微调训练得到的,训练过程中使用了由 DeepSeek-R1 生成的样本数据。',
38
+ displayName: 'DeepSeek R1 Distill Qwen 32B',
39
+ id: 'deepseek-r1-distill-qwen-32b',
40
+ maxOutput: 8000,
41
+ pricing: {
42
+ currency: 'CNY',
43
+ input: 1.5,
44
+ output: 6,
45
+ },
46
+ type: 'chat',
47
+ },
48
+ {
49
+ abilities: {
50
+ reasoning: true,
51
+ },
52
+ config: {
53
+ deploymentName: 'deepseek-r1-distill-qwen-7b-250120',
54
+ },
55
+ contextWindowTokens: 32_768,
56
+ description:
57
+ 'DeepSeek-R1-Distill 模型是在开源模型的基础上通过微调训练得到的,训练过程中使用了由 DeepSeek-R1 生成的样本数据。',
58
+ displayName: 'DeepSeek R1 Distill Qwen 7B',
59
+ id: 'deepseek-r1-distill-qwen-7b',
60
+ maxOutput: 8000,
61
+ pricing: {
62
+ currency: 'CNY',
63
+ input: 0.6,
64
+ output: 2.4,
65
+ },
14
66
  type: 'chat',
15
67
  },
16
68
  {
17
69
  abilities: {
18
70
  functionCall: true,
19
71
  },
72
+ config: {
73
+ deploymentName: 'deepseek-v3-241226',
74
+ },
20
75
  contextWindowTokens: 65_536,
21
76
  description:
22
77
  'DeepSeek-V3 是一款由深度求索公司自研的MoE模型。DeepSeek-V3 多项评测成绩超越了 Qwen2.5-72B 和 Llama-3.1-405B 等其他开源模型,并在性能上和世界顶尖的闭源模型 GPT-4o 以及 Claude-3.5-Sonnet 不分伯仲。',
23
78
  displayName: 'DeepSeek V3',
24
79
  enabled: true,
25
80
  id: 'deepseek-v3',
81
+ maxOutput: 8000,
82
+ pricing: {
83
+ currency: 'CNY',
84
+ input: 2,
85
+ output: 8,
86
+ },
87
+ type: 'chat',
88
+ },
89
+ {
90
+ abilities: {
91
+ functionCall: true,
92
+ },
93
+ config: {
94
+ deploymentName: 'doubao-1-5-pro-32k-250115',
95
+ },
96
+ contextWindowTokens: 32_768,
97
+ description:
98
+ 'Doubao-1.5-pro 全新一代主力模型,性能全面升级,在知识、代码、推理、等方面表现卓越。',
99
+ displayName: 'Doubao 1.5 Pro 32k',
100
+ enabled: true,
101
+ id: 'doubao-1.5-pro-32k',
102
+ maxOutput: 12_000,
103
+ pricing: {
104
+ currency: 'CNY',
105
+ input: 0.8,
106
+ output: 2,
107
+ },
108
+ type: 'chat',
109
+ },
110
+ {
111
+ abilities: {
112
+ functionCall: true,
113
+ },
114
+ config: {
115
+ deploymentName: 'doubao-1-5-pro-256k-250115',
116
+ },
117
+ contextWindowTokens: 32_768,
118
+ description:
119
+ 'Doubao-1.5-pro-256k 基于 Doubao-1.5-Pro 全面升级版,整体效果大幅提升 10%。支持 256k 上下文窗口的推理,输出长度支持最大 12k tokens。更高性能、更大窗口、超高性价比,适用于更广泛的应用场景。',
120
+ displayName: 'Doubao 1.5 Pro 256k',
121
+ enabled: true,
122
+ id: 'doubao-1.5-pro-256k',
123
+ maxOutput: 12_000,
124
+ pricing: {
125
+ currency: 'CNY',
126
+ input: 5,
127
+ output: 9,
128
+ },
129
+ type: 'chat',
130
+ },
131
+ {
132
+ abilities: {
133
+ functionCall: true,
134
+ },
135
+ config: {
136
+ deploymentName: 'doubao-1-5-lite-32k-250115',
137
+ },
138
+ contextWindowTokens: 32_768,
139
+ description:
140
+ 'Doubao-1.5-lite 全新一代轻量版模型,极致响应速度,效果与时延均达到全球一流水平。',
141
+ displayName: 'Doubao 1.5 Lite 32k',
142
+ enabled: true,
143
+ id: 'doubao-1.5-lite-32k',
144
+ maxOutput: 12_000,
145
+ pricing: {
146
+ currency: 'CNY',
147
+ input: 0.3,
148
+ output: 0.6,
149
+ },
150
+ type: 'chat',
151
+ },
152
+ {
153
+ abilities: {
154
+ vision: true,
155
+ },
156
+ config: {
157
+ deploymentName: 'doubao-1-5-vision-pro-32k-250115',
158
+ },
159
+ contextWindowTokens: 32_768,
160
+ description:
161
+ 'Doubao-1.5-vision-pro 全新升级的多模态大模型,支持任意分辨率和极端长宽比图像识别,增强视觉推理、文档识别、细节信息理解和指令遵循能力。',
162
+ displayName: 'Doubao 1.5 Vision Pro 32k',
163
+ enabled: true,
164
+ id: 'Doubao-1.5-vision-pro-32k',
165
+ maxOutput: 12_000,
166
+ pricing: {
167
+ currency: 'CNY',
168
+ input: 3,
169
+ output: 9,
170
+ },
171
+ releasedAt: '2025-01-15',
172
+ type: 'chat',
173
+ },
174
+ {
175
+ abilities: {
176
+ vision: true,
177
+ },
178
+ config: {
179
+ deploymentName: 'doubao-vision-pro-32k-241028',
180
+ },
181
+ contextWindowTokens: 32_768,
182
+ description:
183
+ 'Doubao-vision 模型是豆包推出的多模态大模型,具备强大的图片理解与推理能力,以及精准的指令理解能力。模型在图像文本信息抽取、基于图像的推理任务上有展现出了强大的性能,能够应用于更复杂、更广泛的视觉问答任务。',
184
+ displayName: 'Doubao Vision Pro 32k',
185
+ id: 'Doubao-vision-pro-32k',
186
+ maxOutput: 4096,
187
+ pricing: {
188
+ currency: 'CNY',
189
+ input: 3,
190
+ output: 9,
191
+ },
192
+ releasedAt: '2024-10-28',
193
+ type: 'chat',
194
+ },
195
+ {
196
+ abilities: {
197
+ vision: true,
198
+ },
199
+ config: {
200
+ deploymentName: 'doubao-vision-lite-32k-241015',
201
+ },
202
+ contextWindowTokens: 32_768,
203
+ description:
204
+ 'Doubao-vision 模型是豆包推出的多模态大模型,具备强大的图片理解与推理能力,以及精准的指令理解能力。模型在图像文本信息抽取、基于图像的推理任务上有展现出了强大的性能,能够应用于更复杂、更广泛的视觉问答任务。',
205
+ displayName: 'Doubao Vision Lite 32k',
206
+ id: 'Doubao-vision-lite-32k',
207
+ maxOutput: 4096,
208
+ pricing: {
209
+ currency: 'CNY',
210
+ input: 1.5,
211
+ output: 4.5,
212
+ },
213
+ releasedAt: '2024-10-15',
26
214
  type: 'chat',
27
215
  },
28
216
  {
@@ -31,22 +219,46 @@ const doubaoChatModels: AIChatModelCard[] = [
31
219
  '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 4k 上下文窗口的推理和精调。',
32
220
  displayName: 'Doubao Lite 4k',
33
221
  id: 'Doubao-lite-4k',
222
+ maxOutput: 4096,
223
+ pricing: {
224
+ currency: 'CNY',
225
+ input: 0.3,
226
+ output: 0.6,
227
+ },
34
228
  type: 'chat',
35
229
  },
36
230
  {
231
+ config: {
232
+ deploymentName: 'doubao-lite-32k-240828',
233
+ },
37
234
  contextWindowTokens: 32_768,
38
235
  description:
39
236
  '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 32k 上下文窗口的推理和精调。',
40
237
  displayName: 'Doubao Lite 32k',
41
238
  id: 'Doubao-lite-32k',
239
+ maxOutput: 4096,
240
+ pricing: {
241
+ currency: 'CNY',
242
+ input: 0.3,
243
+ output: 0.6,
244
+ },
42
245
  type: 'chat',
43
246
  },
44
247
  {
248
+ config: {
249
+ deploymentName: 'doubao-lite-128k-240828',
250
+ },
45
251
  contextWindowTokens: 128_000,
46
252
  description:
47
253
  '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 128k 上下文窗口的推理和精调。',
48
254
  displayName: 'Doubao Lite 128k',
49
255
  id: 'Doubao-lite-128k',
256
+ maxOutput: 4096,
257
+ pricing: {
258
+ currency: 'CNY',
259
+ input: 0.8,
260
+ output: 1,
261
+ },
50
262
  type: 'chat',
51
263
  },
52
264
  {
@@ -55,17 +267,29 @@ const doubaoChatModels: AIChatModelCard[] = [
55
267
  '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 4k 上下文窗口的推理和精调。',
56
268
  displayName: 'Doubao Pro 4k',
57
269
  id: 'Doubao-pro-4k',
270
+ maxOutput: 4096,
271
+ pricing: {
272
+ currency: 'CNY',
273
+ input: 0.8,
274
+ output: 2,
275
+ },
58
276
  type: 'chat',
59
277
  },
60
278
  {
61
279
  config: {
62
- deploymentName: 'Doubao-pro-test',
280
+ deploymentName: 'doubao-pro-32k-241215',
63
281
  },
64
282
  contextWindowTokens: 32_768,
65
283
  description:
66
284
  '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 32k 上下文窗口的推理和精调。',
67
285
  displayName: 'Doubao Pro 32k',
68
286
  id: 'Doubao-pro-32k',
287
+ maxOutput: 4096,
288
+ pricing: {
289
+ currency: 'CNY',
290
+ input: 0.8,
291
+ output: 2,
292
+ },
69
293
  type: 'chat',
70
294
  },
71
295
  {
@@ -74,6 +298,29 @@ const doubaoChatModels: AIChatModelCard[] = [
74
298
  '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 128k 上下文窗口的推理和精调。',
75
299
  displayName: 'Doubao Pro 128k',
76
300
  id: 'Doubao-pro-128k',
301
+ maxOutput: 4096,
302
+ pricing: {
303
+ currency: 'CNY',
304
+ input: 5,
305
+ output: 9,
306
+ },
307
+ type: 'chat',
308
+ },
309
+ {
310
+ config: {
311
+ deploymentName: 'doubao-pro-256k-241115',
312
+ },
313
+ contextWindowTokens: 256_000,
314
+ description:
315
+ '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 256k 上下文窗口的推理和精调。',
316
+ displayName: 'Doubao Pro 256k',
317
+ id: 'Doubao-pro-256k',
318
+ maxOutput: 4096,
319
+ pricing: {
320
+ currency: 'CNY',
321
+ input: 5,
322
+ output: 9,
323
+ },
77
324
  type: 'chat',
78
325
  },
79
326
  ];
@@ -115,21 +115,34 @@ export class AiProviderModel {
115
115
  const encrypt = encryptor ?? defaultSerialize;
116
116
  const keyVaults = await encrypt(JSON.stringify(value.keyVaults));
117
117
 
118
+ const commonFields = {
119
+ checkModel: value.checkModel,
120
+ fetchOnClient: value.fetchOnClient,
121
+ keyVaults,
122
+ };
123
+
118
124
  return this.db
119
- .update(aiProviders)
120
- .set({ ...value, keyVaults, updatedAt: new Date() })
121
- .where(and(eq(aiProviders.id, id), eq(aiProviders.userId, this.userId)));
125
+ .insert(aiProviders)
126
+ .values({
127
+ ...commonFields,
128
+ id,
129
+ source: this.getProviderSource(id),
130
+ updatedAt: new Date(),
131
+ userId: this.userId,
132
+ })
133
+ .onConflictDoUpdate({
134
+ set: { ...commonFields, updatedAt: new Date() },
135
+ target: [aiProviders.id, aiProviders.userId],
136
+ });
122
137
  };
123
138
 
124
139
  toggleProviderEnabled = async (id: string, enabled: boolean) => {
125
- const isBuiltin = Object.values(ModelProvider).includes(id as any);
126
-
127
140
  return this.db
128
141
  .insert(aiProviders)
129
142
  .values({
130
143
  enabled,
131
144
  id,
132
- source: isBuiltin ? 'builtin' : 'custom',
145
+ source: this.getProviderSource(id),
133
146
  updatedAt: new Date(),
134
147
  userId: this.userId,
135
148
  })
@@ -142,15 +155,13 @@ export class AiProviderModel {
142
155
  updateOrder = async (sortMap: { id: string; sort: number }[]) => {
143
156
  await this.db.transaction(async (tx) => {
144
157
  const updates = sortMap.map(({ id, sort }) => {
145
- const isBuiltin = Object.values(ModelProvider).includes(id as any);
146
-
147
158
  return tx
148
159
  .insert(aiProviders)
149
160
  .values({
150
161
  enabled: true,
151
162
  id,
152
163
  sort,
153
- source: isBuiltin ? 'builtin' : 'custom',
164
+ source: this.getProviderSource(id),
154
165
  updatedAt: new Date(),
155
166
  userId: this.userId,
156
167
  })
@@ -238,4 +249,6 @@ export class AiProviderModel {
238
249
  };
239
250
 
240
251
  private isBuiltInProvider = (id: string) => Object.values(ModelProvider).includes(id as any);
252
+
253
+ private getProviderSource = (id: string) => (this.isBuiltInProvider(id) ? 'builtin' : 'custom');
241
254
  }
@@ -224,6 +224,7 @@ export class TopicModel {
224
224
  .insert(topics)
225
225
  .values({
226
226
  ...originalTopic,
227
+ clientId: null,
227
228
  id: this.genId(),
228
229
  title: newTitle || originalTopic?.title,
229
230
  })
@@ -242,6 +243,7 @@ export class TopicModel {
242
243
  .insert(messages)
243
244
  .values({
244
245
  ...message,
246
+ clientId: null,
245
247
  id: idGenerator('messages'),
246
248
  topicId: duplicatedTopic.id,
247
249
  })
@@ -0,0 +1,43 @@
1
+ import { Highlighter } from '@lobehub/ui';
2
+ import { Tabs } from 'antd';
3
+ import { memo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ interface DebugProps {
7
+ payload: object;
8
+ requestArgs?: string;
9
+ }
10
+
11
+ const Debug = memo<DebugProps>(({ payload, requestArgs }) => {
12
+ const { t } = useTranslation('plugin');
13
+ let params;
14
+ try {
15
+ params = JSON.stringify(JSON.parse(requestArgs || ''), null, 2);
16
+ } catch {
17
+ params = '';
18
+ }
19
+
20
+ return (
21
+ <Tabs
22
+ items={[
23
+ {
24
+ children: <Highlighter language={'json'}>{params}</Highlighter>,
25
+ key: 'arguments',
26
+ label: t('debug.arguments'),
27
+ },
28
+ {
29
+ children: <Highlighter language={'json'}>{JSON.stringify(payload, null, 2)}</Highlighter>,
30
+ key: 'function_call',
31
+ label: t('debug.function_call'),
32
+ },
33
+ // {
34
+ // children: <PluginResult content={content} />,
35
+ // key: 'response',
36
+ // label: t('debug.response'),
37
+ // },
38
+ ]}
39
+ style={{ display: 'grid', maxWidth: 800, minWidth: 400 }}
40
+ />
41
+ );
42
+ });
43
+ export default Debug;
@@ -0,0 +1,58 @@
1
+ import { createStyles } from 'antd-style';
2
+
3
+ export const useStyles = createStyles(({ css, token }, borderWidth: number = 2.5) => ({
4
+ background: css`
5
+ position: absolute;
6
+ inset: 0;
7
+
8
+ aspect-ratio: 1;
9
+ width: 100%;
10
+ border-radius: 50%;
11
+
12
+ background: ${token.colorFill};
13
+
14
+ mask: radial-gradient(farthest-side, #0000 calc(100% - ${borderWidth}px), #000 0);
15
+ `,
16
+ container: css`
17
+ position: relative;
18
+ width: 13px;
19
+ height: 13px;
20
+ `,
21
+
22
+ loader: css`
23
+ position: absolute;
24
+ inset: 0;
25
+
26
+ aspect-ratio: 1;
27
+ width: 100%;
28
+ border-radius: 50%;
29
+
30
+ background:
31
+ radial-gradient(farthest-side, ${token.colorTextSecondary} 94%, #0000) top/ ${borderWidth}px
32
+ ${borderWidth}px no-repeat,
33
+ conic-gradient(#0000 50%, ${token.colorTextSecondary});
34
+
35
+ mask: radial-gradient(farthest-side, #0000 calc(100% - ${borderWidth}px), #000 0);
36
+
37
+ animation: small-loader-anim 1s infinite linear;
38
+
39
+ @keyframes small-loader-anim {
40
+ 100% {
41
+ transform: rotate(1turn);
42
+ }
43
+ }
44
+ `,
45
+ }));
46
+
47
+ const Loader = () => {
48
+ const { styles } = useStyles();
49
+
50
+ return (
51
+ <div className={styles.container}>
52
+ <div className={styles.loader} />
53
+ <div className={styles.background} />
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export default Loader;