@lobehub/chat 1.39.3 → 1.40.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 (175) hide show
  1. package/.env.example +19 -8
  2. package/.eslintignore +1 -1
  3. package/CHANGELOG.md +58 -0
  4. package/changelog/v1.json +21 -0
  5. package/docs/.cdn.cache.json +25 -0
  6. package/docs/changelog/2023-09-09-plugin-system.mdx +1 -1
  7. package/docs/changelog/2023-09-09-plugin-system.zh-CN.mdx +1 -1
  8. package/docs/changelog/2024-09-20-artifacts.mdx +1 -1
  9. package/docs/changelog/2024-09-20-artifacts.zh-CN.mdx +1 -1
  10. package/docs/changelog/2024-10-27-pin-assistant.mdx +2 -2
  11. package/docs/changelog/2024-10-27-pin-assistant.zh-CN.mdx +2 -2
  12. package/docs/changelog/2024-11-06-share-text-json.mdx +2 -2
  13. package/docs/changelog/2024-11-06-share-text-json.zh-CN.mdx +2 -2
  14. package/docs/changelog/index.json +16 -16
  15. package/locales/ar/changelog.json +18 -0
  16. package/locales/ar/common.json +1 -0
  17. package/locales/ar/metadata.json +4 -0
  18. package/locales/bg-BG/changelog.json +18 -0
  19. package/locales/bg-BG/common.json +1 -0
  20. package/locales/bg-BG/metadata.json +4 -0
  21. package/locales/de-DE/changelog.json +18 -0
  22. package/locales/de-DE/common.json +1 -0
  23. package/locales/de-DE/metadata.json +4 -0
  24. package/locales/en-US/changelog.json +18 -0
  25. package/locales/en-US/common.json +1 -0
  26. package/locales/en-US/metadata.json +4 -0
  27. package/locales/es-ES/changelog.json +18 -0
  28. package/locales/es-ES/common.json +1 -0
  29. package/locales/es-ES/metadata.json +4 -0
  30. package/locales/fa-IR/changelog.json +18 -0
  31. package/locales/fa-IR/common.json +1 -0
  32. package/locales/fa-IR/metadata.json +4 -0
  33. package/locales/fr-FR/changelog.json +18 -0
  34. package/locales/fr-FR/common.json +1 -0
  35. package/locales/fr-FR/metadata.json +4 -0
  36. package/locales/it-IT/changelog.json +18 -0
  37. package/locales/it-IT/common.json +1 -0
  38. package/locales/it-IT/metadata.json +4 -0
  39. package/locales/ja-JP/changelog.json +18 -0
  40. package/locales/ja-JP/common.json +1 -0
  41. package/locales/ja-JP/metadata.json +4 -0
  42. package/locales/ko-KR/changelog.json +18 -0
  43. package/locales/ko-KR/common.json +1 -0
  44. package/locales/ko-KR/metadata.json +4 -0
  45. package/locales/nl-NL/changelog.json +18 -0
  46. package/locales/nl-NL/common.json +1 -0
  47. package/locales/nl-NL/metadata.json +4 -0
  48. package/locales/pl-PL/changelog.json +18 -0
  49. package/locales/pl-PL/common.json +1 -0
  50. package/locales/pl-PL/metadata.json +4 -0
  51. package/locales/pt-BR/changelog.json +18 -0
  52. package/locales/pt-BR/common.json +1 -0
  53. package/locales/pt-BR/metadata.json +4 -0
  54. package/locales/ru-RU/changelog.json +18 -0
  55. package/locales/ru-RU/common.json +1 -0
  56. package/locales/ru-RU/metadata.json +4 -0
  57. package/locales/tr-TR/changelog.json +18 -0
  58. package/locales/tr-TR/common.json +1 -0
  59. package/locales/tr-TR/metadata.json +4 -0
  60. package/locales/vi-VN/changelog.json +18 -0
  61. package/locales/vi-VN/common.json +1 -0
  62. package/locales/vi-VN/metadata.json +4 -0
  63. package/locales/zh-CN/changelog.json +18 -0
  64. package/locales/zh-CN/common.json +1 -0
  65. package/locales/zh-CN/metadata.json +4 -0
  66. package/locales/zh-TW/changelog.json +18 -0
  67. package/locales/zh-TW/common.json +1 -0
  68. package/locales/zh-TW/metadata.json +4 -0
  69. package/package.json +6 -1
  70. package/scripts/cdnWorkflow/index.ts +217 -0
  71. package/scripts/cdnWorkflow/optimized.ts +21 -0
  72. package/scripts/cdnWorkflow/s3/index.ts +120 -0
  73. package/scripts/cdnWorkflow/s3/types.ts +25 -0
  74. package/scripts/cdnWorkflow/s3/utils.ts +106 -0
  75. package/scripts/cdnWorkflow/uploader.ts +73 -0
  76. package/scripts/cdnWorkflow/utils.ts +93 -0
  77. package/src/app/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +25 -12
  78. package/src/app/(main)/(mobile)/me/(home)/features/useCategory.tsx +19 -9
  79. package/src/app/(main)/_layout/Desktop.tsx +4 -1
  80. package/src/app/(main)/_layout/Mobile.tsx +2 -1
  81. package/src/app/(main)/changelog/_layout/Desktop.tsx +25 -0
  82. package/src/app/(main)/changelog/_layout/Mobile/Header.tsx +33 -0
  83. package/src/app/(main)/changelog/_layout/Mobile/index.tsx +21 -0
  84. package/src/app/(main)/changelog/error.tsx +5 -0
  85. package/src/app/(main)/changelog/features/GridLayout.tsx +22 -0
  86. package/src/app/(main)/changelog/features/Hero.tsx +40 -0
  87. package/src/app/(main)/changelog/features/Post.tsx +56 -0
  88. package/src/app/(main)/changelog/features/PublishedTime.tsx +50 -0
  89. package/src/app/(main)/changelog/features/VersionTag.tsx +27 -0
  90. package/src/app/(main)/changelog/layout.tsx +10 -0
  91. package/src/app/(main)/changelog/loading.tsx +3 -0
  92. package/src/app/(main)/changelog/modal/page.tsx +23 -0
  93. package/src/app/(main)/changelog/not-found.tsx +3 -0
  94. package/src/app/(main)/changelog/page.tsx +73 -0
  95. package/src/app/(main)/chat/(workspace)/_layout/Desktop/HotKeys.tsx +7 -0
  96. package/src/app/(main)/chat/(workspace)/page.tsx +9 -2
  97. package/src/app/(main)/settings/about/features/Version.tsx +2 -2
  98. package/src/app/@modal/(.)changelog/modal/features/Cover.tsx +48 -0
  99. package/src/app/@modal/(.)changelog/modal/features/Hero.tsx +29 -0
  100. package/src/app/@modal/(.)changelog/modal/features/Pagination.tsx +54 -0
  101. package/src/app/@modal/(.)changelog/modal/features/Post.tsx +57 -0
  102. package/src/app/@modal/(.)changelog/modal/features/PublishedTime.tsx +50 -0
  103. package/src/app/@modal/(.)changelog/modal/features/ReadDetail.tsx +94 -0
  104. package/src/app/@modal/(.)changelog/modal/features/UpdateChangelogStatus.tsx +21 -0
  105. package/src/app/@modal/(.)changelog/modal/features/VersionTag.tsx +27 -0
  106. package/src/app/@modal/(.)changelog/modal/layout.tsx +39 -0
  107. package/src/app/@modal/(.)changelog/modal/loading.tsx +10 -0
  108. package/src/app/@modal/(.)changelog/modal/page.tsx +37 -0
  109. package/src/app/@modal/(.)settings/modal/layout.tsx +19 -16
  110. package/src/app/@modal/_layout/ModalLayout.tsx +63 -0
  111. package/src/app/@modal/chat/(.)settings/modal/layout.tsx +20 -17
  112. package/src/app/@modal/layout.tsx +5 -69
  113. package/src/components/mdx/Image.tsx +50 -0
  114. package/src/components/mdx/index.tsx +2 -0
  115. package/src/const/hotkeys.ts +1 -0
  116. package/src/const/url.ts +1 -0
  117. package/src/features/ChangelogModal/index.tsx +22 -0
  118. package/src/features/User/UserPanel/useMenu.tsx +50 -46
  119. package/src/features/User/__tests__/useMenu.test.tsx +7 -6
  120. package/src/hooks/useInterceptingRoutes.ts +1 -6
  121. package/src/hooks/useShare.tsx +1 -0
  122. package/src/libs/agent-runtime/openai/index.ts +2 -0
  123. package/src/locales/default/changelog.ts +18 -0
  124. package/src/locales/default/common.ts +1 -0
  125. package/src/locales/default/index.ts +2 -0
  126. package/src/locales/default/metadata.ts +4 -0
  127. package/src/server/metadata.ts +5 -3
  128. package/src/server/routers/edge/appStatus.ts +3 -0
  129. package/src/server/routers/edge/index.ts +2 -0
  130. package/src/server/routers/lambda/agent.ts +1 -1
  131. package/src/server/services/changelog/index.test.ts +310 -0
  132. package/src/server/services/changelog/index.ts +196 -0
  133. package/src/server/services/discover/index.test.ts +0 -1
  134. package/src/server/sitemap.ts +4 -1
  135. package/src/services/__tests__/chat.test.ts +1 -1
  136. package/src/services/__tests__/global.test.ts +5 -2
  137. package/src/services/_auth.ts +1 -1
  138. package/src/services/agent.ts +25 -21
  139. package/src/services/chat.ts +2 -2
  140. package/src/services/file/ClientS3/index.ts +6 -6
  141. package/src/services/file/client.ts +14 -15
  142. package/src/services/file/server.ts +20 -25
  143. package/src/services/global.ts +2 -2
  144. package/src/services/import/client.ts +6 -5
  145. package/src/services/import/server.ts +6 -5
  146. package/src/services/import/type.ts +7 -0
  147. package/src/services/knowledgeBase.ts +19 -19
  148. package/src/services/message/_deprecated.ts +5 -0
  149. package/src/services/message/client.ts +52 -48
  150. package/src/services/message/server.ts +50 -53
  151. package/src/services/message/type.ts +2 -2
  152. package/src/services/plugin/client.ts +16 -22
  153. package/src/services/plugin/server.ts +15 -19
  154. package/src/services/rag.ts +18 -18
  155. package/src/services/ragEval.ts +29 -26
  156. package/src/services/session/_deprecated.ts +2 -2
  157. package/src/services/session/client.ts +55 -81
  158. package/src/services/session/server.ts +50 -74
  159. package/src/services/session/type.ts +4 -6
  160. package/src/services/share.ts +4 -4
  161. package/src/services/textToImage.ts +5 -2
  162. package/src/services/thread/client.ts +9 -15
  163. package/src/services/thread/server.ts +10 -15
  164. package/src/services/topic/client.ts +25 -25
  165. package/src/services/topic/server.ts +25 -42
  166. package/src/services/trace.ts +4 -4
  167. package/src/services/user/client.ts +13 -17
  168. package/src/services/user/server.ts +9 -13
  169. package/src/services/user/type.ts +1 -1
  170. package/src/store/chat/slices/message/reducer.ts +3 -2
  171. package/src/store/global/action.ts +27 -22
  172. package/src/store/global/initialState.ts +1 -0
  173. package/src/types/changelog.ts +6 -0
  174. package/src/types/message/index.ts +10 -8
  175. package/src/app/@modal/features/InterceptingContext.tsx +0 -9
