@lobehub/chat 0.108.0 → 0.109.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 (93) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/docs/Environment-Variable.md +2 -2
  5. package/docs/Environment-Variable.zh-CN.md +2 -2
  6. package/locales/en_US/plugin.json +19 -0
  7. package/locales/en_US/setting.json +26 -0
  8. package/locales/ja_JP/plugin.json +19 -0
  9. package/locales/ja_JP/setting.json +26 -0
  10. package/locales/ko_KR/plugin.json +19 -0
  11. package/locales/ko_KR/setting.json +26 -0
  12. package/locales/ru_RU/plugin.json +19 -0
  13. package/locales/ru_RU/setting.json +26 -0
  14. package/locales/zh_CN/plugin.json +19 -0
  15. package/locales/zh_CN/setting.json +26 -5
  16. package/locales/zh_TW/plugin.json +19 -0
  17. package/locales/zh_TW/setting.json +26 -0
  18. package/package.json +3 -3
  19. package/src/app/chat/features/ChatHeader/PluginTag/PluginStatus.tsx +6 -6
  20. package/src/app/chat/features/ChatHeader/PluginTag/index.tsx +4 -4
  21. package/src/app/chat/features/ChatInput/ActionBar/Tools/ToolItem.tsx +37 -0
  22. package/src/app/chat/features/ChatInput/ActionBar/Tools/index.tsx +116 -0
  23. package/src/app/chat/features/ChatInput/ActionBar/config.ts +3 -1
  24. package/src/app/chat/features/Conversation/ChatList/Error/Plugin/PluginSettings.tsx +4 -4
  25. package/src/app/chat/features/Conversation/ChatList/Plugins/Inspector/Settings.tsx +3 -3
  26. package/src/app/chat/features/Conversation/ChatList/Plugins/Inspector/index.tsx +4 -4
  27. package/src/app/chat/features/Conversation/ChatList/Plugins/Render/DefaultType/index.tsx +2 -2
  28. package/src/app/chat/features/Conversation/ChatList/Plugins/Render/StandaloneType/Iframe.tsx +4 -4
  29. package/src/app/chat/features/Conversation/ChatList/Plugins/Render/StandaloneType/index.tsx +2 -2
  30. package/src/app/chat/features/Conversation/useInitConversation.ts +2 -2
  31. package/src/app/settings/common/Common.tsx +2 -2
  32. package/src/features/AgentSetting/AgentPlugin/AddPluginButton.tsx +56 -0
  33. package/src/features/AgentSetting/AgentPlugin/LoadingList.tsx +48 -0
  34. package/src/features/AgentSetting/AgentPlugin/LocalPluginItem.tsx +5 -5
  35. package/src/features/AgentSetting/AgentPlugin/PluginAction/index.tsx +36 -0
  36. package/src/features/AgentSetting/AgentPlugin/index.tsx +157 -9
  37. package/src/features/AgentSetting/store/action.ts +0 -1
  38. package/src/features/PluginDevModal/MetaForm.tsx +3 -3
  39. package/src/features/PluginDevModal/PluginPreview.tsx +1 -1
  40. package/src/features/PluginDevModal/index.tsx +4 -1
  41. package/src/features/PluginSettings/index.tsx +3 -3
  42. package/src/features/PluginSettingsModal/index.tsx +22 -17
  43. package/src/features/PluginStore/Loading.tsx +13 -0
  44. package/src/features/PluginStore/PluginItem.tsx +81 -0
  45. package/src/features/PluginStore/PluginSettings.tsx +40 -0
  46. package/src/features/{AgentSetting/AgentPlugin/MarketSettingModal.tsx → PluginStore/StoreSetting.tsx} +2 -2
  47. package/src/features/PluginStore/index.tsx +95 -0
  48. package/src/layout/GlobalLayout/StoreHydration.tsx +3 -3
  49. package/src/locales/default/plugin.ts +19 -0
  50. package/src/locales/default/setting.ts +26 -5
  51. package/src/services/__tests__/chat.test.ts +221 -0
  52. package/src/services/__tests__/message.test.ts +333 -0
  53. package/src/services/__tests__/plugin.test.ts +88 -0
  54. package/src/services/__tests__/session.test.ts +227 -0
  55. package/src/services/__tests__/topic.test.ts +220 -0
  56. package/src/services/chat.ts +4 -6
  57. package/src/services/plugin.ts +12 -1
  58. package/src/store/chat/actions/message.test.ts +0 -1
  59. package/src/store/session/slices/agent/action.ts +24 -8
  60. package/src/store/{plugin → tool}/helpers.ts +2 -13
  61. package/src/store/tool/index.ts +2 -0
  62. package/src/store/tool/initialState.ts +11 -0
  63. package/src/store/tool/selectors.ts +3 -0
  64. package/src/store/tool/slices/customPlugin/action.test.ts +164 -0
  65. package/src/store/{plugin → tool}/slices/customPlugin/action.ts +2 -2
  66. package/src/store/tool/slices/customPlugin/selectors.test.ts +59 -0
  67. package/src/store/tool/slices/customPlugin/selectors.ts +9 -0
  68. package/src/store/tool/slices/plugin/action.test.ts +141 -0
  69. package/src/store/tool/slices/plugin/action.ts +95 -0
  70. package/src/store/{plugin → tool}/slices/plugin/initialState.ts +0 -7
  71. package/src/store/{plugin → tool/slices/plugin}/selectors.test.ts +4 -41
  72. package/src/store/{plugin → tool/slices/plugin}/selectors.ts +17 -19
  73. package/src/store/tool/slices/store/action.test.ts +396 -0
  74. package/src/store/tool/slices/store/action.ts +103 -0
  75. package/src/store/tool/slices/store/index.ts +3 -0
  76. package/src/store/tool/slices/store/initialState.ts +17 -0
  77. package/src/store/tool/slices/store/selectors.test.ts +48 -0
  78. package/src/store/tool/slices/store/selectors.ts +21 -0
  79. package/src/store/{plugin → tool}/store.ts +8 -6
  80. package/vitest.config.ts +1 -0
  81. package/src/features/AgentSetting/AgentPlugin/MarketList.tsx +0 -232
  82. package/src/features/AgentSetting/AgentPlugin/PluginSettings.tsx +0 -80
  83. package/src/store/chat/reducers/files.test.ts +0 -38
  84. package/src/store/chat/reducers/files.ts +0 -37
  85. package/src/store/plugin/hooks/useSessionHydrated.ts +0 -21
  86. package/src/store/plugin/index.ts +0 -2
  87. package/src/store/plugin/initialState.ts +0 -9
  88. package/src/store/plugin/slices/plugin/action.ts +0 -173
  89. /package/src/store/{plugin → tool}/slices/customPlugin/index.ts +0 -0
  90. /package/src/store/{plugin → tool}/slices/customPlugin/initialState.ts +0 -0
  91. /package/src/store/{plugin → tool}/slices/customPlugin/reducers/customPluginList.ts +0 -0
  92. /package/src/store/{plugin → tool}/slices/plugin/index.ts +0 -0
  93. /package/src/store/{plugin → tool}/slices/plugin/reducers/manifest.ts +0 -0
