@lobehub/chat 0.74.0 → 0.76.0

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 (110) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +26 -5
  3. package/README.zh-CN.md +25 -4
  4. package/docs/deploy-with-azure-openai.zh-CN.md +45 -0
  5. package/locales/en_US/market.json +12 -0
  6. package/locales/en_US/plugin.json +11 -2
  7. package/locales/en_US/setting.json +3 -1
  8. package/locales/ru_RU/market.json +12 -0
  9. package/locales/ru_RU/plugin.json +44 -49
  10. package/locales/ru_RU/setting.json +3 -1
  11. package/locales/zh_CN/common.json +1 -1
  12. package/locales/zh_CN/market.json +12 -0
  13. package/locales/zh_CN/plugin.json +19 -5
  14. package/locales/zh_CN/setting.json +62 -14
  15. package/next.config.mjs +3 -1
  16. package/package.json +5 -5
  17. package/scripts/i18nWorkflow/const.ts +19 -0
  18. package/scripts/i18nWorkflow/genDefaultLocale.ts +19 -0
  19. package/scripts/i18nWorkflow/genDiff.ts +50 -0
  20. package/scripts/i18nWorkflow/genResources.ts +26 -0
  21. package/scripts/i18nWorkflow/index.ts +15 -0
  22. package/scripts/i18nWorkflow/utils.ts +85 -0
  23. package/src/config/client.ts +14 -0
  24. package/src/config/server.ts +5 -0
  25. package/src/const/layoutTokens.ts +3 -1
  26. package/src/const/market.ts +15 -0
  27. package/src/const/settings.ts +2 -1
  28. package/src/const/url.ts +29 -4
  29. package/src/features/AgentSetting/AgentConfig/index.tsx +1 -2
  30. package/src/features/AgentSetting/AgentPlugin/MarketSettingModal.tsx +1 -1
  31. package/src/features/AgentSetting/store/initialState.ts +1 -1
  32. package/src/features/MobileTabBar/index.tsx +2 -2
  33. package/src/features/SideBar/TopActions.tsx +2 -2
  34. package/src/locales/default/market.ts +12 -0
  35. package/src/locales/default/setting.ts +1 -0
  36. package/src/locales/resources/en_US.ts +2 -0
  37. package/src/locales/resources/ru_RU.ts +2 -0
  38. package/src/locales/resources/zh_CN.ts +2 -0
  39. package/src/pages/api/openai/chat.api.ts +6 -10
  40. package/src/pages/api/openai/createAzureOpenai.ts +13 -9
  41. package/src/pages/chat/features/Conversation/Input/{Action.tsx → ActionBar/ActionLeft.tsx} +2 -2
  42. package/src/pages/chat/features/Conversation/Input/ActionBar/ActionRight.tsx +36 -0
  43. package/src/pages/chat/features/Conversation/Input/Desktop.tsx +40 -0
  44. package/src/pages/chat/features/Conversation/Input/Footer/SaveTopic.tsx +27 -0
  45. package/src/pages/chat/features/Conversation/Input/Footer/index.tsx +35 -0
  46. package/src/pages/chat/features/Conversation/Input/Mobile.tsx +12 -0
  47. package/src/pages/chat/features/Conversation/Input/index.tsx +20 -38
  48. package/src/pages/chat/features/SessionList/Header/Desktop.tsx +6 -13
  49. package/src/pages/chat/features/SessionList/Header/Mobile.tsx +1 -1
  50. package/src/pages/chat/features/SessionList/List/AddButton.tsx +1 -1
  51. package/src/pages/chat/features/SessionList/List/Item/index.tsx +4 -3
  52. package/src/pages/chat/features/SessionList/List/index.tsx +1 -3
  53. package/src/pages/chat/features/SessionList/Mobile.tsx +2 -12
  54. package/src/pages/chat/features/SessionSearchBar/index.tsx +26 -0
  55. package/src/pages/chat/features/Sidebar/Topic/index.tsx +18 -6
  56. package/src/pages/chat/features/Sidebar/TopicSearchBar/index.tsx +24 -0
  57. package/src/pages/chat/features/Sidebar/index.tsx +2 -9
  58. package/src/pages/market/features/AgentCard/AgentCardBanner.tsx +64 -0
  59. package/src/pages/market/features/AgentCard/AgentCardItem.tsx +57 -0
  60. package/src/pages/market/features/AgentCard/Loading.tsx +13 -0
  61. package/src/pages/market/features/AgentCard/index.tsx +37 -0
  62. package/src/pages/market/features/AgentCard/style.ts +22 -0
  63. package/src/pages/market/features/AgentSearchBar/index.tsx +26 -0
  64. package/src/pages/market/features/Header/Desktop.tsx +15 -4
  65. package/src/pages/market/features/Header/Mobile.tsx +7 -24
  66. package/src/pages/market/features/SideBar/AgentInfo/Comment.tsx +16 -0
  67. package/src/pages/market/features/SideBar/AgentInfo/Header.tsx +68 -0
  68. package/src/pages/market/features/SideBar/AgentInfo/Loading.tsx +61 -0
  69. package/src/pages/market/features/SideBar/AgentInfo/TokenTag.tsx +25 -0
  70. package/src/pages/market/features/SideBar/AgentInfo/index.tsx +68 -0
  71. package/src/pages/market/features/SideBar/AgentInfo/style.ts +46 -0
  72. package/src/pages/market/features/SideBar/Desktop.tsx +70 -0
  73. package/src/pages/market/features/SideBar/Mobile.tsx +36 -0
  74. package/src/pages/market/features/SideBar/index.tsx +23 -0
  75. package/src/pages/market/features/TagList/index.tsx +29 -0
  76. package/src/pages/market/index.page.tsx +11 -2
  77. package/src/pages/market/layout.mobile.tsx +8 -7
  78. package/src/pages/market/layout.tsx +39 -1
  79. package/src/pages/settings/features/Header/Desktop.tsx +2 -4
  80. package/src/pages/settings/features/Header/Mobile.tsx +1 -1
  81. package/src/pages/settings/features/Settings/Common.tsx +1 -2
  82. package/src/pages/settings/features/Settings/LLM/index.tsx +12 -1
  83. package/src/pages/settings/features/Settings/index.tsx +17 -4
  84. package/src/services/_header.ts +1 -1
  85. package/src/services/agentMarket.ts +21 -0
  86. package/src/store/global/initialState.ts +1 -2
  87. package/src/store/global/selectors.test.ts +0 -1
  88. package/src/store/market/action.ts +57 -0
  89. package/src/store/market/index.ts +3 -0
  90. package/src/store/market/initialState.ts +17 -0
  91. package/src/store/market/selectors.ts +36 -0
  92. package/src/store/market/store.ts +51 -0
  93. package/src/store/session/slices/session/action.ts +5 -3
  94. package/src/store/session/slices/session/initialState.ts +2 -0
  95. package/src/store/session/slices/session/reducers/session.test.ts +4 -4
  96. package/src/types/market.ts +19 -0
  97. package/src/types/meta.ts +1 -1
  98. package/src/utils/filter.ts +1 -1
  99. package/src/utils/findDuplicates.ts +22 -0
  100. package/scripts/genDefaultLocale.ts +0 -18
  101. package/scripts/genResources.ts +0 -51
  102. package/scripts/toc.ts +0 -7
  103. package/src/components/Empty/index.tsx +0 -63
  104. package/src/components/Empty/style.ts +0 -31
  105. package/src/components/SelectWithImg/index.tsx +0 -97
  106. package/src/components/SelectWithImg/styles.ts +0 -43
  107. package/src/pages/chat/features/Conversation/Input/ActionRight.tsx +0 -31
  108. package/src/pages/chat/features/Conversation/Input/Footer.tsx +0 -49
  109. /package/src/components/{ManifestPreviewer.tsx → ManifestPreviewer/index.tsx} +0 -0
  110. /package/src/pages/chat/features/Conversation/Input/{Token.tsx → ActionBar/Token.tsx} +0 -0