@@ -6,6 +6,7 @@ import dynamic from 'next/dynamic';
6
6
  import { PropsWithChildren, memo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
+ import ModalLayout from '@/app/@modal/_layout/ModalLayout';
9
10
  import StoreUpdater from '@/features/AgentSetting/StoreUpdater';
10
11
  import { Provider, createStore } from '@/features/AgentSetting/store';
11
12
  import { useQuery } from '@/hooks/useQuery';
@@ -35,23 +36,25 @@ const Layout = memo<PropsWithChildren>(({ children }) => {
35
36
  ]);
36
37
 
37
38
  return (
38
- <SettingModalLayout
39
- activeTitle={t(`agentTab.${tab as ChatSettingsTabs}`)}
40
- category={<CategoryContent />}
41
- desc={t('header.sessionDesc')}
42
- title={t('header.session')}
43
- >
44
- <Provider createStore={createStore}>
45
- <StoreUpdater
46
- config={config}
47
- id={id}
48
- meta={meta}
49
- onConfigChange={updateAgentConfig}
50
- onMetaChange={updateAgentMeta}
51
- />
52
- {children}
53
- </Provider>
54
- </SettingModalLayout>
39
+ <ModalLayout>
40
+ <SettingModalLayout
41
+ activeTitle={t(`agentTab.${tab as ChatSettingsTabs}`)}
42
+ category={<CategoryContent />}
43
+ desc={t('header.sessionDesc')}
44
+ title={t('header.session')}
45
+ >
46
+ <Provider createStore={createStore}>
47
+ <StoreUpdater
48
+ config={config}
49
+ id={id}
50
+ meta={meta}
51
+ onConfigChange={updateAgentConfig}
52
+ onMetaChange={updateAgentMeta}
53
+ />
54
+ {children}
55
+ </Provider>
56
+ </SettingModalLayout>
57
+ </ModalLayout>
55
58
  );
56
59
  });