@@ -5,8 +5,8 @@ import { memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
7
  import { settingsSelectors, useGlobalStore } from '@/store/global';
8
- import { usePluginStore } from '@/store/plugin';
9
- import { pluginSelectors } from '@/store/plugin/selectors';
8
+ import { useToolStore } from '@/store/tool';
9
+ import { pluginSelectors } from '@/store/tool/selectors';
10
10
 
11
11
  const EmojiPicker = dynamic(() => import('@lobehub/ui/es/EmojiPicker'), { ssr: false });
12
12
 
@@ -14,7 +14,7 @@ const MetaForm = memo<{ form: FormInstance; mode?: 'edit' | 'create' }>(({ form,
14
14
  const isEditMode = mode === 'edit';
15
15
  const locale = useGlobalStore(settingsSelectors.currentLanguage);
16
16
  const { t } = useTranslation('plugin');
17
- const [plugins] = usePluginStore((s) => [pluginSelectors.pluginList(s).map((i) => i.identifier)]);
17
+ const [plugins] = useToolStore((s) => [pluginSelectors.pluginList(s).map((i) => i.identifier)]);
18
18
 
19
19
  const configItem: FormItemProps[] = [
20
20
  {
@@ -4,7 +4,7 @@ import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { Flexbox } from 'react-layout-kit';
6
6
 
7
- import { pluginHelpers } from '@/store/plugin';
7
+ import { pluginHelpers } from '@/store/tool';
8
8
  import { CustomPlugin } from '@/types/plugin';
9
9
 
10
10
  const PluginPreview = memo<{ form: FormInstance }>(({ form }) => {
@@ -96,7 +96,10 @@ const DevModal = memo<DevModalProps>(
96
96
  cancelText={t('cancel', { ns: 'common' })}
97
97
  footer={footer}
98
98
  okText={t('dev.save')}
99
- onCancel={() => onOpenChange(false)}
99
+ onCancel={(e) => {
100
+ e.stopPropagation();
101
+ onOpenChange(false);
102
+ }}
100
103
  onOk={() => form.submit()}
101
104
  open={open}
102
105
  title={t('dev.title')}
@@ -4,7 +4,7 @@ import { createStyles } from 'antd-style';
4
4
  import isEqual from 'fast-deep-equal';
5
5
  import { memo } from 'react';
6
6
 
7
- import { usePluginStore } from '@/store/plugin';
7
+ import { useToolStore } from '@/store/tool';
8
8
 
9
9
  import PluginSettingRender from './PluginSettingRender';
10
10
 
@@ -41,8 +41,8 @@ const PluginSettingsConfig = memo<PluginSettingsConfigProps>(({ schema, id }) =>
41
41
  const items = transformPluginSettings(schema);
42
42
 
43
43
  const { styles } = useStyles();
44
- const [updatePluginSettings] = usePluginStore((s) => [s.updatePluginSettings]);
45
- const pluginSetting = usePluginStore((s) => s.pluginsSettings[id] || {}, isEqual);
44
+ const [updatePluginSettings] = useToolStore((s) => [s.updatePluginSettings]);
45
+ const pluginSetting = useToolStore((s) => s.pluginsSettings[id] || {}, isEqual);
46
46
 
47
47
  return (
48
48
  <Form layout={'vertical'}>
@@ -6,9 +6,10 @@ import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Center, Flexbox } from 'react-layout-kit';
8
8
 
9
+ import MobilePadding from '@/components/MobilePadding';
9
10
  import PluginSettingsConfig from '@/features/PluginSettings';
10
- import { pluginHelpers, usePluginStore } from '@/store/plugin';
11
- import { pluginSelectors } from '@/store/plugin/selectors';
11
+ import { pluginHelpers, useToolStore } from '@/store/tool';
12
+ import { pluginSelectors } from '@/store/tool/selectors';
12
13
 
13
14
  interface PluginSettingsModalProps {
14
15
  id: string;
@@ -18,27 +19,31 @@ interface PluginSettingsModalProps {
18
19
  }
19
20
 
20
21
  const PluginSettingsModal = memo<PluginSettingsModalProps>(({ schema, onClose, id, open }) => {
21
- const pluginMeta = usePluginStore(pluginSelectors.getPluginMetaById(id), isEqual);
22
+ const pluginMeta = useToolStore(pluginSelectors.getPluginMetaById(id), isEqual);
22
23
 
23
24
  const { t } = useTranslation('plugin');
24
25
  const theme = useTheme();
25
26
  return (
26
27
  <Modal onCancel={onClose} open={open} title={t('setting')} width={600}>
27
- <Center gap={16}>
28
- <Avatar
29
- avatar={pluginHelpers.getPluginAvatar(pluginMeta?.meta) || '⚙️'}
30
- background={theme.colorFillContent}
31
- gap={12}
32
- size={64}
33
- />
28
+ <MobilePadding>
29
+ <Center gap={16}>
30
+ <Avatar
31
+ avatar={pluginHelpers.getPluginAvatar(pluginMeta?.meta) || '⚙️'}
32
+ background={theme.colorFillContent}
33
+ gap={12}
34
+ size={64}
35
+ />
34
36
 
35
- <Flexbox style={{ fontSize: 20 }}>{pluginHelpers.getPluginTitle(pluginMeta?.meta)}</Flexbox>
36
- <Typography.Text type={'secondary'}>
37
- {pluginHelpers.getPluginDesc(pluginMeta?.meta)}
38
- </Typography.Text>
39
- <Divider style={{ marginBottom: 0, marginTop: 8 }} />
40
- {schema && <PluginSettingsConfig id={id} schema={schema} />}
41
- </Center>
37
+ <Flexbox style={{ fontSize: 20 }}>
38
+ {pluginHelpers.getPluginTitle(pluginMeta?.meta)}
39
+ </Flexbox>
40
+ <Typography.Text type={'secondary'}>
41
+ {pluginHelpers.getPluginDesc(pluginMeta?.meta)}
42
+ </Typography.Text>
43
+ <Divider style={{ marginBottom: 0, marginTop: 8 }} />
44
+ {schema && <PluginSettingsConfig id={id} schema={schema} />}
45
+ </Center>
46
+ </MobilePadding>
42
47
  </Modal>
43
48
  );
44
49
  });
@@ -0,0 +1,13 @@
1
+ import { Skeleton } from 'antd';
2
+ import { memo } from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+
5
+ const Loading = memo(() => {
6
+ return (
7
+ <Flexbox>
8
+ <Skeleton paragraph={{ rows: 8 }} />
9
+ </Flexbox>
10
+ );
11
+ });
12
+
13
+ export default Loading;
@@ -0,0 +1,81 @@
1
+ import { LobeChatPluginMeta } from '@lobehub/chat-plugin-sdk';
2
+ import { Avatar, Tag } from '@lobehub/ui';
3
+ import { Button } from 'antd';
4
+ import { createStyles } from 'antd-style';
5
+ import Link from 'next/link';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import { useToolStore } from '@/store/tool';
11
+ import { pluginStoreSelectors } from '@/store/tool/selectors';
12
+
13
+ import PluginSettings from './PluginSettings';
14
+
15
+ const useStyles = createStyles(({ css, token }) => ({
16
+ desc: css`
17
+ color: ${token.colorTextSecondary};
18
+ `,
19
+ link: css`
20
+ color: ${token.colorTextDescription};
21
+ `,
22
+ tag: css`
23
+ font-weight: normal;
24
+ `,
25
+ title: css`
26
+ font-size: ${token.fontSizeLG}px;
27
+ font-weight: bold;
28
+ line-height: 2;
29
+ `,
30
+ }));
31
+ const PluginItem = memo<LobeChatPluginMeta>(({ identifier, createdAt, homepage, author, meta }) => {
32
+ const [installed, installing, installPlugin, unInstallPlugin] = useToolStore((s) => [
33
+ pluginStoreSelectors.isPluginInstalled(identifier)(s),
34
+ pluginStoreSelectors.isPluginInstallLoading(identifier)(s),
35
+ s.installPlugin,
36
+ s.unInstallPlugin,
37
+ ]);
38
+ const { styles } = useStyles();
39
+
40
+ const { t } = useTranslation('plugin');
41
+ return (
42
+ <Flexbox gap={8} padding={16}>
43
+ <Flexbox horizontal justify={'space-between'}>
44
+ <Avatar avatar={meta.avatar} size={56} style={{ flex: 'none' }} />
45
+
46
+ <Flexbox gap={8} horizontal>
47
+ <PluginSettings identifier={identifier} />
48
+ <Button
49
+ loading={installing}
50
+ onClick={() => {
51
+ if (installed) {
52
+ unInstallPlugin(identifier);
53
+ } else installPlugin(identifier);
54
+ }}
55
+ type={installed ? 'default' : 'primary'}
56
+ >
57
+ {t(installed ? 'store.uninstall' : 'store.install')}
58
+ </Button>
59
+ </Flexbox>
60
+ </Flexbox>
61
+
62
+ <Flexbox gap={4}>
63
+ <Flexbox align={'center'} gap={8} horizontal>
64
+ <div className={styles.title}>{meta.title}</div>
65
+ <Tag className={styles.tag}> {identifier}</Tag>
66
+ </Flexbox>
67
+ <div className={styles.desc}>{meta.description}</div>
68
+ <Flexbox className={styles.link} gap={8} horizontal>
69
+ {author && (
70
+ <Link className={styles.link} href={homepage} target={'_blank'}>
71
+ @{author}
72
+ </Link>
73
+ )}
74
+ {t('store.releasedAt', { createdAt })}
75
+ </Flexbox>
76
+ </Flexbox>
77
+ </Flexbox>
78
+ );
79
+ });
80
+
81
+ export default PluginItem;
@@ -0,0 +1,40 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { SettingsIcon } from 'lucide-react';
3
+ import { memo, useState } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import PluginSettingsModal from '@/features/PluginSettingsModal';
7
+ import { useToolStore } from '@/store/tool';
8
+ import { pluginSelectors } from '@/store/tool/selectors';
9
+
10
+ const PluginSettings = memo<{ identifier: string }>(({ identifier }) => {
11
+ const { t } = useTranslation('setting');
12
+
13
+ const [open, setOpen] = useState(false);
14
+
15
+ const plugin = useToolStore(pluginSelectors.getPluginManifestById(identifier));
16
+
17
+ if (!plugin?.settings) return null;
18
+
19
+ return (
20
+ <>
21
+ <ActionIcon
22
+ icon={SettingsIcon}
23
+ onClick={() => {
24
+ setOpen(true);
25
+ }}
26
+ title={t('plugin.settings.tooltip')}
27
+ />
28
+ <PluginSettingsModal
29
+ id={identifier}
30
+ onClose={() => {
31
+ setOpen(false);
32
+ }}
33
+ open={open}
34
+ schema={plugin.settings}
35
+ />
36
+ </>
37
+ );
38
+ });
39
+
40
+ export default PluginSettings;
@@ -11,7 +11,7 @@ interface MarketSettingModalProps {
11
11
  open?: boolean;
12
12
  }
13
13
 
14
- const MarketSettingModal = memo<MarketSettingModalProps>(({ open, onOpenChange }) => {
14
+ const StoreSetting = memo<MarketSettingModalProps>(({ open, onOpenChange }) => {
15
15
  const { t } = useTranslation('plugin');
16
16
 
17
17
  return (
@@ -53,4 +53,4 @@ const MarketSettingModal = memo<MarketSettingModalProps>(({ open, onOpenChange }
53
53
  );
54
54
  });
55
55
 
56
- export default MarketSettingModal;
56
+ export default StoreSetting;
@@ -0,0 +1,95 @@
1
+ import { Icon, Modal, SpotlightCard, TabsNav } from '@lobehub/ui';
2
+ import { Button, Empty } from 'antd';
3
+ import isEqual from 'fast-deep-equal';
4
+ import { ServerCrash } from 'lucide-react';
5
+ import { memo } from 'react';
6
+ import { useTranslation } from 'react-i18next';
7
+ import { Center, Flexbox } from 'react-layout-kit';
8
+
9
+ import MobilePadding from '@/components/MobilePadding';
10
+ import { useToolStore } from '@/store/tool';
11
+ import { pluginStoreSelectors } from '@/store/tool/selectors';
12
+
13
+ import Loading from './Loading';
14
+ import PluginItem from './PluginItem';
15
+
16
+ interface PluginStoreProps {
17
+ open?: boolean;
18
+ setOpen: (open: boolean) => void;
19
+ }
20
+ export const PluginStore = memo<PluginStoreProps>(({ setOpen, open }) => {
21
+ const { t } = useTranslation('plugin');
22
+
23
+ const [listType, useFetchPluginList, installPlugins] = useToolStore((s) => [
24
+ s.listType,
25
+ s.useFetchPluginStore,
26
+ s.installPlugins,
27
+ ]);
28
+
29
+ const pluginStoreList = useToolStore(pluginStoreSelectors.onlinePluginStore, isEqual);
30
+ const { isLoading, error } = useFetchPluginList();
31
+ const isEmpty = pluginStoreList.length === 0;
32
+
33
+ return (
34
+ <Modal
35
+ footer={null}
36
+ onCancel={() => {
37
+ setOpen(false);
38
+ }}
39
+ open={open}
40
+ title={t('store.title')}
41
+ width={800}
42
+ >
43
+ <MobilePadding>
44
+ <Center>
45
+ <Flexbox gap={24} width={'100%'}>
46
+ <Flexbox align={'center'} horizontal justify={'space-between'}>
47
+ <TabsNav
48
+ activeKey={listType}
49
+ items={[
50
+ { key: 'all', label: t('store.tabs.all') },
51
+ { key: 'installed', label: t('store.tabs.installed') },
52
+ ]}
53
+ onChange={(v) => {
54
+ useToolStore.setState({ listType: v as any });
55
+ }}
56
+ />
57
+ <Flexbox gap={8} horizontal>
58
+ {listType === 'all' && (
59
+ <Button
60
+ onClick={() => {
61
+ installPlugins(pluginStoreList.map((item) => item.identifier));
62
+ }}
63
+ >
64
+ {t('store.installAllPlugins')}
65
+ </Button>
66
+ )}
67
+ </Flexbox>
68
+ </Flexbox>
69
+ {isLoading ? (
70
+ <Loading />
71
+ ) : isEmpty ? (
72
+ <Center gap={12} padding={40}>
73
+ {error ? (
74
+ <>
75
+ <Icon icon={ServerCrash} size={{ fontSize: 80 }} />
76
+ {t('store.networkError')}
77
+ </>
78
+ ) : (
79
+ <Empty
80
+ description={t('store.empty')}
81
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
82
+ ></Empty>
83
+ )}
84
+ </Center>
85
+ ) : (
86
+ <SpotlightCard columns={2} gap={16} items={pluginStoreList} renderItem={PluginItem} />
87
+ )}
88
+ </Flexbox>
89
+ </Center>
90
+ </MobilePadding>
91
+ </Modal>
92
+ );
93
+ });
94
+
95
+ export default PluginStore;
@@ -3,12 +3,12 @@ import { useRouter } from 'next/navigation';
3
3
  import { memo, useEffect } from 'react';
4
4
 
5
5
  import { useGlobalStore } from '@/store/global';
6
- import { usePluginStore } from '@/store/plugin';
7
6
  import {
8
7
  useEffectAfterSessionHydrated,
9
8
  useOnFinishHydrationSession,
10
9
  useSessionStore,
11
10
  } from '@/store/session';
11
+ import { useToolStore } from '@/store/tool';
12
12
 
13
13
  const StoreHydration = memo(() => {
14
14
  const router = useRouter();
@@ -17,11 +17,11 @@ const StoreHydration = memo(() => {
17
17
  // refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
18
18
  useSessionStore.persist.rehydrate();
19
19
  useGlobalStore.persist.rehydrate();
20
- usePluginStore.persist.rehydrate();
20
+ useToolStore.persist.rehydrate();
21
21
  }, []);
22
22
 
23
23
  useOnFinishHydrationSession((s, store) => {
24
- usePluginStore.getState().checkLocalEnabledPlugins(s.sessions);
24
+ useToolStore.getState().checkLocalEnabledPlugins(s.sessions);
25
25
 
26
26
  // add router instance to store
27
27
  store.setState({ router });
@@ -82,6 +82,12 @@ export default {
82
82
  update: '更新',
83
83
  updateSuccess: '插件设置更新成功',
84
84
  },
85
+ error: {
86
+ fetchError: '请求失败',
87
+ installError: '插件 {{name}} 安装失败',
88
+ manifestInvalid: '描述文件格式不正确',
89
+ noManifest: '描述文件不存在',
90
+ },
85
91
  list: {
86
92
  item: {
87
93
  'deprecated.title': '已删除',
@@ -106,4 +112,17 @@ export default {
106
112
  modalDesc: '配置插件市场的地址后,可以使用自定义的插件市场',
107
113
  title: '设置插件市场',
108
114
  },
115
+ store: {
116
+ empty: '暂无已安装插件',
117
+ install: '安装',
118
+ installAllPlugins: '安装全部',
119
+ networkError: '获取插件商店失败,请检测网络连接后重试',
120
+ releasedAt: '发布于 {{createdAt}}',
121
+ tabs: {
122
+ all: '全部',
123
+ installed: '已安装',
124
+ },
125
+ title: '插件商店',
126
+ uninstall: '卸载',
127
+ },
109
128
  };
@@ -84,6 +84,20 @@ export default {
84
84
  },
85
85
  waitingForMore: '更多模型正在 <1>计划接入</1> 中,敬请期待 ✨',
86
86
  },
87
+ plugin: {
88
+ addTooltip: '添加自定义插件',
89
+ clearDeprecated: '移除无效插件',
90
+ empty: '暂无已安装插件,欢迎前往 <1>插件商店</1> 探索',
91
+ installStatus: {
92
+ deprecated: '已卸载',
93
+ },
94
+ settings: {
95
+ hint: '请根据描述填写以下配置',
96
+ title: '{{id}} 插件配置',
97
+ tooltip: '插件配置',
98
+ },
99
+ store: '插件商店',
100
+ },
87
101
  settingAgent: {
88
102
  avatar: {
89
103
  title: '头像',
@@ -187,11 +201,6 @@ export default {
187
201
  },
188
202
  },
189
203
  settingPlugin: {
190
- add: '添加',
191
- addTooltip: '添加自定义插件',
192
- clearDeprecated: '移除无效插件',
193
- config: '{{id}} 插件配置',
194
- settings: '配置插件市场',
195
204
  title: '插件列表',
196
205
  },
197
206
  settingSystem: {
@@ -277,4 +286,16 @@ export default {
277
286
  llm: '语言模型',
278
287
  tts: '语音服务',
279
288
  },
289
+ tools: {
290
+ builtins: {
291
+ groupName: '内置',
292
+ },
293
+ plugins: {
294
+ enabled: '已启用 {{num}}',
295
+ groupName: '插件',
296
+ noEnabled: '暂无启用插件',
297
+ store: '插件商店',
298
+ },
299
+ title: '扩展工具',
300
+ },
280
301
  };