@lobehub/chat 1.40.4 → 1.42.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.
- package/CHANGELOG.md +52 -0
- package/changelog/v1.json +18 -0
- package/docs/self-hosting/advanced/auth/next-auth/wechat.mdx +46 -0
- package/docs/self-hosting/advanced/auth/next-auth/wechat.zh-CN.mdx +43 -0
- package/package.json +3 -3
- package/src/app/(backend)/webapi/assistant/store/route.ts +2 -11
- package/src/app/(main)/discover/(detail)/provider/[slug]/features/ProviderConfig.tsx +7 -4
- package/src/config/app.ts +4 -0
- package/src/config/modelProviders/spark.ts +3 -6
- package/src/features/MobileTabBar/index.tsx +3 -2
- package/src/features/User/UserAvatar.tsx +2 -2
- package/src/features/User/UserPanel/useMenu.tsx +5 -20
- package/src/hooks/useInterceptingRoutes.test.ts +2 -16
- package/src/hooks/useInterceptingRoutes.ts +2 -18
- package/src/libs/agent-runtime/qwen/index.test.ts +13 -188
- package/src/libs/agent-runtime/qwen/index.ts +47 -126
- package/src/libs/agent-runtime/spark/index.test.ts +24 -28
- package/src/libs/agent-runtime/spark/index.ts +4 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.test.ts +131 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +14 -3
- package/src/libs/agent-runtime/utils/streams/index.ts +1 -0
- package/src/libs/agent-runtime/utils/streams/spark.test.ts +199 -0
- package/src/libs/agent-runtime/utils/streams/spark.ts +134 -0
- package/src/libs/next-auth/sso-providers/index.ts +2 -0
- package/src/libs/next-auth/sso-providers/wechat.ts +24 -0
- package/src/server/modules/AssistantStore/index.test.ts +5 -5
- package/src/server/modules/AssistantStore/index.ts +39 -1
- package/src/server/modules/EdgeConfig/index.ts +23 -0
- package/src/server/services/discover/index.ts +2 -13
- package/src/types/discover.ts +20 -0
- package/src/app/@modal/(.)settings/modal/index.tsx +0 -45
- package/src/app/@modal/(.)settings/modal/layout.tsx +0 -47
- package/src/app/@modal/(.)settings/modal/loading.tsx +0 -5
- package/src/app/@modal/(.)settings/modal/page.tsx +0 -19
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,58 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
## [Version 1.42.0](https://github.com/lobehub/lobe-chat/compare/v1.41.0...v1.42.0)
|
6
|
+
|
7
|
+
<sup>Released on **2024-12-29**</sup>
|
8
|
+
|
9
|
+
#### ✨ Features
|
10
|
+
|
11
|
+
- **misc**: Add custom stream handle support for LobeOpenAICompatibleFactory.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's improved
|
19
|
+
|
20
|
+
- **misc**: Add custom stream handle support for LobeOpenAICompatibleFactory, closes [#5039](https://github.com/lobehub/lobe-chat/issues/5039) ([ea7e732](https://github.com/lobehub/lobe-chat/commit/ea7e732))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
30
|
+
## [Version 1.41.0](https://github.com/lobehub/lobe-chat/compare/v1.40.4...v1.41.0)
|
31
|
+
|
32
|
+
<sup>Released on **2024-12-28**</sup>
|
33
|
+
|
34
|
+
#### ✨ Features
|
35
|
+
|
36
|
+
- **auth**: Add WeChat authentication support.
|
37
|
+
- **misc**: Support white list for discover assistant.
|
38
|
+
|
39
|
+
<br/>
|
40
|
+
|
41
|
+
<details>
|
42
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
43
|
+
|
44
|
+
#### What's improved
|
45
|
+
|
46
|
+
- **auth**: Add WeChat authentication support, closes [#5195](https://github.com/lobehub/lobe-chat/issues/5195) ([95153a4](https://github.com/lobehub/lobe-chat/commit/95153a4))
|
47
|
+
- **misc**: Support white list for discover assistant, closes [#5216](https://github.com/lobehub/lobe-chat/issues/5216) ([90bb20d](https://github.com/lobehub/lobe-chat/commit/90bb20d))
|
48
|
+
|
49
|
+
</details>
|
50
|
+
|
51
|
+
<div align="right">
|
52
|
+
|
53
|
+
[](#readme-top)
|
54
|
+
|
55
|
+
</div>
|
56
|
+
|
5
57
|
### [Version 1.40.4](https://github.com/lobehub/lobe-chat/compare/v1.40.3...v1.40.4)
|
6
58
|
|
7
59
|
<sup>Released on **2024-12-28**</sup>
|
package/changelog/v1.json
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"children": {
|
4
|
+
"features": [
|
5
|
+
"Add custom stream handle support for LobeOpenAICompatibleFactory."
|
6
|
+
]
|
7
|
+
},
|
8
|
+
"date": "2024-12-29",
|
9
|
+
"version": "1.42.0"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"children": {
|
13
|
+
"features": [
|
14
|
+
"Support white list for discover assistant."
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"date": "2024-12-28",
|
18
|
+
"version": "1.41.0"
|
19
|
+
},
|
2
20
|
{
|
3
21
|
"children": {
|
4
22
|
"improvements": [
|
@@ -0,0 +1,46 @@
|
|
1
|
+
---
|
2
|
+
title: Configure Wechat Authentication Service in LobeChat
|
3
|
+
description: Learn how to configure Wechat authentication service in LobeChat, including creating a new Wechat App, setting permissions, and environment variables.
|
4
|
+
tags:
|
5
|
+
- Wechat Authentication
|
6
|
+
- Wechat App
|
7
|
+
- Environment Variable Configuration
|
8
|
+
- Single Sign-On
|
9
|
+
- LobeChat
|
10
|
+
---
|
11
|
+
|
12
|
+
# Configure Wechat Authentication Service
|
13
|
+
|
14
|
+
## Wechat Configuration Process
|
15
|
+
|
16
|
+
<Steps>
|
17
|
+
### Create a Wechat Application
|
18
|
+
|
19
|
+
Click [here](https://open.weixin.qq.com/cgi-bin/index) and then click "Management Center", "Website Application", and "Create Website Application" in sequence.
|
20
|
+
|
21
|
+
Fill in the information as required by the official website prompts and submit for review.
|
22
|
+
|
23
|
+
After successful creation, click "Application Details" to obtain the AppID and AppSecret.
|
24
|
+
|
25
|
+
### Configure Environment Variables
|
26
|
+
|
27
|
+
When deploying LobeChat, you need to configure the following environment variables:
|
28
|
+
|
29
|
+
| Environment Variable | Type | Description |
|
30
|
+
| --- | --- | --- |
|
31
|
+
| `NEXT_AUTH_SECRET` | Required | Key used to encrypt Auth.js session tokens. You can generate the key using the command: `openssl rand -base64 32` |
|
32
|
+
| `NEXT_AUTH_SSO_PROVIDERS` | Required | Select the Single Sign-On provider for LobeChat. Use `github` for Github. |
|
33
|
+
| `WECHAT_CLIENT_ID` | Required | Client ID from the Wechat website application details page |
|
34
|
+
| `WECHAT_CLIENT_SECRET` | Required | Client Secret from the Wechat website application details page |
|
35
|
+
| `NEXTAUTH_URL` | Required | This URL is used to specify the callback address for Auth.js when performing OAuth authentication. Only set it if the default generated redirect address is incorrect. `https://example.com/api/auth` |
|
36
|
+
|
37
|
+
<Callout type={'tip'}>
|
38
|
+
Go to [📘 Environment Variables](/en/docs/self-hosting/environment-variables/auth#wechat) for more details about related variables.
|
39
|
+
|
40
|
+
</Callout>
|
41
|
+
</Steps>
|
42
|
+
|
43
|
+
<Callout type={'info'}>
|
44
|
+
After successful deployment, users will be able to authenticate through the WeChat Open Platform
|
45
|
+
and use LobeChat.
|
46
|
+
</Callout>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
---
|
2
|
+
title: 在 LobeChat 中配置微信身份验证服务
|
3
|
+
description: 学习如何在 LobeChat 中配置微信身份验证服务,包括创建新的微信网站应用、设置权限和环境变量。
|
4
|
+
tags:
|
5
|
+
-微信身份验证
|
6
|
+
-微信网站应用
|
7
|
+
- 环境变量配置
|
8
|
+
- 单点登录
|
9
|
+
- LobeChat
|
10
|
+
---
|
11
|
+
|
12
|
+
# 配置微信身份验证服务
|
13
|
+
|
14
|
+
##微信配置流程
|
15
|
+
|
16
|
+
<Steps>
|
17
|
+
### 创建微信网站应用
|
18
|
+
|
19
|
+
点击 [这里](https://open.weixin.qq.com/cgi-bin/index) 依次点击“管理中心”、“网站应用”、“创建网站应用”
|
20
|
+
|
21
|
+
按照管网提示要求填写信息并提交审核。
|
22
|
+
|
23
|
+
创建成功后,点击“应用详情”,可获知AppID和AppSecret。
|
24
|
+
|
25
|
+
### 配置环境变量
|
26
|
+
|
27
|
+
在部署 LobeChat 时,你需要配置以下环境变量:
|
28
|
+
|
29
|
+
| 环境变量 | 类型 | 描述 |
|
30
|
+
| --- | --- | --- |
|
31
|
+
| `NEXT_AUTH_SECRET` | 必选 | 用于加密 Auth.js 会话令牌的密钥。您可以使用以下命令生成秘钥: `openssl rand -base64 32` |
|
32
|
+
| `NEXT_AUTH_SSO_PROVIDERS` | 必选 | 选择 LoboChat 的单点登录提供商。使用 Github 请填写 `github`。 |
|
33
|
+
| `WECHAT_CLIENT_ID` | 必选 |微信网站应用详情页的 客户端 ID |
|
34
|
+
| `WECHAT_CLIENT_SECRET` | 必选 |微信网站应用详情页的 客户端 Secret |
|
35
|
+
| `NEXTAUTH_URL` | 必选 | 该 URL 用于指定 Auth.js 在执行 OAuth 验证时的回调地址,当默认生成的重定向地址发生不正确时才需要设置。`https://example.com/api/auth` |
|
36
|
+
|
37
|
+
<Callout type={'tip'}>
|
38
|
+
前往 [📘 环境变量](/zh/docs/self-hosting/environment-variables/auth#wechat) 可查阅相关变量详情。
|
39
|
+
|
40
|
+
</Callout>
|
41
|
+
</Steps>
|
42
|
+
|
43
|
+
<Callout type={'info'}>部署成功后,用户将可以通过微信开放平台身份认证并使用 LobeChat。</Callout>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.42.0",
|
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",
|
@@ -297,7 +297,7 @@
|
|
297
297
|
"markdown-to-txt": "^2.0.1",
|
298
298
|
"mime": "^4.0.4",
|
299
299
|
"node-fetch": "^3.3.2",
|
300
|
-
"node-gyp": "^
|
300
|
+
"node-gyp": "^11.0.0",
|
301
301
|
"openapi-typescript": "^6.7.6",
|
302
302
|
"p-map": "^7.0.2",
|
303
303
|
"prettier": "^3.3.3",
|
@@ -314,7 +314,7 @@
|
|
314
314
|
"vitest": "~1.2.2",
|
315
315
|
"vitest-canvas-mock": "^0.3.3"
|
316
316
|
},
|
317
|
-
"packageManager": "pnpm@9.15.
|
317
|
+
"packageManager": "pnpm@9.15.2",
|
318
318
|
"publishConfig": {
|
319
319
|
"access": "public",
|
320
320
|
"registry": "https://registry.npmjs.org"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { NextResponse } from 'next/server';
|
2
2
|
|
3
|
-
import { DEFAULT_LANG } from '@/const/locale';
|
4
3
|
import { AssistantStore } from '@/server/modules/AssistantStore';
|
5
4
|
|
6
5
|
export const runtime = 'edge';
|
@@ -11,18 +10,10 @@ export const GET = async (req: Request) => {
|
|
11
10
|
|
12
11
|
const market = new AssistantStore();
|
13
12
|
|
14
|
-
|
13
|
+
const data = await market.getAgentIndex(locale as any);
|
15
14
|
|
16
|
-
res = await fetch(market.getAgentIndexUrl(locale as any));
|
17
|
-
|
18
|
-
if (res.status === 404) {
|
19
|
-
res = await fetch(market.getAgentIndexUrl(DEFAULT_LANG));
|
20
|
-
}
|
21
|
-
|
22
|
-
const data = await res.json();
|
23
15
|
return NextResponse.json(data);
|
24
|
-
} catch
|
25
|
-
console.error(e);
|
16
|
+
} catch {
|
26
17
|
return new Response(`failed to fetch agent market index`, {
|
27
18
|
headers: {
|
28
19
|
'Access-Control-Allow-Origin': '*',
|
@@ -5,12 +5,11 @@ import { Button, Dropdown } from 'antd';
|
|
5
5
|
import { createStyles } from 'antd-style';
|
6
6
|
import { ChevronDownIcon, SquareArrowOutUpRight } from 'lucide-react';
|
7
7
|
import Link from 'next/link';
|
8
|
+
import { useRouter } from 'next/navigation';
|
8
9
|
import { memo } from 'react';
|
9
10
|
import { useTranslation } from 'react-i18next';
|
10
11
|
import { FlexboxProps } from 'react-layout-kit';
|
11
12
|
|
12
|
-
import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
|
13
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
14
13
|
import { DiscoverProviderItem } from '@/types/discover';
|
15
14
|
|
16
15
|
const useStyles = createStyles(({ css }) => ({
|
@@ -29,7 +28,11 @@ interface ProviderConfigProps extends FlexboxProps {
|
|
29
28
|
const ProviderConfig = memo<ProviderConfigProps>(({ data }) => {
|
30
29
|
const { styles } = useStyles();
|
31
30
|
const { t } = useTranslation('discover');
|
32
|
-
|
31
|
+
|
32
|
+
const router = useRouter();
|
33
|
+
const openSettings = () => {
|
34
|
+
router.push('/settings/llm');
|
35
|
+
};
|
33
36
|
|
34
37
|
const icon = <Icon icon={SquareArrowOutUpRight} size={{ fontSize: 16 }} />;
|
35
38
|
|
@@ -56,7 +59,7 @@ const ProviderConfig = memo<ProviderConfigProps>(({ data }) => {
|
|
56
59
|
|
57
60
|
if (!items || items?.length === 0)
|
58
61
|
return (
|
59
|
-
<Button
|
62
|
+
<Button size={'large'} style={{ flex: 1 }} type={'primary'}>
|
60
63
|
{t('providers.config')}
|
61
64
|
</Button>
|
62
65
|
);
|
package/src/config/app.ts
CHANGED
@@ -47,6 +47,8 @@ export const getAppConfig = () => {
|
|
47
47
|
PLUGIN_SETTINGS: z.string().optional(),
|
48
48
|
|
49
49
|
APP_URL: z.string().optional(),
|
50
|
+
VERCEL_EDGE_CONFIG: z.string().optional(),
|
51
|
+
|
50
52
|
CDN_USE_GLOBAL: z.boolean().optional(),
|
51
53
|
CUSTOM_FONT_FAMILY: z.string().optional(),
|
52
54
|
CUSTOM_FONT_URL: z.string().optional(),
|
@@ -75,6 +77,8 @@ export const getAppConfig = () => {
|
|
75
77
|
|
76
78
|
PLUGIN_SETTINGS: process.env.PLUGIN_SETTINGS,
|
77
79
|
|
80
|
+
VERCEL_EDGE_CONFIG: process.env.VERCEL_EDGE_CONFIG,
|
81
|
+
|
78
82
|
APP_URL,
|
79
83
|
CUSTOM_FONT_FAMILY: process.env.CUSTOM_FONT_FAMILY,
|
80
84
|
CUSTOM_FONT_URL: process.env.CUSTOM_FONT_URL,
|
@@ -10,7 +10,6 @@ const Spark: ModelProviderCard = {
|
|
10
10
|
'Spark Lite 是一款轻量级大语言模型,具备极低的延迟与高效的处理能力,完全免费开放,支持实时在线搜索功能。其快速响应的特性使其在低算力设备上的推理应用和模型微调中表现出色,为用户带来出色的成本效益和智能体验,尤其在知识问答、内容生成及搜索场景下表现不俗。',
|
11
11
|
displayName: 'Spark Lite',
|
12
12
|
enabled: true,
|
13
|
-
functionCall: false,
|
14
13
|
id: 'lite',
|
15
14
|
maxOutput: 4096,
|
16
15
|
},
|
@@ -20,7 +19,6 @@ const Spark: ModelProviderCard = {
|
|
20
19
|
'Spark Pro 是一款为专业领域优化的高性能大语言模型,专注数学、编程、医疗、教育等多个领域,并支持联网搜索及内置天气、日期等插件。其优化后模型在复杂知识问答、语言理解及高层次文本创作中展现出色表现和高效性能,是适合专业应用场景的理想选择。',
|
21
20
|
displayName: 'Spark Pro',
|
22
21
|
enabled: true,
|
23
|
-
functionCall: false,
|
24
22
|
id: 'generalv3',
|
25
23
|
maxOutput: 8192,
|
26
24
|
},
|
@@ -30,7 +28,6 @@ const Spark: ModelProviderCard = {
|
|
30
28
|
'Spark Pro 128K 配置了特大上下文处理能力,能够处理多达128K的上下文信息,特别适合需通篇分析和长期逻辑关联处理的长文内容,可在复杂文本沟通中提供流畅一致的逻辑与多样的引用支持。',
|
31
29
|
displayName: 'Spark Pro 128K',
|
32
30
|
enabled: true,
|
33
|
-
functionCall: false,
|
34
31
|
id: 'pro-128k',
|
35
32
|
maxOutput: 4096,
|
36
33
|
},
|
@@ -40,7 +37,7 @@ const Spark: ModelProviderCard = {
|
|
40
37
|
'Spark Max 为功能最为全面的版本,支持联网搜索及众多内置插件。其全面优化的核心能力以及系统角色设定和函数调用功能,使其在各种复杂应用场景中的表现极为优异和出色。',
|
41
38
|
displayName: 'Spark Max',
|
42
39
|
enabled: true,
|
43
|
-
functionCall:
|
40
|
+
functionCall: true,
|
44
41
|
id: 'generalv3.5',
|
45
42
|
maxOutput: 8192,
|
46
43
|
},
|
@@ -50,7 +47,7 @@ const Spark: ModelProviderCard = {
|
|
50
47
|
'Spark Max 32K 配置了大上下文处理能力,更强的上下文理解和逻辑推理能力,支持32K tokens的文本输入,适用于长文档阅读、私有知识问答等场景',
|
51
48
|
displayName: 'Spark Max 32K',
|
52
49
|
enabled: true,
|
53
|
-
functionCall:
|
50
|
+
functionCall: true,
|
54
51
|
id: 'max-32k',
|
55
52
|
maxOutput: 8192,
|
56
53
|
},
|
@@ -60,7 +57,7 @@ const Spark: ModelProviderCard = {
|
|
60
57
|
'Spark Ultra 是星火大模型系列中最为强大的版本,在升级联网搜索链路同时,提升对文本内容的理解和总结能力。它是用于提升办公生产力和准确响应需求的全方位解决方案,是引领行业的智能产品。',
|
61
58
|
displayName: 'Spark 4.0 Ultra',
|
62
59
|
enabled: true,
|
63
|
-
functionCall:
|
60
|
+
functionCall: true,
|
64
61
|
id: '4.0Ultra',
|
65
62
|
maxOutput: 8192,
|
66
63
|
},
|
@@ -6,7 +6,6 @@ import { rgba } from 'polished';
|
|
6
6
|
import { memo, useMemo } from 'react';
|
7
7
|
import { useTranslation } from 'react-i18next';
|
8
8
|
|
9
|
-
import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
|
10
9
|
import { SidebarTabKey } from '@/store/global/initialState';
|
11
10
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
12
11
|
|
@@ -26,8 +25,10 @@ interface Props {
|
|
26
25
|
export default memo<Props>(({ className, tabBarKey }) => {
|
27
26
|
const { t } = useTranslation('common');
|
28
27
|
const { styles } = useStyles();
|
29
|
-
const openSettings = useOpenSettings();
|
30
28
|
const router = useRouter();
|
29
|
+
const openSettings = () => {
|
30
|
+
router.push('/settings/llm');
|
31
|
+
};
|
31
32
|
const { showMarket } = useServerConfigStore(featureFlagsSelectors);
|
32
33
|
|
33
34
|
const items: MobileTabBarProps['items'] = useMemo(
|
@@ -57,8 +57,8 @@ const UserAvatar = forwardRef<HTMLDivElement, UserAvatarProps>(
|
|
57
57
|
|
58
58
|
return (
|
59
59
|
<Avatar
|
60
|
-
alt={isSignedIn
|
61
|
-
avatar={isSignedIn
|
60
|
+
alt={isSignedIn && !!username ? username : BRANDING_NAME}
|
61
|
+
avatar={isSignedIn && !!avatar ? avatar : DEFAULT_USER_AVATAR_URL}
|
62
62
|
background={isSignedIn && avatar ? background : undefined}
|
63
63
|
className={cx(clickable && styles.clickable, className)}
|
64
64
|
ref={ref}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { DiscordIcon, Icon } from '@lobehub/ui';
|
2
2
|
import { Badge } from 'antd';
|
3
3
|
import { ItemType } from 'antd/es/menu/interface';
|
4
4
|
import {
|
@@ -13,14 +13,12 @@ import {
|
|
13
13
|
LifeBuoy,
|
14
14
|
LogOut,
|
15
15
|
Mail,
|
16
|
-
Maximize,
|
17
16
|
Settings2,
|
18
17
|
} from 'lucide-react';
|
19
18
|
import Link from 'next/link';
|
20
19
|
import { PropsWithChildren, memo } from 'react';
|
21
20
|
import { useTranslation } from 'react-i18next';
|
22
21
|
import { Flexbox } from 'react-layout-kit';
|
23
|
-
import urlJoin from 'url-join';
|
24
22
|
|
25
23
|
import type { MenuProps } from '@/components/Menu';
|
26
24
|
import { LOBE_CHAT_CLOUD } from '@/const/branding';
|
@@ -35,11 +33,8 @@ import {
|
|
35
33
|
} from '@/const/url';
|
36
34
|
import { isServerMode } from '@/const/version';
|
37
35
|
import DataImporter from '@/features/DataImporter';
|
38
|
-
import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
|
39
36
|
import { usePWAInstall } from '@/hooks/usePWAInstall';
|
40
|
-
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
41
37
|
import { configService } from '@/services/config';
|
42
|
-
import { SettingsTabs } from '@/store/global/initialState';
|
43
38
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
44
39
|
import { useUserStore } from '@/store/user';
|
45
40
|
import { authSelectors } from '@/store/user/selectors';
|
@@ -51,7 +46,7 @@ const NewVersionBadge = memo(
|
|
51
46
|
children,
|
52
47
|
showBadge,
|
53
48
|
onClick,
|
54
|
-
}: PropsWithChildren & { onClick
|
49
|
+
}: PropsWithChildren & { onClick?: () => void; showBadge?: boolean }) => {
|
55
50
|
const { t } = useTranslation('common');
|
56
51
|
if (!showBadge)
|
57
52
|
return (
|
@@ -69,10 +64,8 @@ const NewVersionBadge = memo(
|
|
69
64
|
);
|
70
65
|
|
71
66
|
export const useMenu = () => {
|
72
|
-
const router = useQueryRoute();
|
73
67
|
const { canInstall, install } = usePWAInstall();
|
74
68
|
const hasNewVersion = useNewVersion();
|
75
|
-
const openSettings = useOpenSettings();
|
76
69
|
const { t } = useTranslation(['common', 'setting', 'auth']);
|
77
70
|
const { showCloudPromotion, hideDocs } = useServerConfigStore(featureFlagsSelectors);
|
78
71
|
const [isLogin, isLoginWithAuth, isLoginWithClerk, openUserProfile] = useUserStore((s) => [
|
@@ -93,20 +86,12 @@ export const useMenu = () => {
|
|
93
86
|
|
94
87
|
const settings: MenuProps['items'] = [
|
95
88
|
{
|
96
|
-
extra: (
|
97
|
-
<ActionIcon
|
98
|
-
icon={Maximize}
|
99
|
-
onClick={() => router.push(urlJoin('/settings', SettingsTabs.Common))}
|
100
|
-
size={'small'}
|
101
|
-
title={t('fullscreen')}
|
102
|
-
/>
|
103
|
-
),
|
104
89
|
icon: <Icon icon={Settings2} />,
|
105
90
|
key: 'setting',
|
106
91
|
label: (
|
107
|
-
<
|
108
|
-
{t('userPanel.setting')}
|
109
|
-
</
|
92
|
+
<Link href={'/settings/common'}>
|
93
|
+
<NewVersionBadge showBadge={hasNewVersion}>{t('userPanel.setting')}</NewVersionBadge>
|
94
|
+
</Link>
|
110
95
|
),
|
111
96
|
},
|
112
97
|
{
|
@@ -8,7 +8,7 @@ import { useGlobalStore } from '@/store/global';
|
|
8
8
|
import { ChatSettingsTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
|
9
9
|
import { useSessionStore } from '@/store/session';
|
10
10
|
|
11
|
-
import { useOpenChatSettings
|
11
|
+
import { useOpenChatSettings } from './useInterceptingRoutes';
|
12
12
|
|
13
13
|
// Mocks
|
14
14
|
vi.mock('next/navigation', () => ({
|
@@ -32,26 +32,12 @@ vi.mock('@/store/global', () => ({
|
|
32
32
|
},
|
33
33
|
}));
|
34
34
|
|
35
|
-
describe('useOpenSettings', () => {
|
36
|
-
it('should handle mobile route correctly', () => {
|
37
|
-
vi.mocked(useIsMobile).mockReturnValue(true);
|
38
|
-
const { result } = renderHook(() => useOpenSettings(SettingsTabs.Common));
|
39
|
-
expect(result.current()).toBe('/settings/common');
|
40
|
-
});
|
41
|
-
|
42
|
-
it('should handle desktop route correctly', () => {
|
43
|
-
vi.mocked(useIsMobile).mockReturnValue(false);
|
44
|
-
const { result } = renderHook(() => useOpenSettings(SettingsTabs.Agent));
|
45
|
-
expect(result.current()).toBe('/settings/modal?tab=agent');
|
46
|
-
});
|
47
|
-
});
|
48
|
-
|
49
35
|
describe('useOpenChatSettings', () => {
|
50
36
|
it('should handle inbox session id correctly', () => {
|
51
37
|
vi.mocked(useSessionStore).mockReturnValue(INBOX_SESSION_ID);
|
52
38
|
const { result } = renderHook(() => useOpenChatSettings());
|
53
39
|
|
54
|
-
expect(result.current()).toBe('/settings/
|
40
|
+
expect(result.current()).toBe('/settings/agent'); // Assuming openSettings returns a function
|
55
41
|
});
|
56
42
|
|
57
43
|
it('should handle mobile route for chat settings', () => {
|
@@ -8,24 +8,8 @@ import { useGlobalStore } from '@/store/global';
|
|
8
8
|
import { ChatSettingsTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
|
9
9
|
import { useSessionStore } from '@/store/session';
|
10
10
|
|
11
|
-
export const useOpenSettings = (tab: SettingsTabs = SettingsTabs.Common) => {
|
12
|
-
const activeId = useSessionStore((s) => s.activeId);
|
13
|
-
const router = useQueryRoute();
|
14
|
-
const mobile = useIsMobile();
|
15
|
-
|
16
|
-
return useMemo(() => {
|
17
|
-
if (mobile) {
|
18
|
-
return () => router.push(urlJoin('/settings', tab));
|
19
|
-
} else {
|
20
|
-
// use Intercepting Routes on Desktop
|
21
|
-
return () => router.push('/settings/modal', { query: { session: activeId, tab } });
|
22
|
-
}
|
23
|
-
}, [mobile, tab, activeId, router]);
|
24
|
-
};
|
25
|
-
|
26
11
|
export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Meta) => {
|
27
12
|
const activeId = useSessionStore((s) => s.activeId);
|
28
|
-
const openSettings = useOpenSettings(SettingsTabs.Agent);
|
29
13
|
const router = useQueryRoute();
|
30
14
|
const mobile = useIsMobile();
|
31
15
|
|
@@ -34,7 +18,7 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
|
|
34
18
|
useGlobalStore.setState({
|
35
19
|
sidebarKey: SidebarTabKey.Setting,
|
36
20
|
});
|
37
|
-
return
|
21
|
+
return () => router.push(urlJoin('/settings', SettingsTabs.Agent));
|
38
22
|
}
|
39
23
|
if (mobile) {
|
40
24
|
return () => router.push('/chat/settings');
|
@@ -42,5 +26,5 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
|
|
42
26
|
// use Intercepting Routes on Desktop
|
43
27
|
return () => router.push('/chat/settings/modal', { query: { session: activeId, tab } });
|
44
28
|
}
|
45
|
-
}, [
|
29
|
+
}, [mobile, activeId, router, tab]);
|
46
30
|
};
|