@lobehub/chat 1.19.20 → 1.19.22

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 CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.19.22](https://github.com/lobehub/lobe-chat/compare/v1.19.21...v1.19.22)
6
+
7
+ <sup>Released on **2024-09-22**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix ollama model download panel.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix ollama model download panel, closes [#4070](https://github.com/lobehub/lobe-chat/issues/4070) ([fc33336](https://github.com/lobehub/lobe-chat/commit/fc33336))
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 1.19.21](https://github.com/lobehub/lobe-chat/compare/v1.19.20...v1.19.21)
31
+
32
+ <sup>Released on **2024-09-21**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **misc**: Refactor to improve branding customization.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### Code refactoring
44
+
45
+ - **misc**: Refactor to improve branding customization, closes [#4061](https://github.com/lobehub/lobe-chat/issues/4061) ([6199e68](https://github.com/lobehub/lobe-chat/commit/6199e68))
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 1.19.20](https://github.com/lobehub/lobe-chat/compare/v1.19.19...v1.19.20)
6
56
 
7
57
  <sup>Released on **2024-09-21**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.19.20",
3
+ "version": "1.19.22",
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",
@@ -3,15 +3,16 @@
3
3
  import { memo } from 'react';
4
4
 
5
5
  import PageTitle from '@/components/PageTitle';
6
+ import { useChatStore } from '@/store/chat';
7
+ import { topicSelectors } from '@/store/chat/selectors';
6
8
  import { useSessionStore } from '@/store/session';
7
9
  import { sessionMetaSelectors } from '@/store/session/selectors';
8
10
 
9
11
  const Title = memo(() => {
10
- const [avatar, title] = useSessionStore((s) => [
11
- sessionMetaSelectors.currentAgentAvatar(s),
12
- sessionMetaSelectors.currentAgentTitle(s),
13
- ]);
12
+ const agentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle);
14
13
 
15
- return <PageTitle title={[avatar, title].filter(Boolean).join(' ')} />;
14
+ const topicTitle = useChatStore((s) => topicSelectors.currentActiveTopic(s)?.title);
15
+ return <PageTitle title={[topicTitle, agentTitle].filter(Boolean).join(' · ')} />;
16
16
  });
17
+
17
18
  export default Title;
@@ -1,11 +1,12 @@
1
1
  import { GridShowcase } from '@lobehub/ui';
2
- import { LobeHub } from '@lobehub/ui/brand';
3
2
  import { PropsWithChildren } from 'react';
4
3
  import { Flexbox } from 'react-layout-kit';
5
4
 
5
+ import { ORG_NAME } from '@/const/branding';
6
+ import { isCustomORG } from '@/const/version';
6
7
  import Follow from '@/features/Follow';
7
8
 
8
- const COPYRIGHT = `© ${new Date().getFullYear()} LobeHub, LLC`;
9
+ const COPYRIGHT = `© ${new Date().getFullYear()} ${ORG_NAME}`;
9
10
 
10
11
  const DesktopLayout = ({ children }: PropsWithChildren) => {
11
12
  return (
@@ -18,7 +19,7 @@ const DesktopLayout = ({ children }: PropsWithChildren) => {
18
19
  style={{ overflow: 'hidden', position: 'relative' }}
19
20
  width={'100%'}
20
21
  >
21
- <LobeHub size={36} style={{ alignSelf: 'flex-start' }} type={'text'} />
22
+ <div />
22
23
  <GridShowcase
23
24
  innerProps={{ gap: 24 }}
24
25
  style={{ maxHeight: 'calc(100% - 104px)', maxWidth: 1024 }}
@@ -28,7 +29,7 @@ const DesktopLayout = ({ children }: PropsWithChildren) => {
28
29
  </GridShowcase>
29
30
  <Flexbox align={'center'} horizontal justify={'space-between'}>
30
31
  <span style={{ opacity: 0.5 }}>{COPYRIGHT}</span>
31
- <Follow />
32
+ {isCustomORG ? <div /> : <Follow />}
32
33
  </Flexbox>
33
34
  </Flexbox>
34
35
  {/* ↓ cloud slot ↓ */}
@@ -1,3 +1,4 @@
1
+ import { WelcomeLogo } from '@/components/Branding';
1
2
  import StructuredData from '@/components/StructuredData';
2
3
  import { BRANDING_NAME } from '@/const/branding';
3
4
  import { ldModule } from '@/server/ld';
@@ -7,7 +8,6 @@ import { isMobileDevice } from '@/utils/responsive';
7
8
 
8
9
  import Actions from './features/Actions';
9
10
  import Hero from './features/Hero';
10
- import Logo from './features/Logo';
11
11
 
12
12
  export const generateMetadata = async () => {
13
13
  const { t } = await translation('metadata');
@@ -30,7 +30,7 @@ const Page = async () => {
30
30
  return (
31
31
  <>
32
32
  <StructuredData ld={ld} />
33
- <Logo mobile={mobile} />
33
+ <WelcomeLogo mobile={mobile} />
34
34
  <Hero />
35
35
  <Actions mobile={mobile} />
36
36
  </>
@@ -6,11 +6,13 @@ import Link from 'next/link';
6
6
  import { memo } from 'react';
7
7
  import { Flexbox, FlexboxProps } from 'react-layout-kit';
8
8
 
9
+ import { ORG_NAME } from '@/const/branding';
9
10
  import { UTM_SOURCE } from '@/const/url';
11
+ import { isCustomORG } from '@/const/version';
10
12
 
11
13
  const useStyles = createStyles(({ token, css }) => ({
12
14
  logoLink: css`
13
- height: 20px;
15
+ line-height: 1;
14
16
  color: inherit;
15
17
 
16
18
  &:hover {
@@ -31,13 +33,17 @@ const BrandWatermark = memo<Omit<FlexboxProps, 'children'>>(({ style, ...rest })
31
33
  {...rest}
32
34
  >
33
35
  <span>Powered by</span>
34
- <Link
35
- className={styles.logoLink}
36
- href={`https://lobehub.com?utm_source=${UTM_SOURCE}&utm_content=brand_watermark`}
37
- target={'_blank'}
38
- >
39
- <LobeHub size={20} type={'text'} />
40
- </Link>
36
+ {isCustomORG ? (
37
+ <span>{ORG_NAME}</span>
38
+ ) : (
39
+ <Link
40
+ className={styles.logoLink}
41
+ href={`https://lobehub.com?utm_source=${UTM_SOURCE}&utm_content=brand_watermark`}
42
+ target={'_blank'}
43
+ >
44
+ <LobeHub size={20} type={'text'} />
45
+ </Link>
46
+ )}
41
47
  </Flexbox>
42
48
  );
43
49
  });
@@ -0,0 +1,13 @@
1
+ import { LobeHub, type LobeHubProps } from '@lobehub/ui/brand';
2
+ import { memo } from 'react';
3
+
4
+ import { ORG_NAME } from '@/const/branding';
5
+ import { isCustomORG } from '@/const/version';
6
+
7
+ export const OrgBrand = memo<LobeHubProps>((props) => {
8
+ if (isCustomORG) {
9
+ return <span>{ORG_NAME}</span>;
10
+ }
11
+
12
+ return <LobeHub {...props} />;
13
+ });
@@ -3,7 +3,7 @@ import { memo } from 'react';
3
3
 
4
4
  import { isCustomBranding } from '@/const/version';
5
5
 
6
- import CustomLogo from './CustomLogo';
6
+ import CustomLogo from './Custom';
7
7
 
8
8
  export const ProductLogo = memo<LobeChatProps>((props) => {
9
9
  if (isCustomBranding) {
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+
3
+ import Image from 'next/image';
4
+ import { memo } from 'react';
5
+ import { Center } from 'react-layout-kit';
6
+
7
+ import { BRANDING_LOGO_URL, BRANDING_NAME } from '@/const/branding';
8
+
9
+ const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => {
10
+ return mobile ? (
11
+ <Center height={240} width={240}>
12
+ <Image
13
+ alt={BRANDING_NAME}
14
+ height={240}
15
+ src={BRANDING_LOGO_URL}
16
+ unoptimized={true}
17
+ width={240}
18
+ />
19
+ </Center>
20
+ ) : (
21
+ <Center
22
+ style={{
23
+ height: `min(482px, 40vw)`,
24
+ marginBottom: '-10%',
25
+ marginTop: '-20%',
26
+ position: 'relative',
27
+ width: `min(976px, 80vw)`,
28
+ }}
29
+ >
30
+ <Image
31
+ alt={BRANDING_NAME}
32
+ height={240}
33
+ src={BRANDING_LOGO_URL}
34
+ unoptimized={true}
35
+ width={240}
36
+ />
37
+ </Center>
38
+ );
39
+ });
40
+
41
+ export default WelcomeLogo;
@@ -7,7 +7,7 @@ import { Center } from 'react-layout-kit';
7
7
  const LogoThree = dynamic(() => import('@lobehub/ui/es/LogoThree'), { ssr: false });
8
8
  const LogoSpline = dynamic(() => import('@lobehub/ui/es/LogoThree/LogoSpline'), { ssr: false });
9
9
 
10
- const Logo = memo<{ mobile?: boolean }>(({ mobile }) => {
10
+ const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => {
11
11
  return mobile ? (
12
12
  <Center height={240} width={240}>
13
13
  <LogoThree size={240} />
@@ -27,4 +27,4 @@ const Logo = memo<{ mobile?: boolean }>(({ mobile }) => {
27
27
  );
28
28
  });
29
29
 
30
- export default Logo;
30
+ export default WelcomeLogo;
@@ -0,0 +1,16 @@
1
+ 'use client';
2
+
3
+ import { memo } from 'react';
4
+
5
+ import { isCustomBranding } from '@/const/version';
6
+
7
+ import CustomLogo from './Custom';
8
+ import LobeChat from './LobeChat';
9
+
10
+ export const WelcomeLogo = memo<{ mobile?: boolean }>(({ mobile }) => {
11
+ if (isCustomBranding) {
12
+ return <CustomLogo mobile={mobile} />;
13
+ }
14
+
15
+ return <LobeChat mobile={mobile} />;
16
+ });
@@ -0,0 +1,3 @@
1
+ export { OrgBrand } from './OrgBrand';
2
+ export { ProductLogo } from './ProductLogo';
3
+ export { WelcomeLogo } from './WelcomeLogo';
package/src/config/app.ts CHANGED
@@ -43,6 +43,7 @@ export const getAppConfig = () => {
43
43
  PLUGIN_SETTINGS: z.string().optional(),
44
44
 
45
45
  APP_URL: z.string().optional(),
46
+ CDN_USE_GLOBAL: z.boolean().optional(),
46
47
  },
47
48
  runtimeEnv: {
48
49
  NEXT_PUBLIC_BASE_PATH: process.env.NEXT_PUBLIC_BASE_PATH || '',
@@ -64,7 +65,10 @@ export const getAppConfig = () => {
64
65
  : 'https://chat-plugins.lobehub.com',
65
66
 
66
67
  PLUGIN_SETTINGS: process.env.PLUGIN_SETTINGS,
68
+
67
69
  APP_URL,
70
+
71
+ CDN_USE_GLOBAL: process.env.CDN_USE_GLOBAL === '1',
68
72
  },
69
73
  });
70
74
  };
@@ -1,8 +1,10 @@
1
- export const LOBE_CHAT_CLOUD = 'LobeChat Cloud';
2
-
3
1
  // the code below can only be modified with commercial license
4
2
  // if you want to use it in the commercial usage
5
3
  // please contact us for more information: hello@lobehub.com
6
4
 
5
+ export const LOBE_CHAT_CLOUD = 'LobeChat Cloud';
6
+
7
7
  export const BRANDING_NAME = 'LobeChat';
8
8
  export const BRANDING_LOGO_URL = '';
9
+
10
+ export const ORG_NAME = 'LobeHub';
package/src/const/meta.ts CHANGED
@@ -5,5 +5,5 @@ export const DEFAULT_AVATAR = '🤖';
5
5
  export const DEFAULT_USER_AVATAR = '😀';
6
6
  export const DEFAULT_BACKGROUND_COLOR = 'rgba(0,0,0,0)';
7
7
  export const DEFAULT_AGENT_META: MetaData = {};
8
- export const DEFAULT_INBOX_AVATAR = '🤯';
8
+ export const DEFAULT_INBOX_AVATAR = BRANDING_LOGO_URL || '🤯';
9
9
  export const DEFAULT_USER_AVATAR_URL = BRANDING_LOGO_URL || '/icons/icon-192x192.png';
@@ -1,7 +1,7 @@
1
1
  import pkg from '@/../package.json';
2
2
  import { getServerDBConfig } from '@/config/db';
3
3
 
4
- import { BRANDING_NAME } from './branding';
4
+ import { BRANDING_NAME, ORG_NAME } from './branding';
5
5
 
6
6
  export const CURRENT_VERSION = pkg.version;
7
7
 
@@ -9,3 +9,5 @@ export const isServerMode = getServerDBConfig().NEXT_PUBLIC_ENABLED_SERVER_SERVI
9
9
 
10
10
  // @ts-ignore
11
11
  export const isCustomBranding = BRANDING_NAME !== 'LobeChat';
12
+ // @ts-ignore
13
+ export const isCustomORG = ORG_NAME !== 'LobeHub';
@@ -26,7 +26,7 @@ const OllamaModelForm = memo<OllamaModelFormProps>(({ id, model }) => {
26
26
  const [total, setTotal] = useState(0);
27
27
  const { remainingTime, downloadSpeed } = useDownloadMonitor(total, completed);
28
28
  const percent = useMemo(() => {
29
- return total ? Number(((completed / total) * 100).toFixed(0)) : 0;
29
+ return total ? Number(((completed / total) * 100).toFixed(1)) : 0;
30
30
  }, [completed, total]);
31
31
 
32
32
  const [delAndRegenerateMessage, deleteMessage] = useChatStore((s) => [
@@ -114,8 +114,8 @@ const OllamaModelForm = memo<OllamaModelFormProps>(({ id, model }) => {
114
114
  !total
115
115
  ? t('ollama.unlock.starting')
116
116
  : t('ollama.unlock.downloaded', {
117
- completed: formatSize(completed),
118
- total: formatSize(total),
117
+ completed: formatSize(completed, 2),
118
+ total: formatSize(total, 2),
119
119
  })}
120
120
  </Button>
121
121
  {isDownloading ? (
@@ -23,7 +23,7 @@ interface OllamaErrorResponse {
23
23
  error: OllamaError;
24
24
  }
25
25
 
26
- const UNRESOLVED_MODEL_REGEXP = /model '([\w+,-_]+)' not found/;
26
+ const UNRESOLVED_MODEL_REGEXP = /model "([\w+,-_]+)" not found/;
27
27
 
28
28
  const OllamaBizError = memo<ChatMessage>(({ error, id }) => {
29
29
  const errorBody: OllamaErrorResponse = (error as any)?.body;
@@ -79,10 +79,11 @@ export interface AppThemeProps {
79
79
  defaultAppearance?: ThemeAppearance;
80
80
  defaultNeutralColor?: NeutralColors;
81
81
  defaultPrimaryColor?: PrimaryColors;
82
+ globalCDN?: boolean;
82
83
  }
83
84
 
84
85
  const AppTheme = memo<AppThemeProps>(
85
- ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor }) => {
86
+ ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor, globalCDN }) => {
86
87
  // console.debug('server:appearance', defaultAppearance);
87
88
  // console.debug('server:primaryColor', defaultPrimaryColor);
88
89
  // console.debug('server:neutralColor', defaultNeutralColor);
@@ -116,7 +117,14 @@ const AppTheme = memo<AppThemeProps>(
116
117
  >
117
118
  <GlobalStyle />
118
119
  <AntdStaticMethods />
119
- <ConfigProvider config={{ aAs: Link, imgAs: Image, imgUnoptimized: true }}>
120
+ <ConfigProvider
121
+ config={{
122
+ aAs: Link,
123
+ imgAs: Image,
124
+ imgUnoptimized: true,
125
+ proxy: globalCDN ? 'unpkg' : undefined,
126
+ }}
127
+ >
120
128
  {children}
121
129
  </ConfigProvider>
122
130
  </ThemeProvider>
@@ -3,6 +3,7 @@ import { cookies, headers } from 'next/headers';
3
3
  import { FC, PropsWithChildren } from 'react';
4
4
  import { resolveAcceptLanguage } from 'resolve-accept-language';
5
5
 
6
+ import { appEnv } from '@/config/app';
6
7
  import { getDebugConfig } from '@/config/debug';
7
8
  import { getServerFeatureFlagsValue } from '@/config/featureFlags';
8
9
  import { LOBE_LOCALE_COOKIE } from '@/const/locale';
@@ -82,6 +83,7 @@ const GlobalLayout = async ({ children }: PropsWithChildren) => {
82
83
  defaultAppearance={appearance?.value}
83
84
  defaultNeutralColor={neutralColor?.value as any}
84
85
  defaultPrimaryColor={primaryColor?.value as any}
86
+ globalCDN={appEnv.CDN_USE_GLOBAL}
85
87
  >
86
88
  <ServerConfigStoreProvider
87
89
  featureFlags={serverFeatureFlags}