57
60
 
@@ -1,71 +1,7 @@
1
- 'use client';
1
+ import { FC, PropsWithChildren } from 'react';
2
2
 
3
- import { Modal } from '@lobehub/ui';
4
- import { useTheme } from 'antd-style';
5
- import { usePathname, useRouter } from 'next/navigation';
6
- import { PropsWithChildren, memo, useEffect, useState } from 'react';
3
+ const Layout: FC<PropsWithChildren> = ({ children }) => {
4
+ return <div style={{ position: 'absolute', zIndex: 0 }}>{children}</div>;
5
+ };
7
6
 
8
- import InterceptingLayout from './features/InterceptingContext';
9
-
10
- const InterceptingModal = memo<PropsWithChildren>(({ children }) => {
11
- const [open, setOpen] = useState(true);
12
- const router = useRouter();
13
- const pathname = usePathname();
14
- const isDiscover = pathname.startsWith('/discover');
15
- const theme = useTheme();
16
-
17
- const inModal =
18
- pathname.startsWith('/settings') ||
19
- pathname.startsWith('/chat/settings') ||
20
- pathname.startsWith('/discover/assistant/') ||
21
- pathname.startsWith('/discover/model/') ||
22
- pathname.startsWith('/discover/plugin/') ||
23
- pathname.startsWith('/discover/provider/');
24
-
25
- useEffect(() => {
26
- if (!inModal) {
27
- setOpen(false);
28
- } else {
29
- setOpen(true);
30
- }
31
- }, [inModal, router]);
32
-
33
- if (!inModal) return null;
34
-
35
- return (
36
- <InterceptingLayout>
37
- <Modal
38
- afterClose={() => {
39
- if (inModal) {
40
- router.back();
41
- } else {
42
- router.refresh();
43
- }
44
- }}
45
- enableResponsive={false}
46
- footer={null}
47
- onCancel={() => {
48
- setOpen(false);
49
- router.back();
50
- }}
51
- open={open}
52
- styles={{
53
- body: {
54
- display: 'flex',
55
- maxHeight: isDiscover ? '80vh' : undefined,
56
- minHeight: 750,
57
- overflow: 'hidden',
58
- padding: 0,
59
- },
60
- content: { border: 'none', boxShadow: `0 0 0 1px ${theme.colorBorderSecondary}` },
61
- }}
62
- title={false}
63
- width={isDiscover ? 'min(80vw, 1280px)' : 'min(80vw, 1024px)'}
64
- >
65
- {children}
66
- </Modal>
67
- </InterceptingLayout>
68
- );
69
- });
70
-
71
- export default InterceptingModal;
7
+ export default Layout;
@@ -0,0 +1,50 @@
1
+ 'use server';
2
+
3
+ import { Image } from '@lobehub/ui/mdx';
4
+ import Img from 'next/image';
5
+ import { getPlaiceholder } from 'plaiceholder';
6
+ import { FC } from 'react';
7
+
8
+ const DEFAULT_WIDTH = 800;
9
+
10
+ const fetchImage = async (url: string) => {
11
+ const buffer = await fetch(url, { cache: 'force-cache' }).then(async (res) =>
12
+ Buffer.from(await res.arrayBuffer()),
13
+ );
14
+ const {
15
+ base64,
16
+ metadata: { height, width },
17
+ } = await getPlaiceholder(buffer, { format: ['webp'] });
18
+ return {
19
+ base64,
20
+ height: (DEFAULT_WIDTH / width) * height,
21
+ };
22
+ };
23
+
24
+ const ImageWrapper: FC<{ alt: string; src: string }> = async ({ alt, src, ...rest }) => {
25
+ try {
26
+ const { base64, height } = await fetchImage(src);
27
+ return (
28
+ <Image
29
+ alt={alt}
30
+ height={height}
31
+ // @ts-ignore
32
+ placeholder={
33
+ <Img
34
+ alt={alt}
35
+ height={height}
36
+ src={base64}
37
+ style={{ filter: 'blur(24px)', scale: 1.2 }}
38
+ width={DEFAULT_WIDTH}
39
+ />
40
+ }
41
+ src={src}
42
+ width={DEFAULT_WIDTH}
43
+ />
44
+ );
45
+ } catch {
46
+ return <Image alt={alt} src={src} {...rest} />;
47
+ }
48
+ };
49
+
50
+ export default ImageWrapper;
@@ -5,6 +5,7 @@ import { FC } from 'react';
5
5
  import remarkGfm from 'remark-gfm';
