@lobehub/chat 0.114.9 → 0.115.1

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 (88) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/locales/de-DE/tool.json +8 -0
  3. package/locales/en-US/tool.json +8 -0
  4. package/locales/es-ES/tool.json +8 -0
  5. package/locales/fr-FR/tool.json +8 -0
  6. package/locales/it-IT/tool.json +8 -0
  7. package/locales/ja-JP/tool.json +8 -0
  8. package/locales/ko-KR/tool.json +8 -0
  9. package/locales/nl-NL/tool.json +8 -0
  10. package/locales/pl-PL/tool.json +8 -0
  11. package/locales/pt-BR/tool.json +8 -0
  12. package/locales/ru-RU/tool.json +8 -0
  13. package/locales/tr-TR/tool.json +8 -0
  14. package/locales/zh-CN/plugin.json +2 -2
  15. package/locales/zh-CN/setting.json +1 -1
  16. package/locales/zh-CN/tool.json +8 -0
  17. package/locales/zh-TW/tool.json +8 -0
  18. package/package.json +2 -2
  19. package/src/app/api/openai/images/createImageGeneration.ts +26 -0
  20. package/src/app/api/openai/images/route.ts +16 -0
  21. package/src/app/api/proxy/route.ts +3 -1
  22. package/src/app/chat/(desktop)/features/ChatHeader.tsx +56 -56
  23. package/src/app/chat/features/ChatHeader/PluginTag/PluginStatus.tsx +7 -4
  24. package/src/app/chat/features/ChatHeader/PluginTag/index.tsx +3 -3
  25. package/src/app/chat/features/SystemRole/index.tsx +0 -1
  26. package/src/components/GalleyGrid/Grid.tsx +36 -0
  27. package/src/components/GalleyGrid/index.tsx +58 -0
  28. package/src/components/GalleyGrid/style.ts +24 -0
  29. package/src/const/settings.ts +7 -0
  30. package/src/database/schemas/files.ts +1 -0
  31. package/src/database/schemas/message.ts +1 -1
  32. package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
  33. package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -1
  34. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +3 -3
  35. package/src/features/ChatInput/ActionBar/Tools/index.tsx +26 -14
  36. package/src/features/Conversation/ChatList/Messages/Function.tsx +1 -1
  37. package/src/features/Conversation/ChatList/Plugins/Inspector/index.tsx +4 -2
  38. package/src/features/Conversation/ChatList/Plugins/Render/BuiltinType/index.tsx +36 -0
  39. package/src/features/Conversation/ChatList/Plugins/Render/DefaultType/index.tsx +6 -66
  40. package/src/features/Conversation/ChatList/Plugins/Render/Loading.tsx +61 -0
  41. package/src/features/Conversation/ChatList/Plugins/Render/index.tsx +21 -12
  42. package/src/features/Conversation/ChatList/Plugins/Render/useParseContent.ts +15 -0
  43. package/src/locales/default/index.ts +2 -0
  44. package/src/locales/default/plugin.ts +2 -2
  45. package/src/locales/default/setting.ts +1 -1
  46. package/src/locales/default/tool.ts +9 -0
  47. package/src/services/__tests__/chat.test.ts +132 -2
  48. package/src/services/_url.ts +1 -0
  49. package/src/services/chat.ts +3 -5
  50. package/src/services/file.ts +20 -5
  51. package/src/services/imageGeneration.ts +26 -0
  52. package/src/store/chat/actions/enhance.ts +65 -1
  53. package/src/store/chat/actions/plugin.test.ts +9 -9
  54. package/src/store/chat/actions/plugin.ts +38 -6
  55. package/src/store/chat/initialState.ts +3 -0
  56. package/src/store/chat/selectors/enchance.ts +11 -0
  57. package/src/store/chat/selectors/index.ts +1 -0
  58. package/src/store/global/selectors/__snapshots__/settings.test.ts.snap +5 -0
  59. package/src/store/global/selectors/settings.ts +5 -0
  60. package/src/store/tool/helpers.ts +6 -5
  61. package/src/store/tool/initialState.ts +3 -1
  62. package/src/store/tool/selectors/index.ts +5 -0
  63. package/src/store/tool/selectors/tool.test.ts +128 -0
  64. package/src/store/tool/selectors/tool.ts +125 -0
  65. package/src/store/tool/slices/builtin/action.ts +54 -0
  66. package/src/store/tool/slices/builtin/index.ts +2 -0
  67. package/src/store/tool/slices/builtin/initialState.ts +13 -0
  68. package/src/store/tool/slices/builtin/selectors.test.ts +70 -0
  69. package/src/store/tool/slices/builtin/selectors.ts +20 -0
  70. package/src/store/tool/slices/customPlugin/action.ts +0 -3
  71. package/src/store/tool/slices/plugin/selectors.test.ts +0 -69
  72. package/src/store/tool/slices/plugin/selectors.ts +1 -84
  73. package/src/store/tool/store.ts +8 -2
  74. package/src/tools/dalle/Render/EditMode.tsx +66 -0
  75. package/src/tools/dalle/Render/Item.tsx +97 -0
  76. package/src/tools/dalle/Render/ToolBar.tsx +54 -0
  77. package/src/tools/dalle/Render/index.tsx +21 -0
  78. package/src/tools/dalle/index.ts +81 -0
  79. package/src/tools/index.ts +11 -0
  80. package/src/tools/renders.ts +8 -0
  81. package/src/types/chatMessage.ts +1 -1
  82. package/src/types/openai/image.ts +34 -0
  83. package/src/types/settings.ts +6 -0
  84. package/src/types/tool/builtin.ts +36 -0
  85. package/src/types/tool/dalle.ts +12 -0
  86. package/src/types/tool/index.ts +5 -1
  87. package/src/types/tool/tool.ts +9 -0
  88. package/src/store/tool/selectors.ts +0 -3
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.115.1](https://github.com/lobehub/lobe-chat/compare/v0.115.0...v0.115.1)
6
+
7
+ <sup>Released on **2023-12-22**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Lock ui version to fix setting form style.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Lock ui version to fix setting form style ([6cdf548](https://github.com/lobehub/lobe-chat/commit/6cdf548))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ## [Version 0.115.0](https://github.com/lobehub/lobe-chat/compare/v0.114.9...v0.115.0)
31
+
32
+ <sup>Released on **2023-12-22**</sup>
33
+
34
+ #### ✨ Features
35
+
36
+ - **misc**: Support Dall·E 3.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's improved
44
+
45
+ - **misc**: Support Dall·E 3, closes [#697](https://github.com/lobehub/lobe-chat/issues/697) ([e39d199](https://github.com/lobehub/lobe-chat/commit/e39d199))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 0.114.9](https://github.com/lobehub/lobe-chat/compare/v0.114.8...v0.114.9)
6
56
 
7
57
  <sup>Released on **2023-12-22**</sup>
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Automatisch generieren",
4
+ "generate": "Generieren",
5
+ "generating": "Generiert",
6
+ "images": "Bilder:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Auto Generate",
4
+ "generate": "Generate",
5
+ "generating": "Generating...",
6
+ "images": "Images:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Auto-generar",
4
+ "generate": "Generar",
5
+ "generating": "Generando...",
6
+ "images": "Imágenes:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Auto-générer",
4
+ "generate": "Générer",
5
+ "generating": "En cours de génération...",
6
+ "images": "Images :"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Auto-generato",
4
+ "generate": "Genera",
5
+ "generating": "Generazione in corso...",
6
+ "images": "Immagini:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "自動生成",
4
+ "generate": "生成する",
5
+ "generating": "生成中...",
6
+ "images": "画像:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "자동 생성",
4
+ "generate": "생성",
5
+ "generating": "생성 중...",
6
+ "images": "이미지:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Automatisch genereren",
4
+ "generate": "Genereren",
5
+ "generating": "Bezig met genereren...",
6
+ "images": "Afbeeldingen:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Automatyczne generowanie",
4
+ "generate": "Generuj",
5
+ "generating": "Generowanie...",
6
+ "images": "Obrazy:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Auto gerar",
4
+ "generate": "Gerar",
5
+ "generating": "Gerando...",
6
+ "images": "Imagens:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Автогенерация",
4
+ "generate": "Создать",
5
+ "generating": "Создание...",
6
+ "images": "Изображения:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "Otomatik Oluştur",
4
+ "generate": "Oluştur",
5
+ "generating": "Oluşturuluyor...",
6
+ "images": "Görseller:"
7
+ }
8
+ }
@@ -129,8 +129,8 @@
129
129
  },
130
130
  "pluginList": "插件列表",
131
131
  "plugins": {
132
- "loading": "插件检测中...",
133
- "unknown": "未知插件"
132
+ "loading": "工具检测中...",
133
+ "unknown": "未知工具"
134
134
  },
135
135
  "setting": "插件设置",
136
136
  "settings": {
@@ -293,7 +293,7 @@
293
293
  },
294
294
  "tools": {
295
295
  "builtins": {
296
- "groupName": "内置"
296
+ "groupName": "内置扩展"
297
297
  },
298
298
  "plugins": {
299
299
  "enabled": "已启用 {{num}}",
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "自动生成",
4
+ "generate": "生成",
5
+ "generating": "生成中...",
6
+ "images": "图片:"
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "dalle": {
3
+ "autoGenerate": "自動生成",
4
+ "generate": "生成",
5
+ "generating": "生成中...",
6
+ "images": "圖片:"
7
+ }
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.114.9",
3
+ "version": "0.115.1",
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",
@@ -76,7 +76,7 @@
76
76
  "@lobehub/chat-plugin-sdk": "latest",
77
77
  "@lobehub/chat-plugins-gateway": "latest",
78
78
  "@lobehub/tts": "latest",
79
- "@lobehub/ui": "latest",
79
+ "@lobehub/ui": "~1.121.0",
80
80
  "@vercel/analytics": "^1",
81
81
  "ahooks": "^3",
82
82
  "ai": "^2.2.22",
@@ -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
+ };
@@ -6,5 +6,7 @@ export const runtime = 'edge';
6
6
  export const POST = async (req: Request) => {
7
7
  const url = await req.text();
8
8
 
9
- return fetch(url);
9
+ const res = await fetch(url);
10
+
11
+ return new Response(res.body, { headers: res.headers });
10
12
  };
@@ -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 Header = memo(() => {
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
- <ChatHeader
48
- left={
49
- !init ? (
50
- <Flexbox horizontal>
51
- <Skeleton
52
- active
53
- avatar={{ shape: 'circle', size: 'default' }}
54
- paragraph={false}
55
- title={{ style: { margin: 0, marginTop: 8 }, width: 200 }}
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, pluginSelectors } from '@/store/tool/selectors';
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
- pluginSelectors.getPluginManifestLoadingStatus(id)(s),
22
+ toolSelectors.getManifestLoadingStatus(id)(s),
22
23
  customPluginSelectors.isCustomPlugin(id)(s),
23
24
  s.reinstallCustomPlugin,
24
25
  ]);
25
26
 
26
- const manifest = useToolStore(pluginSelectors.getPluginManifestById(id));
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={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 { pluginSelectors } from '@/store/tool/selectors';
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(pluginSelectors.installedPluginMetaList, isEqual);
19
- const displayPlugin = useToolStore(pluginSelectors.getPluginMetaById(plugins[0]), isEqual);
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
 
@@ -78,7 +78,6 @@ const SystemRole = memo(() => {
78
78
  <EditableMessage
79
79
  classNames={{ markdown: styles.prompt }}
80
80
  editing={editing}
81
- height={editing ? 'calc(70vh - 108px)' : 'calc(70vh - 357.43px)'}
82
81
  model={{
83
82
  extra: (
84
83
  <AgentInfo
@@ -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
+ );
@@ -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
  };
@@ -14,6 +14,7 @@ export const DB_FileSchema = z.object({
14
14
  * @example 'image/png'
15
15
  */
16
16
  fileType: z.string(),
17
+ metadata: z.any().optional(),
17
18
  /**
18
19
  * file name
19
20
  * @example 'test.png'
@@ -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({