@lobehub/chat 0.84.0-beta.2 → 0.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/.github/workflows/lighthouse-badger-advanced.yml +74 -0
  2. package/.github/workflows/pre-welcome.yml +22 -0
  3. package/.github/workflows/release.yml +0 -3
  4. package/.github/workflows/sync.yml +11 -2
  5. package/.i18nrc.js +1 -2
  6. package/.releaserc.js +1 -14
  7. package/CHANGELOG.md +47 -10
  8. package/README.md +21 -0
  9. package/README.zh-CN.md +21 -0
  10. package/docs/Home.md +1 -0
  11. package/docs/Lighthouse.md +65 -0
  12. package/docs/Lighthouse.zh-CN.md +65 -0
  13. package/docs/_Sidebar.md +1 -0
  14. package/locales/en_US/common.json +5 -0
  15. package/locales/ja_JP/common.json +103 -0
  16. package/locales/ja_JP/empty.json +6 -0
  17. package/locales/ja_JP/error.json +42 -0
  18. package/locales/ja_JP/market.json +16 -0
  19. package/locales/ja_JP/plugin.json +107 -0
  20. package/locales/ja_JP/setting.json +225 -0
  21. package/locales/ja_JP/welcome.json +14 -0
  22. package/locales/ko_KR/common.json +103 -0
  23. package/locales/ko_KR/empty.json +6 -0
  24. package/locales/ko_KR/error.json +42 -0
  25. package/locales/ko_KR/market.json +16 -0
  26. package/locales/ko_KR/plugin.json +107 -0
  27. package/locales/ko_KR/setting.json +225 -0
  28. package/locales/ko_KR/welcome.json +14 -0
  29. package/locales/ru_RU/common.json +5 -0
  30. package/locales/zh_CN/common.json +5 -0
  31. package/locales/zh_TW/common.json +5 -0
  32. package/next.config.mjs +0 -3
  33. package/package.json +4 -4
  34. package/public/icons/maskable-icon-192x192.png +0 -0
  35. package/public/icons/maskable-icon-512x512.png +0 -0
  36. package/public/manifest.json +34 -5
  37. package/public/screenshots/screenshot-1.png +0 -0
  38. package/public/screenshots/screenshot-2.png +0 -0
  39. package/public/screenshots/screenshot-3.png +0 -0
  40. package/public/screenshots/screenshot-4.png +0 -0
  41. package/src/app/chat/(desktop)/features/{ChatHeader/Desktop.tsx → ChatHeader.tsx} +2 -2
  42. package/src/app/chat/(desktop)/features/{ChatInput/Desktop.tsx → ChatInput.tsx} +5 -7
  43. package/src/app/chat/(desktop)/features/{SessionHeader/Desktop.tsx → SessionHeader.tsx} +1 -1
  44. package/src/app/chat/(desktop)/features/{SessionList/Desktop.tsx → SessionList.tsx} +5 -4
  45. package/src/app/chat/(desktop)/features/{SideBar/Desktop.tsx → SideBar.tsx} +5 -4
  46. package/src/app/chat/(desktop)/index.tsx +14 -8
  47. package/src/app/chat/(desktop)/{layout/Desktop.tsx → layout.desktop.tsx} +7 -8
  48. package/src/app/chat/(desktop)/layout.responsive.tsx +12 -0
  49. package/src/app/chat/(mobile)/features/ChatHeader.tsx +54 -1
  50. package/src/app/chat/(mobile)/features/ChatInput.tsx +28 -8
  51. package/src/app/chat/(mobile)/features/SessionList.tsx +13 -8
  52. package/src/app/chat/{components/Inspector/Mobile.tsx → (mobile)/features/TopicList.tsx} +6 -4
  53. package/src/app/chat/(mobile)/index.tsx +3 -5
  54. package/src/app/chat/(mobile)/layout.mobile.tsx +17 -0
  55. package/src/app/chat/(mobile)/mobile/index.tsx +19 -0
  56. package/src/app/chat/(mobile)/mobile/layout.mobile.tsx +11 -0
  57. package/src/app/chat/(mobile)/mobile/page.tsx +2 -20
  58. package/src/app/chat/{components → features}/ChatHeader/ShareButton/Preview.tsx +25 -9
  59. package/src/app/chat/{components → features}/ChatHeader/ShareButton/style.ts +7 -7
  60. package/src/app/chat/{components/ChatInput → features/ChatInputContent}/Footer/SaveTopic.tsx +1 -1
  61. package/src/app/chat/{components/ChatInput → features/ChatInputContent}/index.tsx +3 -1
  62. package/src/app/chat/{components/SessionList → features/SessionListContent}/Inbox/index.tsx +7 -5
  63. package/src/app/chat/{components/SessionList → features/SessionListContent}/index.tsx +3 -1
  64. package/src/app/chat/{components/Inspector → features/TopicListContent}/index.tsx +3 -1
  65. package/src/app/chat/page.tsx +3 -1
  66. package/src/app/chat/settings/(desktop)/index.tsx +14 -0
  67. package/src/app/chat/settings/(desktop)/layout.desktop.tsx +10 -15
  68. package/src/app/chat/settings/(desktop)/layout.responsive.tsx +12 -0
  69. package/src/app/chat/settings/(mobile)/index.tsx +14 -0
  70. package/src/app/chat/settings/(mobile)/layout.mobile.tsx +4 -8
  71. package/src/app/chat/settings/features/EditPage.tsx +38 -0
  72. package/src/app/chat/settings/page.tsx +9 -33
  73. package/src/app/market/(desktop)/{AgentDetail/Desktop.tsx → features/AgentDetail.tsx} +5 -3
  74. package/src/app/market/(desktop)/index.tsx +12 -0
  75. package/src/app/market/(desktop)/{layout/Desktop.tsx → layout.desktop.tsx} +5 -5
  76. package/src/app/market/(desktop)/layout.responsive.tsx +16 -0
  77. package/src/app/market/{components/AgentDetail/Mobile.tsx → (mobile)/features/AgentDetail.tsx} +6 -4
  78. package/src/app/market/(mobile)/index.tsx +12 -0
  79. package/src/app/market/(mobile)/layout.mobile.tsx +5 -5
  80. package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Header.tsx +1 -0
  81. package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/index.tsx +3 -1
  82. package/src/app/market/features/TagList/index.tsx +2 -1
  83. package/src/app/market/page.tsx +8 -5
  84. package/src/app/settings/{features/Header/Desktop.tsx → (desktop)/features/Header.tsx} +2 -2
  85. package/src/app/settings/(desktop)/index.tsx +17 -0
  86. package/src/app/settings/{layout.desktop/Desktop.tsx → (desktop)/layout.desktop.tsx} +10 -9
  87. package/src/app/settings/(desktop)/layout.responsive.tsx +14 -0
  88. package/src/app/settings/{mobile → (mobile)/features}/ExtraList.tsx +1 -1
  89. package/src/app/settings/(mobile)/features/Header/Home.tsx +8 -0
  90. package/src/app/settings/{features/Header/Mobile.tsx → (mobile)/features/Header/index.tsx} +1 -0
  91. package/src/app/settings/(mobile)/index.tsx +3 -0
  92. package/src/app/settings/(mobile)/layout.mobile.tsx +19 -0
  93. package/src/app/settings/{mobile → (mobile)/mobile}/index.tsx +9 -9
  94. package/src/app/settings/(mobile)/mobile/layout.mobile.tsx +14 -0
  95. package/src/app/settings/agent/Agent.tsx +30 -0
  96. package/src/app/settings/agent/index.tsx +23 -0
  97. package/src/app/settings/agent/layout.tsx +1 -0
  98. package/src/app/settings/agent/page.tsx +2 -31
  99. package/src/app/settings/common/index.tsx +23 -0
  100. package/src/app/settings/common/layout.tsx +1 -0
  101. package/src/app/settings/common/page.tsx +2 -14
  102. package/src/app/settings/features/SideBar/index.tsx +2 -0
  103. package/src/app/settings/features/UpgradeAlert.tsx +32 -0
  104. package/src/app/settings/layout.server.tsx +12 -0
  105. package/src/app/settings/llm/index.tsx +23 -0
  106. package/src/app/settings/llm/layout.tsx +1 -0
  107. package/src/app/settings/llm/page.tsx +2 -14
  108. package/src/app/settings/page.tsx +14 -1
  109. package/src/app/welcome/{features/Footer/index.tsx → (desktop)/features/Footer.tsx} +14 -3
  110. package/src/app/welcome/(desktop)/features/Showcase.tsx +23 -0
  111. package/src/app/welcome/(desktop)/index.tsx +19 -0
  112. package/src/app/welcome/{DesktopLayout/Desktop.tsx → (desktop)/layout.desktop.tsx} +5 -8
  113. package/src/app/welcome/(desktop)/layout.responsive.tsx +14 -0
  114. package/src/app/welcome/(mobile)/features/Header.tsx +6 -0
  115. package/src/app/welcome/(mobile)/features/Showcase.tsx +16 -0
  116. package/src/app/welcome/(mobile)/index.tsx +10 -0
  117. package/src/app/welcome/(mobile)/layout.mobile.tsx +20 -0
  118. package/src/app/welcome/features/Banner/Hero.tsx +2 -3
  119. package/src/app/welcome/features/Banner/index.tsx +34 -31
  120. package/src/app/welcome/features/Banner/style.ts +10 -1
  121. package/src/app/welcome/page.tsx +9 -7
  122. package/src/components/ResponsiveIndex.tsx +17 -0
  123. package/src/const/url.ts +2 -1
  124. package/src/const/version.ts +6 -0
  125. package/src/features/MobileTabBar/index.tsx +1 -1
  126. package/src/features/SideBar/BottomActions.tsx +107 -81
  127. package/src/layout/{AppLayout.tsx → AppLayout.desktop.tsx} +2 -2
  128. package/src/layout/{AppMobileLayout.tsx → AppLayout.mobile.tsx} +2 -2
  129. package/src/layout/GlobalLayout/AppTheme.tsx +3 -3
  130. package/src/layout/GlobalLayout/Locale.tsx +2 -2
  131. package/src/layout/GlobalLayout/StoreHydration.tsx +15 -1
  132. package/src/layout/ResponsiveLayout.client.tsx +18 -0
  133. package/src/{components/ResponsiveLayout.tsx → layout/ResponsiveLayout.server.tsx} +4 -3
  134. package/src/locales/default/common.ts +5 -0
  135. package/src/locales/options.ts +8 -1
  136. package/src/locales/resources/index.ts +4 -0
  137. package/src/locales/resources/ja_JP.ts +19 -0
  138. package/src/locales/resources/ko_KR.ts +19 -0
  139. package/src/services/latestVersion.ts +11 -1
  140. package/src/store/global/initialState.ts +11 -9
  141. package/src/store/global/slices/common.ts +12 -0
  142. package/src/store/session/slices/session/initialState.ts +2 -2
  143. package/src/utils/VersionController.ts +1 -1
  144. package/src/utils/responsive.ts +1 -1
  145. package/.dockerignore +0 -10
  146. package/Dockerfile +0 -47
  147. package/src/app/chat/(desktop)/features/ChatHeader/index.tsx +0 -14
  148. package/src/app/chat/(desktop)/features/ChatInput/index.tsx +0 -22
  149. package/src/app/chat/(desktop)/features/SessionHeader/index.tsx +0 -14
  150. package/src/app/chat/(desktop)/features/SessionList/index.tsx +0 -20
  151. package/src/app/chat/(desktop)/features/SideBar/index.tsx +0 -20
  152. package/src/app/chat/(desktop)/layout/index.tsx +0 -25
  153. package/src/app/chat/(mobile)/features/Topics.tsx +0 -12
  154. package/src/app/chat/(mobile)/layout.tsx +0 -15
  155. package/src/app/chat/components/ChatHeader/Mobile.tsx +0 -54
  156. package/src/app/chat/components/ChatInput/Mobile.tsx +0 -35
  157. package/src/app/chat/components/SessionList/Mobile.tsx +0 -16
  158. package/src/app/chat/layout.tsx +0 -15
  159. package/src/app/chat/settings/layout.tsx +0 -14
  160. package/src/app/market/(desktop)/AgentDetail/index.tsx +0 -16
  161. package/src/app/market/(desktop)/Header/index.tsx +0 -13
  162. package/src/app/market/(desktop)/layout/index.tsx +0 -17
  163. package/src/app/market/(mobile)/AgentDetail.tsx +0 -12
  164. package/src/app/market/layout.tsx +0 -13
  165. package/src/app/settings/features/Header/index.tsx +0 -14
  166. package/src/app/settings/layout.desktop/index.tsx +0 -32
  167. package/src/app/settings/layout.mobile.tsx +0 -16
  168. package/src/app/settings/layout.tsx +0 -15
  169. package/src/app/settings/mobile/page.tsx +0 -7
  170. package/src/app/welcome/DesktopLayout/index.tsx +0 -15
  171. package/src/app/welcome/MobileLayout.tsx +0 -23
  172. package/src/app/welcome/layout.tsx +0 -22
  173. /package/src/app/chat/{components → features}/ChatHeader/PluginTag/PluginStatus.tsx +0 -0
  174. /package/src/app/chat/{components → features}/ChatHeader/PluginTag/index.tsx +0 -0
  175. /package/src/app/chat/{components → features}/ChatHeader/ShareButton/Inner.tsx +0 -0
  176. /package/src/app/chat/{components → features}/ChatHeader/ShareButton/index.tsx +0 -0
  177. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/ActionLeft.tsx +0 -0
  178. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/ActionRight.tsx +0 -0
  179. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/ActionBar/Token.tsx +0 -0
  180. /package/src/app/chat/{components/ChatInput → features/ChatInputContent}/Footer/index.tsx +0 -0
  181. /package/src/app/chat/features/{PageTitle.tsx → PageTitle/index.tsx} +0 -0
  182. /package/src/app/chat/{components/SessionList → features/SessionListContent}/CollapseGroup/index.tsx +0 -0
  183. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/AddButton.tsx +0 -0
  184. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/Item/Actions.tsx +0 -0
  185. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/Item/index.tsx +0 -0
  186. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/SkeletonList.tsx +0 -0
  187. /package/src/app/chat/{components/SessionList → features/SessionListContent}/List/index.tsx +0 -0
  188. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/Header.tsx +0 -0
  189. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/index.tsx +0 -0
  190. /package/src/app/chat/{components/Inspector → features/TopicListContent}/SystemRole/style.ts +0 -0
  191. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/DefaultContent.tsx +0 -0
  192. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/SkeletonList.tsx +0 -0
  193. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/TopicContent.tsx +0 -0
  194. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/TopicItem.tsx +0 -0
  195. /package/src/app/chat/{components/Inspector → features/TopicListContent}/Topic/index.tsx +0 -0
  196. /package/src/app/chat/{components/Inspector → features/TopicListContent}/TopicSearchBar/index.tsx +0 -0
  197. /package/src/app/market/(desktop)/{Header/Desktop.tsx → features/Header.tsx} +0 -0
  198. /package/src/app/market/(mobile)/{Header.tsx → features/Header.tsx} +0 -0
  199. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Comment.tsx +0 -0
  200. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/Loading.tsx +0 -0
  201. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/TokenTag.tsx +0 -0
  202. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/index.tsx +0 -0
  203. /package/src/app/market/{components/AgentDetail → features/AgentDetailContent}/AgentInfo/style.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { ActionIcon, DiscordIcon, Icon } from '@lobehub/ui';
