@lobehub/chat 0.151.7 → 0.151.9
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/CHANGELOG.md +50 -0
- package/package.json +1 -1
- package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/index.tsx +9 -6
- package/src/app/(main)/@nav/_layout/Mobile.tsx +71 -0
- package/src/app/(main)/@nav/default.tsx +10 -0
- package/src/app/(main)/_layout/Desktop.tsx +33 -0
- package/src/app/(main)/_layout/Mobile.tsx +24 -0
- package/src/app/(main)/_layout/type.ts +6 -0
- package/src/app/(main)/chat/(mobile)/features/ChatInput/index.tsx +1 -1
- package/src/app/(main)/chat/(mobile)/index.tsx +4 -3
- package/src/app/(main)/chat/(mobile)/mobile/ChatHeader/index.tsx +1 -0
- package/src/app/(main)/chat/(mobile)/mobile/page.tsx +6 -9
- package/src/app/(main)/chat/settings/(mobile)/index.tsx +4 -3
- package/src/app/(main)/error.tsx +5 -0
- package/src/app/(main)/layout.tsx +11 -0
- package/src/app/(main)/market/_layout/Mobile/index.tsx +6 -8
- package/src/app/(main)/market/features/AgentSearchBar/index.tsx +15 -12
- package/src/app/(main)/not-found.tsx +3 -0
- package/src/app/(main)/settings/_layout/Mobile/index.tsx +3 -3
- package/src/app/layout.tsx +1 -4
- package/src/app/page.tsx +2 -0
- package/src/components/404/index.tsx +4 -2
- package/src/components/Error/index.tsx +5 -3
- package/src/components/server/MobileNavLayout.tsx +60 -0
- package/src/components/server/ServerLayout.tsx +6 -7
- package/src/database/client/models/__tests__/sessionGroup.test.ts +18 -0
- package/src/features/Conversation/index.tsx +3 -3
- package/src/libs/agent-runtime/minimax/index.test.ts +18 -4
- package/src/libs/agent-runtime/minimax/index.ts +22 -8
- package/src/server/globalConfig/index.ts +2 -0
- package/src/styles/mobileHeader.ts +1 -0
- package/src/layout/DefaultLayout/Desktop/index.tsx +0 -32
- package/src/layout/DefaultLayout/Mobile/index.tsx +0 -59
- package/src/layout/DefaultLayout/index.ts +0 -2
- package/src/layout/routes/Desktop.tsx +0 -18
- package/src/layout/routes/Mobile.tsx +0 -24
- package/src/layout/routes/index.tsx +0 -8
- /package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/Avatar.tsx +0 -0
- /package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/BottomActions.tsx +0 -0
- /package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/TopActions.tsx +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.151.9](https://github.com/lobehub/lobe-chat/compare/v0.151.8...v0.151.9)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-04-30**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Minimax truncationed output.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Minimax truncationed output, closes [#2308](https://github.com/lobehub/lobe-chat/issues/2308) ([488f319](https://github.com/lobehub/lobe-chat/commit/488f319))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.151.8](https://github.com/lobehub/lobe-chat/compare/v0.151.7...v0.151.8)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-04-30**</sup>
|
|
33
|
+
|
|
34
|
+
#### ♻ Code Refactoring
|
|
35
|
+
|
|
36
|
+
- **misc**: Move NavBar to `[@nav](https://github.com/nav)` slot route.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### Code refactoring
|
|
44
|
+
|
|
45
|
+
- **misc**: Move NavBar to `[@nav](https://github.com/nav)` slot route, closes [#2306](https://github.com/lobehub/lobe-chat/issues/2306) ([aee7231](https://github.com/lobehub/lobe-chat/commit/aee7231))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 0.151.7](https://github.com/lobehub/lobe-chat/compare/v0.151.6...v0.151.7)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2024-04-30**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.151.
|
|
3
|
+
"version": "0.151.9",
|
|
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",
|
package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/index.tsx
RENAMED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
import { SideNav } from '@lobehub/ui';
|
|
2
4
|
import { memo } from 'react';
|
|
3
5
|
|
|
4
|
-
import {
|
|
6
|
+
import { useActiveTabKey } from '@/hooks/useActiveTabKey';
|
|
5
7
|
|
|
6
8
|
import Avatar from './Avatar';
|
|
7
9
|
import BottomActions from './BottomActions';
|
|
8
10
|
import TopActions from './TopActions';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
sidebarKey
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default memo<Props>(({ sidebarKey }) => {
|
|
12
|
+
const Nav = memo(() => {
|
|
13
|
+
const sidebarKey = useActiveTabKey();
|
|
15
14
|
return (
|
|
16
15
|
<SideNav
|
|
17
16
|
avatar={<Avatar />}
|
|
@@ -21,3 +20,7 @@ export default memo<Props>(({ sidebarKey }) => {
|
|
|
21
20
|
/>
|
|
22
21
|
);
|
|
23
22
|
});
|
|
23
|
+
|
|
24
|
+
Nav.displayName = 'DesktopNav';
|
|
25
|
+
|
|
26
|
+
export default Nav;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Icon, MobileTabBar, type MobileTabBarProps } from '@lobehub/ui';
|
|
4
|
+
import { createStyles } from 'antd-style';
|
|
5
|
+
import { Bot, MessageSquare, User } from 'lucide-react';
|
|
6
|
+
import { useRouter } from 'next/navigation';
|
|
7
|
+
import { rgba } from 'polished';
|
|
8
|
+
import { memo, useMemo } from 'react';
|
|
9
|
+
import { useTranslation } from 'react-i18next';
|
|
10
|
+
|
|
11
|
+
import { useActiveTabKey } from '@/hooks/useActiveTabKey';
|
|
12
|
+
import { SidebarTabKey } from '@/store/global/initialState';
|
|
13
|
+
|
|
14
|
+
const useStyles = createStyles(({ css, token }) => ({
|
|
15
|
+
active: css`
|
|
16
|
+
svg {
|
|
17
|
+
fill: ${rgba(token.colorPrimary, 0.33)};
|
|
18
|
+
}
|
|
19
|
+
`,
|
|
20
|
+
container: css`
|
|
21
|
+
position: fixed;
|
|
22
|
+
z-index: 100;
|
|
23
|
+
right: 0;
|
|
24
|
+
bottom: 0;
|
|
25
|
+
left: 0;
|
|
26
|
+
`,
|
|
27
|
+
}));
|
|
28
|
+
|
|
29
|
+
const Nav = memo(() => {
|
|
30
|
+
const { t } = useTranslation('common');
|
|
31
|
+
const { styles } = useStyles();
|
|
32
|
+
const activeKey = useActiveTabKey();
|
|
33
|
+
const router = useRouter();
|
|
34
|
+
const items: MobileTabBarProps['items'] = useMemo(
|
|
35
|
+
() => [
|
|
36
|
+
{
|
|
37
|
+
icon: (active) => (
|
|
38
|
+
<Icon className={active ? styles.active : undefined} icon={MessageSquare} />
|
|
39
|
+
),
|
|
40
|
+
key: SidebarTabKey.Chat,
|
|
41
|
+
onClick: () => {
|
|
42
|
+
router.push('/chat');
|
|
43
|
+
},
|
|
44
|
+
title: t('tab.chat'),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
icon: (active) => <Icon className={active ? styles.active : undefined} icon={Bot} />,
|
|
48
|
+
key: SidebarTabKey.Market,
|
|
49
|
+
onClick: () => {
|
|
50
|
+
router.push('/market');
|
|
51
|
+
},
|
|
52
|
+
title: t('tab.market'),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
icon: (active) => <Icon className={active ? styles.active : undefined} icon={User} />,
|
|
56
|
+
key: SidebarTabKey.Setting,
|
|
57
|
+
onClick: () => {
|
|
58
|
+
router.push('/settings');
|
|
59
|
+
},
|
|
60
|
+
title: t('tab.setting'),
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
[t],
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return <MobileTabBar activeKey={activeKey} className={styles.container} items={items} safeArea />;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
Nav.displayName = 'MobileNav';
|
|
70
|
+
|
|
71
|
+
export default Nav;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import { useIsPWA } from '@/hooks/useIsPWA';
|
|
8
|
+
|
|
9
|
+
import { LayoutProps } from './type';
|
|
10
|
+
|
|
11
|
+
const Layout = memo<LayoutProps>(({ children, nav }) => {
|
|
12
|
+
const isPWA = useIsPWA();
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Flexbox
|
|
17
|
+
height={'100%'}
|
|
18
|
+
horizontal
|
|
19
|
+
style={{
|
|
20
|
+
borderTop: isPWA ? `1px solid ${theme.colorBorder}` : undefined,
|
|
21
|
+
position: 'relative',
|
|
22
|
+
}}
|
|
23
|
+
width={'100%'}
|
|
24
|
+
>
|
|
25
|
+
{nav}
|
|
26
|
+
{children}
|
|
27
|
+
</Flexbox>
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
Layout.displayName = 'DesktopMainLayout';
|
|
32
|
+
|
|
33
|
+
export default Layout;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { usePathname } from 'next/navigation';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
|
|
6
|
+
import { LayoutProps } from './type';
|
|
7
|
+
|
|
8
|
+
const MOBILE_IGNORE_NAV_ROUTES = ['/settings/', '/chat/'];
|
|
9
|
+
|
|
10
|
+
const Layout = memo(({ children, nav }: LayoutProps) => {
|
|
11
|
+
const pathname = usePathname();
|
|
12
|
+
const hideNav = MOBILE_IGNORE_NAV_ROUTES.some((path) => pathname.startsWith(path));
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
{children}
|
|
17
|
+
{!hideNav && nav}
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
Layout.displayName = 'MobileMainLayout';
|
|
23
|
+
|
|
24
|
+
export default Layout;
|
|
@@ -27,7 +27,7 @@ const ChatInputMobileLayout = memo(() => {
|
|
|
27
27
|
setExpand={setExpand}
|
|
28
28
|
style={{
|
|
29
29
|
background: `linear-gradient(to bottom, ${theme.colorFillQuaternary}, transparent)`,
|
|
30
|
-
width: '
|
|
30
|
+
width: '100%',
|
|
31
31
|
}}
|
|
32
32
|
textAreaLeftAddons={<STT mobile />}
|
|
33
33
|
textAreaRightAddons={
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { useRouter } from 'next/navigation';
|
|
4
4
|
import { memo, useEffect } from 'react';
|
|
5
5
|
|
|
6
|
+
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
7
|
+
|
|
6
8
|
import SessionHeader from './features/SessionHeader';
|
|
7
9
|
import SessionList from './features/SessionList';
|
|
8
10
|
|
|
@@ -15,10 +17,9 @@ const ChatMobilePage = memo(() => {
|
|
|
15
17
|
}, []);
|
|
16
18
|
|
|
17
19
|
return (
|
|
18
|
-
|
|
19
|
-
<SessionHeader />
|
|
20
|
+
<MobileContentLayout header={<SessionHeader />} withNav>
|
|
20
21
|
<SessionList />
|
|
21
|
-
|
|
22
|
+
</MobileContentLayout>
|
|
22
23
|
);
|
|
23
24
|
});
|
|
24
25
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import dynamic from 'next/dynamic';
|
|
4
4
|
import { memo } from 'react';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
5
|
|
|
6
|
+
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
7
7
|
import Conversation from '@/features/Conversation';
|
|
8
8
|
|
|
9
9
|
import SessionHydration from '../../components/SessionHydration';
|
|
@@ -15,15 +15,12 @@ const TopicList = dynamic(() => import('../features/TopicList'));
|
|
|
15
15
|
|
|
16
16
|
const Chat = memo(() => {
|
|
17
17
|
return (
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
<TopicList />
|
|
23
|
-
<TelemetryNotification mobile />
|
|
24
|
-
</Flexbox>
|
|
18
|
+
<MobileContentLayout header={<ChatHeader />}>
|
|
19
|
+
<Conversation chatInput={<ChatInput />} mobile />
|
|
20
|
+
<TopicList />
|
|
21
|
+
<TelemetryNotification mobile />
|
|
25
22
|
<SessionHydration />
|
|
26
|
-
|
|
23
|
+
</MobileContentLayout>
|
|
27
24
|
);
|
|
28
25
|
});
|
|
29
26
|
export default Chat;
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
import { memo } from 'react';
|
|
4
4
|
|
|
5
|
+
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
6
|
+
|
|
5
7
|
import EditPage from '../features/EditPage';
|
|
6
8
|
import Header from './Header';
|
|
7
9
|
|
|
8
10
|
const ChatSettings = memo(() => (
|
|
9
|
-
|
|
10
|
-
<Header />
|
|
11
|
+
<MobileContentLayout header={<Header />} withNav={false}>
|
|
11
12
|
<EditPage />
|
|
12
|
-
|
|
13
|
+
</MobileContentLayout>
|
|
13
14
|
));
|
|
14
15
|
|
|
15
16
|
export default ChatSettings;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import ServerLayout from '@/components/server/ServerLayout';
|
|
2
|
+
|
|
3
|
+
import Desktop from './_layout/Desktop';
|
|
4
|
+
import Mobile from './_layout/Mobile';
|
|
5
|
+
import { LayoutProps } from './_layout/type';
|
|
6
|
+
|
|
7
|
+
const MainLayout = ServerLayout<LayoutProps>({ Desktop, Mobile });
|
|
8
|
+
|
|
9
|
+
MainLayout.displayName = 'MainLayout';
|
|
10
|
+
|
|
11
|
+
export default MainLayout;
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
3
4
|
|
|
4
5
|
import AgentSearchBar from '../../features/AgentSearchBar';
|
|
5
6
|
import Header from './Header';
|
|
6
7
|
|
|
7
8
|
const MobileLayout = ({ children }: PropsWithChildren) => {
|
|
8
9
|
return (
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{children}
|
|
14
|
-
</Flexbox>
|
|
15
|
-
</>
|
|
10
|
+
<MobileContentLayout gap={16} header={<Header />} style={{ paddingInline: 16 }} withNav>
|
|
11
|
+
<AgentSearchBar mobile />
|
|
12
|
+
{children}
|
|
13
|
+
</MobileContentLayout>
|
|
16
14
|
);
|
|
17
15
|
};
|
|
18
16
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { SearchBar } from '@lobehub/ui';
|
|
4
4
|
import { memo, useCallback, useState } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
7
|
|
|
7
8
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
8
9
|
import { useMarketStore } from '@/store/market';
|
|
@@ -19,18 +20,20 @@ const AgentSearchBar = memo<{ mobile?: boolean }>(({ mobile: controlledMobile })
|
|
|
19
20
|
}, [value, setKeywords]);
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
<Flexbox flex={'none'} paddingBlock={mobile ? 8 : 0}>
|
|
24
|
+
<SearchBar
|
|
25
|
+
allowClear
|
|
26
|
+
enableShortKey={!mobile}
|
|
27
|
+
onChange={(e) => setValue(e.target.value)}
|
|
28
|
+
onPressEnter={handleSearch}
|
|
29
|
+
onSubmit={handleSearch}
|
|
30
|
+
placeholder={t('search.placeholder')}
|
|
31
|
+
shortKey={'k'}
|
|
32
|
+
spotlight={!mobile}
|
|
33
|
+
type={mobile ? 'block' : 'ghost'}
|
|
34
|
+
value={value}
|
|
35
|
+
/>
|
|
36
|
+
</Flexbox>
|
|
34
37
|
);
|
|
35
38
|
});
|
|
36
39
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { PropsWithChildren } from 'react';
|
|
4
4
|
|
|
5
|
+
import MobileContentLayout from '@/components/server/MobileNavLayout';
|
|
5
6
|
import { useIsSubSlug } from '@/hooks/useIsSubSlug';
|
|
6
7
|
|
|
7
8
|
import SubSettingHeader from './SubSettingHeader';
|
|
@@ -11,10 +12,9 @@ const MobileLayout = ({ children }: PropsWithChildren) => {
|
|
|
11
12
|
|
|
12
13
|
if (isSubPath)
|
|
13
14
|
return (
|
|
14
|
-
|
|
15
|
-
<SubSettingHeader />
|
|
15
|
+
<MobileContentLayout header={<SubSettingHeader />} withNav={false}>
|
|
16
16
|
{children}
|
|
17
|
-
|
|
17
|
+
</MobileContentLayout>
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
return children;
|
package/src/app/layout.tsx
CHANGED
|
@@ -8,7 +8,6 @@ import Analytics from '@/components/Analytics';
|
|
|
8
8
|
import { DEFAULT_LANG, LOBE_LOCALE_COOKIE } from '@/const/locale';
|
|
9
9
|
import AuthProvider from '@/layout/AuthProvider';
|
|
10
10
|
import GlobalProvider from '@/layout/GlobalProvider';
|
|
11
|
-
import LayoutRoutes from '@/layout/routes';
|
|
12
11
|
import { isMobileDevice } from '@/utils/responsive';
|
|
13
12
|
|
|
14
13
|
const RootLayout = async ({ children }: PropsWithChildren) => {
|
|
@@ -21,9 +20,7 @@ const RootLayout = async ({ children }: PropsWithChildren) => {
|
|
|
21
20
|
<html dir={direction} lang={lang?.value || DEFAULT_LANG} suppressHydrationWarning>
|
|
22
21
|
<body>
|
|
23
22
|
<GlobalProvider>
|
|
24
|
-
<AuthProvider>
|
|
25
|
-
<LayoutRoutes>{children}</LayoutRoutes>
|
|
26
|
-
</AuthProvider>
|
|
23
|
+
<AuthProvider>{children}</AuthProvider>
|
|
27
24
|
</GlobalProvider>
|
|
28
25
|
<Analytics />
|
|
29
26
|
<SpeedInsights />
|
package/src/app/page.tsx
CHANGED
|
@@ -9,7 +9,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
9
9
|
|
|
10
10
|
import { MAX_WIDTH } from '@/const/layoutTokens';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const NotFound = memo(() => {
|
|
13
13
|
const { t } = useTranslation('error');
|
|
14
14
|
return (
|
|
15
15
|
<Flexbox align={'center'} justify={'center'} style={{ height: '100%', width: '100%' }}>
|
|
@@ -38,4 +38,6 @@ const Page404 = memo(() => {
|
|
|
38
38
|
);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
NotFound.displayName = 'NotFound';
|
|
42
|
+
|
|
43
|
+
export default NotFound;
|
|
@@ -11,12 +11,12 @@ import { MAX_WIDTH } from '@/const/layoutTokens';
|
|
|
11
11
|
|
|
12
12
|
import { type ErrorType, sentryCaptureException } from './sentryCaptureException';
|
|
13
13
|
|
|
14
|
-
interface
|
|
14
|
+
interface ErrorCaptureProps {
|
|
15
15
|
error: ErrorType;
|
|
16
16
|
reset: () => void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const ErrorCapture = memo<ErrorCaptureProps>(({ reset, error }) => {
|
|
20
20
|
const { t } = useTranslation('error');
|
|
21
21
|
|
|
22
22
|
useLayoutEffect(() => {
|
|
@@ -53,4 +53,6 @@ const PageError = memo<PageErrorProps>(({ reset, error }) => {
|
|
|
53
53
|
);
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
ErrorCapture.displayName = 'ErrorCapture';
|
|
57
|
+
|
|
58
|
+
export default ErrorCapture;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Flexbox, type FlexboxProps } from 'react-layout-kit';
|
|
3
|
+
|
|
4
|
+
interface MobileContentLayoutProps extends FlexboxProps {
|
|
5
|
+
header?: ReactNode;
|
|
6
|
+
withNav?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const MobileContentLayout = ({
|
|
10
|
+
children,
|
|
11
|
+
withNav,
|
|
12
|
+
style,
|
|
13
|
+
header,
|
|
14
|
+
...rest
|
|
15
|
+
}: MobileContentLayoutProps) => {
|
|
16
|
+
const content = (
|
|
17
|
+
<Flexbox
|
|
18
|
+
height="100%"
|
|
19
|
+
style={{
|
|
20
|
+
overflowX: 'hidden',
|
|
21
|
+
overflowY: 'auto',
|
|
22
|
+
position: 'relative',
|
|
23
|
+
...style,
|
|
24
|
+
// TabNav Height
|
|
25
|
+
paddingBottom: withNav ? 48 : style?.paddingBottom,
|
|
26
|
+
}}
|
|
27
|
+
width="100%"
|
|
28
|
+
{...rest}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</Flexbox>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (!header) return content;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Flexbox height={'100%'} style={{ overflow: 'hidden', position: 'relative' }} width={'100%'}>
|
|
38
|
+
{header}
|
|
39
|
+
<Flexbox
|
|
40
|
+
height="100%"
|
|
41
|
+
style={{
|
|
42
|
+
overflowX: 'hidden',
|
|
43
|
+
overflowY: 'auto',
|
|
44
|
+
position: 'relative',
|
|
45
|
+
...style,
|
|
46
|
+
// TabNav Height
|
|
47
|
+
paddingBottom: withNav ? 48 : style?.paddingBottom,
|
|
48
|
+
}}
|
|
49
|
+
width="100%"
|
|
50
|
+
{...rest}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</Flexbox>
|
|
54
|
+
</Flexbox>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
MobileContentLayout.displayName = 'MobileContentLayout';
|
|
59
|
+
|
|
60
|
+
export default MobileContentLayout;
|
|
@@ -2,17 +2,16 @@ import { FC, PropsWithChildren } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { isMobileDevice } from '@/utils/responsive';
|
|
4
4
|
|
|
5
|
-
interface ServerLayoutProps {
|
|
6
|
-
Desktop: FC<
|
|
7
|
-
Mobile: FC<
|
|
5
|
+
interface ServerLayoutProps<T> {
|
|
6
|
+
Desktop: FC<T>;
|
|
7
|
+
Mobile: FC<T>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const ServerLayout =
|
|
11
|
-
({ Desktop, Mobile }: ServerLayoutProps) =>
|
|
12
|
-
(
|
|
11
|
+
<T extends PropsWithChildren>({ Desktop, Mobile }: ServerLayoutProps<T>): FC<T> =>
|
|
12
|
+
(props: T) => {
|
|
13
13
|
const mobile = isMobileDevice();
|
|
14
|
-
|
|
15
|
-
return mobile ? <Mobile>{children}</Mobile> : <Desktop>{children}</Desktop>;
|
|
14
|
+
return mobile ? <Mobile {...props} /> : <Desktop {...props} />;
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
ServerLayout.displayName = 'ServerLayout';
|
|
@@ -89,6 +89,16 @@ describe('SessionGroupModel', () => {
|
|
|
89
89
|
expect(session.group).not.toEqual(createdGroup.id);
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
|
+
it('should update associated sessions to default group when a session group is deleted', async () => {
|
|
93
|
+
const createdGroup = await SessionGroupModel.create(
|
|
94
|
+
sessionGroupData.name,
|
|
95
|
+
sessionGroupData.sort,
|
|
96
|
+
);
|
|
97
|
+
const sessionId = await SessionModel.create('agent', {}, createdGroup.id);
|
|
98
|
+
await SessionGroupModel.delete(createdGroup.id);
|
|
99
|
+
const updatedSession = await SessionModel.findById(sessionId.id);
|
|
100
|
+
expect(updatedSession.group).toEqual('default');
|
|
101
|
+
});
|
|
92
102
|
});
|
|
93
103
|
|
|
94
104
|
describe('query', () => {
|
|
@@ -153,6 +163,14 @@ describe('SessionGroupModel', () => {
|
|
|
153
163
|
expect(fetchedGroups[0].id).toEqual(group2.id);
|
|
154
164
|
expect(fetchedGroups[1].id).toEqual(group1.id);
|
|
155
165
|
});
|
|
166
|
+
|
|
167
|
+
it('should sort session groups correctly when only b has a sort value', async () => {
|
|
168
|
+
const groupA = await SessionGroupModel.create('groupA'); // sort undefined
|
|
169
|
+
const groupB = await SessionGroupModel.create('groupB', 1); // sort defined
|
|
170
|
+
const fetchedGroups = await SessionGroupModel.query();
|
|
171
|
+
expect(fetchedGroups[0].id).toEqual(groupB.id);
|
|
172
|
+
expect(fetchedGroups[1].id).toEqual(groupA.id);
|
|
173
|
+
});
|
|
156
174
|
});
|
|
157
175
|
|
|
158
176
|
describe('updateOrder', () => {
|
|
@@ -9,14 +9,13 @@ import SkeletonList from './components/SkeletonList';
|
|
|
9
9
|
const ChatList = lazy(() => import('./components/VirtualizedList'));
|
|
10
10
|
|
|
11
11
|
const useStyles = createStyles(
|
|
12
|
-
({ css, responsive
|
|
12
|
+
({ css, responsive }) => css`
|
|
13
13
|
position: relative;
|
|
14
14
|
overflow-y: auto;
|
|
15
15
|
height: 100%;
|
|
16
16
|
|
|
17
17
|
${responsive.mobile} {
|
|
18
|
-
|
|
19
|
-
width: 100vw;
|
|
18
|
+
width: 100%;
|
|
20
19
|
}
|
|
21
20
|
`,
|
|
22
21
|
);
|
|
@@ -32,6 +31,7 @@ const Conversation = memo<ConversationProps>(({ chatInput, mobile }) => {
|
|
|
32
31
|
return (
|
|
33
32
|
<Flexbox
|
|
34
33
|
flex={1}
|
|
34
|
+
height={'100%'}
|
|
35
35
|
// `relative` is required, ChatInput's absolute position needs it
|
|
36
36
|
style={{ position: 'relative' }}
|
|
37
37
|
>
|
|
@@ -223,7 +223,6 @@ describe('LobeMinimaxAI', () => {
|
|
|
223
223
|
model: 'text-davinci-003',
|
|
224
224
|
temperature: 0.5,
|
|
225
225
|
top_p: 0.8,
|
|
226
|
-
max_tokens: 100,
|
|
227
226
|
};
|
|
228
227
|
|
|
229
228
|
const result = instance['buildCompletionsParams'](payload);
|
|
@@ -234,7 +233,6 @@ describe('LobeMinimaxAI', () => {
|
|
|
234
233
|
stream: true,
|
|
235
234
|
temperature: 0.5,
|
|
236
235
|
top_p: 0.8,
|
|
237
|
-
max_tokens: 100,
|
|
238
236
|
});
|
|
239
237
|
});
|
|
240
238
|
|
|
@@ -244,7 +242,6 @@ describe('LobeMinimaxAI', () => {
|
|
|
244
242
|
model: 'text-davinci-003',
|
|
245
243
|
temperature: 0,
|
|
246
244
|
top_p: 0,
|
|
247
|
-
max_tokens: 100,
|
|
248
245
|
};
|
|
249
246
|
|
|
250
247
|
const result = instance['buildCompletionsParams'](payload);
|
|
@@ -253,7 +250,24 @@ describe('LobeMinimaxAI', () => {
|
|
|
253
250
|
messages: [{ content: 'Hello', role: 'user' }],
|
|
254
251
|
model: 'text-davinci-003',
|
|
255
252
|
stream: true,
|
|
256
|
-
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('should include max tokens when model is abab6.5-chat', () => {
|
|
257
|
+
const payload: ChatStreamPayload = {
|
|
258
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
259
|
+
model: 'abab6.5-chat',
|
|
260
|
+
temperature: 0,
|
|
261
|
+
top_p: 0,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const result = instance['buildCompletionsParams'](payload);
|
|
265
|
+
|
|
266
|
+
expect(result).toEqual({
|
|
267
|
+
messages: [{ content: 'Hello', role: 'user' }],
|
|
268
|
+
model: 'abab6.5-chat',
|
|
269
|
+
stream: true,
|
|
270
|
+
max_tokens: 2048,
|
|
257
271
|
});
|
|
258
272
|
});
|
|
259
273
|
});
|
|
@@ -49,7 +49,7 @@ function throwIfErrorResponse(data: MinimaxResponse) {
|
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function parseMinimaxResponse(chunk: string):
|
|
52
|
+
function parseMinimaxResponse(chunk: string): MinimaxResponse | undefined {
|
|
53
53
|
let body = chunk;
|
|
54
54
|
if (body.startsWith('data:')) {
|
|
55
55
|
body = body.slice(5).trim();
|
|
@@ -57,10 +57,7 @@ function parseMinimaxResponse(chunk: string): string | undefined {
|
|
|
57
57
|
if (isEmpty(body)) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
|
|
61
|
-
if (data.choices?.at(0)?.delta?.content) {
|
|
62
|
-
return data.choices.at(0)?.delta.content || undefined;
|
|
63
|
-
}
|
|
60
|
+
return JSON.parse(body) as MinimaxResponse;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
@@ -136,11 +133,25 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
|
136
133
|
}
|
|
137
134
|
}
|
|
138
135
|
|
|
136
|
+
// the document gives the default value of max tokens, but abab6.5 and abab6.5s
|
|
137
|
+
// will meet length finished error, and output is truncationed
|
|
138
|
+
// so here fill the max tokens number to fix it
|
|
139
|
+
// https://www.minimaxi.com/document/guides/chat-model/V2
|
|
140
|
+
private getMaxTokens(model: string): number | undefined {
|
|
141
|
+
switch (model) {
|
|
142
|
+
case 'abab6.5-chat':
|
|
143
|
+
case 'abab6.5s-chat': {
|
|
144
|
+
return 2048;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
139
149
|
private buildCompletionsParams(payload: ChatStreamPayload) {
|
|
140
150
|
const { temperature, top_p, ...params } = payload;
|
|
141
151
|
|
|
142
152
|
return {
|
|
143
153
|
...params,
|
|
154
|
+
max_tokens: this.getMaxTokens(payload.model),
|
|
144
155
|
stream: true,
|
|
145
156
|
temperature: temperature === 0 ? undefined : temperature,
|
|
146
157
|
top_p: top_p === 0 ? undefined : top_p,
|
|
@@ -159,7 +170,8 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
|
159
170
|
const { value, done: doneReading } = await reader.read();
|
|
160
171
|
done = doneReading;
|
|
161
172
|
const chunkValue = decoder.decode(value, { stream: true });
|
|
162
|
-
const
|
|
173
|
+
const data = parseMinimaxResponse(chunkValue);
|
|
174
|
+
const text = data?.choices?.at(0)?.delta?.content || undefined;
|
|
163
175
|
streamController?.enqueue(encoder.encode(text));
|
|
164
176
|
}
|
|
165
177
|
|
|
@@ -173,12 +185,14 @@ export class LobeMinimaxAI implements LobeRuntimeAI {
|
|
|
173
185
|
const chunkValue = decoder.decode(value, { stream: true });
|
|
174
186
|
let data;
|
|
175
187
|
try {
|
|
176
|
-
data =
|
|
188
|
+
data = parseMinimaxResponse(chunkValue);
|
|
177
189
|
} catch {
|
|
178
190
|
// parse error, skip it
|
|
179
191
|
return;
|
|
180
192
|
}
|
|
181
|
-
|
|
193
|
+
if (data) {
|
|
194
|
+
throwIfErrorResponse(data);
|
|
195
|
+
}
|
|
182
196
|
}
|
|
183
197
|
}
|
|
184
198
|
|
|
@@ -25,6 +25,7 @@ export const getServerGlobalConfig = () => {
|
|
|
25
25
|
ENABLED_GROQ,
|
|
26
26
|
ENABLED_PERPLEXITY,
|
|
27
27
|
ENABLED_ANTHROPIC,
|
|
28
|
+
ENABLED_MINIMAX,
|
|
28
29
|
ENABLED_MISTRAL,
|
|
29
30
|
|
|
30
31
|
ENABLED_AZURE_OPENAI,
|
|
@@ -64,6 +65,7 @@ export const getServerGlobalConfig = () => {
|
|
|
64
65
|
bedrock: { enabled: ENABLED_AWS_BEDROCK },
|
|
65
66
|
google: { enabled: ENABLED_GOOGLE },
|
|
66
67
|
groq: { enabled: ENABLED_GROQ },
|
|
68
|
+
minimax: { enabled: ENABLED_MINIMAX },
|
|
67
69
|
mistral: { enabled: ENABLED_MISTRAL },
|
|
68
70
|
moonshot: { enabled: ENABLED_MOONSHOT },
|
|
69
71
|
ollama: {
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useTheme } from 'antd-style';
|
|
4
|
-
import { PropsWithChildren, memo } from 'react';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import ClientResponsiveLayout from '@/components/client/ClientResponsiveLayout';
|
|
8
|
-
import { useActiveTabKey } from '@/hooks/useActiveTabKey';
|
|
9
|
-
import { useIsPWA } from '@/hooks/useIsPWA';
|
|
10
|
-
|
|
11
|
-
import SideBar from './SideBar';
|
|
12
|
-
|
|
13
|
-
const Desktop = memo<PropsWithChildren>(({ children }) => {
|
|
14
|
-
const isPWA = useIsPWA();
|
|
15
|
-
const theme = useTheme();
|
|
16
|
-
|
|
17
|
-
const sidebarKey = useActiveTabKey();
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Flexbox
|
|
21
|
-
height={'100%'}
|
|
22
|
-
horizontal
|
|
23
|
-
style={isPWA ? { borderTop: `1px solid ${theme.colorBorder}` } : {}}
|
|
24
|
-
width={'100%'}
|
|
25
|
-
>
|
|
26
|
-
<SideBar sidebarKey={sidebarKey} />
|
|
27
|
-
{children}
|
|
28
|
-
</Flexbox>
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
export default ClientResponsiveLayout({ Desktop, Mobile: () => import('../Mobile') });
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { type MobileNavBarTitleProps } from '@lobehub/ui';
|
|
4
|
-
import { createStyles } from 'antd-style';
|
|
5
|
-
import dynamic from 'next/dynamic';
|
|
6
|
-
import { CSSProperties, PropsWithChildren, memo } from 'react';
|
|
7
|
-
import { Flexbox } from 'react-layout-kit';
|
|
8
|
-
|
|
9
|
-
import SafeSpacing from '@/components/SafeSpacing';
|
|
10
|
-
import { SidebarTabKey } from '@/store/global/initialState';
|
|
11
|
-
|
|
12
|
-
const MobileTabBar = dynamic(() => import('@/features/MobileTabBar'));
|
|
13
|
-
|
|
14
|
-
const useStyles = createStyles(({ css, cx, stylish }) => ({
|
|
15
|
-
container: cx(
|
|
16
|
-
stylish.noScrollbar,
|
|
17
|
-
css`
|
|
18
|
-
position: relative;
|
|
19
|
-
overflow: hidden auto;
|
|
20
|
-
width: 100vw;
|
|
21
|
-
height: 100%;
|
|
22
|
-
`,
|
|
23
|
-
),
|
|
24
|
-
mobileTabBar: css`
|
|
25
|
-
position: fixed;
|
|
26
|
-
z-index: 100;
|
|
27
|
-
right: 0;
|
|
28
|
-
bottom: 0;
|
|
29
|
-
left: 0;
|
|
30
|
-
`,
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
interface AppMobileLayoutProps extends PropsWithChildren {
|
|
34
|
-
className?: string;
|
|
35
|
-
showTabBar?: boolean;
|
|
36
|
-
style?: CSSProperties;
|
|
37
|
-
tabBarKey?: SidebarTabKey;
|
|
38
|
-
title?: MobileNavBarTitleProps;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const AppLayoutMobile = memo<AppMobileLayoutProps>(
|
|
42
|
-
({ children, showTabBar, tabBarKey, style, className }) => {
|
|
43
|
-
const { styles, cx } = useStyles();
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<Flexbox className={cx(styles.container, className)} style={style}>
|
|
47
|
-
{children}
|
|
48
|
-
{showTabBar && (
|
|
49
|
-
<>
|
|
50
|
-
<SafeSpacing mobile position={'bottom'} />
|
|
51
|
-
<MobileTabBar className={styles.mobileTabBar} tabBarKey={tabBarKey} />
|
|
52
|
-
</>
|
|
53
|
-
)}
|
|
54
|
-
</Flexbox>
|
|
55
|
-
);
|
|
56
|
-
},
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
export default AppLayoutMobile;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { usePathname } from 'next/navigation';
|
|
4
|
-
import { PropsWithChildren, memo } from 'react';
|
|
5
|
-
|
|
6
|
-
import { DefaultLayoutDesktop } from '@/layout/DefaultLayout';
|
|
7
|
-
|
|
8
|
-
const defaultLayoutRoutes = new Set(['/']);
|
|
9
|
-
|
|
10
|
-
const DesktopLayout = memo<PropsWithChildren>(({ children }) => {
|
|
11
|
-
const pathname = usePathname();
|
|
12
|
-
|
|
13
|
-
if (defaultLayoutRoutes.has(pathname)) return children;
|
|
14
|
-
|
|
15
|
-
return <DefaultLayoutDesktop>{children}</DefaultLayoutDesktop>;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export default DesktopLayout;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { usePathname } from 'next/navigation';
|
|
4
|
-
import { PropsWithChildren, memo } from 'react';
|
|
5
|
-
|
|
6
|
-
import { useActiveTabKey } from '@/hooks/useActiveTabKey';
|
|
7
|
-
import { useIsSubSlug } from '@/hooks/useIsSubSlug';
|
|
8
|
-
import { DefaultLayoutMobile } from '@/layout/DefaultLayout';
|
|
9
|
-
|
|
10
|
-
const MobileLayout = memo<PropsWithChildren>(({ children }) => {
|
|
11
|
-
const pathname = usePathname();
|
|
12
|
-
const tabBarKey = useActiveTabKey();
|
|
13
|
-
const isSubPath = useIsSubSlug();
|
|
14
|
-
|
|
15
|
-
if (pathname === '/') return children;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<DefaultLayoutMobile showTabBar={!isSubPath} tabBarKey={tabBarKey}>
|
|
19
|
-
{children}
|
|
20
|
-
</DefaultLayoutMobile>
|
|
21
|
-
);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
export default MobileLayout;
|
/package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/Avatar.tsx
RENAMED
|
File without changes
|
|
File without changes
|
/package/src/{layout/DefaultLayout/Desktop/SideBar → app/(main)/@nav/_layout/Desktop}/TopActions.tsx
RENAMED
|
File without changes
|