@lobehub/chat 1.48.2 → 1.48.4
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 +50 -0
- package/changelog/v1.json +18 -0
- package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +197 -194
- package/locales/ar/chat.json +0 -4
- package/locales/ar/components.json +5 -0
- package/locales/bg-BG/chat.json +0 -4
- package/locales/bg-BG/components.json +5 -0
- package/locales/de-DE/chat.json +0 -4
- package/locales/de-DE/components.json +5 -0
- package/locales/en-US/chat.json +0 -4
- package/locales/en-US/components.json +5 -0
- package/locales/es-ES/chat.json +0 -4
- package/locales/es-ES/components.json +5 -0
- package/locales/fa-IR/chat.json +0 -4
- package/locales/fa-IR/components.json +5 -0
- package/locales/fr-FR/chat.json +0 -4
- package/locales/fr-FR/components.json +5 -0
- package/locales/it-IT/chat.json +0 -4
- package/locales/it-IT/components.json +5 -0
- package/locales/ja-JP/chat.json +0 -4
- package/locales/ja-JP/components.json +5 -0
- package/locales/ko-KR/chat.json +0 -4
- package/locales/ko-KR/components.json +5 -0
- package/locales/nl-NL/chat.json +0 -4
- package/locales/nl-NL/components.json +5 -0
- package/locales/pl-PL/chat.json +0 -4
- package/locales/pl-PL/components.json +5 -0
- package/locales/pt-BR/chat.json +0 -4
- package/locales/pt-BR/components.json +5 -0
- package/locales/ru-RU/chat.json +0 -4
- package/locales/ru-RU/components.json +5 -0
- package/locales/tr-TR/chat.json +0 -4
- package/locales/tr-TR/components.json +5 -0
- package/locales/vi-VN/chat.json +0 -4
- package/locales/vi-VN/components.json +5 -0
- package/locales/zh-CN/chat.json +0 -4
- package/locales/zh-CN/components.json +5 -0
- package/locales/zh-TW/chat.json +0 -4
- package/locales/zh-TW/components.json +5 -0
- package/package.json +1 -1
- package/src/app/(main)/settings/provider/features/ModelList/ModelItem.tsx +31 -36
- package/src/components/Thinking/index.tsx +137 -0
- package/src/const/currency.ts +2 -0
- package/src/const/discover.ts +0 -2
- package/src/features/Conversation/Messages/Assistant/Reasoning/index.tsx +6 -110
- package/src/locales/default/chat.ts +0 -4
- package/src/locales/default/components.ts +5 -0
- package/src/utils/format.test.ts +2 -9
- package/src/utils/format.ts +2 -2
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "No enabled model. Please go to settings to enable.",
|
87
87
|
"provider": "Provider"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Deep in thought...",
|
91
|
+
"thought": "Thought deeply",
|
92
|
+
"thoughtWithDuration": "Thought deeply (took {{duration}} seconds)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/es-ES/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Pensando profundamente",
|
87
|
-
"thought": "He reflexionado profundamente (durante {{duration}} segundos)"
|
88
|
-
},
|
89
85
|
"regenerate": "Regenerar",
|
90
86
|
"roleAndArchive": "Rol y archivo",
|
91
87
|
"searchAgentPlaceholder": "Asistente de búsqueda...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "No hay modelos habilitados. Vaya a la configuración para habilitarlos.",
|
87
87
|
"provider": "Proveedor"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Pensando profundamente...",
|
91
|
+
"thought": "He pensado profundamente",
|
92
|
+
"thoughtWithDuration": "He pensado profundamente (durante {{duration}} segundos)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/fa-IR/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "در حال تفکر عمیق",
|
87
|
-
"thought": "به طور عمیق فکر شده است (زمان صرف شده: {{duration}} ثانیه)"
|
88
|
-
},
|
89
85
|
"regenerate": "بازتولید",
|
90
86
|
"roleAndArchive": "نقشها و بایگانی",
|
91
87
|
"searchAgentPlaceholder": "جستجوی دستیار...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "هیچ مدلی فعال نیست، لطفاً به تنظیمات بروید و آن را فعال کنید",
|
87
87
|
"provider": "ارائهدهنده"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "در حال تفکر عمیق...",
|
91
|
+
"thought": "تفکر عمیق انجام شد",
|
92
|
+
"thoughtWithDuration": "تفکر عمیق انجام شد (مدت زمان {{duration}} ثانیه)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/fr-FR/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "En pleine réflexion profonde",
|
87
|
-
"thought": "J'ai réfléchi en profondeur (durée : {{duration}} secondes)"
|
88
|
-
},
|
89
85
|
"regenerate": "Regénérer",
|
90
86
|
"roleAndArchive": "Rôle et archivage",
|
91
87
|
"searchAgentPlaceholder": "Assistant de recherche...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Aucun modèle activé. Veuillez vous rendre dans les paramètres pour l'activer.",
|
87
87
|
"provider": "Fournisseur"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "En pleine réflexion...",
|
91
|
+
"thought": "Réflexion terminée",
|
92
|
+
"thoughtWithDuration": "Réflexion terminée (durée : {{duration}} secondes)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/it-IT/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "In profonda riflessione",
|
87
|
-
"thought": "Pensato in profondità (tempo impiegato {{duration}} secondi)"
|
88
|
-
},
|
89
85
|
"regenerate": "Rigenera",
|
90
86
|
"roleAndArchive": "Ruolo e archivio",
|
91
87
|
"searchAgentPlaceholder": "Assistente di ricerca...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Nessun modello attivo. Vai alle impostazioni per attivarne uno.",
|
87
87
|
"provider": "Provider"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Pensando profondamente...",
|
91
|
+
"thought": "Pensato profondamente",
|
92
|
+
"thoughtWithDuration": "Pensato profondamente (tempo impiegato {{duration}} secondi)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/ja-JP/chat.json
CHANGED
package/locales/ko-KR/chat.json
CHANGED
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "활성화된 모델이 없습니다. 설정으로 이동하여 활성화하세요",
|
87
87
|
"provider": "제공자"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "심층적으로 생각 중...",
|
91
|
+
"thought": "심층적으로 생각했습니다",
|
92
|
+
"thoughtWithDuration": "심층적으로 생각했습니다 (소요 시간: {{duration}} 초)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/nl-NL/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Diep aan het denken",
|
87
|
-
"thought": "Diep nagedacht (tijd: {{duration}} seconden)"
|
88
|
-
},
|
89
85
|
"regenerate": "Opnieuw genereren",
|
90
86
|
"roleAndArchive": "Rol en archief",
|
91
87
|
"searchAgentPlaceholder": "Zoekassistent...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "No enabled model, please go to settings to enable.",
|
87
87
|
"provider": "Provider"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Diep in gedachten...",
|
91
|
+
"thought": "Diep nagedacht",
|
92
|
+
"thoughtWithDuration": "Diep nagedacht (geduurd {{duration}} seconden)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/pl-PL/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Głęboko myślę",
|
87
|
-
"thought": "Głęboko myślałem (czas: {{duration}} sekund)"
|
88
|
-
},
|
89
85
|
"regenerate": "Wygeneruj ponownie",
|
90
86
|
"roleAndArchive": "Rola i archiwum",
|
91
87
|
"searchAgentPlaceholder": "Wyszukaj pomocnika...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Brak włączonych modeli, przejdź do ustawień i włącz je",
|
87
87
|
"provider": "Dostawca"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Głęboko myślę...",
|
91
|
+
"thought": "Już głęboko myślałem",
|
92
|
+
"thoughtWithDuration": "Już głęboko myślałem (czas: {{duration}} sekund)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/pt-BR/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Pensando profundamente",
|
87
|
-
"thought": "Pensou profundamente (tempo gasto: {{duration}} segundos)"
|
88
|
-
},
|
89
85
|
"regenerate": "Regenerar",
|
90
86
|
"roleAndArchive": "Função e Arquivo",
|
91
87
|
"searchAgentPlaceholder": "Assistente de busca...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Nenhum modelo habilitado. Por favor, vá para as configurações e habilite um.",
|
87
87
|
"provider": "Fornecedor"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Pensando profundamente...",
|
91
|
+
"thought": "Pensamento profundo concluído",
|
92
|
+
"thoughtWithDuration": "Pensamento profundo concluído (durante {{duration}} segundos)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/ru-RU/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Глубокое размышление",
|
87
|
-
"thought": "Глубоко размышлял (время: {{duration}} секунд)"
|
88
|
-
},
|
89
85
|
"regenerate": "Сгенерировать заново",
|
90
86
|
"roleAndArchive": "Роль и архив",
|
91
87
|
"searchAgentPlaceholder": "Поиск помощника...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Нет активированных моделей. Пожалуйста, перейдите в настройки и включите модель",
|
87
87
|
"provider": "Поставщик"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Глубокое размышление...",
|
91
|
+
"thought": "Глубоко размышлено",
|
92
|
+
"thoughtWithDuration": "Глубоко размышлено (время: {{duration}} секунд)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/tr-TR/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Derin düşünme aşamasında",
|
87
|
-
"thought": "Derinlemesine düşündü (geçen süre {{duration}} saniye)"
|
88
|
-
},
|
89
85
|
"regenerate": "Tekrarla",
|
90
86
|
"roleAndArchive": "Rol ve Arşiv",
|
91
87
|
"searchAgentPlaceholder": "Arama Asistanı...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Etkinleştirilmiş model bulunmamaktadır, lütfen ayarlara giderek açın",
|
87
87
|
"provider": "Sağlayıcı"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Derin düşünme aşamasında...",
|
91
|
+
"thought": "Derin düşünme tamamlandı",
|
92
|
+
"thoughtWithDuration": "Derin düşünme tamamlandı (geçen süre {{duration}} saniye)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/vi-VN/chat.json
CHANGED
@@ -82,10 +82,6 @@
|
|
82
82
|
}
|
83
83
|
}
|
84
84
|
},
|
85
|
-
"reasoning": {
|
86
|
-
"thinking": "Đang suy nghĩ sâu sắc",
|
87
|
-
"thought": "Đã suy nghĩ sâu sắc (thời gian: {{duration}} giây)"
|
88
|
-
},
|
89
85
|
"regenerate": "Tạo lại",
|
90
86
|
"roleAndArchive": "Vai trò và lưu trữ",
|
91
87
|
"searchAgentPlaceholder": "Trợ lý tìm kiếm...",
|
@@ -85,5 +85,10 @@
|
|
85
85
|
"ModelSwitchPanel": {
|
86
86
|
"emptyModel": "Không có mô hình nào được kích hoạt, vui lòng điều chỉnh trong cài đặt",
|
87
87
|
"provider": "Nhà cung cấp"
|
88
|
+
},
|
89
|
+
"Thinking": {
|
90
|
+
"thinking": "Đang suy nghĩ sâu sắc...",
|
91
|
+
"thought": "Đã suy nghĩ sâu sắc",
|
92
|
+
"thoughtWithDuration": "Đã suy nghĩ sâu sắc (thời gian: {{duration}} giây)"
|
88
93
|
}
|
89
94
|
}
|
package/locales/zh-CN/chat.json
CHANGED
package/locales/zh-TW/chat.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.48.
|
3
|
+
"version": "1.48.4",
|
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",
|
@@ -11,12 +11,10 @@ import { ModelInfoTags } from '@/components/ModelSelect';
|
|
11
11
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
12
12
|
import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
|
13
13
|
import { AiModelSourceEnum, AiProviderModelListItem, ChatModelPricing } from '@/types/aiModel';
|
14
|
+
import { formatPriceByCurrency } from '@/utils/format';
|
14
15
|
|
15
16
|
import ModelConfigModal from './ModelConfigModal';
|
16
17
|
|
17
|
-
const f = (number: number | undefined, text: string) =>
|
18
|
-
typeof number !== 'undefined' ? text : undefined;
|
19
|
-
|
20
18
|
export const useStyles = createStyles(({ css, token, cx }) => {
|
21
19
|
const config = css`
|
22
20
|
opacity: 0;
|
@@ -74,7 +72,7 @@ const ModelItem = memo<ModelItemProps>(
|
|
74
72
|
type,
|
75
73
|
}) => {
|
76
74
|
const { styles } = useStyles();
|
77
|
-
const { t } = useTranslation(['modelProvider', 'components', 'models']);
|
75
|
+
const { t } = useTranslation(['modelProvider', 'components', 'models', 'common']);
|
78
76
|
const theme = useTheme();
|
79
77
|
|
80
78
|
const [activeAiProvider, isModelLoading, toggleModelEnabled, removeAiModel] = useAiInfraStore(
|
@@ -90,41 +88,43 @@ const ModelItem = memo<ModelItemProps>(
|
|
90
88
|
const [showConfig, setShowConfig] = useState(false);
|
91
89
|
|
92
90
|
const formatPricing = (): string[] => {
|
91
|
+
if (!pricing) return [];
|
92
|
+
|
93
93
|
switch (type) {
|
94
94
|
case 'chat': {
|
95
95
|
return [
|
96
|
-
|
97
|
-
pricing
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
pricing
|
102
|
-
|
103
|
-
|
96
|
+
typeof pricing.input === 'number' &&
|
97
|
+
t('providerModels.item.pricing.inputTokens', {
|
98
|
+
amount: formatPriceByCurrency(pricing.input, pricing?.currency),
|
99
|
+
}),
|
100
|
+
typeof pricing.output === 'number' &&
|
101
|
+
t('providerModels.item.pricing.outputTokens', {
|
102
|
+
amount: formatPriceByCurrency(pricing.output, pricing?.currency),
|
103
|
+
}),
|
104
104
|
].filter(Boolean) as string[];
|
105
105
|
}
|
106
106
|
case 'embedding': {
|
107
107
|
return [
|
108
|
-
|
109
|
-
pricing
|
110
|
-
|
111
|
-
|
108
|
+
typeof pricing.input === 'number' &&
|
109
|
+
t('providerModels.item.pricing.inputTokens', {
|
110
|
+
amount: formatPriceByCurrency(pricing.input, pricing?.currency),
|
111
|
+
}),
|
112
112
|
].filter(Boolean) as string[];
|
113
113
|
}
|
114
114
|
case 'tts': {
|
115
115
|
return [
|
116
|
-
|
117
|
-
pricing
|
118
|
-
|
119
|
-
|
116
|
+
typeof pricing.input === 'number' &&
|
117
|
+
t('providerModels.item.pricing.inputCharts', {
|
118
|
+
amount: formatPriceByCurrency(pricing.input, pricing?.currency),
|
119
|
+
}),
|
120
120
|
].filter(Boolean) as string[];
|
121
121
|
}
|
122
122
|
case 'stt': {
|
123
123
|
return [
|
124
|
-
|
125
|
-
pricing
|
126
|
-
|
127
|
-
|
124
|
+
typeof pricing.input === 'number' &&
|
125
|
+
t('providerModels.item.pricing.inputMinutes', {
|
126
|
+
amount: formatPriceByCurrency(pricing.input, pricing?.currency),
|
127
|
+
}),
|
128
128
|
].filter(Boolean) as string[];
|
129
129
|
}
|
130
130
|
|
@@ -142,7 +142,12 @@ const ModelItem = memo<ModelItemProps>(
|
|
142
142
|
releasedAt && t('providerModels.item.releasedAt', { releasedAt }),
|
143
143
|
...formatPricing(),
|
144
144
|
].filter(Boolean) as string[];
|
145
|
+
|
145
146
|
const { message, modal } = App.useApp();
|
147
|
+
const copyModelId = async () => {
|
148
|
+
await copyToClipboard(id);
|
149
|
+
message.success({ content: t('copySuccess', { ns: 'common' }) });
|
150
|
+
};
|
146
151
|
|
147
152
|
const isMobile = useIsMobile();
|
148
153
|
|
@@ -179,12 +184,7 @@ const ModelItem = memo<ModelItemProps>(
|
|
179
184
|
</Flexbox>
|
180
185
|
</Flexbox>
|
181
186
|
<div>
|
182
|
-
<Tag
|
183
|
-
onClick={() => {
|
184
|
-
copyToClipboard(id);
|
185
|
-
}}
|
186
|
-
style={{ cursor: 'pointer', marginRight: 0 }}
|
187
|
-
>
|
187
|
+
<Tag onClick={copyModelId} style={{ cursor: 'pointer', marginRight: 0 }}>
|
188
188
|
{id}
|
189
189
|
</Tag>
|
190
190
|
</div>
|
@@ -251,12 +251,7 @@ const ModelItem = memo<ModelItemProps>(
|
|
251
251
|
<Flexbox flex={1} gap={2} style={{ minWidth: 0 }}>
|
252
252
|
<Flexbox align={'center'} gap={8} horizontal>
|
253
253
|
{displayName || id}
|
254
|
-
<Tag
|
255
|
-
onClick={() => {
|
256
|
-
copyToClipboard(id);
|
257
|
-
}}
|
258
|
-
style={{ cursor: 'pointer', marginRight: 0 }}
|
259
|
-
>
|
254
|
+
<Tag onClick={copyModelId} style={{ cursor: 'pointer', marginRight: 0 }}>
|
260
255
|
{id}
|
261
256
|
</Tag>
|
262
257
|
<Flexbox className={styles.config} horizontal>
|
@@ -0,0 +1,137 @@
|
|
1
|
+
import { Icon, Markdown } from '@lobehub/ui';
|
2
|
+
import { createStyles } from 'antd-style';
|
3
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
4
|
+
import { AtomIcon, ChevronDown, ChevronRight } from 'lucide-react';
|
5
|
+
import { rgba } from 'polished';
|
6
|
+
import { memo, useEffect, useState } from 'react';
|
7
|
+
import { useTranslation } from 'react-i18next';
|
8
|
+
import { Flexbox } from 'react-layout-kit';
|
9
|
+
|
10
|
+
const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
11
|
+
container: css`
|
12
|
+
cursor: pointer;
|
13
|
+
|
14
|
+
width: fit-content;
|
15
|
+
padding-block: 4px;
|
16
|
+
padding-inline: 8px;
|
17
|
+
border-radius: 6px;
|
18
|
+
|
19
|
+
color: ${token.colorTextTertiary};
|
20
|
+
|
21
|
+
&:hover {
|
22
|
+
background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary};
|
23
|
+
}
|
24
|
+
`,
|
25
|
+
expand: css`
|
26
|
+
background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary} !important;
|
27
|
+
`,
|
28
|
+
shinyText: css`
|
29
|
+
color: ${rgba(token.colorText, 0.45)};
|
30
|
+
|
31
|
+
background: linear-gradient(
|
32
|
+
120deg,
|
33
|
+
${rgba(token.colorTextBase, 0)} 40%,
|
34
|
+
${token.colorTextSecondary} 50%,
|
35
|
+
${rgba(token.colorTextBase, 0)} 60%
|
36
|
+
);
|
37
|
+
background-clip: text;
|
38
|
+
background-size: 200% 100%;
|
39
|
+
|
40
|
+
animation: shine 1.5s linear infinite;
|
41
|
+
|
42
|
+
@keyframes shine {
|
43
|
+
0% {
|
44
|
+
background-position: 100%;
|
45
|
+
}
|
46
|
+
|
47
|
+
100% {
|
48
|
+
background-position: -100%;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
`,
|
52
|
+
title: css`
|
53
|
+
overflow: hidden;
|
54
|
+
display: -webkit-box;
|
55
|
+
-webkit-box-orient: vertical;
|
56
|
+
-webkit-line-clamp: 1;
|
57
|
+
|
58
|
+
font-size: 12px;
|
59
|
+
text-overflow: ellipsis;
|
60
|
+
`,
|
61
|
+
}));
|
62
|
+
|
63
|
+
interface ThinkingProps {
|
64
|
+
content?: string;
|
65
|
+
duration?: number;
|
66
|
+
thinking?: boolean;
|
67
|
+
}
|
68
|
+
|
69
|
+
const Thinking = memo<ThinkingProps>(({ content = '', duration, thinking }) => {
|
70
|
+
const { t } = useTranslation('components');
|
71
|
+
const { styles, cx } = useStyles();
|
72
|
+
|
73
|
+
const [showDetail, setShowDetail] = useState(false);
|
74
|
+
|
75
|
+
useEffect(() => {
|
76
|
+
if (thinking && !content) {
|
77
|
+
setShowDetail(true);
|
78
|
+
}
|
79
|
+
|
80
|
+
if (!thinking) {
|
81
|
+
setShowDetail(false);
|
82
|
+
}
|
83
|
+
}, [thinking, content]);
|
84
|
+
|
85
|
+
return (
|
86
|
+
<Flexbox
|
87
|
+
className={cx(styles.container, showDetail && styles.expand)}
|
88
|
+
gap={16}
|
89
|
+
onClick={() => {
|
90
|
+
setShowDetail(!showDetail);
|
91
|
+
}}
|
92
|
+
>
|
93
|
+
<Flexbox distribution={'space-between'} flex={1} horizontal>
|
94
|
+
{thinking ? (
|
95
|
+
<Flexbox gap={8} horizontal>
|
96
|
+
<Icon icon={AtomIcon} />
|
97
|
+
<Flexbox className={styles.shinyText} horizontal>
|
98
|
+
{t('Thinking.thinking')}
|
99
|
+
</Flexbox>
|
100
|
+
</Flexbox>
|
101
|
+
) : (
|
102
|
+
<Flexbox gap={8} horizontal>
|
103
|
+
<Icon icon={AtomIcon} />
|
104
|
+
{typeof duration === 'undefined'
|
105
|
+
? t('Thinking.thoughtWithDuration')
|
106
|
+
: t('Thinking.thought', { duration: ((duration || 0) / 1000).toFixed(1) })}
|
107
|
+
</Flexbox>
|
108
|
+
)}
|
109
|
+
<Icon icon={showDetail ? ChevronDown : ChevronRight} />
|
110
|
+
</Flexbox>
|
111
|
+
|
112
|
+
<AnimatePresence initial={false}>
|
113
|
+
{showDetail && (
|
114
|
+
<motion.div
|
115
|
+
animate="open"
|
116
|
+
exit="collapsed"
|
117
|
+
initial="collapsed"
|
118
|
+
style={{ overflow: 'hidden' }}
|
119
|
+
transition={{
|
120
|
+
duration: 0.2,
|
121
|
+
ease: [0.4, 0, 0.2, 1], // 使用 ease-out 缓动函数
|
122
|
+
}}
|
123
|
+
variants={{
|
124
|
+
collapsed: { height: 0, opacity: 0, width: 'auto' },
|
125
|
+
open: { height: 'auto', opacity: 1, width: 'auto' },
|
126
|
+
}}
|
127
|
+
>
|
128
|
+
<Markdown variant={'chat'}>{content}</Markdown>
|
129
|
+
</motion.div>
|
130
|
+
)}
|
131
|
+
{/*<Flexbox></Flexbox>*/}
|
132
|
+
</AnimatePresence>
|
133
|
+
</Flexbox>
|
134
|
+
);
|
135
|
+
});
|
136
|
+
|
137
|
+
export default Thinking;
|
package/src/const/discover.ts
CHANGED