@lobehub/chat 0.114.8 → 0.115.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.
- package/.i18nrc.js +3 -0
- package/CHANGELOG.md +50 -0
- package/locales/de-DE/common.json +20 -0
- package/locales/de-DE/tool.json +8 -0
- package/locales/en-US/common.json +20 -0
- package/locales/en-US/tool.json +8 -0
- package/locales/es-ES/common.json +20 -0
- package/locales/es-ES/tool.json +8 -0
- package/locales/fr-FR/common.json +20 -0
- package/locales/fr-FR/tool.json +8 -0
- package/locales/it-IT/chat.json +77 -0
- package/locales/it-IT/common.json +113 -0
- package/locales/it-IT/empty.json +6 -0
- package/locales/it-IT/error.json +53 -0
- package/locales/it-IT/market.json +30 -0
- package/locales/it-IT/migration.json +45 -0
- package/locales/it-IT/plugin.json +166 -0
- package/locales/it-IT/setting.json +306 -0
- package/locales/it-IT/tool.json +8 -0
- package/locales/it-IT/welcome.json +14 -0
- package/locales/ja-JP/common.json +20 -0
- package/locales/ja-JP/tool.json +8 -0
- package/locales/ko-KR/common.json +20 -0
- package/locales/ko-KR/tool.json +8 -0
- package/locales/nl-NL/chat.json +77 -0
- package/locales/nl-NL/common.json +113 -0
- package/locales/nl-NL/empty.json +6 -0
- package/locales/nl-NL/error.json +53 -0
- package/locales/nl-NL/market.json +30 -0
- package/locales/nl-NL/migration.json +45 -0
- package/locales/nl-NL/plugin.json +166 -0
- package/locales/nl-NL/setting.json +306 -0
- package/locales/nl-NL/tool.json +8 -0
- package/locales/nl-NL/welcome.json +14 -0
- package/locales/pl-PL/chat.json +77 -0
- package/locales/pl-PL/common.json +113 -0
- package/locales/pl-PL/empty.json +6 -0
- package/locales/pl-PL/error.json +53 -0
- package/locales/pl-PL/market.json +30 -0
- package/locales/pl-PL/migration.json +45 -0
- package/locales/pl-PL/plugin.json +166 -0
- package/locales/pl-PL/setting.json +306 -0
- package/locales/pl-PL/tool.json +8 -0
- package/locales/pl-PL/welcome.json +14 -0
- package/locales/pt-BR/common.json +20 -0
- package/locales/pt-BR/tool.json +8 -0
- package/locales/ru-RU/common.json +20 -0
- package/locales/ru-RU/tool.json +8 -0
- package/locales/tr-TR/common.json +20 -0
- package/locales/tr-TR/tool.json +8 -0
- package/locales/zh-CN/common.json +20 -0
- package/locales/zh-CN/plugin.json +2 -2
- package/locales/zh-CN/setting.json +1 -1
- package/locales/zh-CN/tool.json +8 -0
- package/locales/zh-TW/common.json +20 -0
- package/locales/zh-TW/tool.json +8 -0
- package/package.json +1 -1
- package/src/app/api/openai/images/createImageGeneration.ts +26 -0
- package/src/app/api/openai/images/route.ts +16 -0
- package/src/app/api/proxy/route.ts +3 -1
- package/src/app/chat/(desktop)/features/ChatHeader.tsx +56 -56
- package/src/app/chat/features/ChatHeader/PluginTag/PluginStatus.tsx +7 -4
- package/src/app/chat/features/ChatHeader/PluginTag/index.tsx +3 -3
- package/src/app/chat/features/SystemRole/index.tsx +0 -1
- package/src/components/GalleyGrid/Grid.tsx +36 -0
- package/src/components/GalleyGrid/index.tsx +58 -0
- package/src/components/GalleyGrid/style.ts +24 -0
- package/src/const/settings.ts +7 -0
- package/src/database/schemas/files.ts +1 -0
- package/src/database/schemas/message.ts +1 -1
- package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
- package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -1
- package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +3 -3
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +26 -14
- package/src/features/Conversation/ChatList/Messages/Function.tsx +1 -1
- package/src/features/Conversation/ChatList/Plugins/Inspector/index.tsx +4 -2
- package/src/features/Conversation/ChatList/Plugins/Render/BuiltinType/index.tsx +36 -0
- package/src/features/Conversation/ChatList/Plugins/Render/DefaultType/index.tsx +6 -66
- package/src/features/Conversation/ChatList/Plugins/Render/Loading.tsx +61 -0
- package/src/features/Conversation/ChatList/Plugins/Render/index.tsx +21 -12
- package/src/features/Conversation/ChatList/Plugins/Render/useParseContent.ts +15 -0
- package/src/locales/default/common.ts +20 -0
- package/src/locales/default/index.ts +2 -0
- package/src/locales/default/plugin.ts +2 -2
- package/src/locales/default/setting.ts +1 -1
- package/src/locales/default/tool.ts +9 -0
- package/src/locales/options.ts +14 -2
- package/src/services/__tests__/chat.test.ts +132 -2
- package/src/services/_url.ts +1 -0
- package/src/services/chat.ts +3 -5
- package/src/services/file.ts +20 -5
- package/src/services/imageGeneration.ts +26 -0
- package/src/store/chat/actions/enhance.ts +65 -1
- package/src/store/chat/actions/plugin.test.ts +9 -9
- package/src/store/chat/actions/plugin.ts +38 -6
- package/src/store/chat/initialState.ts +3 -0
- package/src/store/chat/selectors/enchance.ts +11 -0
- package/src/store/chat/selectors/index.ts +1 -0
- package/src/store/global/selectors/__snapshots__/settings.test.ts.snap +5 -0
- package/src/store/global/selectors/settings.ts +5 -0
- package/src/store/tool/helpers.ts +6 -5
- package/src/store/tool/initialState.ts +3 -1
- package/src/store/tool/selectors/index.ts +5 -0
- package/src/store/tool/selectors/tool.test.ts +128 -0
- package/src/store/tool/selectors/tool.ts +125 -0
- package/src/store/tool/slices/builtin/action.ts +54 -0
- package/src/store/tool/slices/builtin/index.ts +2 -0
- package/src/store/tool/slices/builtin/initialState.ts +13 -0
- package/src/store/tool/slices/builtin/selectors.test.ts +70 -0
- package/src/store/tool/slices/builtin/selectors.ts +20 -0
- package/src/store/tool/slices/customPlugin/action.ts +0 -3
- package/src/store/tool/slices/plugin/selectors.test.ts +0 -69
- package/src/store/tool/slices/plugin/selectors.ts +1 -84
- package/src/store/tool/store.ts +8 -2
- package/src/tools/dalle/Render/EditMode.tsx +66 -0
- package/src/tools/dalle/Render/Item.tsx +97 -0
- package/src/tools/dalle/Render/ToolBar.tsx +54 -0
- package/src/tools/dalle/Render/index.tsx +21 -0
- package/src/tools/dalle/index.ts +81 -0
- package/src/tools/index.ts +11 -0
- package/src/tools/renders.ts +8 -0
- package/src/types/chatMessage.ts +1 -1
- package/src/types/openai/image.ts +34 -0
- package/src/types/settings.ts +6 -0
- package/src/types/tool/builtin.ts +36 -0
- package/src/types/tool/dalle.ts +12 -0
- package/src/types/tool/index.ts +5 -1
- package/src/types/tool/tool.ts +9 -0
- package/src/store/tool/selectors.ts +0 -3
|
@@ -50,16 +50,36 @@
|
|
|
50
50
|
"title": "匯入資料"
|
|
51
51
|
},
|
|
52
52
|
"lang": {
|
|
53
|
+
"bn": "孟加拉語",
|
|
54
|
+
"cs-CZ": "捷克語",
|
|
55
|
+
"da-DK": "丹麥語",
|
|
53
56
|
"de-DE": "德語",
|
|
57
|
+
"el-GR": "希臘語",
|
|
54
58
|
"en": "英文",
|
|
55
59
|
"en-US": "英文",
|
|
56
60
|
"es-ES": "西班牙語",
|
|
61
|
+
"fi-FI": "芬蘭語",
|
|
57
62
|
"fr-FR": "法語",
|
|
63
|
+
"hi-IN": "印地語",
|
|
64
|
+
"hu-HU": "匈牙利語",
|
|
65
|
+
"id-ID": "印尼語",
|
|
66
|
+
"it-IT": "義大利語",
|
|
58
67
|
"ja-JP": "日文",
|
|
59
68
|
"ko-KR": "韓文",
|
|
69
|
+
"nl-NL": "荷蘭語",
|
|
70
|
+
"no-NO": "挪威語",
|
|
71
|
+
"pl-PL": "波蘭語",
|
|
60
72
|
"pt-BR": "葡萄牙語",
|
|
73
|
+
"pt-PT": "葡萄牙語",
|
|
74
|
+
"ro-RO": "羅馬尼亞語",
|
|
61
75
|
"ru-RU": "俄文",
|
|
76
|
+
"sk-SK": "斯洛伐克語",
|
|
77
|
+
"sr-RS": "塞爾維亞語",
|
|
78
|
+
"sv-SE": "瑞典語",
|
|
79
|
+
"th-TH": "泰語",
|
|
62
80
|
"tr-TR": "土耳其",
|
|
81
|
+
"uk-UA": "烏克蘭語",
|
|
82
|
+
"vi-VN": "越南語",
|
|
63
83
|
"zh": "簡體中文",
|
|
64
84
|
"zh-CN": "簡體中文",
|
|
65
85
|
"zh-TW": "繁體中文"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.115.0",
|
|
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",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
|
|
3
|
+
import { OpenAIImagePayload } from '@/types/openai/image';
|
|
4
|
+
|
|
5
|
+
export const createImageGeneration = async ({
|
|
6
|
+
openai,
|
|
7
|
+
payload,
|
|
8
|
+
}: {
|
|
9
|
+
openai: OpenAI;
|
|
10
|
+
payload: OpenAIImagePayload;
|
|
11
|
+
}) => {
|
|
12
|
+
const res = await openai.images.generate({ ...payload, response_format: 'url' });
|
|
13
|
+
|
|
14
|
+
const urls = res.data.map((o) => o.url) as string[];
|
|
15
|
+
|
|
16
|
+
return new Response(JSON.stringify(urls));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// const mockImages = [
|
|
20
|
+
// 'https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/292159272-032d5c8b-20be-48d9-8dbb-f2491f231bac.png',
|
|
21
|
+
// 'https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/292159798-cad89421-20c5-44b0-a337-fcbb857f1f70.png',
|
|
22
|
+
// 'https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/292160015-2263156f-d41f-48ae-9c2c-d96799b9d2b8.png',
|
|
23
|
+
// 'https://github-production-user-asset-6210df.s3.amazonaws.com/28616219/292160229-592d112f-5dfd-47d7-98d3-44bc09dc91f7.png',
|
|
24
|
+
// ];
|
|
25
|
+
// export const createImageGeneration = async () =>
|
|
26
|
+
// new Response(JSON.stringify([mockImages[Math.round(Math.random() * 3)]]));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { OpenAIImagePayload } from '@/types/openai/image';
|
|
2
|
+
|
|
3
|
+
import { createBizOpenAI } from '../createBizOpenAI';
|
|
4
|
+
import { createImageGeneration } from './createImageGeneration';
|
|
5
|
+
|
|
6
|
+
export const runtime = 'edge';
|
|
7
|
+
|
|
8
|
+
export const POST = async (req: Request) => {
|
|
9
|
+
const payload = (await req.json()) as OpenAIImagePayload;
|
|
10
|
+
|
|
11
|
+
const openaiOrErrResponse = createBizOpenAI(req, payload.model);
|
|
12
|
+
// if resOrOpenAI is a Response, it means there is an error,just return it
|
|
13
|
+
if (openaiOrErrResponse instanceof Response) return openaiOrErrResponse;
|
|
14
|
+
|
|
15
|
+
return createImageGeneration({ openai: openaiOrErrResponse, payload });
|
|
16
|
+
};
|
|
@@ -17,12 +17,11 @@ import PluginTag from '../../features/ChatHeader/PluginTag';
|
|
|
17
17
|
import SettingButton from '../../features/ChatHeader/SettingButton';
|
|
18
18
|
import ShareButton from '../../features/ChatHeader/ShareButton';
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const Left = memo(() => {
|
|
21
|
+
const { t } = useTranslation('chat');
|
|
21
22
|
const init = useSessionChatInit();
|
|
22
23
|
const router = useRouter();
|
|
23
24
|
|
|
24
|
-
const { t } = useTranslation('chat');
|
|
25
|
-
|
|
26
25
|
const [isInbox, title, description, avatar, backgroundColor, model, plugins] = useSessionStore(
|
|
27
26
|
(s) => [
|
|
28
27
|
sessionSelectors.isInboxSession(s),
|
|
@@ -35,66 +34,67 @@ const Header = memo(() => {
|
|
|
35
34
|
],
|
|
36
35
|
);
|
|
37
36
|
|
|
37
|
+
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
38
|
+
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
39
|
+
|
|
40
|
+
return !init ? (
|
|
41
|
+
<Flexbox horizontal>
|
|
42
|
+
<Skeleton
|
|
43
|
+
active
|
|
44
|
+
avatar={{ shape: 'circle', size: 'default' }}
|
|
45
|
+
paragraph={false}
|
|
46
|
+
title={{ style: { margin: 0, marginTop: 8 }, width: 200 }}
|
|
47
|
+
/>
|
|
48
|
+
</Flexbox>
|
|
49
|
+
) : (
|
|
50
|
+
<Flexbox align={'flex-start'} gap={12} horizontal>
|
|
51
|
+
<Avatar
|
|
52
|
+
avatar={avatar}
|
|
53
|
+
background={backgroundColor}
|
|
54
|
+
onClick={() =>
|
|
55
|
+
isInbox
|
|
56
|
+
? router.push('/settings/agent')
|
|
57
|
+
: router.push(pathString('/chat/settings', { hash: location.hash }))
|
|
58
|
+
}
|
|
59
|
+
size={40}
|
|
60
|
+
title={title}
|
|
61
|
+
/>
|
|
62
|
+
<ChatHeaderTitle
|
|
63
|
+
desc={displayDesc}
|
|
64
|
+
tag={
|
|
65
|
+
<>
|
|
66
|
+
<Tag icon={<SiOpenai size={'1em'} />}>{model}</Tag>
|
|
67
|
+
{plugins?.length > 0 && <PluginTag plugins={plugins} />}
|
|
68
|
+
</>
|
|
69
|
+
}
|
|
70
|
+
title={displayTitle}
|
|
71
|
+
/>
|
|
72
|
+
</Flexbox>
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const Right = memo(() => {
|
|
77
|
+
const { t } = useTranslation('chat');
|
|
78
|
+
|
|
38
79
|
const [showAgentSettings, toggleConfig] = useGlobalStore((s) => [
|
|
39
80
|
s.preference.showChatSideBar,
|
|
40
81
|
s.toggleChatSideBar,
|
|
41
82
|
]);
|
|
42
83
|
|
|
43
|
-
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
44
|
-
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
45
|
-
|
|
46
84
|
return (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</Flexbox>
|
|
58
|
-
) : (
|
|
59
|
-
<Flexbox align={'flex-start'} gap={12} horizontal>
|
|
60
|
-
<Avatar
|
|
61
|
-
avatar={avatar}
|
|
62
|
-
background={backgroundColor}
|
|
63
|
-
onClick={() =>
|
|
64
|
-
isInbox
|
|
65
|
-
? router.push('/settings/agent')
|
|
66
|
-
: router.push(pathString('/chat/settings', { hash: location.hash }))
|
|
67
|
-
}
|
|
68
|
-
size={40}
|
|
69
|
-
title={title}
|
|
70
|
-
/>
|
|
71
|
-
<ChatHeaderTitle
|
|
72
|
-
desc={displayDesc}
|
|
73
|
-
tag={
|
|
74
|
-
<>
|
|
75
|
-
<Tag icon={<SiOpenai size={'1em'} />}>{model}</Tag>
|
|
76
|
-
{plugins?.length > 0 && <PluginTag plugins={plugins} />}
|
|
77
|
-
</>
|
|
78
|
-
}
|
|
79
|
-
title={displayTitle}
|
|
80
|
-
/>
|
|
81
|
-
</Flexbox>
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
right={
|
|
85
|
-
<>
|
|
86
|
-
<ShareButton />
|
|
87
|
-
<ActionIcon
|
|
88
|
-
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
|
|
89
|
-
onClick={() => toggleConfig()}
|
|
90
|
-
size={DESKTOP_HEADER_ICON_SIZE}
|
|
91
|
-
title={t('roleAndArchive')}
|
|
92
|
-
/>
|
|
93
|
-
<SettingButton />
|
|
94
|
-
</>
|
|
95
|
-
}
|
|
96
|
-
/>
|
|
85
|
+
<>
|
|
86
|
+
<ShareButton />
|
|
87
|
+
<ActionIcon
|
|
88
|
+
icon={showAgentSettings ? PanelRightClose : PanelRightOpen}
|
|
89
|
+
onClick={() => toggleConfig()}
|
|
90
|
+
size={DESKTOP_HEADER_ICON_SIZE}
|
|
91
|
+
title={t('roleAndArchive')}
|
|
92
|
+
/>
|
|
93
|
+
<SettingButton />
|
|
94
|
+
</>
|
|
97
95
|
);
|
|
98
96
|
});
|
|
99
97
|
|
|
98
|
+
const Header = memo(() => <ChatHeader left={<Left />} right={<Right />} />);
|
|
99
|
+
|
|
100
100
|
export default Header;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ActionIcon } from '@lobehub/ui';
|
|
2
2
|
import { Badge, Button, Tag } from 'antd';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
3
4
|
import { LucideRotateCw, LucideTrash2, RotateCwIcon } from 'lucide-react';
|
|
4
5
|
import { memo, useMemo } from 'react';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -8,7 +9,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
8
9
|
import ManifestPreviewer from '@/components/ManifestPreviewer';
|
|
9
10
|
import { useSessionStore } from '@/store/session';
|
|
10
11
|
import { useToolStore } from '@/store/tool';
|
|
11
|
-
import { customPluginSelectors,
|
|
12
|
+
import { customPluginSelectors, toolSelectors } from '@/store/tool/selectors';
|
|
12
13
|
|
|
13
14
|
interface PluginStatusProps {
|
|
14
15
|
deprecated?: boolean;
|
|
@@ -18,12 +19,12 @@ interface PluginStatusProps {
|
|
|
18
19
|
const PluginStatus = memo<PluginStatusProps>(({ title, id, deprecated }) => {
|
|
19
20
|
const { t } = useTranslation('common');
|
|
20
21
|
const [status, isCustom, reinstallCustomPlugin] = useToolStore((s) => [
|
|
21
|
-
|
|
22
|
+
toolSelectors.getManifestLoadingStatus(id)(s),
|
|
22
23
|
customPluginSelectors.isCustomPlugin(id)(s),
|
|
23
24
|
s.reinstallCustomPlugin,
|
|
24
25
|
]);
|
|
25
26
|
|
|
26
|
-
const manifest = useToolStore(
|
|
27
|
+
const manifest = useToolStore(toolSelectors.getManifestById(id), isEqual);
|
|
27
28
|
|
|
28
29
|
const removePlugin = useSessionStore((s) => s.removePlugin);
|
|
29
30
|
|
|
@@ -44,8 +45,10 @@ const PluginStatus = memo<PluginStatusProps>(({ title, id, deprecated }) => {
|
|
|
44
45
|
/>
|
|
45
46
|
);
|
|
46
47
|
}
|
|
48
|
+
|
|
49
|
+
default:
|
|
47
50
|
case 'success': {
|
|
48
|
-
return <Badge status={
|
|
51
|
+
return <Badge status={'success'} />;
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
}, [status]);
|
|
@@ -6,7 +6,7 @@ import { LucideToyBrick } from 'lucide-react';
|
|
|
6
6
|
import { memo } from 'react';
|
|
7
7
|
|
|
8
8
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
9
|
-
import {
|
|
9
|
+
import { toolSelectors } from '@/store/tool/selectors';
|
|
10
10
|
|
|
11
11
|
import PluginStatus from './PluginStatus';
|
|
12
12
|
|
|
@@ -15,8 +15,8 @@ export interface PluginTagProps {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const PluginTag = memo<PluginTagProps>(({ plugins }) => {
|
|
18
|
-
const list = useToolStore(
|
|
19
|
-
const displayPlugin = useToolStore(
|
|
18
|
+
const list = useToolStore(toolSelectors.metaList, isEqual);
|
|
19
|
+
const displayPlugin = useToolStore(toolSelectors.getMetaById(plugins[0]), isEqual);
|
|
20
20
|
|
|
21
21
|
if (plugins.length === 0) return null;
|
|
22
22
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CSSProperties, ReactNode, memo } from 'react';
|
|
2
|
+
import { Flexbox } from 'react-layout-kit';
|
|
3
|
+
|
|
4
|
+
import { MAX_SIZE_DESKTOP, MIN_IMAGE_SIZE, useStyles } from './style';
|
|
5
|
+
|
|
6
|
+
interface GridProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
col?: number;
|
|
10
|
+
gap?: number;
|
|
11
|
+
max?: number;
|
|
12
|
+
min?: number;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Grid = memo<GridProps>(
|
|
17
|
+
({
|
|
18
|
+
gap = 4,
|
|
19
|
+
col = 3,
|
|
20
|
+
max = MAX_SIZE_DESKTOP,
|
|
21
|
+
min = MIN_IMAGE_SIZE,
|
|
22
|
+
children,
|
|
23
|
+
className,
|
|
24
|
+
style,
|
|
25
|
+
}) => {
|
|
26
|
+
const { styles, cx } = useStyles({ col, gap, max, min });
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Flexbox className={cx(styles.container, className)} gap={gap} horizontal style={style}>
|
|
30
|
+
{children}
|
|
31
|
+
</Flexbox>
|
|
32
|
+
);
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export default Grid;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
2
|
+
import { ReactNode, memo, useMemo } from 'react';
|
|
3
|
+
import { Flexbox } from 'react-layout-kit';
|
|
4
|
+
|
|
5
|
+
import Grid from './Grid';
|
|
6
|
+
import { MAX_SIZE_DESKTOP, MAX_SIZE_MOBILE } from './style';
|
|
7
|
+
|
|
8
|
+
interface GalleyGridProps<T = any> {
|
|
9
|
+
items: T[];
|
|
10
|
+
renderItem: (props: T) => ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const GalleyGrid = memo<GalleyGridProps>(({ items, renderItem: Render }) => {
|
|
14
|
+
const { mobile } = useResponsive();
|
|
15
|
+
|
|
16
|
+
const { firstRow, lastRow } = useMemo(() => {
|
|
17
|
+
if (items.length === 4) {
|
|
18
|
+
return {
|
|
19
|
+
firstRow: items.slice(0, 2),
|
|
20
|
+
lastRow: items.slice(2, 4),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const firstCol = items.length % 3 === 0 ? 3 : items.length % 3;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
firstRow: items.slice(0, firstCol),
|
|
28
|
+
lastRow: items.slice(firstCol, items.length),
|
|
29
|
+
};
|
|
30
|
+
}, [items]);
|
|
31
|
+
|
|
32
|
+
const { gap, max } = useMemo(
|
|
33
|
+
() => ({
|
|
34
|
+
gap: mobile ? 4 : 6,
|
|
35
|
+
max: mobile ? MAX_SIZE_MOBILE : MAX_SIZE_DESKTOP,
|
|
36
|
+
}),
|
|
37
|
+
[mobile],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Flexbox gap={gap}>
|
|
42
|
+
<Grid col={firstRow.length} gap={gap} max={max}>
|
|
43
|
+
{firstRow.map((i, index) => (
|
|
44
|
+
<Render {...i} key={index} />
|
|
45
|
+
))}
|
|
46
|
+
</Grid>
|
|
47
|
+
{lastRow.length > 0 && (
|
|
48
|
+
<Grid col={lastRow.length > 2 ? 3 : lastRow.length} gap={gap} max={max}>
|
|
49
|
+
{lastRow.map((i, index) => (
|
|
50
|
+
<Render {...i} key={index} />
|
|
51
|
+
))}
|
|
52
|
+
</Grid>
|
|
53
|
+
)}
|
|
54
|
+
</Flexbox>
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export default GalleyGrid;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createStyles } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
export const MIN_IMAGE_SIZE = 64;
|
|
4
|
+
export const MAX_SIZE_DESKTOP = 640;
|
|
5
|
+
export const MAX_SIZE_MOBILE = 280;
|
|
6
|
+
export const useStyles = createStyles(
|
|
7
|
+
({ css }, { col, gap, max, min }: { col: number; gap: number; max: number; min: number }) => ({
|
|
8
|
+
container: css`
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-gap: ${gap}px;
|
|
11
|
+
grid-template-columns: repeat(${col}, 1fr);
|
|
12
|
+
|
|
13
|
+
width: 100%;
|
|
14
|
+
max-width: ${max}px;
|
|
15
|
+
|
|
16
|
+
& > div {
|
|
17
|
+
width: 100%;
|
|
18
|
+
min-width: ${min}px;
|
|
19
|
+
min-height: ${min}px;
|
|
20
|
+
max-height: ${(max - gap * (col - 1)) / col}px;
|
|
21
|
+
}
|
|
22
|
+
`,
|
|
23
|
+
}),
|
|
24
|
+
);
|
package/src/const/settings.ts
CHANGED
|
@@ -72,9 +72,16 @@ export const DEFAULT_TTS_CONFIG: GlobalTTSConfig = {
|
|
|
72
72
|
sttServer: 'openai',
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
export const DEFAULT_TOOL_CONFIG = {
|
|
76
|
+
dalle: {
|
|
77
|
+
autoGenerate: false,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
75
81
|
export const DEFAULT_SETTINGS: GlobalSettings = {
|
|
76
82
|
defaultAgent: DEFAULT_AGENT,
|
|
77
83
|
languageModel: DEFAULT_LLM_CONFIG,
|
|
84
|
+
tool: DEFAULT_TOOL_CONFIG,
|
|
78
85
|
tts: DEFAULT_TTS_CONFIG,
|
|
79
86
|
...DEFAULT_BASE_SETTINGS,
|
|
80
87
|
};
|
|
@@ -11,7 +11,7 @@ const PluginSchema = z.object({
|
|
|
11
11
|
identifier: z.string(),
|
|
12
12
|
arguments: z.string(),
|
|
13
13
|
apiName: z.string(),
|
|
14
|
-
type: z.enum(['default', 'standalone']).default('default'),
|
|
14
|
+
type: z.enum(['default', 'standalone', 'builtin']).default('default'),
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
export const DB_MessageSchema = z.object({
|
|
@@ -10,7 +10,7 @@ import { FORM_STYLE } from '@/const/layoutTokens';
|
|
|
10
10
|
import PluginStore from '@/features/PluginStore';
|
|
11
11
|
import PluginTag from '@/features/PluginStore/PluginItem/PluginTag';
|
|
12
12
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
13
|
-
import {
|
|
13
|
+
import { toolSelectors } from '@/store/tool/selectors';
|
|
14
14
|
|
|
15
15
|
import { useStore } from '../store';
|
|
16
16
|
import AddPluginButton from './AddPluginButton';
|
|
@@ -28,7 +28,7 @@ const AgentPlugin = memo(() => {
|
|
|
28
28
|
s.toggleAgentPlugin,
|
|
29
29
|
]);
|
|
30
30
|
|
|
31
|
-
const installedPlugins = useToolStore(
|
|
31
|
+
const installedPlugins = useToolStore(toolSelectors.metaList, isEqual);
|
|
32
32
|
const useFetchInstalledPlugins = useToolStore((s) => s.useFetchInstalledPlugins);
|
|
33
33
|
|
|
34
34
|
const { isLoading } = useFetchInstalledPlugins();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ActionIcon } from '@lobehub/ui';
|
|
2
2
|
import { Dropdown } from 'antd';
|
|
3
|
+
import isEqual from 'fast-deep-equal';
|
|
3
4
|
import { BrainCog } from 'lucide-react';
|
|
4
5
|
import { memo } from 'react';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -16,7 +17,7 @@ const ModelSwitch = memo(() => {
|
|
|
16
17
|
return [agentSelectors.currentAgentModel(s), s.updateAgentConfig];
|
|
17
18
|
});
|
|
18
19
|
|
|
19
|
-
const modelList = useGlobalStore(settingsSelectors.modelList);
|
|
20
|
+
const modelList = useGlobalStore(settingsSelectors.modelList, isEqual);
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
23
|
<Dropdown
|
|
@@ -9,7 +9,7 @@ import { chatSelectors } from '@/store/chat/selectors';
|
|
|
9
9
|
import { useSessionStore } from '@/store/session';
|
|
10
10
|
import { agentSelectors } from '@/store/session/selectors';
|
|
11
11
|
import { useToolStore } from '@/store/tool';
|
|
12
|
-
import {
|
|
12
|
+
import { toolSelectors } from '@/store/tool/selectors';
|
|
13
13
|
import { LanguageModel } from '@/types/llm';
|
|
14
14
|
|
|
15
15
|
const Token = memo(() => {
|
|
@@ -28,8 +28,8 @@ const Token = memo(() => {
|
|
|
28
28
|
const plugins = useSessionStore(agentSelectors.currentAgentPlugins);
|
|
29
29
|
|
|
30
30
|
const toolsString = useToolStore((s) => {
|
|
31
|
-
const pluginSystemRoles =
|
|
32
|
-
const schemaNumber =
|
|
31
|
+
const pluginSystemRoles = toolSelectors.enabledSystemRoles(plugins)(s);
|
|
32
|
+
const schemaNumber = toolSelectors
|
|
33
33
|
.enabledSchema(plugins)(s)
|
|
34
34
|
.map((i) => JSON.stringify(i))
|
|
35
35
|
.join('');
|
|
@@ -11,7 +11,7 @@ import PluginStore from '@/features/PluginStore';
|
|
|
11
11
|
import { useSessionStore } from '@/store/session';
|
|
12
12
|
import { agentSelectors } from '@/store/session/selectors';
|
|
13
13
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
14
|
-
import { pluginSelectors } from '@/store/tool/selectors';
|
|
14
|
+
import { builtinToolSelectors, pluginSelectors } from '@/store/tool/selectors';
|
|
15
15
|
|
|
16
16
|
import ToolItem from './ToolItem';
|
|
17
17
|
|
|
@@ -31,7 +31,15 @@ const useStyles = createStyles(({ css, prefixCls }) => ({
|
|
|
31
31
|
const Tools = memo(() => {
|
|
32
32
|
const { t } = useTranslation('setting');
|
|
33
33
|
const list = useToolStore(pluginSelectors.installedPluginMetaList, isEqual);
|
|
34
|
-
const
|
|
34
|
+
const builtinList = useToolStore(builtinToolSelectors.metaList, isEqual);
|
|
35
|
+
|
|
36
|
+
const enablePluginCount = useSessionStore(
|
|
37
|
+
(s) =>
|
|
38
|
+
agentSelectors
|
|
39
|
+
.currentAgentPlugins(s)
|
|
40
|
+
.filter((i) => !builtinList.some((b) => b.identifier === i)).length,
|
|
41
|
+
);
|
|
42
|
+
|
|
35
43
|
const [open, setOpen] = useState(false);
|
|
36
44
|
const { styles } = useStyles();
|
|
37
45
|
|
|
@@ -42,18 +50,22 @@ const Tools = memo(() => {
|
|
|
42
50
|
menu={{
|
|
43
51
|
className: styles.menu,
|
|
44
52
|
items: [
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
{
|
|
54
|
+
children: builtinList.map((item) => ({
|
|
55
|
+
icon: <Avatar avatar={item.meta.avatar} size={24} />,
|
|
56
|
+
key: item.identifier,
|
|
57
|
+
label: (
|
|
58
|
+
<ToolItem
|
|
59
|
+
identifier={item.identifier}
|
|
60
|
+
label={item.meta?.title || item.identifier}
|
|
61
|
+
/>
|
|
62
|
+
),
|
|
63
|
+
})),
|
|
64
|
+
|
|
65
|
+
key: 'builtins',
|
|
66
|
+
label: t('tools.builtins.groupName'),
|
|
67
|
+
type: 'group',
|
|
68
|
+
},
|
|
57
69
|
{
|
|
58
70
|
children: [
|
|
59
71
|
...list.map((item) => ({
|
|
@@ -24,8 +24,8 @@ export const FunctionMessage = memo<ChatMessage>(({ id, content, plugin }) => {
|
|
|
24
24
|
<PluginRender
|
|
25
25
|
content={content}
|
|
26
26
|
id={id}
|
|
27
|
+
identifier={plugin?.identifier}
|
|
27
28
|
loading={fcProps.loading}
|
|
28
|
-
name={plugin?.identifier}
|
|
29
29
|
payload={fcProps.command}
|
|
30
30
|
type={fcProps.type}
|
|
31
31
|
/>
|
|
@@ -15,7 +15,7 @@ import { useTranslation } from 'react-i18next';
|
|
|
15
15
|
import { Flexbox } from 'react-layout-kit';
|
|
16
16
|
|
|
17
17
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
18
|
-
import { pluginSelectors } from '@/store/tool/selectors';
|
|
18
|
+
import { pluginSelectors, toolSelectors } from '@/store/tool/selectors';
|
|
19
19
|
|
|
20
20
|
import PluginResult from './PluginResultJSON';
|
|
21
21
|
import Settings from './Settings';
|
|
@@ -47,9 +47,11 @@ const Inspector = memo<InspectorProps>(
|
|
|
47
47
|
const { styles } = useStyles();
|
|
48
48
|
const [open, setOpen] = useState(false);
|
|
49
49
|
|
|
50
|
-
const pluginMeta = useToolStore(
|
|
50
|
+
const pluginMeta = useToolStore(toolSelectors.getMetaById(id), isEqual);
|
|
51
|
+
|
|
51
52
|
const showRightAction = useToolStore(pluginSelectors.isPluginHasUI(id));
|
|
52
53
|
const pluginAvatar = pluginHelpers.getPluginAvatar(pluginMeta);
|
|
54
|
+
|
|
53
55
|
const pluginTitle = pluginHelpers.getPluginTitle(pluginMeta) ?? t('plugins.loading');
|
|
54
56
|
|
|
55
57
|
const avatar = pluginAvatar ? (
|