6
6
 
7
7
  import CodeBlock from './CodeBlock';
8
+ import Image from './Image';
8
9
  import Link from './Link';
9
10
 
10
11
  export const Typography = ({
@@ -31,6 +32,7 @@ export const CustomMDX: FC<MDXRemoteProps & { mobile?: boolean }> = ({ mobile, .
31
32
  const list: any = {};
32
33
  Object.entries({
33
34
  ...mdxComponents,
35
+ Image: Image,
34
36
  a: Link,
35
37
  pre: CodeBlock,
36
38
  ...rest.components,
@@ -4,6 +4,7 @@ export const SAVE_TOPIC_KEY = 'n';
4
4
  export const CLEAN_MESSAGE_KEY = 'backspace';
5
5
 
6
6
  export const HOTKEYS = {
7
+ chatSettings: 'mod+comma',
7
8
  regenerate: 'alt+r',
8
9
  saveTopic: 'alt+n',
9
10
  zenMode: 'mod+\\',
package/src/const/url.ts CHANGED
@@ -73,3 +73,4 @@ export const mailTo = (email: string) => `mailto:${email}`;
73
73
  export const AES_GCM_URL = 'https://datatracker.ietf.org/doc/html/draft-ietf-avt-srtp-aes-gcm-01';
74
74
  export const BASE_PROVIDER_DOC_URL = 'https://lobehub.com/docs/usage/providers';
75
75
  export const SITEMAP_BASE_URL = isDev ? '/sitemap.xml/' : 'sitemap';
76
+ export const CHANGELOG_URL = urlJoin(OFFICIAL_SITE, 'changelog/versions');
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { useTimeout } from 'ahooks';
4
+ import { useRouter } from 'next/navigation';
5
+ import { memo } from 'react';
6
+
7
+ import { useGlobalStore } from '@/store/global';
8
+
9
+ const ChangelogModal = memo<{ currentId?: string }>(({ currentId }) => {
10
+ const latestChangelogId = useGlobalStore((s) => s.status.latestChangelogId);
11
+ const router = useRouter();
12
+
13
+ useTimeout(() => {
14
+ if (latestChangelogId !== currentId) {
15
+ router.push('/changelog/modal');
16
+ }
17
+ }, 1000);
18
+
19
+ return null;
20
+ });
21
+
22
+ export default ChangelogModal;
@@ -7,6 +7,7 @@ import {
7
7
  Cloudy,
8
8
  Download,
9
9
  Feather,
10
+ FileClockIcon,
10
11
  HardDriveDownload,
11
12
  HardDriveUpload,
12
13
  LifeBuoy,
@@ -174,15 +175,38 @@ export const useMenu = () => {
174
175
  },
175
176
  ].filter(Boolean) as ItemType[]);
176
177
 
177
- const helps: MenuProps['items'] = hideDocs
178
- ? []
179
- : ([
180
- showCloudPromotion && {
181
- icon: <Icon icon={Cloudy} />,
182
- key: 'cloud',
178
+ const helps: MenuProps['items'] = [
179
+ showCloudPromotion && {
180
+ icon: <Icon icon={Cloudy} />,
181
+ key: 'cloud',
182
+ label: (
183
+ <Link href={`${OFFICIAL_URL}?utm_source=${UTM_SOURCE}`} target={'_blank'}>
184
+ {t('userPanel.cloud', { name: LOBE_CHAT_CLOUD })}
185
+ </Link>
186
+ ),
187
+ },
188
+ {
189
+ icon: <Icon icon={FileClockIcon} />,
190
+ key: 'changelog',
191
+ label: <Link href={'/changelog'}>{t('changelog')}</Link>,
192
+ },
193
+ {
194
+ children: [
195
+ {
196
+ icon: <Icon icon={Book} />,
197
+ key: 'docs',
183
198
  label: (
184
- <Link href={`${OFFICIAL_URL}?utm_source=${UTM_SOURCE}`} target={'_blank'}>
185
- {t('userPanel.cloud', { name: LOBE_CHAT_CLOUD })}
199
+ <Link href={DOCUMENTS_REFER_URL} target={'_blank'}>
200
+ {t('userPanel.docs')}
201
+ </Link>
202
+ ),
203
+ },
204
+ {
205
+ icon: <Icon icon={Feather} />,
206
+ key: 'feedback',
207
+ label: (
208
+ <Link href={GITHUB_ISSUES} target={'_blank'}>
209
+ {t('userPanel.feedback')}
186
210
  </Link>
187
211
  ),
188
212
  },
@@ -196,56 +220,36 @@ export const useMenu = () => {
196
220
  ),
197
221
  },
198
222
  {
199
- children: [
200
- {
201
- icon: <Icon icon={Book} />,
202
- key: 'docs',
203
- label: (
204
- <Link href={DOCUMENTS_REFER_URL} target={'_blank'}>
205
- {t('userPanel.docs')}
206
- </Link>
207
- ),
208
- },
209
- {
210
- icon: <Icon icon={Feather} />,
211
- key: 'feedback',
212
- label: (
213
- <Link href={GITHUB_ISSUES} target={'_blank'}>
214
- {t('userPanel.feedback')}
215
- </Link>
216
- ),
217
- },
218
- {
219
- icon: <Icon icon={Mail} />,
220
- key: 'email',
221
- label: (
222
- <Link href={mailTo(EMAIL_SUPPORT)} target={'_blank'}>
223
- {t('userPanel.email')}
224
- </Link>
225
- ),
226
- },
227
- ],
228
- icon: <Icon icon={LifeBuoy} />,
229
- key: 'help',
230
- label: t('userPanel.help'),
231
- },
232
- {
233
- type: 'divider',
223
+ icon: <Icon icon={Mail} />,
224
+ key: 'email',
225
+ label: (
226
+ <Link href={mailTo(EMAIL_SUPPORT)} target={'_blank'}>
227
+ {t('userPanel.email')}
228
+ </Link>
229
+ ),
234
230
  },
235
- ].filter(Boolean) as ItemType[]);
231
+ ],
232
+ icon: <Icon icon={LifeBuoy} />,
233
+ key: 'help',
234
+ label: t('userPanel.help'),
235
+ },
236
+ {
237
+ type: 'divider',
238
+ },
239
+ ].filter(Boolean) as ItemType[];
236
240
 
237
241
  const mainItems = [
238
242
  {
239
243
  type: 'divider',
240
244
  },
241
- ...(isLogin ? settings : []),
242
245
  ...(isLoginWithClerk ? profile : []),
246
+ ...(isLogin ? settings : []),
243
247
  /* ↓ cloud slot ↓ */
244
248
 
245
249
  /* ↑ cloud slot ↑ */
246
250
  ...(canInstall ? pwa : []),
247
251
  ...data,
248
- ...helps,
252
+ ...(!hideDocs ? helps : []),
249
253
  ].filter(Boolean) as MenuProps['items'];
250
254
 
251
255
  const logoutItems: MenuProps['items'] = isLoginWithAuth
@@ -1,13 +1,14 @@
1
1
  import { act, renderHook } from '@testing-library/react';
2
2
  import { describe, expect, it, vi } from 'vitest';
3
3
 
4
- import { useUserStore } from '@/store/user';
5
4
  import { ServerConfigStoreProvider } from '@/store/serverConfig';
5
+ import { useUserStore } from '@/store/user';
6
6
 
7
7
  import { useMenu } from '../UserPanel/useMenu';
8
8
 
9
- const wrapper: React.JSXElementConstructor<{ children: React.ReactNode }> = ({ children }) =>
9
+ const wrapper: React.JSXElementConstructor<{ children: React.ReactNode }> = ({ children }) => (
10
10
  <ServerConfigStoreProvider>{children}</ServerConfigStoreProvider>
11
+ );
11
12
 
12
13
  // Mock dependencies
13
14
  vi.mock('next/link', () => ({
@@ -81,7 +82,7 @@ describe('useMenu', () => {
81
82
  expect(mainItems?.some((item) => item?.key === 'setting')).toBe(true);
82
83
  expect(mainItems?.some((item) => item?.key === 'import')).toBe(true);
83
84
  expect(mainItems?.some((item) => item?.key === 'export')).toBe(true);
84
- expect(mainItems?.some((item) => item?.key === 'discord')).toBe(true);
85
+ expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
85
86
  expect(logoutItems.some((item) => item?.key === 'logout')).toBe(true);
86
87
  });
87
88
  });
@@ -101,7 +102,7 @@ describe('useMenu', () => {
101
102
  expect(mainItems?.some((item) => item?.key === 'setting')).toBe(true);
102
103
  expect(mainItems?.some((item) => item?.key === 'import')).toBe(true);
103
104
  expect(mainItems?.some((item) => item?.key === 'export')).toBe(true);
104
- expect(mainItems?.some((item) => item?.key === 'discord')).toBe(true);
105
+ expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
105
106
  expect(logoutItems.some((item) => item?.key === 'logout')).toBe(true);
106
107
  });
107
108
  });
@@ -120,7 +121,7 @@ describe('useMenu', () => {
120
121
  expect(mainItems?.some((item) => item?.key === 'setting')).toBe(true);
121
122
  expect(mainItems?.some((item) => item?.key === 'import')).toBe(true);
122
123
  expect(mainItems?.some((item) => item?.key === 'export')).toBe(true);
123
- expect(mainItems?.some((item) => item?.key === 'discord')).toBe(true);
124
+ expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
124
125
  expect(logoutItems.some((item) => item?.key === 'logout')).toBe(false);
125
126
  });
126
127
  });
@@ -139,7 +140,7 @@ describe('useMenu', () => {
139
140
  expect(mainItems?.some((item) => item?.key === 'setting')).toBe(false);
140
141
  expect(mainItems?.some((item) => item?.key === 'import')).toBe(false);
141
142
  expect(mainItems?.some((item) => item?.key === 'export')).toBe(false);
142
- expect(mainItems?.some((item) => item?.key === 'discord')).toBe(true);
143
+ expect(mainItems?.some((item) => item?.key === 'changelog')).toBe(true);
143
144
  expect(logoutItems.some((item) => item?.key === 'logout')).toBe(false);
144
145
  });
145
146
  });
@@ -1,7 +1,6 @@
1
- import { useContext, useMemo } from 'react';
1
+ import { useMemo } from 'react';
2
2
  import urlJoin from 'url-join';
3
3
 
4
- import { InterceptContext } from '@/app/@modal/features/InterceptingContext';
5
4
  import { INBOX_SESSION_ID } from '@/const/session';
6
5
  import { useIsMobile } from '@/hooks/useIsMobile';
7
6
  import { useQueryRoute } from '@/hooks/useQueryRoute';
@@ -45,7 +44,3 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
45
44
  }
