@lobehub/chat 1.47.1 → 1.47.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +2 -2
- package/src/features/Conversation/Error/APIKeyForm/ProviderApiKeyForm.tsx +3 -8
- package/src/features/Conversation/Error/APIKeyForm/useApiKey.ts +34 -0
- package/src/hooks/useInterceptingRoutes.ts +1 -5
- package/src/libs/trpc/client/lambda.ts +3 -2
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +14 -14
- package/src/types/aiProvider.ts +1 -1
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,56 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.47.3](https://github.com/lobehub/lobe-chat/compare/v1.47.2...v1.47.3)
|
6
|
+
|
7
|
+
<sup>Released on **2025-01-18**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: Fix hydration error.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **misc**: Fix hydration error, closes [#5502](https://github.com/lobehub/lobe-chat/issues/5502) ([cbe469a](https://github.com/lobehub/lobe-chat/commit/cbe469a))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
30
|
+
### [Version 1.47.2](https://github.com/lobehub/lobe-chat/compare/v1.47.1...v1.47.2)
|
31
|
+
|
32
|
+
<sup>Released on **2025-01-17**</sup>
|
33
|
+
|
34
|
+
#### 🐛 Bug Fixes
|
35
|
+
|
36
|
+
- **misc**: Fix api key in api key form.
|
37
|
+
|
38
|
+
<br/>
|
39
|
+
|
40
|
+
<details>
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
42
|
+
|
43
|
+
#### What's fixed
|
44
|
+
|
45
|
+
- **misc**: Fix api key in api key form, closes [#5498](https://github.com/lobehub/lobe-chat/issues/5498) ([b4a160b](https://github.com/lobehub/lobe-chat/commit/b4a160b))
|
46
|
+
|
47
|
+
</details>
|
48
|
+
|
49
|
+
<div align="right">
|
50
|
+
|
51
|
+
[](#readme-top)
|
52
|
+
|
53
|
+
</div>
|
54
|
+
|
5
55
|
### [Version 1.47.1](https://github.com/lobehub/lobe-chat/compare/v1.47.0...v1.47.1)
|
6
56
|
|
7
57
|
<sup>Released on **2025-01-17**</sup>
|
package/changelog/v1.json
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
[
|
2
|
+
{
|
3
|
+
"children": {
|
4
|
+
"fixes": [
|
5
|
+
"Fix hydration error."
|
6
|
+
]
|
7
|
+
},
|
8
|
+
"date": "2025-01-18",
|
9
|
+
"version": "1.47.3"
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"children": {
|
13
|
+
"fixes": [
|
14
|
+
"Fix api key in api key form."
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"date": "2025-01-17",
|
18
|
+
"version": "1.47.2"
|
19
|
+
},
|
2
20
|
{
|
3
21
|
"children": {},
|
4
22
|
"date": "2025-01-17",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.47.
|
3
|
+
"version": "1.47.3",
|
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",
|
@@ -39,7 +39,7 @@
|
|
39
39
|
"db:push-test": "NODE_ENV=test drizzle-kit push",
|
40
40
|
"db:studio": "drizzle-kit studio",
|
41
41
|
"db:z-pull": "drizzle-kit introspect",
|
42
|
-
"dev": "next dev --
|
42
|
+
"dev": "next dev --turbopack -p 3010",
|
43
43
|
"docs:i18n": "lobe-i18n md && npm run lint:md && npm run lint:mdx",
|
44
44
|
"docs:seo": "lobe-seo && npm run lint:mdx",
|
45
45
|
"i18n": "npm run workflow:i18n && lobe-i18n",
|
@@ -6,11 +6,10 @@ import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
7
7
|
import { useProviderName } from '@/hooks/useProviderName';
|
8
8
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
9
|
-
import { useUserStore } from '@/store/user';
|
10
|
-
import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
11
9
|
import { GlobalLLMProviderKey } from '@/types/user/settings';
|
12
10
|
|
13
11
|
import { FormAction } from '../style';
|
12
|
+
import { useApiKey } from './useApiKey';
|
14
13
|
|
15
14
|
interface ProviderApiKeyFormProps {
|
16
15
|
apiKeyPlaceholder?: string;
|
@@ -25,11 +24,7 @@ const ProviderApiKeyForm = memo<ProviderApiKeyFormProps>(
|
|
25
24
|
const { t: errorT } = useTranslation('error');
|
26
25
|
const [showProxy, setShow] = useState(false);
|
27
26
|
|
28
|
-
const
|
29
|
-
keyVaultsConfigSelectors.getVaultByProvider(provider)(s)?.apiKey,
|
30
|
-
keyVaultsConfigSelectors.getVaultByProvider(provider)(s)?.baseURL,
|
31
|
-
s.updateKeyVaultConfig,
|
32
|
-
]);
|
27
|
+
const { apiKey, baseURL, setConfig } = useApiKey(provider);
|
33
28
|
const { showOpenAIProxyUrl } = useServerConfigStore(featureFlagsSelectors);
|
34
29
|
const providerName = useProviderName(provider);
|
35
30
|
|
@@ -58,7 +53,7 @@ const ProviderApiKeyForm = memo<ProviderApiKeyFormProps>(
|
|
58
53
|
}}
|
59
54
|
placeholder={'https://api.openai.com/v1'}
|
60
55
|
type={'block'}
|
61
|
-
value={
|
56
|
+
value={baseURL}
|
62
57
|
/>
|
63
58
|
) : (
|
64
59
|
<Button
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import isEqual from 'fast-deep-equal';
|
2
|
+
|
3
|
+
import { isDeprecatedEdition } from '@/const/version';
|
4
|
+
import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
|
5
|
+
import { useUserStore } from '@/store/user';
|
6
|
+
import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
7
|
+
|
8
|
+
export const useApiKey = (provider: string) => {
|
9
|
+
const [apiKey, baseURL, setConfig] = useUserStore((s) => [
|
10
|
+
keyVaultsConfigSelectors.getVaultByProvider(provider as any)(s)?.apiKey,
|
11
|
+
keyVaultsConfigSelectors.getVaultByProvider(provider as any)(s)?.baseURL,
|
12
|
+
s.updateKeyVaultConfig,
|
13
|
+
]);
|
14
|
+
|
15
|
+
const updateAiProviderConfig = useAiInfraStore((s) => s.updateAiProviderConfig);
|
16
|
+
const data = useAiInfraStore(aiProviderSelectors.providerConfigById(provider), isEqual);
|
17
|
+
|
18
|
+
// TODO: remove this in V2
|
19
|
+
if (isDeprecatedEdition) return { apiKey, baseURL, setConfig };
|
20
|
+
//
|
21
|
+
|
22
|
+
return {
|
23
|
+
apiKey: data?.keyVaults.apiKey,
|
24
|
+
baseURL: data?.keyVaults?.baseURL,
|
25
|
+
setConfig: async (id: string, params: Record<string, string>) => {
|
26
|
+
await updateAiProviderConfig(id, {
|
27
|
+
keyVaults: {
|
28
|
+
...data?.keyVaults,
|
29
|
+
...params,
|
30
|
+
},
|
31
|
+
});
|
32
|
+
},
|
33
|
+
};
|
34
|
+
};
|
@@ -4,8 +4,7 @@ import urlJoin from 'url-join';
|
|
4
4
|
import { INBOX_SESSION_ID } from '@/const/session';
|
5
5
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
6
6
|
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
7
|
-
import {
|
8
|
-
import { ChatSettingsTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
|
7
|
+
import { ChatSettingsTabs, SettingsTabs } from '@/store/global/initialState';
|
9
8
|
import { useSessionStore } from '@/store/session';
|
10
9
|
|
11
10
|
export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Meta) => {
|
@@ -15,9 +14,6 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
|
|
15
14
|
|
16
15
|
return useMemo(() => {
|
17
16
|
if (activeId === INBOX_SESSION_ID) {
|
18
|
-
useGlobalStore.setState({
|
19
|
-
sidebarKey: SidebarTabKey.Setting,
|
20
|
-
});
|
21
17
|
return () => router.push(urlJoin('/settings', SettingsTabs.Agent));
|
22
18
|
}
|
23
19
|
if (mobile) {
|
@@ -2,8 +2,6 @@ import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
|
2
2
|
import { createTRPCReact } from '@trpc/react-query';
|
3
3
|
import superjson from 'superjson';
|
4
4
|
|
5
|
-
import { fetchErrorNotification } from '@/components/Error/fetchErrorNotification';
|
6
|
-
import { loginRequired } from '@/components/Error/loginRequiredNotification';
|
7
5
|
import { ModelProvider } from '@/libs/agent-runtime';
|
8
6
|
import type { LambdaRouter } from '@/server/routers/lambda';
|
9
7
|
|
@@ -17,6 +15,9 @@ const links = [
|
|
17
15
|
|
18
16
|
const errorRes: ErrorResponse = await response.clone().json();
|
19
17
|
|
18
|
+
const { loginRequired } = await import('@/components/Error/loginRequiredNotification');
|
19
|
+
const { fetchErrorNotification } = await import('@/components/Error/fetchErrorNotification');
|
20
|
+
|
20
21
|
errorRes.forEach((item) => {
|
21
22
|
const errorData = item.error.json;
|
22
23
|
|
@@ -37,6 +37,17 @@ const isActiveProviderApiKeyNotEmpty = (s: AIProviderStoreState) => {
|
|
37
37
|
return !!vault?.apiKey || !!vault?.accessKeyId || !!vault?.secretAccessKey;
|
38
38
|
};
|
39
39
|
|
40
|
+
const providerConfigById =
|
41
|
+
(id: string) =>
|
42
|
+
(s: AIProviderStoreState): AiProviderRuntimeConfig | undefined => {
|
43
|
+
if (!id) return undefined;
|
44
|
+
|
45
|
+
return s.aiProviderRuntimeConfig?.[id];
|
46
|
+
};
|
47
|
+
|
48
|
+
const isProviderConfigUpdating = (id: string) => (s: AIProviderStoreState) =>
|
49
|
+
s.aiProviderConfigUpdatingIds.includes(id);
|
50
|
+
|
40
51
|
/**
|
41
52
|
* @description The conditions to enable client fetch
|
42
53
|
* 1. If no baseUrl and apikey input, force on Server.
|
@@ -46,7 +57,7 @@ const isActiveProviderApiKeyNotEmpty = (s: AIProviderStoreState) => {
|
|
46
57
|
*/
|
47
58
|
const isProviderFetchOnClient =
|
48
59
|
(provider: GlobalLLMProviderKey | string) => (s: AIProviderStoreState) => {
|
49
|
-
const config =
|
60
|
+
const config = providerConfigById(provider)(s);
|
50
61
|
|
51
62
|
// If the provider already disable broswer request in model config, force on Server.
|
52
63
|
if (isProviderDisableBroswerRequest(provider)) return false;
|
@@ -56,8 +67,8 @@ const isProviderFetchOnClient =
|
|
56
67
|
return config?.fetchOnClient;
|
57
68
|
|
58
69
|
// 1. If no baseUrl and apikey input, force on Server.
|
59
|
-
const isProviderEndpointNotEmpty =
|
60
|
-
const isProviderApiKeyNotEmpty =
|
70
|
+
const isProviderEndpointNotEmpty = !!config?.keyVaults.baseURL;
|
71
|
+
const isProviderApiKeyNotEmpty = !!config?.keyVaults.apiKey;
|
61
72
|
if (!isProviderEndpointNotEmpty && !isProviderApiKeyNotEmpty) return false;
|
62
73
|
|
63
74
|
// 2. If only contains baseUrl, force on Client
|
@@ -76,17 +87,6 @@ const providerKeyVaults = (provider: string | undefined) => (s: AIProviderStoreS
|
|
76
87
|
return s.aiProviderRuntimeConfig?.[provider]?.keyVaults;
|
77
88
|
};
|
78
89
|
|
79
|
-
const providerConfigById =
|
80
|
-
(id: string) =>
|
81
|
-
(s: AIProviderStoreState): AiProviderRuntimeConfig | undefined => {
|
82
|
-
if (!id) return undefined;
|
83
|
-
|
84
|
-
return s.aiProviderRuntimeConfig?.[id];
|
85
|
-
};
|
86
|
-
|
87
|
-
const isProviderConfigUpdating = (id: string) => (s: AIProviderStoreState) =>
|
88
|
-
s.aiProviderConfigUpdatingIds.includes(id);
|
89
|
-
|
90
90
|
export const aiProviderSelectors = {
|
91
91
|
activeProviderConfig,
|
92
92
|
disabledAiProviderList,
|
package/src/types/aiProvider.ts
CHANGED