@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +197 -194
  4. package/locales/ar/chat.json +0 -4
  5. package/locales/ar/components.json +5 -0
  6. package/locales/bg-BG/chat.json +0 -4
  7. package/locales/bg-BG/components.json +5 -0
  8. package/locales/de-DE/chat.json +0 -4
  9. package/locales/de-DE/components.json +5 -0
  10. package/locales/en-US/chat.json +0 -4
  11. package/locales/en-US/components.json +5 -0
  12. package/locales/es-ES/chat.json +0 -4
  13. package/locales/es-ES/components.json +5 -0
  14. package/locales/fa-IR/chat.json +0 -4
  15. package/locales/fa-IR/components.json +5 -0
  16. package/locales/fr-FR/chat.json +0 -4
  17. package/locales/fr-FR/components.json +5 -0
  18. package/locales/it-IT/chat.json +0 -4
  19. package/locales/it-IT/components.json +5 -0
  20. package/locales/ja-JP/chat.json +0 -4
  21. package/locales/ja-JP/components.json +5 -0
  22. package/locales/ko-KR/chat.json +0 -4
  23. package/locales/ko-KR/components.json +5 -0
  24. package/locales/nl-NL/chat.json +0 -4
  25. package/locales/nl-NL/components.json +5 -0
  26. package/locales/pl-PL/chat.json +0 -4
  27. package/locales/pl-PL/components.json +5 -0
  28. package/locales/pt-BR/chat.json +0 -4
  29. package/locales/pt-BR/components.json +5 -0
  30. package/locales/ru-RU/chat.json +0 -4
  31. package/locales/ru-RU/components.json +5 -0
  32. package/locales/tr-TR/chat.json +0 -4
  33. package/locales/tr-TR/components.json +5 -0
  34. package/locales/vi-VN/chat.json +0 -4
  35. package/locales/vi-VN/components.json +5 -0
  36. package/locales/zh-CN/chat.json +0 -4
  37. package/locales/zh-CN/components.json +5 -0
  38. package/locales/zh-TW/chat.json +0 -4
  39. package/locales/zh-TW/components.json +5 -0
  40. package/package.json +1 -1
  41. package/src/app/(main)/settings/provider/features/ModelList/ModelItem.tsx +31 -36
  42. package/src/components/Thinking/index.tsx +137 -0
  43. package/src/const/currency.ts +2 -0
  44. package/src/const/discover.ts +0 -2
  45. package/src/features/Conversation/Messages/Assistant/Reasoning/index.tsx +6 -110
  46. package/src/locales/default/chat.ts +0 -4
  47. package/src/locales/default/components.ts +5 -0
  48. package/src/utils/format.test.ts +2 -9
  49. package/src/utils/format.ts +2 -2
@@ -1,123 +1,19 @@
1
- import { Icon, Markdown } from '@lobehub/ui';
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
- const useStyles = createStyles(({ css, token, isDarkMode }) => ({
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 Thinking = memo<ThinkingProps>(({ content = '', duration, id }) => {
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
- useEffect(() => {
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 Thinking;
19
+ export default Reasoning;
@@ -84,10 +84,6 @@ export default {
84
84
  },
85
85
  },
86
86
  },
87
- reasoning: {
88
- thinking: '深度思考中',
89
- thought: '已深度思考(用时 {{duration}} 秒)',
90
- },
91
87
  regenerate: '重新生成',
92
88
  roleAndArchive: '角色与记录',
93
89
  searchAgentPlaceholder: '搜索助手...',
@@ -88,4 +88,9 @@ export default {
88
88
  emptyModel: '没有启用的模型,请前往设置开启',
89
89
  provider: '提供商',
90
90
  },
91
+ Thinking: {
92
+ thinking: '深度思考中...',
93
+ thought: '已深度思考',
94
+ thoughtWithDuration: '已深度思考(用时 {{duration}} 秒)',
95
+ },
91
96
  };
@@ -1,7 +1,7 @@
1
1
  import dayjs from 'dayjs';
2
2
  import { describe, expect, it } from 'vitest';
3
3
 
4
- import { CNY_TO_USD } from '@/const/discover';
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 / CNY_TO_USD);
199
+ const expectedCNY = formatPrice(price / USD_TO_CNY);
207
200
  expect(formatPriceByCurrency(price, 'CNY')).toBe(expectedCNY);
208
201
  });
209
202
  });
@@ -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 { CNY_TO_USD } from '@/const/discover';
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 / CNY_TO_USD);
121
+ return formatPrice(price / USD_TO_CNY);
122
122
  }
123
123
  return formatPrice(price);
124
124
  };