2
- import { Dropdown, MenuProps, Upload } from 'antd';
2
+ import { Badge, ConfigProvider, Dropdown, MenuProps, Upload } from 'antd';
3
3
  import {
4
+ Book,
4
5
  Feather,
5
6
  FileClock,
6
7
  Github,
@@ -11,13 +12,14 @@ import {
11
12
  Settings2,
12
13
  } from 'lucide-react';
13
14
  import { useRouter } from 'next/navigation';
14
- import { memo, useMemo } from 'react';
15
+ import { memo } from 'react';
15
16
  import { useTranslation } from 'react-i18next';
17
+ import { Flexbox } from 'react-layout-kit';
16
18
 
17
- import { ABOUT, CHANGELOG, DISCORD, FEEDBACK, GITHUB } from '@/const/url';
19
+ import { ABOUT, CHANGELOG, DISCORD, FEEDBACK, GITHUB, WIKI } from '@/const/url';
18
20
  import { useExportConfig } from '@/hooks/useExportConfig';
19
21
  import { useImportConfig } from '@/hooks/useImportConfig';
20
- import { GlobalStore } from '@/store/global';
22
+ import { GlobalStore, useGlobalStore } from '@/store/global';
21
23
  import { SidebarTabKey } from '@/store/global/initialState';
22
24
 
23
25
  export interface BottomActionProps {
@@ -31,83 +33,97 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
31
33
  const { exportSessions, exportSettings, exportAll, exportAgents } = useExportConfig();
32
34
  const { importConfig } = useImportConfig();
33
35
 
34
- const items: MenuProps['items'] = useMemo(
35
- () => [
36
- {
37
- icon: <Icon icon={HardDriveUpload} />,
38
- key: 'import',
39
- label: (
40
- <Upload maxCount={1} onChange={importConfig} showUploadList={false}>
41
- {t('import')}
42
- </Upload>
43
- ),
44
- },
45
- {
46
- children: [
47
- {
48
- key: 'allAgent',
49
- label: <div>{t('exportType.allAgent')}</div>,
50
- onClick: exportAgents,
51
- },
52
- {
53
- key: 'allAgentWithMessage',
54
- label: <div>{t('exportType.allAgentWithMessage')}</div>,
55
- onClick: exportSessions,
56
- },
57
- {
58
- key: 'globalSetting',
59
- label: <div>{t('exportType.globalSetting')}</div>,
60
- onClick: exportSettings,
61
- },
62
- {
63
- type: 'divider',
64
- },
65
- {
66
- key: 'all',
67
- label: <div>{t('exportType.all')}</div>,
68
- onClick: exportAll,
69
- },
70
- ],
71
- icon: <Icon icon={HardDriveDownload} />,
72
- key: 'export',
73
- label: t('export'),
74
- },
75
- {
76
- type: 'divider',
77
- },
78
- {
79
- icon: <Icon icon={Feather} />,
80
- key: 'feedback',
81
- label: t('feedback'),
82
- onClick: () => window.open(FEEDBACK, '__blank'),
83
- },
84
- {
85
- icon: <Icon icon={FileClock} />,
86
- key: 'changelog',
87
- label: t('changelog'),
88
- onClick: () => window.open(CHANGELOG, '__blank'),
89
- },
90
- {
91
- icon: <Icon icon={Heart} />,
92
- key: 'about',
93
- label: t('about'),
94
- onClick: () => window.open(ABOUT, '__blank'),
95
- },
96
- {
97
- type: 'divider',
98
- },
99
- {
100
- icon: <Icon icon={Settings} />,
101
- key: 'setting',
102
- label: t('setting'),
103
- onClick: () => {
104
- setTab(SidebarTabKey.Setting);
105
- router.push('/settings');
36
+ const [hasNewVersion, useCheckLatestVersion] = useGlobalStore((s) => [
37
+ s.hasNewVersion,
38
+ s.useCheckLatestVersion,
39
+ ]);
40
+
41
+ useCheckLatestVersion();
42
+
43
+ const items: MenuProps['items'] = [
44
+ {
45
+ icon: <Icon icon={HardDriveUpload} />,
46
+ key: 'import',
47
+ label: (
48
+ <Upload maxCount={1} onChange={importConfig} showUploadList={false}>
49
+ {t('import')}
50
+ </Upload>
51
+ ),
52
+ },
53
+ {
54
+ children: [
55
+ {
56
+ key: 'allAgent',
57
+ label: <div>{t('exportType.allAgent')}</div>,
58
+ onClick: exportAgents,
59
+ },
60
+ {
61
+ key: 'allAgentWithMessage',
62
+ label: <div>{t('exportType.allAgentWithMessage')}</div>,
63
+ onClick: exportSessions,
64
+ },
65
+ {
66
+ key: 'globalSetting',
67
+ label: <div>{t('exportType.globalSetting')}</div>,
68
+ onClick: exportSettings,
106
69
  },
70
+ {
71
+ type: 'divider',
72
+ },
73
+ {
74
+ key: 'all',
75
+ label: <div>{t('exportType.all')}</div>,
76
+ onClick: exportAll,
77
+ },
78
+ ],
79
+ icon: <Icon icon={HardDriveDownload} />,
80
+ key: 'export',
81
+ label: t('export'),
82
+ },
83
+ {
84
+ type: 'divider',
85
+ },
86
+ {
87
+ icon: <Icon icon={Feather} />,
88
+ key: 'feedback',
89
+ label: t('feedback'),
90
+ onClick: () => window.open(FEEDBACK, '__blank'),
91
+ },
92
+ {
93
+ icon: <Icon icon={FileClock} />,
94
+ key: 'changelog',
95
+ label: t('changelog'),
96
+ onClick: () => window.open(CHANGELOG, '__blank'),
97
+ },
98
+ {
99
+ icon: <Icon icon={Book} />,
100
+ key: 'wiki',
101
+ label: 'WIKI',
102
+ onClick: () => window.open(WIKI, '__blank'),
103
+ },
104
+ {
105
+ icon: <Icon icon={Heart} />,
106
+ key: 'about',
107
+ label: t('about'),
108
+ onClick: () => window.open(ABOUT, '__blank'),
109
+ },
110
+ {
111
+ type: 'divider',
112
+ },
113
+ {
114
+ icon: <Icon icon={Settings} />,
115
+ key: 'setting',
116
+ label: (
117
+ <Flexbox align={'center'} distribution={'space-between'} gap={8} horizontal>
118
+ {t('setting')} {hasNewVersion && <Badge count={t('upgradeVersion.hasNew')} />}
119
+ </Flexbox>
120
+ ),
121
+ onClick: () => {
122
+ setTab(SidebarTabKey.Setting);
123
+ router.push('/settings/common');
107
124
  },
108
- ],
109
- [],
110
- );
125
+ },
126
+ ];
111
127
 
112
128
  return (
113
129
  <>
@@ -121,10 +137,20 @@ const BottomActions = memo<BottomActionProps>(({ tab, setTab }) => {
121
137
  icon={Github}
122
138
  onClick={() => window.open(GITHUB, '__blank')}
123
139
  placement={'right'}
124
- title={'Github'}
140
+ title={'GitHub'}
125
141
  />
126
142
  <Dropdown arrow={false} menu={{ items }} trigger={['click']}>
127
- <ActionIcon active={tab === SidebarTabKey.Setting} icon={Settings2} />
143
+ {hasNewVersion ? (
144
+ <Flexbox>
145
+ <ConfigProvider theme={{ components: { Badge: { dotSize: 8 } } }}>
146
+ <Badge dot offset={[-4, 4]}>
147
+ <ActionIcon active={tab === SidebarTabKey.Setting} icon={Settings2} />
148
+ </Badge>
149
+ </ConfigProvider>
150
+ </Flexbox>
151
+ ) : (
152
+ <ActionIcon active={tab === SidebarTabKey.Setting} icon={Settings2} />
153
+ )}
128
154
  </Dropdown>
129
155
  </>
130
156
  );
@@ -5,7 +5,7 @@ import { Flexbox } from 'react-layout-kit';
5
5
  import SideBar from '@/features/SideBar';
6
6
  import { useIsPWA } from '@/hooks/useIsPWA';
7
7
 
8
- const AppLayout = memo<PropsWithChildren>(({ children }) => {
8
+ const AppLayoutDesktop = memo<PropsWithChildren>(({ children }) => {
9
9
  const isPWA = useIsPWA();
10
10
  const theme = useTheme();
11
11
  return (
@@ -20,4 +20,4 @@ const AppLayout = memo<PropsWithChildren>(({ children }) => {
20
20
  );
21
21
  });
22
22
 
23
- export default AppLayout;
23
+ export default AppLayoutDesktop;
@@ -43,7 +43,7 @@ interface AppMobileLayoutProps extends PropsWithChildren {
43
43
  title?: MobileNavBarTitleProps;
44
44
  }
45
45
 
46
- const AppMobileLayout = memo<AppMobileLayoutProps>(
46
+ const AppLayoutMobile = memo<AppMobileLayoutProps>(
47
47
  ({ children, showTabBar, navBar, style, className }) => {
48
48
  const { styles, cx } = useStyles();
49
49
 
@@ -67,4 +67,4 @@ const AppMobileLayout = memo<AppMobileLayoutProps>(
67
67
  },
68
68
  );
69
69
 
70
- export default AppMobileLayout;
70
+ export default AppLayoutMobile;
@@ -20,9 +20,9 @@ export interface AppThemeProps {
20
20
 
21
21
  const AppTheme = memo<AppThemeProps>(
22
22
  ({ children, defaultAppearance, defaultPrimaryColor, defaultNeutralColor }) => {
23
- // console.log('server:appearance', defaultAppearance);
24
- // console.log('server:primaryColor', defaultPrimaryColor);
25
- // console.log('server:neutralColor', defaultNeutralColor);
23
+ // console.debug('server:appearance', defaultAppearance);
24
+ // console.debug('server:primaryColor', defaultPrimaryColor);
25
+ // console.debug('server:neutralColor', defaultNeutralColor);
26
26
  const themeMode = useGlobalStore((s) => s.settings.themeMode);
27
27
 
28
28
  const [primaryColor, neutralColor] = useGlobalStore((s) => [
@@ -20,9 +20,9 @@ const InnerLocale = memo<LocaleLayoutProps>(({ children, lang }) => {
20
20
  } else {
21
21
  // if on browser side, init i18n instance only once
22
22
  if (!i18n.instance.isInitialized)
23
- // console.log('locale', lang);
23
+ // console.debug('locale', lang);
24
24
  i18n.init().then(() => {
25
- // console.log('inited.');
25
+ // console.debug('inited.');
26
26
  });
27
27
  }
28
28
 
@@ -1,9 +1,14 @@
1
+ import { useResponsive } from 'antd-style';
1
2
  import { useRouter } from 'next/navigation';
2
3
  import { memo, useEffect } from 'react';
3
4
 
4
5
  import { useGlobalStore } from '@/store/global';
5
6
  import { usePluginStore } from '@/store/plugin';
6
- import { useOnFinishHydrationSession, useSessionStore } from '@/store/session';
7
+ import {
8
+ useEffectAfterSessionHydrated,
9
+ useOnFinishHydrationSession,
10
+ useSessionStore,
11
+ } from '@/store/session';
7
12
 
8
13
  const StoreHydration = memo(() => {
9
14
  const router = useRouter();
@@ -22,6 +27,15 @@ const StoreHydration = memo(() => {
22
27
  store.setState({ router });
23
28
  });
24
29
 
30
+ const { mobile } = useResponsive();
31
+
32
+ useEffectAfterSessionHydrated(
33
+ (store) => {
34
+ store.setState({ isMobile: mobile });
35
+ },
36
+ [mobile],
37
+ );
38
+
25
39
  return null;
26
40
  });
27
41
 
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import { PropsWithChildren, ReactNode } from 'react';
4
+
5
+ import { useIsMobile } from '@/hooks/useIsMobile';
6
+
7
+ interface ServerResponsiveLayoutProps {
8
+ Desktop: (props: PropsWithChildren) => ReactNode;
9
+ Mobile: (props: PropsWithChildren) => ReactNode;
10
+ children?: ReactNode;
11
+ }
12
+ const ResponsiveLayout = ({ children, Desktop, Mobile }: ServerResponsiveLayoutProps) => {
13
+ const mobile = useIsMobile();
14
+
15
+ return mobile ? <Mobile>{children}</Mobile> : <Desktop>{children}</Desktop>;
16
+ };
17
+
18
+ export default ResponsiveLayout;
@@ -1,13 +1,14 @@
1
1
  import { PropsWithChildren, ReactNode } from 'react';
2
2
 
3
+ import { isMobileDevice } from '@/utils/responsive';
4
+
3
5
  interface ServerResponsiveLayoutProps {
4
6
  Desktop: (props: PropsWithChildren) => ReactNode;
5
7
  Mobile: (props: PropsWithChildren) => ReactNode;
6
8
  children?: ReactNode;
7
- isMobile: () => boolean;
8
9
  }
9
- const ResponsiveLayout = ({ children, Desktop, Mobile, isMobile }: ServerResponsiveLayoutProps) => {
10
- const mobile = isMobile();
10
+ const ResponsiveLayout = ({ children, Desktop, Mobile }: ServerResponsiveLayoutProps) => {
11
+ const mobile = isMobileDevice();
11
12
 
12
13
  return mobile ? <Mobile>{children}</Mobile> : <Desktop>{children}</Desktop>;
13
14
  };
@@ -96,5 +96,10 @@ export default {
96
96
  },
97
97
  updateAgent: '更新助理信息',
98
98
  updatePrompt: '更新提示词',
99
+ upgradeVersion: {
100
+ action: '立即升级',
101
+ hasNew: '有可用更新',
102
+ newVersion: '有新版本可用:{{version}}',
103
+ },
99
104
  warp: '换行',
100
105
  };
@@ -1,4 +1,3 @@
1
-
2
1
  import type { Locales } from '@/types/locale';
3
2
 
4
3
  type LocaleOptions = {
@@ -19,6 +18,14 @@ export const localeOptions: LocaleOptions = [
19
18
  label: 'English',
20
19
  value: 'en-US',
21
20
  },
21
+ {
22
+ label: '日本語',
23
+ value: 'ja-JP',
24
+ },
25
+ {
26
+ label: '한국어',
27
+ value: 'ko-KR',
28
+ },
22
29
  {
23
30
  label: 'Russian',
24
31
  value: 'ru-RU',
@@ -1,10 +1,14 @@
1
1
  import en_US from './en_US';
2
+ import ja_JP from './ja_JP';
3
+ import ko_KR from './ko_KR';
2
4
  import ru_RU from './ru_RU';
3
5
  import zh_CN from './zh_CN';
4
6
  import zh_TW from './zh_TW';
5
7
 
6
8
  const resources = {
7
9
  'en-US': en_US,
10
+ 'ja-JP': ja_JP,
11
+ 'ko-KR': ko_KR,
8
12
  'ru-RU': ru_RU,
9
13
  'zh-CN': zh_CN,
10
14
  'zh-TW': zh_TW,
@@ -0,0 +1,19 @@
1
+ import common from '../../../locales/ja_JP/common.json';
2
+ import empty from '../../../locales/ja_JP/empty.json';
3
+ import error from '../../../locales/ja_JP/error.json';
4
+ import market from '../../../locales/ja_JP/market.json';
5
+ import plugin from '../../../locales/ja_JP/plugin.json';
6
+ import setting from '../../../locales/ja_JP/setting.json';
7
+ import welcome from '../../../locales/ja_JP/welcome.json';
8
+
9
+ const resources = {
10
+ common,
11
+ empty,
12
+ error,
13
+ market,
14
+ plugin,
15
+ setting,
16
+ welcome,
17
+ } as const;
18
+
19
+ export default resources;
@@ -0,0 +1,19 @@
1
+ import common from '../../../locales/ko_KR/common.json';
2
+ import empty from '../../../locales/ko_KR/empty.json';
3
+ import error from '../../../locales/ko_KR/error.json';
4
+ import market from '../../../locales/ko_KR/market.json';
5
+ import plugin from '../../../locales/ko_KR/plugin.json';
6
+ import setting from '../../../locales/ko_KR/setting.json';
7
+ import welcome from '../../../locales/ko_KR/welcome.json';
8
+
9
+ const resources = {
10
+ common,
11
+ empty,
12
+ error,
13
+ market,
14
+ plugin,
15
+ setting,
16
+ welcome,
17
+ } as const;
18
+
19
+ export default resources;
@@ -1 +1,11 @@
1
- fetch('https://registry.npmmirror.com/@lobehub/chat');
1
+ const VERSION_URL = 'https://registry.npmmirror.com/@lobehub/chat';
2
+
3
+ /**
4
+ * get latest version from npm
5
+ */
6
+ export const featLatestVersion = async (): Promise<string> => {
7
+ const res = await fetch(VERSION_URL);
8
+ const data = await res.json();
9
+
10
+ return data['dist-tags']?.latest;
11
+ };
@@ -18,7 +18,18 @@ export interface Guide {
18
18
  topic?: boolean;
19
19
  }
20
20
 
21
+ export interface GlobalPreference {
22
+ guide?: Guide;
23
+ inputHeight: number;
24
+ mobileShowTopic?: boolean;
25
+ sessionsWidth: number;
26
+ showChatSideBar?: boolean;
27
+ showSessionPanel?: boolean;
28
+ }
29
+
21
30
  export interface GlobalState {
31
+ hasNewVersion?: boolean;
32
+ latestVersion?: string;
22
33
  /**
23
34
  * 用户偏好的 UI 状态
24
35
  * @localStorage
@@ -33,15 +44,6 @@ export interface GlobalState {
33
44
  sidebarKey: SidebarTabKey;
34
45
  }
35
46
 
36
- export interface GlobalPreference {
37
- guide?: Guide;
38
- inputHeight: number;
39
- mobileShowTopic?: boolean;
40
- sessionsWidth: number;
41
- showChatSideBar?: boolean;
42
- showSessionPanel?: boolean;
43
- }
44
-
45
47
  export const initialState: GlobalState = {
46
48
  preference: {
47
49
  guide: {},
@@ -1,6 +1,10 @@
1
1
  import { produce } from 'immer';
2
+ import { gt } from 'semver';
3
+ import useSWR, { SWRResponse } from 'swr';
2
4
  import type { StateCreator } from 'zustand/vanilla';
3
5
 
6
+ import { CURRENT_VERSION } from '@/const/version';
7
+ import { featLatestVersion } from '@/services/latestVersion';
4
8
  import { merge } from '@/utils/merge';
5
9
  import { setNamespace } from '@/utils/storeDebug';
6
10
 
@@ -22,6 +26,7 @@ export interface CommonAction {
22
26
  toggleMobileTopic: (visible?: boolean) => void;
23
27
  updateGuideState: (guide: Partial<Guide>) => void;
24
28
  updatePreference: (preference: Partial<GlobalPreference>, action?: string) => void;
29
+ useCheckLatestVersion: () => SWRResponse<string>;
25
30
  }
26
31
 
27
32
  export const createCommonSlice: StateCreator<
@@ -59,4 +64,11 @@ export const createCommonSlice: StateCreator<
59
64
  action,
60
65
  );
61
66
  },
67
+ useCheckLatestVersion: () =>
68
+ useSWR('checkLatestVersion', featLatestVersion, {
69
+ onSuccess: (data: string) => {
70
+ if (gt(data, CURRENT_VERSION))
71
+ set({ hasNewVersion: true, latestVersion: data }, false, t('checkLatestVersion'));
72
+ },
73
+ }),
62
74
  });
@@ -33,7 +33,7 @@ export const initLobeSession: LobeAgentSession = {
33
33
 
34
34
  export const initInbox = merge({}, initLobeSession, {
35
35
  config: {
36
- systemRole: '你是一名 AI 助理',
36
+ systemRole: '',
37
37
  } as LobeAgentConfig,
38
38
  id: 'inbox',
39
39
  meta: {
@@ -42,7 +42,7 @@ export const initInbox = merge({}, initLobeSession, {
42
42
  } as Partial<LobeAgentSession>);
43
43
 
44
44
  export const initialSessionState: SessionState = {
45
- activeId: undefined,
45
+ activeId: 'inbox',
46
46
  inbox: initInbox,
47
47
  isMobile: false,
48
48
  searchKeywords: '',
@@ -56,7 +56,7 @@ export class VersionController<T> {
56
56
  nextData = migration.migrate(nextData);
57
57
 
58
58
  nextData.version += 1;
59
- console.log('迁移器:', migration, '数据:', nextData, '迁移后版本:', nextData.version);
59
+ console.debug('迁移器:', migration, '数据:', nextData, '迁移后版本:', nextData.version);
60
60
  }
61
61
 
62
62
  return nextData;
@@ -12,7 +12,7 @@ export const isMobileDevice = () => {
12
12
  const { get } = headers();
13
13
  const ua = get('user-agent');
14
14
 
15
- // console.log(ua);
15
+ // console.debug(ua);
16
16
  const device = new UAParser(ua || '').getDevice();
17
17
 
18
18
  return device.type === 'mobile';
package/.dockerignore DELETED
@@ -1,10 +0,0 @@
1
- Dockerfile
2
- .dockerignore
3
- node_modules
4
- npm-debug.log
5
- .next
6
- .git
7
- scripts
8
- docs
9
- .github
10
- *.md
package/Dockerfile DELETED
@@ -1,47 +0,0 @@
1
- FROM node:20-slim AS base
2
- ENV PNPM_HOME="/pnpm"
3
- ENV PATH="$PNPM_HOME:$PATH"
4
- RUN corepack enable
5
-
6
- ## Install dependencies only when needed
7
- FROM base AS builder
8
- WORKDIR /app
9
-
10
- COPY package.json ./
11
-
12
- RUN pnpm i -g bun
13
- # If you want to build docker in China
14
- #RUN npm config set registry https://registry.npmmirror.com/
15
- RUN bun i
16
-
17
- COPY . .
18
- RUN pnpm run build:docker # run build standalone for docker version
19
-
20
- ## Production image, copy all the files and run next
21
- FROM base AS runner
22
- WORKDIR /app
23
-
24
- ENV NODE_ENV production
25
-
26
- RUN addgroup --system --gid 1001 nodejs
27
- RUN adduser --system --uid 1001 nextjs
28
-
29
- COPY --from=builder /app/public ./public
30
-
31
- # Set the correct permission for prerender cache
32
- RUN mkdir .next
33
- RUN chown nextjs:nodejs .next
34
-
35
- # Automatically leverage output traces to reduce image size
36
- # https://nextjs.org/docs/advanced-features/output-file-tracing
37
- COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
38
- COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
39
-
40
- USER nextjs
41
-
42
- EXPOSE 3000
43
-
44
- # set hostname to localhost
45
- ENV HOSTNAME "0.0.0.0"
46
-
47
- CMD ["node", "server.js"]
@@ -1,14 +0,0 @@
1
- import { useResponsive } from 'antd-style';
2
- import { memo } from 'react';
3
-
4
- import Mobile from '../../../components/ChatHeader/Mobile';
5
- import Desktop from './Desktop';
6
-
7
- const Header = memo(() => {
8
- const { mobile } = useResponsive();
9
- const Render = mobile ? Mobile : Desktop;
10
-
11
- return <Render />;
12
- });
13
-
14
- export default Header;
@@ -1,22 +0,0 @@
1
- import { useResponsive } from 'antd-style';
2
- import { memo, useState } from 'react';
3
-
4
- import { ChatInputContent } from '../../../components/ChatInput';
5
- import Mobile from '../../../components/ChatInput/Mobile';
6
- import Desktop from './Desktop';
7
-
8
- const ChatInput = () => {
9
- const [expand, setExpand] = useState<boolean>(false);
10
-
11
- const { mobile } = useResponsive();
12
-
13
- const Render = mobile ? Mobile : Desktop;
14
-
15
- return (
16
- <Render expand={expand}>
17
- <ChatInputContent expand={expand} onExpandChange={setExpand} />
18
- </Render>
19
- );
20
- };
21
-
22
- export default memo(ChatInput);
@@ -1,14 +0,0 @@
1
- import { useResponsive } from 'antd-style';
2
- import { memo } from 'react';
3
-
4
- import Mobile from '../../../(mobile)/features/SessionHeader';
5
- import Desktop from './Desktop';
6
-
7
- const Header = memo(() => {
8
- const { mobile } = useResponsive();
9
- const Render = mobile ? Mobile : Desktop;
10
-
11
- return <Render />;
12
- });
13
-
14
- export default Header;