46
45
  }, [openSettings, mobile, activeId, router, tab]);
47
46
  };
48
-
49
- export const useInterceptingRoutes = () => {
50
- return useContext(InterceptContext);
51
- };
@@ -15,6 +15,7 @@ const stringifyHashtags = (hashtags: string[], joinfix: string = ',', prefix?: s
15
15
  if (prefix) hashtags = hashtags.map((tag) => prefix + camelCase(tag));
16
16
  return hashtags.filter(Boolean).join(joinfix);
17
17
  };
18
+
18
19
  export const useShare = ({
19
20
  url,
20
21
  title,
@@ -7,6 +7,8 @@ export const o1Models = new Set([
7
7
  'o1-preview-2024-09-12',
8
8
  'o1-mini',
9
9
  'o1-mini-2024-09-12',
10
+ 'o1',
11
+ 'o1-2024-12-17',
10
12
  ]);
11
13
 
12
14
  export const pruneO1Payload = (payload: ChatStreamPayload) => ({
@@ -0,0 +1,18 @@
1
+ export default {
2
+ actions: {
3
+ followOnX: '在 X 上关注我们',
4
+ subscribeToUpdates: '订阅更新',
5
+ versions: '版本详情',
6
+ },
7
+ addedWhileAway: '在您离开期间,我们带来了新的特性。',
8
+ allChangelog: '查看所有更新日志',
9
+ description: '持续追踪 {{appName}} 的新功能和改进',
10
+ pagination: {
11
+ older: '查看历史变更',
12
+ prev: '上一页',
13
+ },
14
+ readDetails: '阅读详情',
15
+ title: '更新日志',
16
+ versionDetails: '版本详情',
17
+ welcomeBack: '欢迎回来!',
18
+ };
@@ -220,6 +220,7 @@ export default {
220
220
  pinOff: '取消置顶',
221
221
  privacy: '隐私政策',
222
222
  regenerate: '重新生成',
223
+ releaseNotes: '版本详情',
223
224
  rename: '重命名',
224
225
  reset: '重置',
225
226
  retry: '重试',
@@ -1,4 +1,5 @@
1
1
  import auth from './auth';
2
+ import changelog from './changelog';
2
3
  import chat from './chat';
3
4
  import clerk from './clerk';
4
5
  import common from './common';
@@ -23,6 +24,7 @@ import welcome from './welcome';
23
24
 
24
25
  const resources = {
25
26
  auth,
27
+ changelog,
26
28
  chat,
27
29
  clerk,
28
30
  common,
@@ -1,4 +1,8 @@
1
1
  export default {
2
+ changelog: {
3
+ description: '持续追踪 {{appName}} 的新功能和改进',
4
+ title: '更新日志',
5
+ },
2
6
  chat: {
3
7
  description: '{{appName}} 带给你最好的 ChatGPT, Claude , Gemini, OLLaMA WebUI 使用体验',
4
8
  title: '{{appName}}:个人 AI 效能工具,给自己一个更聪明的大脑',
@@ -18,8 +18,10 @@ export class Meta {
18
18
  tags,
19
19
  alternate,
20
20
  locale = DEFAULT_LANG,
21
+ canonical,
21
22
  }: {
22
23
  alternate?: boolean;
24
+ canonical?: string;
23
25
  description?: string;
24
26
  image?: string;
25
27
  locale?: Locales;
@@ -35,9 +37,9 @@ export class Meta {
35
37
  const siteTitle = title.includes(BRANDING_NAME) ? title : title + ` · ${BRANDING_NAME}`;
36
38
  return {
37
39
  alternates: {
38
- canonical: getCanonicalUrl(
39
- alternate ? qs.stringifyUrl({ query: { hl: locale }, url }) : url,
40
- ),
40
+ canonical:
41
+ canonical ||
42
+ getCanonicalUrl(alternate ? qs.stringifyUrl({ query: { hl: locale }, url }) : url),
41
43
  languages: alternate ? this.genAlternateLocales(locale, url) : undefined,
42
44
  },
43
45
  description: formatedDescription,
@@ -0,0 +1,3 @@
1
+ import { router } from '@/libs/trpc';
2
+
3
+ export const appStatusRouter = router({});
@@ -3,10 +3,12 @@
3
3
  */
4
4
  import { publicProcedure, router } from '@/libs/trpc';
5
5
 
6
+ import { appStatusRouter } from './appStatus';
6
7
  import { configRouter } from './config';
7
8
  import { uploadRouter } from './upload';
8
9
 
9
10
  export const edgeRouter = router({
11
+ appStatus: appStatusRouter,
10
12
  config: configRouter,
11
13
  healthcheck: publicProcedure.query(() => "i'm live!"),
12
14
  upload: uploadRouter,
@@ -101,7 +101,7 @@ export const agentRouter = router({
101
101
  if (!session) throw new Error('Session not found');
102
102
  const sessionId = session.id;
103
103
 
104
- return await ctx.agentModel.findBySessionId(sessionId);
104
+ return ctx.agentModel.findBySessionId(sessionId);
105
105
  }),
106
106
 
107
107
  getKnowledgeBasesAndFiles: agentProcedure