@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
@@ -1,123 +1,19 @@
|
|
1
|
-
import {
|
2
|
-
import { createStyles } from 'antd-style';
|
3
|
-
import { AtomIcon, ChevronDown, ChevronRight } from 'lucide-react';
|
4
|
-
import { rgba } from 'polished';
|
5
|
-
import { memo, useEffect, useState } from 'react';
|
6
|
-
import { useTranslation } from 'react-i18next';
|
7
|
-
import { Flexbox } from 'react-layout-kit';
|
1
|
+
import { memo } from 'react';
|
8
2
|
|
3
|
+
import Thinking from '@/components/Thinking';
|
9
4
|
import { useChatStore } from '@/store/chat';
|
10
5
|
import { aiChatSelectors } from '@/store/chat/selectors';
|
11
6
|
|
12
|
-
|
13
|
-
container: css`
|
14
|
-
cursor: pointer;
|
15
|
-
|
16
|
-
width: fit-content;
|
17
|
-
padding-block: 4px;
|
18
|
-
padding-inline: 8px;
|
19
|
-
border-radius: 6px;
|
20
|
-
|
21
|
-
color: ${token.colorTextTertiary};
|
22
|
-
|
23
|
-
&:hover {
|
24
|
-
background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary};
|
25
|
-
}
|
26
|
-
`,
|
27
|
-
expand: css`
|
28
|
-
background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary} !important;
|
29
|
-
`,
|
30
|
-
shinyText: css`
|
31
|
-
color: ${rgba(token.colorText, 0.45)};
|
32
|
-
|
33
|
-
background: linear-gradient(
|
34
|
-
120deg,
|
35
|
-
${rgba(token.colorTextBase, 0)} 40%,
|
36
|
-
${token.colorTextSecondary} 50%,
|
37
|
-
${rgba(token.colorTextBase, 0)} 60%
|
38
|
-
);
|
39
|
-
background-clip: text;
|
40
|
-
background-size: 200% 100%;
|
41
|
-
|
42
|
-
animation: shine 1.5s linear infinite;
|
43
|
-
|
44
|
-
@keyframes shine {
|
45
|
-
0% {
|
46
|
-
background-position: 100%;
|
47
|
-
}
|
48
|
-
|
49
|
-
100% {
|
50
|
-
background-position: -100%;
|
51
|
-
}
|
52
|
-
}
|
53
|
-
`,
|
54
|
-
title: css`
|
55
|
-
overflow: hidden;
|
56
|
-
display: -webkit-box;
|
57
|
-
-webkit-box-orient: vertical;
|
58
|
-
-webkit-line-clamp: 1;
|
59
|
-
|
60
|
-
font-size: 12px;
|
61
|
-
text-overflow: ellipsis;
|
62
|
-
`,
|
63
|
-
}));
|
64
|
-
|
65
|
-
interface ThinkingProps {
|
7
|
+
interface ReasoningProps {
|
66
8
|
content?: string;
|
67
9
|
duration?: number;
|
68
10
|
id: string;
|
69
11
|
}
|
70
12
|
|
71
|
-
const
|
72
|
-
const { t } = useTranslation('chat');
|
73
|
-
const { styles, cx } = useStyles();
|
74
|
-
|
75
|
-
const [showDetail, setShowDetail] = useState(false);
|
76
|
-
|
13
|
+
const Reasoning = memo<ReasoningProps>(({ content = '', duration, id }) => {
|
77
14
|
const isReasoning = useChatStore(aiChatSelectors.isMessageInReasoning(id));
|
78
15
|
|
79
|
-
|
80
|
-
if (isReasoning && !content) {
|
81
|
-
setShowDetail(true);
|
82
|
-
}
|
83
|
-
|
84
|
-
if (!isReasoning) {
|
85
|
-
setShowDetail(false);
|
86
|
-
}
|
87
|
-
}, [isReasoning, content]);
|
88
|
-
|
89
|
-
return (
|
90
|
-
<Flexbox
|
91
|
-
className={cx(styles.container, showDetail && styles.expand)}
|
92
|
-
gap={16}
|
93
|
-
onClick={() => {
|
94
|
-
setShowDetail(!showDetail);
|
95
|
-
}}
|
96
|
-
>
|
97
|
-
<Flexbox distribution={'space-between'} flex={1} horizontal>
|
98
|
-
{isReasoning ? (
|
99
|
-
<Flexbox gap={8} horizontal>
|
100
|
-
<Icon icon={AtomIcon} />
|
101
|
-
<Flexbox className={styles.shinyText} horizontal>
|
102
|
-
{t('reasoning.thinking')}
|
103
|
-
</Flexbox>
|
104
|
-
</Flexbox>
|
105
|
-
) : (
|
106
|
-
<Flexbox gap={8} horizontal>
|
107
|
-
<Icon icon={AtomIcon} />
|
108
|
-
{t('reasoning.thought', { duration: ((duration || 0) / 1000).toFixed(1) })}
|
109
|
-
</Flexbox>
|
110
|
-
)}
|
111
|
-
<Icon icon={showDetail ? ChevronDown : ChevronRight} />
|
112
|
-
</Flexbox>
|
113
|
-
|
114
|
-
{showDetail && (
|
115
|
-
<Flexbox>
|
116
|
-
<Markdown variant={'chat'}>{content}</Markdown>
|
117
|
-
</Flexbox>
|
118
|
-
)}
|
119
|
-
</Flexbox>
|
120
|
-
);
|
16
|
+
return <Thinking content={content} duration={duration} thinking={isReasoning} />;
|
121
17
|
});
|
122
18
|
|
123
|
-
export default
|
19
|
+
export default Reasoning;
|
package/src/utils/format.test.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import dayjs from 'dayjs';
|
2
2
|
import { describe, expect, it } from 'vitest';
|
3
3
|
|
4
|
-
import {
|
4
|
+
import { USD_TO_CNY } from '@/const/currency';
|
5
5
|
|
6
6
|
import {
|
7
7
|
formatDate,
|
@@ -194,16 +194,9 @@ describe('format', () => {
|
|
194
194
|
expect(formatPriceByCurrency(1234.56, 'USD')).toBe('1,234.56');
|
195
195
|
});
|
196
196
|
|
197
|
-
it('should format CNY prices correctly', () => {
|
198
|
-
// Assuming CNY_TO_USD is 6.5
|
199
|
-
const CNY_TO_USD = 6.5;
|
200
|
-
expect(formatPriceByCurrency(1000, 'CNY')).toBe('140.06');
|
201
|
-
expect(formatPriceByCurrency(6500, 'CNY')).toBe('910.36');
|
202
|
-
});
|
203
|
-
|
204
197
|
it('should use the correct CNY_TO_USD conversion rate', () => {
|
205
198
|
const price = 1000;
|
206
|
-
const expectedCNY = formatPrice(price /
|
199
|
+
const expectedCNY = formatPrice(price / USD_TO_CNY);
|
207
200
|
expect(formatPriceByCurrency(price, 'CNY')).toBe(expectedCNY);
|
208
201
|
});
|
209
202
|
});
|
package/src/utils/format.ts
CHANGED
@@ -2,7 +2,7 @@ import dayjs from 'dayjs';
|
|
2
2
|
import { isNumber } from 'lodash-es';
|
3
3
|
import numeral from 'numeral';
|
4
4
|
|
5
|
-
import {
|
5
|
+
import { USD_TO_CNY } from '@/const/currency';
|
6
6
|
import { ModelPriceCurrency } from '@/types/llm';
|
7
7
|
|
8
8
|
export const formatSize = (bytes: number, fractionDigits: number = 1): string => {
|
@@ -118,7 +118,7 @@ export const formatPrice = (price: number, fractionDigits: number = 2) => {
|
|
118
118
|
|
119
119
|
export const formatPriceByCurrency = (price: number, currency?: ModelPriceCurrency) => {
|
120
120
|
if (currency === 'CNY') {
|
121
|
-
return formatPrice(price /
|
121
|
+
return formatPrice(price / USD_TO_CNY);
|
122
122
|
}
|
123
123
|
return formatPrice(price);
|
124
124
|
};
|