@lobehub/chat 1.60.2 → 1.60.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 CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.60.4](https://github.com/lobehub/lobe-chat/compare/v1.60.3...v1.60.4)
6
+
7
+ <sup>Released on **2025-02-17**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix agent config not load correctly.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix agent config not load correctly, closes [#6252](https://github.com/lobehub/lobe-chat/issues/6252) ([fe9bc16](https://github.com/lobehub/lobe-chat/commit/fe9bc16))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 1.60.3](https://github.com/lobehub/lobe-chat/compare/v1.60.2...v1.60.3)
31
+
32
+ <sup>Released on **2025-02-17**</sup>
33
+
34
+ #### 🐛 Bug Fixes
35
+
36
+ - **misc**: User feedback for empty/long group names in create/edit group modals.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's fixed
44
+
45
+ - **misc**: User feedback for empty/long group names in create/edit group modals, closes [#6247](https://github.com/lobehub/lobe-chat/issues/6247) ([25c80d1](https://github.com/lobehub/lobe-chat/commit/25c80d1))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.60.2](https://github.com/lobehub/lobe-chat/compare/v1.60.1...v1.60.2)
6
56
 
7
57
  <sup>Released on **2025-02-17**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,22 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Fix agent config not load correctly."
6
+ ]
7
+ },
8
+ "date": "2025-02-17",
9
+ "version": "1.60.4"
10
+ },
11
+ {
12
+ "children": {
13
+ "fixes": [
14
+ "User feedback for empty/long group names in create/edit group modals."
15
+ ]
16
+ },
17
+ "date": "2025-02-17",
18
+ "version": "1.60.3"
19
+ },
2
20
  {
3
21
  "children": {
4
22
  "fixes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.60.2",
3
+ "version": "1.60.4",
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",
@@ -11,10 +11,10 @@ import { ActionKeys } from '@/features/ChatInput/ActionBar/config';
11
11
  import STT from '@/features/ChatInput/STT';
12
12
  import SaveTopic from '@/features/ChatInput/Topic';
13
13
  import { useSendMessage } from '@/features/ChatInput/useSend';
14
+ import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
14
15
  import { useChatStore } from '@/store/chat';
15
16
  import { chatSelectors } from '@/store/chat/selectors';
16
17
 
17
- import { useInitAgentConfig } from '../../../../_layout/useInitAgentConfig';
18
18
  import Files from './Files';
19
19
  import InputArea from './InputArea';
20
20
  import SendButton from './Send';
@@ -31,7 +31,8 @@ const SystemRole = memo(() => {
31
31
  sessionMetaSelectors.currentAgentMeta(s),
32
32
  ]);
33
33
 
34
- const [systemRole, updateAgentConfig] = useAgentStore((s) => [
34
+ const [isAgentConfigLoading, systemRole, updateAgentConfig] = useAgentStore((s) => [
35
+ agentSelectors.isAgentConfigLoading(s),
35
36
  agentSelectors.currentAgentSystemRole(s),
36
37
  s.updateAgentConfig,
37
38
  ]);
@@ -49,14 +50,16 @@ const SystemRole = memo(() => {
49
50
 
50
51
  const { t } = useTranslation('common');
51
52
 
53
+ const isLoading = !init || isAgentConfigLoading;
54
+
52
55
  const handleOpenWithEdit = () => {
53
- if (!init) return;
56
+ if (isLoading) return;
54
57
  setEditing(true);
55
58
  setOpen(true);
56
59
  };
57
60
 
58
61
  const handleOpen = () => {
59
- if (!init) return;
62
+ if (isLoading) return;
60
63
 
61
64
  setOpen(true);
62
65
  };
@@ -77,7 +80,7 @@ const SystemRole = memo(() => {
77
80
  if (e.altKey) handleOpenWithEdit();
78
81
  }}
79
82
  >
80
- {!init ? (
83
+ {isLoading ? (
81
84
  <Skeleton
82
85
  active
83
86
  avatar={false}
@@ -10,13 +10,13 @@ import { useTranslation } from 'react-i18next';
10
10
  import { Flexbox } from 'react-layout-kit';
11
11
 
12
12
  import { DESKTOP_HEADER_ICON_SIZE } from '@/const/layoutTokens';
13
+ import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
13
14
  import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
14
15
  import { useGlobalStore } from '@/store/global';
15
16
  import { systemStatusSelectors } from '@/store/global/selectors';
16
17
  import { useSessionStore } from '@/store/session';
17
18
  import { sessionMetaSelectors, sessionSelectors } from '@/store/session/selectors';
18
19
 
19
- import { useInitAgentConfig } from '../../useInitAgentConfig';
20
20
  import Tags from './Tags';
21
21
 
22
22
  const Main = memo(() => {
@@ -1,4 +1,5 @@
1
1
  import { ModelTag } from '@lobehub/icons';
2
+ import { Skeleton } from 'antd';
2
3
  import isEqual from 'fast-deep-equal';
3
4
  import { memo } from 'react';
4
5
  import { Flexbox } from 'react-layout-kit';
@@ -21,8 +22,11 @@ const TitleTags = memo(() => {
21
22
  const enabledKnowledge = useAgentStore(agentSelectors.currentEnabledKnowledge, isEqual);
22
23
 
23
24
  const showPlugin = useModelSupportToolUse(model, provider);
25
+ const isLoading = useAgentStore(agentSelectors.isAgentConfigLoading);
24
26
 
25
- return (
27
+ return isLoading ? (
28
+ <Skeleton.Button active size={'small'} style={{ height: 20 }} />
29
+ ) : (
26
30
  <Flexbox align={'center'} horizontal>
27
31
  <ModelSwitchPanel>
28
32
  <ModelTag model={model} />
@@ -14,10 +14,10 @@ import AgentMeta from '@/features/AgentSetting/AgentMeta';
14
14
  import AgentModal from '@/features/AgentSetting/AgentModal';
15
15
  import AgentPlugin from '@/features/AgentSetting/AgentPlugin';
16
16
  import AgentPrompt from '@/features/AgentSetting/AgentPrompt';
17
+ import { AgentSettingsProvider } from '@/features/AgentSetting/AgentSettingsProvider';
17
18
  import AgentTTS from '@/features/AgentSetting/AgentTTS';
18
- import StoreUpdater from '@/features/AgentSetting/StoreUpdater';
19
- import { Provider, createStore } from '@/features/AgentSetting/store';
20
19
  import Footer from '@/features/Setting/Footer';
20
+ import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
21
21
  import { useAgentStore } from '@/store/agent';
22
22
  import { agentSelectors } from '@/store/agent/slices/chat';
23
23
  import { ChatSettingsTabs } from '@/store/global/initialState';
@@ -31,6 +31,8 @@ const AgentSettings = memo(() => {
31
31
  const id = useSessionStore((s) => s.activeId);
32
32
  const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
33
33
  const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
34
+
35
+ const { isLoading } = useInitAgentConfig();
34
36
  const [showAgentSetting, updateAgentConfig] = useAgentStore((s) => [
35
37
  s.showAgentSetting,
36
38
  s.updateAgentConfig,
@@ -49,14 +51,14 @@ const AgentSettings = memo(() => {
49
51
 
50
52
  const category = <CategoryContent setTab={setTab} tab={tab} />;
51
53
  return (
52
- <Provider createStore={createStore}>
53
- <StoreUpdater
54
- config={config}
55
- id={id}
56
- meta={meta}
57
- onConfigChange={updateAgentConfig}
58
- onMetaChange={updateAgentMeta}
59
- />
54
+ <AgentSettingsProvider
55
+ config={config}
56
+ id={id}
57
+ loading={isLoading}
58
+ meta={meta}
59
+ onConfigChange={updateAgentConfig}
60
+ onMetaChange={updateAgentMeta}
61
+ >
60
62
  <Drawer
61
63
  height={'100vh'}
62
64
  onClose={() => {
@@ -109,7 +111,7 @@ const AgentSettings = memo(() => {
109
111
  </Flexbox>
110
112
  </Flexbox>
111
113
  </Drawer>
112
- </Provider>
114
+ </AgentSettingsProvider>
113
115
  );
114
116
  });
115
117
 
@@ -35,8 +35,6 @@ const CreateGroupModal = memo<CreateGroupModalProps>(
35
35
  onCancel?.(e);
36
36
  }}
37
37
  onOk={async (e: MouseEvent<HTMLButtonElement>) => {
38
- if (!input) return;
39
-
40
38
  if (input.length === 0 || input.length > 20)
41
39
  return message.warning(t('sessionGroup.tooLong'));
42
40
 
@@ -17,13 +17,13 @@ const RenameGroupModal = memo<RenameGroupModalProps>(({ id, open, onCancel }) =>
17
17
  const updateSessionGroupName = useSessionStore((s) => s.updateSessionGroupName);
18
18
  const group = useSessionStore((s) => sessionGroupSelectors.getGroupById(id)(s), isEqual);
19
19
 
20
- const [input, setInput] = useState<string>();
20
+ const [input, setInput] = useState<string>('');
21
21
  const [loading, setLoading] = useState(false);
22
22
 
23
23
  const { message } = App.useApp();
24
24
 
25
25
  useEffect(() => {
26
- setInput(group?.name);
26
+ setInput(group?.name ?? '');
27
27
  }, [group]);
28
28
 
29
29
  return (
@@ -32,11 +32,10 @@ const RenameGroupModal = memo<RenameGroupModalProps>(({ id, open, onCancel }) =>
32
32
  destroyOnClose
33
33
  okButtonProps={{ loading }}
34
34
  onCancel={(e) => {
35
- setInput(group?.name);
35
+ setInput(group?.name ?? '');
36
36
  onCancel?.(e);
37
37
  }}
38
38
  onOk={async (e) => {
39
- if (!input) return;
40
39
  if (input.length === 0 || input.length > 20)
41
40
  return message.warning(t('sessionGroup.tooLong'));
42
41
  setLoading(true);
@@ -14,6 +14,7 @@ import AgentModal from '@/features/AgentSetting/AgentModal';
14
14
  import AgentPlugin from '@/features/AgentSetting/AgentPlugin';
15
15
  import AgentPrompt from '@/features/AgentSetting/AgentPrompt';
16
16
  import AgentTTS from '@/features/AgentSetting/AgentTTS';
17
+ import { useInitAgentConfig } from '@/hooks/useInitAgentConfig';
17
18
  import { useAgentStore } from '@/store/agent';
18
19
  import { agentSelectors } from '@/store/agent/selectors';
19
20
  import { ChatSettingsTabs } from '@/store/global/initialState';
@@ -30,15 +31,14 @@ const EditPage = memo(() => {
30
31
  s.updateSessionMeta,
31
32
  sessionMetaSelectors.currentAgentTitle(s),
32
33
  ]);
33
- const [useFetchAgentConfig, updateAgentConfig] = useAgentStore((s) => [
34
- s.useFetchAgentConfig,
35
- s.updateAgentConfig,
36
- ]);
34
+
35
+ const [updateAgentConfig] = useAgentStore((s) => [s.updateAgentConfig]);
37
36
 
38
37
  const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
39
38
  const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
40
39
 
41
- const { isLoading } = useFetchAgentConfig(id);
40
+ const { isLoading } = useInitAgentConfig();
41
+
42
42
  const { enablePlugins } = useServerConfigStore(featureFlagsSelectors);
43
43
 
44
44
  return (
@@ -47,6 +47,26 @@ const AgentPrompt = memo<{ modal?: boolean }>(({ modal }) => {
47
47
  ]);
48
48
 
49
49
  if (loading) {
50
+ if (modal)
51
+ return (
52
+ <Form
53
+ items={[
54
+ {
55
+ children: (
56
+ <>
57
+ <div style={{ height: 24 }} />
58
+ <Skeleton active title={false} />
59
+ </>
60
+ ),
61
+ title: t('settingAgent.prompt.title'),
62
+ },
63
+ ]}
64
+ itemsType={'group'}
65
+ variant={'pure'}
66
+ {...FORM_STYLE}
67
+ />
68
+ );
69
+
50
70
  return (
51
71
  <div className={styles.wrapper}>
52
72
  <Flexbox className={styles.container} padding={4}>
@@ -25,5 +25,6 @@ export const initialState: State = {
25
25
  title: false,
26
26
  },
27
27
  config: DEFAULT_AGENT_CONFIG,
28
+ loading: true,
28
29
  meta: DEFAULT_AGENT_META,
29
30
  };
@@ -1,10 +1,16 @@
1
1
  import { useAgentStore } from '@/store/agent';
2
2
  import { useSessionStore } from '@/store/session';
3
+ import { useUserStore } from '@/store/user';
4
+ import { authSelectors } from '@/store/user/selectors';
3
5
 
4
6
  export const useInitAgentConfig = () => {
5
7
  const [useFetchAgentConfig] = useAgentStore((s) => [s.useFetchAgentConfig]);
6
8
 
9
+ const isLogin = useUserStore(authSelectors.isLogin);
10
+
7
11
  const [sessionId] = useSessionStore((s) => [s.activeId]);
8
12
 
9
- return useFetchAgentConfig(sessionId);
13
+ const data = useFetchAgentConfig(isLogin, sessionId);
14
+
15
+ return { ...data, isLoading: data.isLoading && isLogin };
10
16
  };
@@ -1,8 +1,6 @@
1
- import dayjs from 'dayjs';
2
1
  import { and, eq } from 'drizzle-orm';
3
- import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
3
 
5
- import { MessageModel } from '@/database/_deprecated/models/message';
6
4
  import { clientDB, initializeDB } from '@/database/client/db';
7
5
  import {
8
6
  files,
@@ -1,8 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
3
2
  import { lambdaClient } from '@/libs/trpc/client';
4
- import { useUserStore } from '@/store/user';
5
- import { authSelectors } from '@/store/user/selectors';
6
3
 
7
4
  import { ISessionService } from './type';
8
5
 
@@ -55,9 +52,6 @@ export class ServerService implements ISessionService {
55
52
  // TODO: Need to be fixed
56
53
  // @ts-ignore
57
54
  getSessionConfig: ISessionService['getSessionConfig'] = async (id) => {
58
- const isLogin = authSelectors.isLogin(useUserStore.getState());
59
- if (!isLogin) return DEFAULT_AGENT_CONFIG;
60
-
61
55
  return lambdaClient.agent.getAgentConfig.query({ sessionId: id });
62
56
  };
63
57
 
@@ -175,7 +175,7 @@ describe('AgentSlice', () => {
175
175
 
176
176
  vi.spyOn(sessionService, 'getSessionConfig').mockResolvedValueOnce({ model: 'gpt-4' } as any);
177
177
 
178
- renderHook(() => result.current.useFetchAgentConfig('test-session-id'));
178
+ renderHook(() => result.current.useFetchAgentConfig(true, 'test-session-id'));
179
179
 
180
180
  await waitFor(() => {
181
181
  expect(result.current.agentMap['test-session-id']).toEqual({ model: 'gpt-4' });
@@ -199,7 +199,7 @@ describe('AgentSlice', () => {
199
199
  model: 'gpt-3.5-turbo',
200
200
  } as any);
201
201
 
202
- renderHook(() => result.current.useFetchAgentConfig('test-session-id'));
202
+ renderHook(() => result.current.useFetchAgentConfig(true, 'test-session-id'));
203
203
 
204
204
  await waitFor(() => {
205
205
  expect(result.current.agentMap['test-session-id']).toEqual({ model: 'gpt-3.5-turbo' });
@@ -48,7 +48,7 @@ export interface AgentChatAction {
48
48
  togglePlugin: (id: string, open?: boolean) => Promise<void>;
49
49
  updateAgentChatConfig: (config: Partial<LobeAgentChatConfig>) => Promise<void>;
50
50
  updateAgentConfig: (config: DeepPartial<LobeAgentConfig>) => Promise<void>;
51
- useFetchAgentConfig: (id: string) => SWRResponse<LobeAgentConfig>;
51
+ useFetchAgentConfig: (isLogin: boolean | undefined, id: string) => SWRResponse<LobeAgentConfig>;
52
52
  useFetchFilesAndKnowledgeBases: () => SWRResponse<KnowledgeItem[]>;
53
53
  useInitInboxAgentStore: (
54
54
  isLogin: boolean | undefined,
@@ -158,14 +158,22 @@ export const createChatSlice: StateCreator<
158
158
 
159
159
  await get().internal_updateAgentConfig(activeId, config, controller.signal);
160
160
  },
161
- useFetchAgentConfig: (sessionId) =>
161
+ useFetchAgentConfig: (isLogin, sessionId) =>
162
162
  useClientDataSWR<LobeAgentConfig>(
163
- [FETCH_AGENT_CONFIG_KEY, sessionId],
163
+ isLogin ? [FETCH_AGENT_CONFIG_KEY, sessionId] : null,
164
164
  ([, id]: string[]) => sessionService.getSessionConfig(id),
165
165
  {
166
166
  onSuccess: (data) => {
167
167
  get().internal_dispatchAgentMap(sessionId, data, 'fetch');
168
- set({ activeAgentId: data.id }, false, 'updateActiveAgentId');
168
+
169
+ set(
170
+ {
171
+ activeAgentId: data.id,
172
+ agentConfigInitMap: { ...get().agentConfigInitMap, [sessionId]: true },
173
+ },
174
+ false,
175
+ 'fetchAgentConfig',
176
+ );
169
177
  },
170
178
  },
171
179
  ),
@@ -7,6 +7,7 @@ import { LobeAgentConfig } from '@/types/agent';
7
7
  export interface AgentState {
8
8
  activeAgentId?: string;
9
9
  activeId: string;
10
+ agentConfigInitMap: Record<string, boolean>;
10
11
  agentMap: Record<string, DeepPartial<LobeAgentConfig>>;
11
12
  agentSettingInstance?: AgentSettingsInstance | null;
12
13
  defaultAgentConfig: LobeAgentConfig;
@@ -18,6 +19,7 @@ export interface AgentState {
18
19
 
19
20
  export const initialAgentChatState: AgentState = {
20
21
  activeId: 'inbox',
22
+ agentConfigInitMap: {},
21
23
  agentMap: {},
22
24
  defaultAgentConfig: DEFAULT_AGENT_CONFIG,
23
25
  isInboxAgentConfigInit: false,
@@ -138,6 +138,8 @@ const currentKnowledgeIds = (s: AgentStore) => {
138
138
  };
139
139
  };
140
140
 
141
+ const isAgentConfigLoading = (s: AgentStore) => !s.agentConfigInitMap[s.activeId];
142
+
141
143
  export const agentSelectors = {
142
144
  currentAgentChatConfig,
143
145
  currentAgentConfig,
@@ -157,5 +159,6 @@ export const agentSelectors = {
157
159
  hasSystemRole,
158
160
  inboxAgentConfig,
159
161
  inboxAgentModel,
162
+ isAgentConfigLoading,
160
163
  isInboxSession,
161
164
  };