package/src/types/meta.ts CHANGED
@@ -10,7 +10,7 @@ export interface MetaData {
10
10
  */
11
11
  backgroundColor?: string;
12
12
  description?: string;
13
- tag?: string[];
13
+ tags?: string[];
14
14
  /**
15
15
  * 名称
16
16
  * @description 可选参数,如果不传则使用默认名称
@@ -11,7 +11,7 @@ export const filterWithKeywords = <T extends BaseDataModel>(
11
11
  Object.entries(map).filter(([, item]) => {
12
12
  const meta = item.meta;
13
13
 
14
- const keyList = [meta.title, meta.description, meta.tag?.join('')].filter(
14
+ const keyList = [meta.title, meta.description, meta.tags?.join('')].filter(
15
15
  Boolean,
16
16
  ) as string[];
17
17
 
@@ -0,0 +1,22 @@
1
+ export const findDuplicates = (arr: string[]): string[] => {
2
+ const duplicates: { [key: string]: number } = {};
3
+
4
+ // 统计每个项目出现的次数
5
+ for (const item of arr) {
6
+ if (duplicates[item]) {
7
+ duplicates[item]++;
8
+ } else {
9
+ duplicates[item] = 1;
10
+ }
11
+ }
12
+
13
+ // 挑出重复出现 3 次以上的项目
14
+ const COUNT = 3;
15
+
16
+ const result = Object.keys(duplicates).filter((item) => duplicates[item] >= COUNT);
17
+
18
+ // 按重复次数从多到少排序
19
+ result.sort((a, b) => duplicates[b] - duplicates[a]);
20
+
21
+ return result;
22
+ };
@@ -1,18 +0,0 @@
1
- import { consola } from 'consola';
2
- import { colors } from 'consola/utils';
3
- import fs from 'node:fs';
4
- import { resolve } from 'node:path';
5
-
6
- import i18nConfig from '../.i18nrc';
7
-
8
- export const genDefaultLocale = (input: string) => {
9
- consola.info(`Default locale is ${i18nConfig.entryLocale}...`);
10
- const resources = require(`../${input}/${i18nConfig.entryLocale}`);
11
- const data = Object.entries(resources.default);
12
- consola.start(`Generate default locale json, found ${data.length} namespaces...`);
13
- for (const [ns, value] of data) {
14
- const filepath = resolve(i18nConfig.output, i18nConfig.entryLocale, `${ns}.json`);
15
- fs.writeFileSync(filepath, JSON.stringify(value, null, 2));
16
- consola.success(colors.bgWhiteBright(colors.black(` ${ns} `)), colors.gray(filepath));
17
- }
18
- };
@@ -1,51 +0,0 @@
1
- import { consola } from 'consola';
2
- import { colors } from 'consola/utils';
3
- import { tocForResources } from 'i18next-resources-for-ts';
4
- import fs from 'node:fs';
5
- import { resolve } from 'node:path';
6
-
7
- import i18nConfig from '../.i18nrc.js';
8
-
9
- const locales = [i18nConfig.entryLocale, ...i18nConfig.outputLocales];
10
- export const genResources = (output: string) => {
11
- let index = '';
12
- let indexObj = '';
13
- consola.start(`Generate locale resources and types, found ${locales.length} locales...`);
14
- for (const locale of locales) {
15
- const files = fs
16
- .readdirSync(resolve(i18nConfig.output, locale))
17
- .filter((name) => name.includes('.json'));
18
- index += `import ${locale} from "./${locale}";\n`;
19
- indexObj += ` "${locale.replace('_', '-')}": ${locale},\n`;
20
- const ns = [];
21
- for (const file of files) {
22
- ns.push({
23
- name: file.replace('.json', ''),
24
- path: resolve(i18nConfig.output, locale, file),
25
- });
26
- }
27
- let toc = tocForResources(ns, resolve(output)).replaceAll('\\', '/');
28
- if (locale === i18nConfig.entryLocale) {
29
- toc = toc.replaceAll('.json', '').replaceAll('../../../locales/zh_CN', '../default');
30
- }
31
- const filepath = resolve(output, `${locale}.ts`);
32
- fs.writeFileSync(filepath, toc);
33
- consola.success(colors.bgBlue(colors.black(` ${locale} `)), colors.gray(filepath));
34
- }
35
- const indexFilepath = resolve(output, `index.ts`);
36
- fs.writeFileSync(
37
- indexFilepath,
38
- `${index}
39
- const resources = {
40
- ${indexObj}} as const;
41
- export default resources;
42
- export const defaultResources = ${i18nConfig.entryLocale};
43
- export type Resources = typeof resources;
44
- export type DefaultResources = typeof defaultResources;
45
- export type Namespaces = keyof DefaultResources;
46
- export type Locales = keyof Resources;
47
- `,
48
- );
49
-
50
- consola.success(colors.bgGreen(colors.black(` INDEX `)), colors.gray(indexFilepath));
51
- };
package/scripts/toc.ts DELETED
@@ -1,7 +0,0 @@
1
- import { genDefaultLocale } from './genDefaultLocale';
2
- import { genResources } from './genResources';
3
-
4
- const RES_OUTPUT = 'src/locales/resources';
5
-
6
- genDefaultLocale(RES_OUTPUT);
7
- genResources(RES_OUTPUT);
@@ -1,63 +0,0 @@
1
- import { ActionIcon, DivProps } from '@lobehub/ui';
2
- import { X } from 'lucide-react';
3
- import Image from 'next/image';
4
- import { memo } from 'react';
5
- import { Flexbox } from 'react-layout-kit';
6
- import useMergeState from 'use-merge-value';
7
-
8
- import { useStyles } from './style';
9
-
10
- interface EmptyProps extends DivProps {
11
- alt: string;
12
- cover: string;
13
- defaultVisible?: boolean;
14
- desc: string;
15
- height?: number;
16
- onVisibleChange?: (visible: boolean) => void;
17
- title: string;
18
- visible?: boolean;
19
- width?: number;
20
- }
21
-
22
- const Empty = memo<EmptyProps>(
23
- ({
24
- cover,
25
- visible,
26
- defaultVisible,
27
- onVisibleChange,
28
- alt,
29
- title,
30
- desc,
31
- width,
32
- height,
33
- ...props
34
- }) => {
35
- const [value, setValue] = useMergeState(true, {
36
- defaultValue: defaultVisible,
37
- onChange: onVisibleChange,
38
- value: visible,
39
- });
40
-
41
- const { styles } = useStyles();
42
- if (!value) return null;
43
- return (
44
- <Flexbox className={styles.container} {...props}>
45
- <ActionIcon
46
- className={styles.close}
47
- icon={X}
48
- onClick={() => setValue(false)}
49
- size={{ blockSize: 24, fontSize: 16 }}
50
- />
51
- {cover && (
52
- <Image alt={alt} className={styles.image} height={height} src={cover} width={width} />
53
- )}
54
- <div className={styles.content}>
55
- {title && <h3>{title}</h3>}
56
- {desc && <p className={styles.desc}>{desc}</p>}
57
- </div>
58
- </Flexbox>
59
- );
60
- },
61
- );
62
-
63
- export default Empty;
@@ -1,31 +0,0 @@
1
- import { createStyles } from 'antd-style';
2
-
3
- export const useStyles = createStyles(({ css, token, isDarkMode }) => ({
4
- close: css`
5
- position: absolute;
6
- top: 8px;
7
- right: 8px;
8
- `,
9
- container: css`
10
- position: relative;
11
-
12
- overflow: hidden;
13
-
14
- background: linear-gradient(
15
- to bottom,
16
- ${isDarkMode ? token.colorBgElevated : token.colorBgLayout},
17
- ${token.colorBgContainer}
18
- );
19
- border: 1px solid ${token.colorBorderSecondary};
20
- border-radius: ${token.borderRadius}px;
21
- `,
22
- content: css`
23
- padding: 0 16px 16px;
24
- `,
25
- desc: css`
26
- color: ${token.colorTextDescription};
27
- `,
28
- image: css`
29
- align-self: center;
30
- `,
31
- }));
@@ -1,97 +0,0 @@
1
- import { Icon, IconProps } from '@lobehub/ui';
2
- import { SelectProps } from 'antd';
3
- import { type CSSProperties, ReactNode, memo } from 'react';
4
- import { Flexbox } from 'react-layout-kit';
5
- import useControlledState from 'use-merge-value';
6
-
7
- import { useStyles } from './styles';
8
-
9
- export interface SelectWithImgOptionItem {
10
- icon?: IconProps['icon'];
11
- img: string;
12
- label: ReactNode;
13
- value: string;
14
- }
15
-
16
- export interface SelectWithImgProps {
17
- className?: string;
18
- classNames?: {
19
- img?: string;
20
- };
21
- defaultValue?: SelectProps['defaultValue'];
22
- height: number;
23
- onChange?: (value: this['value']) => void;
24
- options?: SelectWithImgOptionItem[];
25
- style?: CSSProperties;
26
-
27
- styles?: {
28
- img?: CSSProperties;
29
- };
30
- value?: SelectProps['value'];
31
- width: number;
32
- }
33
-
34
- const SelectWithImg = memo<SelectWithImgProps>(
35
- ({
36
- className,
37
- style,
38
- value,
39
- defaultValue,
40
- onChange,
41
- options,
42
- width,
43
- height,
44
- styles: outStyles = {},
45
- classNames = {},
46
- }) => {
47
- const [currentValue, setCurrentValue] = useControlledState<string>(defaultValue, {
48
- defaultValue,
49
- onChange,
50
- value,
51
- });
52
-
53
- const { styles, cx } = useStyles();
54
-
55
- return (
56
- <Flexbox className={className} gap={16} horizontal style={style}>
57
- {options?.map((item) => {
58
- const isActive = item.value === currentValue;
59
- return (
60
- <Flexbox
61
- align={'center'}
62
- className={cx(styles.container, isActive && styles.active)}
63
- gap={4}
64
- key={item.value}
65
- onClick={() => setCurrentValue(item.value)}
66
- >
67
- <div
68
- className={cx(styles.imgCtn, isActive && styles.imgActive, classNames.img)}
69
- style={{
70
- ...outStyles.img,
71
- height,
72
- width,
73
- }}
74
- >
75
- <div
76
- className={styles.img}
77
- style={{
78
- backgroundImage: `url(${item.img})`,
79
- backgroundSize: 'contain',
80
- height,
81
- width,
82
- }}
83
- />
84
- </div>
85
- <Flexbox align={'center'} gap={4} horizontal>
86
- {item.icon && <Icon icon={item.icon} />}
87
- {item.label}
88
- </Flexbox>
89
- </Flexbox>
90
- );
91
- })}
92
- </Flexbox>
93
- );
94
- },
95
- );
96
-
97
- export default SelectWithImg;
@@ -1,43 +0,0 @@
1
- import { createStyles } from 'antd-style';
2
-
3
- export const useStyles = createStyles(({ css, token, cx }) => {
4
- const hover = css`
5
- &:hover {
6
- border-color: ${token.colorText};
7
- box-shadow: 0 0 0 2px ${token.colorText};
8
- }
9
- `;
10
-
11
- const img = cx(
12
- css`
13
- border-radius: ${token.borderRadius}px;
14
- box-shadow: inset 0 0 0 2px ${token.colorSplit};
15
- transition: all 100ms ${token.motionEaseOut};
16
- `,
17
- hover,
18
- );
19
-
20
- return {
21
- active: css`
22
- color: ${token.colorText};
23
- `,
24
- container: css`
25
- cursor: pointer;
26
- color: ${token.colorTextDescription};
27
- `,
28
- img,
29
- imgActive: css`
30
- box-shadow: 0 0 0 2px ${token.colorTextTertiary};
31
-
32
- .${img} {
33
- box-shadow: none;
34
- }
35
- `,
36
- imgCtn: css`
37
- background: ${token.colorFillTertiary};
38
- border-radius: ${token.borderRadius}px;
39
-
40
- ${hover}
41
- `,
42
- };
43
- });
@@ -1,31 +0,0 @@
1
- import { ActionIcon } from '@lobehub/ui';
2
- import { Popconfirm } from 'antd';
3
- import { Eraser } from 'lucide-react';
4
- import { memo } from 'react';
5
- import { useTranslation } from 'react-i18next';
6
-
7
- import { useSessionStore } from '@/store/session';
8
-
9
- const ActionsRight = memo(() => {
10
- const { t } = useTranslation('setting');
11
- const [clearMessage] = useSessionStore((s) => [s.clearMessage, s.updateAgentConfig]);
12
-
13
- return (
14
- <Popconfirm
15
- cancelText={t('cancel', { ns: 'common' })}
16
- okButtonProps={{ danger: true }}
17
- okText={t('ok', { ns: 'common' })}
18
- onConfirm={() => clearMessage()}
19
- placement={'topRight'}
20
- title={t('confirmClearCurrentMessages', { ns: 'common' })}
21
- >
22
- <ActionIcon
23
- icon={Eraser}
24
- placement={'bottom'}
25
- title={t('clearCurrentMessages', { ns: 'common' })}
26
- />
27
- </Popconfirm>
28
- );
29
- });
30
-
31
- export default ActionsRight;
@@ -1,49 +0,0 @@
1
- import { Icon, Tooltip } from '@lobehub/ui';
2
- import { Button } from 'antd';
3
- import { useTheme } from 'antd-style';
4
- import { ArrowBigUp, CornerDownLeft, LucideGalleryVerticalEnd } from 'lucide-react';
5
- import { memo } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
- import { Flexbox } from 'react-layout-kit';
8
-
9
- export interface FooterProps {
10
- hasTopic: boolean;
11
- saveToTopic: () => void;
12
- }
13
-
14
- const Footer = memo<FooterProps>(({ hasTopic, saveToTopic }) => {
15
- const theme = useTheme();
16
- const { t } = useTranslation('common');
17
-
18
- const saveTopic = hasTopic ? null : (
19
- <Tooltip title={t('topic.saveCurrentMessages')}>
20
- <Button icon={<Icon icon={LucideGalleryVerticalEnd} />} onClick={saveToTopic} />
21
- </Tooltip>
22
- );
23
-
24
- const footerTooltip = (
25
- <Flexbox
26
- gap={4}
27
- horizontal
28
- style={{ color: theme.colorTextDescription, fontSize: 12, marginRight: 12 }}
29
- >
30
- <Icon icon={CornerDownLeft} />
31
- <span>{t('send')}</span>
32
- <span>/</span>
33
- <Flexbox horizontal>
34
- <Icon icon={ArrowBigUp} />
35
- <Icon icon={CornerDownLeft} />
36
- </Flexbox>
37
- <span>{t('warp')}</span>
38
- </Flexbox>
39
- );
40
-
41
- return (
42
- <>
43
- {footerTooltip}
44
- {saveTopic}
45
- </>
46
- );
47
- });
48
-
49
- export default Footer;