@lobehub/chat 0.82.2 → 0.82.4
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/package.json +1 -1
- package/src/app/chat/features/Conversation/ChatList/Error/ApiKeyForm.tsx +44 -20
- package/src/app/chat/features/Conversation/ChatList/Error/InvalidAccess.tsx +20 -18
- package/src/app/chat/features/Conversation/ChatList/Error/OpenAiBizError.tsx +1 -11
- package/src/app/chat/features/Conversation/ChatList/OTPInput.tsx +0 -6
- package/src/locales/default/error.ts +1 -0
- package/src/store/global/selectors.ts +7 -0
- package/src/store/global/slices/settings.ts +5 -1
- package/src/store/middleware/createHyperStorage/localStorage.ts +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,58 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.82.4](https://github.com/lobehub/lobe-chat/compare/v0.82.3...v0.82.4)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-09-29**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: 修正 localStorage 不存在造成设置页刷新 500 保存的问题.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: 修正 localStorage 不存在造成设置页刷新 500 保存的问题 ([b894cc8](https://github.com/lobehub/lobe-chat/commit/b894cc8))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.82.3](https://github.com/lobehub/lobe-chat/compare/v0.82.2...v0.82.3)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-09-29**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: 修正 access code 校验逻辑,修正 api key 无法正常显示在秘钥输入框,并增加显示关闭按钮,修正移动端输入 access code 默认打开数据键盘的问题.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: 修正 access code 校验逻辑,closes [#184](https://github.com/lobehub/lobe-chat/issues/184) ([a7301c3](https://github.com/lobehub/lobe-chat/commit/a7301c3))
|
|
46
|
+
- **misc**: 修正 api key 无法正常显示在秘钥输入框,并增加显示关闭按钮,closes [#182](https://github.com/lobehub/lobe-chat/issues/182) ([def1153](https://github.com/lobehub/lobe-chat/commit/def1153))
|
|
47
|
+
- **misc**: 修正移动端输入 access code 默认打开数据键盘的问题 ([7994982](https://github.com/lobehub/lobe-chat/commit/7994982))
|
|
48
|
+
|
|
49
|
+
</details>
|
|
50
|
+
|
|
51
|
+
<div align="right">
|
|
52
|
+
|
|
53
|
+
[](#readme-top)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
5
57
|
### [Version 0.82.2](https://github.com/lobehub/lobe-chat/compare/v0.82.1...v0.82.2)
|
|
6
58
|
|
|
7
59
|
<sup>Released on **2023-09-28**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.4",
|
|
4
4
|
"description": "An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
@@ -1,34 +1,58 @@
|
|
|
1
|
-
import { Avatar } from '@lobehub/ui';
|
|
2
1
|
import { Button, Input } from 'antd';
|
|
3
2
|
import { memo } from 'react';
|
|
4
3
|
import { useTranslation } from 'react-i18next';
|
|
5
4
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
6
5
|
|
|
7
|
-
import { useGlobalStore } from '@/store/global';
|
|
6
|
+
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
7
|
+
import { useSessionStore } from '@/store/session';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { FormAction } from './style';
|
|
10
10
|
|
|
11
|
-
const APIKeyForm = memo<{
|
|
11
|
+
const APIKeyForm = memo<{ id: string }>(({ id }) => {
|
|
12
12
|
const { t } = useTranslation('error');
|
|
13
|
-
|
|
14
|
-
const [apiKey,
|
|
13
|
+
|
|
14
|
+
const [apiKey, setKeys] = useGlobalStore((s) => [
|
|
15
|
+
settingsSelectors.openAIAPI(s),
|
|
16
|
+
s.setOpenAIAPIKey,
|
|
17
|
+
]);
|
|
18
|
+
const [resend, deleteMessage] = useSessionStore((s) => [s.resendMessage, s.deleteMessage]);
|
|
15
19
|
|
|
16
20
|
return (
|
|
17
21
|
<Center gap={16} style={{ maxWidth: 300 }}>
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</
|
|
22
|
+
<FormAction
|
|
23
|
+
avatar={'🔑'}
|
|
24
|
+
description={t('unlock.apikey.description')}
|
|
25
|
+
title={t('unlock.apikey.title')}
|
|
26
|
+
>
|
|
27
|
+
<Input.Password
|
|
28
|
+
onChange={(e) => {
|
|
29
|
+
setKeys(e.target.value);
|
|
30
|
+
}}
|
|
31
|
+
placeholder={'sk-*****************************************'}
|
|
32
|
+
type={'block'}
|
|
33
|
+
value={apiKey}
|
|
34
|
+
/>
|
|
35
|
+
</FormAction>
|
|
36
|
+
<Flexbox gap={12} width={'100%'}>
|
|
37
|
+
<Button
|
|
38
|
+
block
|
|
39
|
+
onClick={() => {
|
|
40
|
+
resend(id);
|
|
41
|
+
deleteMessage(id);
|
|
42
|
+
}}
|
|
43
|
+
style={{ marginTop: 8 }}
|
|
44
|
+
type={'primary'}
|
|
45
|
+
>
|
|
46
|
+
{t('unlock.confirm')}
|
|
47
|
+
</Button>
|
|
48
|
+
<Button
|
|
49
|
+
onClick={() => {
|
|
50
|
+
deleteMessage(id);
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
{t('unlock.closeMessage')}
|
|
54
|
+
</Button>
|
|
55
|
+
</Flexbox>
|
|
32
56
|
</Center>
|
|
33
57
|
);
|
|
34
58
|
});
|
|
@@ -51,29 +51,31 @@ const InvalidAccess = memo<{ id: string }>(({ id }) => {
|
|
|
51
51
|
onChange={(e) => {
|
|
52
52
|
setSettings({ password: e });
|
|
53
53
|
}}
|
|
54
|
-
validationPattern={
|
|
54
|
+
validationPattern={/.*/}
|
|
55
55
|
value={password}
|
|
56
56
|
/>
|
|
57
57
|
</FormAction>
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
<Flexbox gap={12}>
|
|
59
|
+
<Button
|
|
60
|
+
onClick={() => {
|
|
61
|
+
resend(id);
|
|
62
|
+
deleteMessage(id);
|
|
63
|
+
}}
|
|
64
|
+
type={'primary'}
|
|
65
|
+
>
|
|
66
|
+
{t('unlock.confirm')}
|
|
67
|
+
</Button>
|
|
68
|
+
<Button
|
|
69
|
+
onClick={() => {
|
|
70
|
+
deleteMessage(id);
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
{t('unlock.closeMessage')}
|
|
74
|
+
</Button>
|
|
75
|
+
</Flexbox>
|
|
67
76
|
</>
|
|
68
77
|
)}
|
|
69
|
-
{mode === Tab.Api &&
|
|
70
|
-
<APIKeyForm
|
|
71
|
-
onConfirm={() => {
|
|
72
|
-
resend(id);
|
|
73
|
-
deleteMessage(id);
|
|
74
|
-
}}
|
|
75
|
-
/>
|
|
76
|
-
)}
|
|
78
|
+
{mode === Tab.Api && <APIKeyForm id={id} />}
|
|
77
79
|
</Flexbox>
|
|
78
80
|
</ErrorActionContainer>
|
|
79
81
|
);
|
|
@@ -2,8 +2,6 @@ import { Highlighter } from '@lobehub/ui';
|
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
5
|
-
import { useSessionStore } from '@/store/session';
|
|
6
|
-
|
|
7
5
|
import APIKeyForm from './ApiKeyForm';
|
|
8
6
|
import { ErrorActionContainer, useStyles } from './style';
|
|
9
7
|
|
|
@@ -21,20 +19,12 @@ interface OpenAIErrorResponse {
|
|
|
21
19
|
const OpenAiBizError = memo<{ content: OpenAIErrorResponse; id: string }>(({ content, id }) => {
|
|
22
20
|
const { styles } = useStyles();
|
|
23
21
|
|
|
24
|
-
const [resend, deleteMessage] = useSessionStore((s) => [s.resendMessage, s.deleteMessage]);
|
|
25
|
-
|
|
26
22
|
const errorCode = content.error?.code;
|
|
27
23
|
|
|
28
24
|
if (errorCode === 'invalid_api_key') {
|
|
29
25
|
return (
|
|
30
26
|
<ErrorActionContainer>
|
|
31
|
-
<APIKeyForm
|
|
32
|
-
onConfirm={() => {
|
|
33
|
-
console.log(id);
|
|
34
|
-
resend(id);
|
|
35
|
-
deleteMessage(id);
|
|
36
|
-
}}
|
|
37
|
-
/>
|
|
27
|
+
<APIKeyForm id={id} />
|
|
38
28
|
</ErrorActionContainer>
|
|
39
29
|
);
|
|
40
30
|
}
|
|
@@ -118,13 +118,7 @@ const OtpInput = memo<OtpInputProps>((props) => {
|
|
|
118
118
|
<input
|
|
119
119
|
key={index}
|
|
120
120
|
{...restProps}
|
|
121
|
-
/**
|
|
122
|
-
* Add some styling to the input using daisyUI + tailwind.
|
|
123
|
-
* Allows the user to override the classname for a different styling
|
|
124
|
-
*/
|
|
125
|
-
autoComplete="one-time-code"
|
|
126
121
|
className={cx(styles, className)}
|
|
127
|
-
inputMode="numeric"
|
|
128
122
|
maxLength={6}
|
|
129
123
|
onChange={(e) => handleInputChange(e, index)}
|
|
130
124
|
onKeyUp={handleKeyUp}
|
|
@@ -13,6 +13,9 @@ const defaultAgentConfig = (s: GlobalStore) => merge(DEFAULT_AGENT_CONFIG, defau
|
|
|
13
13
|
|
|
14
14
|
const defaultAgentMeta = (s: GlobalStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
15
15
|
|
|
16
|
+
const openAIAPIKeySelectors = (s: GlobalStore) =>
|
|
17
|
+
s.settings.languageModel.openAI.OPENAI_API_KEY || s.settings.OPENAI_API_KEY;
|
|
18
|
+
|
|
16
19
|
export const exportSettings = (s: GlobalStore) => {
|
|
17
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
18
21
|
const { OPENAI_API_KEY: _, password: __, ...settings } = s.settings;
|
|
@@ -27,3 +30,7 @@ export const globalSelectors = {
|
|
|
27
30
|
defaultAgentMeta,
|
|
28
31
|
exportSettings,
|
|
29
32
|
};
|
|
33
|
+
|
|
34
|
+
export const settingsSelectors = {
|
|
35
|
+
openAIAPI: openAIAPIKeySelectors,
|
|
36
|
+
};
|
|
@@ -23,6 +23,7 @@ export interface SettingsAction {
|
|
|
23
23
|
* 重置设置
|
|
24
24
|
*/
|
|
25
25
|
resetSettings: () => void;
|
|
26
|
+
setOpenAIAPIKey: (apikey: string) => void;
|
|
26
27
|
/**
|
|
27
28
|
* 设置部分配置设置
|
|
28
29
|
* @param settings - 部分配置设置
|
|
@@ -62,6 +63,10 @@ export const createSettingsSlice: StateCreator<
|
|
|
62
63
|
resetSettings: () => {
|
|
63
64
|
set({ settings: DEFAULT_SETTINGS }, false, t('resetSettings'));
|
|
64
65
|
},
|
|
66
|
+
setOpenAIAPIKey: (apikey) => {
|
|
67
|
+
get().setSettings({ languageModel: { openAI: { OPENAI_API_KEY: apikey } } });
|
|
68
|
+
},
|
|
69
|
+
|
|
65
70
|
setSettings: (settings) => {
|
|
66
71
|
const oldSetting = get().settings;
|
|
67
72
|
const nextSettings = merge(oldSetting, settings);
|
|
@@ -70,7 +75,6 @@ export const createSettingsSlice: StateCreator<
|
|
|
70
75
|
|
|
71
76
|
set({ settings: merge(oldSetting, settings) }, false, t('setSettings', settings));
|
|
72
77
|
},
|
|
73
|
-
|
|
74
78
|
switchSettingTabs: (tab) => {
|
|
75
79
|
set({ settingsTab: tab });
|
|
76
80
|
},
|
|
@@ -2,6 +2,7 @@ import { StorageValue } from 'zustand/middleware/persist';
|
|
|
2
2
|
|
|
3
3
|
export const createLocalStorage = <State extends any>() => ({
|
|
4
4
|
getItem: <T extends State>(name: string): StorageValue<T> | undefined => {
|
|
5
|
+
if (!global.localStorage) return undefined;
|
|
5
6
|
const string = localStorage.getItem(name);
|
|
6
7
|
|
|
7
8
|
if (string) return JSON.parse(string) as StorageValue<T>;
|
|
@@ -9,9 +10,9 @@ export const createLocalStorage = <State extends any>() => ({
|
|
|
9
10
|
return undefined;
|
|
10
11
|
},
|
|
11
12
|
removeItem: (name: string) => {
|
|
12
|
-
localStorage.removeItem(name);
|
|
13
|
+
if (global.localStorage) localStorage.removeItem(name);
|
|
13
14
|
},
|
|
14
15
|
setItem: <T extends State>(name: string, state: T, version: number | undefined) => {
|
|
15
|
-
localStorage.setItem(name, JSON.stringify({ state, version }));
|
|
16
|
+
if (global.localStorage) localStorage.setItem(name, JSON.stringify({ state, version }));
|
|
16
17
|
},
|
|
17
18
|
});
|