@lobehub/chat 0.120.5 → 0.121.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/.github/ISSUE_TEMPLATE/2_feature_request_cn.yml +1 -1
- package/CHANGELOG.md +50 -0
- package/README.md +9 -9
- package/README.zh-CN.md +9 -9
- package/docs/Development/Feature-Development-Frontend.zh-CN.md +126 -0
- package/docs/Development/Feature-Development.zh-CN.md +664 -83
- package/docs/Development/{State-Management/State-Management-Intro.zh-CN.md → State-Management-Intro.zh-CN.md} +9 -9
- package/docs/Home.md +1 -0
- package/docs/_Sidebar.md +1 -0
- package/locales/ar/chat.json +13 -1
- package/locales/ar/common.json +1 -0
- package/locales/de-DE/chat.json +13 -1
- package/locales/de-DE/common.json +1 -0
- package/locales/en-US/chat.json +13 -1
- package/locales/en-US/common.json +1 -0
- package/locales/es-ES/chat.json +13 -1
- package/locales/es-ES/common.json +1 -0
- package/locales/fr-FR/chat.json +13 -1
- package/locales/fr-FR/common.json +1 -0
- package/locales/it-IT/chat.json +13 -1
- package/locales/it-IT/common.json +1 -0
- package/locales/ja-JP/chat.json +13 -1
- package/locales/ja-JP/common.json +1 -0
- package/locales/ko-KR/chat.json +13 -1
- package/locales/ko-KR/common.json +1 -0
- package/locales/nl-NL/chat.json +13 -1
- package/locales/nl-NL/common.json +1 -0
- package/locales/pl-PL/chat.json +13 -1
- package/locales/pl-PL/common.json +1 -0
- package/locales/pt-BR/chat.json +13 -1
- package/locales/pt-BR/common.json +1 -0
- package/locales/ru-RU/chat.json +13 -1
- package/locales/ru-RU/common.json +1 -0
- package/locales/tr-TR/chat.json +13 -1
- package/locales/tr-TR/common.json +1 -0
- package/locales/vi-VN/chat.json +13 -1
- package/locales/vi-VN/common.json +1 -0
- package/locales/zh-CN/chat.json +13 -1
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-TW/chat.json +13 -1
- package/locales/zh-TW/common.json +1 -0
- package/package.json +4 -6
- package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +18 -5
- package/src/app/chat/(desktop)/features/ChatInput/index.tsx +1 -1
- package/src/app/chat/features/ChatHeader/ShareButton/index.tsx +0 -1
- package/src/app/chat/features/ChatHeader/ShareButton/style.ts +0 -1
- package/src/app/chat/features/Migration/Failed.tsx +2 -0
- package/src/app/chat/features/SessionListContent/CollapseGroup/Actions.tsx +115 -0
- package/src/app/chat/features/SessionListContent/CollapseGroup/index.tsx +6 -0
- package/src/app/chat/features/SessionListContent/DefaultMode.tsx +63 -23
- package/src/app/chat/features/SessionListContent/List/AddButton.tsx +3 -3
- package/src/app/chat/features/SessionListContent/List/Item/Actions.tsx +89 -35
- package/src/app/chat/features/SessionListContent/List/Item/index.tsx +35 -15
- package/src/app/chat/features/SessionListContent/List/index.tsx +4 -2
- package/src/app/chat/features/SessionListContent/Modals/ConfigGroupModal/GroupItem.tsx +84 -0
- package/src/app/chat/features/SessionListContent/Modals/ConfigGroupModal/index.tsx +79 -0
- package/src/app/chat/features/SessionListContent/Modals/CreateGroupModal.tsx +63 -0
- package/src/app/chat/features/SessionListContent/Modals/RenameGroupModal.tsx +50 -0
- package/src/app/chat/features/SessionListContent/SearchMode.tsx +1 -1
- package/src/app/settings/common/Common.tsx +5 -1
- package/src/components/FullscreenLoading/index.tsx +1 -1
- package/src/database/core/__tests__/db-upgrade.test.ts +42 -0
- package/src/database/core/db.ts +26 -4
- package/src/database/core/schemas.ts +14 -1
- package/src/database/core/types/db.ts +2 -0
- package/src/database/models/__tests__/message.test.ts +42 -0
- package/src/database/models/__tests__/plugin.test.ts +77 -0
- package/src/database/models/__tests__/session.test.ts +202 -63
- package/src/database/models/__tests__/sessionGroup.test.ts +195 -0
- package/src/database/models/__tests__/topic.test.ts +76 -1
- package/src/database/models/message.ts +7 -8
- package/src/database/models/session.ts +103 -7
- package/src/database/models/sessionGroup.ts +76 -0
- package/src/database/schemas/session.ts +1 -0
- package/src/database/schemas/sessionGroup.ts +8 -0
- package/src/features/ChatInput/ActionBar/Clear.tsx +2 -1
- package/src/features/Conversation/Actions/Assistant.tsx +1 -1
- package/src/features/Conversation/Actions/Function.tsx +2 -2
- package/src/features/Conversation/Actions/User.tsx +1 -1
- package/src/features/Conversation/hooks/useChatListActionsBar.tsx +3 -3
- package/src/features/PluginDevModal/index.tsx +3 -0
- package/src/features/PluginStore/PluginItem/Action.tsx +2 -0
- package/src/locales/default/chat.ts +13 -1
- package/src/locales/default/common.ts +1 -0
- package/src/migrations/FromV2ToV3/fixtures/input-v2-session.json +72 -0
- package/src/migrations/FromV2ToV3/fixtures/output-v3-from-v1.json +203 -0
- package/src/migrations/FromV2ToV3/fixtures/output-v3.json +74 -0
- package/src/migrations/FromV2ToV3/index.ts +30 -0
- package/src/migrations/FromV2ToV3/migrations.test.ts +42 -0
- package/src/migrations/FromV2ToV3/types/v3.ts +27 -0
- package/src/migrations/index.ts +7 -1
- package/src/services/__tests__/session.test.ts +198 -7
- package/src/services/config.ts +23 -7
- package/src/services/session.ts +67 -14
- package/src/store/global/slices/common/action.test.ts +130 -0
- package/src/store/global/slices/common/action.ts +14 -0
- package/src/store/global/slices/common/initialState.ts +6 -2
- package/src/store/global/slices/common/selectors.ts +1 -4
- package/src/store/global/slices/settings/__snapshots__/selectors.test.ts.snap +83 -0
- package/src/store/global/slices/settings/action.ts +2 -2
- package/src/store/global/slices/settings/selectors.test.ts +132 -182
- package/src/store/global/store.ts +7 -0
- package/src/store/session/initialState.ts +5 -30
- package/src/store/session/selectors.ts +2 -1
- package/src/store/session/slices/session/action.test.ts +56 -0
- package/src/store/session/slices/session/action.ts +13 -9
- package/src/store/session/slices/session/helpers.ts +2 -3
- package/src/store/session/slices/session/initialState.ts +31 -23
- package/src/store/session/slices/session/selectors/index.ts +0 -1
- package/src/store/session/slices/session/selectors/list.ts +11 -18
- package/src/store/session/slices/sessionGroup/action.ts +54 -0
- package/src/store/session/slices/sessionGroup/initialState.ts +5 -0
- package/src/store/session/slices/sessionGroup/selectors.ts +15 -0
- package/src/store/session/store.ts +9 -2
- package/src/styles/antdOverride.ts +0 -7
- package/src/types/exportConfig.ts +3 -1
- package/src/types/session.ts +27 -3
- package/src/store/session/slices/session/selectors/export.ts +0 -31
- /package/docs/Development/{Feature-Development.md → Feature-Development-Frontend.md} +0 -0
- /package/docs/Development/{State-Management/State-Management-Intro.md → State-Management-Intro.md} +0 -0
- /package/docs/Development/{State-Management/Selectors.md → State-Management-Selectors.md} +0 -0
- /package/docs/Development/{State-Management/Selectors.zh-CN.md → State-Management-Selectors.zh-CN.md} +0 -0
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
import { INBOX_SESSION_ID } from '@/const/session';
|
|
2
2
|
import { sessionHelpers } from '@/store/session/slices/session/helpers';
|
|
3
3
|
import { MetaData } from '@/types/meta';
|
|
4
|
-
import { LobeAgentSession, LobeSessions
|
|
4
|
+
import { CustomSessionGroup, LobeAgentSession, LobeSessions } from '@/types/session';
|
|
5
5
|
|
|
6
6
|
import { SessionStore } from '../../../store';
|
|
7
7
|
import { initLobeSession } from '../initialState';
|
|
8
8
|
|
|
9
|
-
const defaultSessions = (s: SessionStore): LobeSessions => s.
|
|
9
|
+
const defaultSessions = (s: SessionStore): LobeSessions => s.defaultSessions;
|
|
10
|
+
const pinnedSessions = (s: SessionStore): LobeSessions => s.pinnedSessions;
|
|
11
|
+
const customSessionGroups = (s: SessionStore): CustomSessionGroup[] => s.customSessionGroups;
|
|
10
12
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const pinnedSessionList = (s: SessionStore) =>
|
|
14
|
-
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Pinned);
|
|
13
|
+
const allSessions = (s: SessionStore): LobeSessions => s.sessions;
|
|
15
14
|
|
|
16
|
-
const
|
|
17
|
-
defaultSessions(s).filter((s) => s.group === SessionGroupDefaultKeys.Default);
|
|
15
|
+
const searchSessions = (s: SessionStore): LobeSessions => s.searchSessions;
|
|
18
16
|
|
|
19
17
|
const getSessionById =
|
|
20
18
|
(id: string) =>
|
|
21
19
|
(s: SessionStore): LobeAgentSession =>
|
|
22
|
-
sessionHelpers.getSessionById(id, s
|
|
20
|
+
sessionHelpers.getSessionById(id, allSessions(s));
|
|
23
21
|
|
|
24
22
|
const getSessionMetaById =
|
|
25
23
|
(id: string) =>
|
|
@@ -33,18 +31,13 @@ const getSessionMetaById =
|
|
|
33
31
|
const currentSession = (s: SessionStore): LobeAgentSession | undefined => {
|
|
34
32
|
if (!s.activeId) return;
|
|
35
33
|
|
|
36
|
-
return s.
|
|
34
|
+
return allSessions(s).find((i) => i.id === s.activeId);
|
|
37
35
|
};
|
|
38
36
|
|
|
39
37
|
const currentSessionSafe = (s: SessionStore): LobeAgentSession => {
|
|
40
38
|
return currentSession(s) || initLobeSession;
|
|
41
39
|
};
|
|
42
40
|
|
|
43
|
-
const hasPinnedSessionList = (s: SessionStore) => {
|
|
44
|
-
const list = pinnedSessionList(s);
|
|
45
|
-
return list?.length > 0;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
41
|
const hasCustomAgents = (s: SessionStore) => defaultSessions(s).length > 0;
|
|
49
42
|
|
|
50
43
|
const isInboxSession = (s: SessionStore) => s.activeId === INBOX_SESSION_ID;
|
|
@@ -57,14 +50,14 @@ const isSomeSessionActive = (s: SessionStore) => !!s.activeId && isSessionListIn
|
|
|
57
50
|
export const sessionSelectors = {
|
|
58
51
|
currentSession,
|
|
59
52
|
currentSessionSafe,
|
|
53
|
+
customSessionGroups,
|
|
54
|
+
defaultSessions,
|
|
60
55
|
getSessionById,
|
|
61
56
|
getSessionMetaById,
|
|
62
57
|
hasCustomAgents,
|
|
63
|
-
hasPinnedSessionList,
|
|
64
58
|
isInboxSession,
|
|
65
59
|
isSessionListInit,
|
|
66
60
|
isSomeSessionActive,
|
|
67
|
-
|
|
61
|
+
pinnedSessions,
|
|
68
62
|
searchSessions,
|
|
69
|
-
unpinnedSessionList,
|
|
70
63
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { StateCreator } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
import { sessionService } from '@/services/session';
|
|
4
|
+
import { SessionStore } from '@/store/session';
|
|
5
|
+
import { SessionGroupItem } from '@/types/session';
|
|
6
|
+
|
|
7
|
+
export interface SessionGroupAction {
|
|
8
|
+
addSessionGroup: (name: string) => Promise<string>;
|
|
9
|
+
clearSessionGroups: () => Promise<void>;
|
|
10
|
+
removeSessionGroup: (id: string) => Promise<void>;
|
|
11
|
+
updateSessionGroupId: (sessionId: string, groupId: string) => Promise<void>;
|
|
12
|
+
updateSessionGroupName: (id: string, name: string) => Promise<void>;
|
|
13
|
+
updateSessionGroupSort: (items: SessionGroupItem[]) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const createSessionGroupSlice: StateCreator<
|
|
17
|
+
SessionStore,
|
|
18
|
+
[['zustand/devtools', never]],
|
|
19
|
+
[],
|
|
20
|
+
SessionGroupAction
|
|
21
|
+
> = (set, get) => ({
|
|
22
|
+
addSessionGroup: async (name) => {
|
|
23
|
+
const id = await sessionService.createSessionGroup(name);
|
|
24
|
+
|
|
25
|
+
await get().refreshSessions();
|
|
26
|
+
|
|
27
|
+
return id;
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
clearSessionGroups: async () => {
|
|
31
|
+
await sessionService.clearSessionGroups();
|
|
32
|
+
await get().refreshSessions();
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
removeSessionGroup: async (id) => {
|
|
36
|
+
await sessionService.removeSessionGroup(id);
|
|
37
|
+
await get().refreshSessions();
|
|
38
|
+
},
|
|
39
|
+
updateSessionGroupId: async (sessionId, groupId) => {
|
|
40
|
+
await sessionService.updateSessionGroupId(sessionId, groupId);
|
|
41
|
+
|
|
42
|
+
await get().refreshSessions();
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
updateSessionGroupName: async (id, name) => {
|
|
46
|
+
await sessionService.updateSessionGroup(id, { name });
|
|
47
|
+
await get().refreshSessions();
|
|
48
|
+
},
|
|
49
|
+
updateSessionGroupSort: async (items) => {
|
|
50
|
+
const sortMap = items.map((item, index) => ({ id: item.id, sort: index }));
|
|
51
|
+
await sessionService.updateSessionGroupOrder(sortMap);
|
|
52
|
+
await get().refreshSessions();
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SessionStore } from '@/store/session';
|
|
2
|
+
|
|
3
|
+
const sessionGroupItems = (s: SessionStore) =>
|
|
4
|
+
s.customSessionGroups.map((group) => ({
|
|
5
|
+
id: group.id,
|
|
6
|
+
name: group.name,
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
const getGroupById = (id: string) => (s: SessionStore) =>
|
|
10
|
+
sessionGroupItems(s).find((group) => group.id === id);
|
|
11
|
+
|
|
12
|
+
export const sessionGroupSelectors = {
|
|
13
|
+
getGroupById,
|
|
14
|
+
sessionGroupItems,
|
|
15
|
+
};
|
|
@@ -8,17 +8,24 @@ import { isDev } from '@/utils/env';
|
|
|
8
8
|
import { SessionStoreState, initialState } from './initialState';
|
|
9
9
|
import { AgentAction, createAgentSlice } from './slices/agent/action';
|
|
10
10
|
import { SessionAction, createSessionSlice } from './slices/session/action';
|
|
11
|
+
import { SessionGroupAction, createSessionGroupSlice } from './slices/sessionGroup/action';
|
|
11
12
|
|
|
12
13
|
// =============== 聚合 createStoreFn ============ //
|
|
13
14
|
|
|
14
|
-
export
|
|
15
|
+
export interface SessionStore
|
|
16
|
+
extends SessionAction,
|
|
17
|
+
AgentAction,
|
|
18
|
+
SessionGroupAction,
|
|
19
|
+
SessionStoreState {}
|
|
20
|
+
|
|
15
21
|
const createStore: StateCreator<SessionStore, [['zustand/devtools', never]]> = (...parameters) => ({
|
|
16
22
|
...initialState,
|
|
17
23
|
...createAgentSlice(...parameters),
|
|
18
24
|
...createSessionSlice(...parameters),
|
|
25
|
+
...createSessionGroupSlice(...parameters),
|
|
19
26
|
});
|
|
20
27
|
|
|
21
|
-
// ===============
|
|
28
|
+
// =============== implement useStore ============ //
|
|
22
29
|
|
|
23
30
|
export const useSessionStore = createWithEqualityFn<SessionStore>()(
|
|
24
31
|
subscribeWithSelector(
|
|
@@ -4,11 +4,4 @@ export default ({ token }: { prefixCls: string; token: Theme }) => css`
|
|
|
4
4
|
.${token.prefixCls}-popover {
|
|
5
5
|
z-index: 1100;
|
|
6
6
|
}
|
|
7
|
-
.${token.prefixCls}-dropdown {
|
|
8
|
-
> ul {
|
|
9
|
-
border: 1px solid ${token.colorBorderSecondary};
|
|
10
|
-
border-radius: ${token.borderRadius}px !important;
|
|
11
|
-
box-shadow: ${token.boxShadowSecondary};
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
7
|
`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChatMessage } from '@/types/message';
|
|
2
|
-
import { LobeSessions } from '@/types/session';
|
|
2
|
+
import { LobeSessions, SessionGroupItem } from '@/types/session';
|
|
3
3
|
import { GlobalSettings } from '@/types/settings';
|
|
4
4
|
import { ChatTopic } from '@/types/topic';
|
|
5
5
|
|
|
@@ -43,6 +43,7 @@ export interface ConfigModelMap {
|
|
|
43
43
|
*/
|
|
44
44
|
export interface ConfigStateSessions {
|
|
45
45
|
messages: ChatMessage[];
|
|
46
|
+
sessionGroups: SessionGroupItem[];
|
|
46
47
|
sessions: LobeSessions;
|
|
47
48
|
topics: ChatTopic[];
|
|
48
49
|
}
|
|
@@ -60,6 +61,7 @@ export interface ConfigStateSingleSession {
|
|
|
60
61
|
* 配置状态:角色
|
|
61
62
|
*/
|
|
62
63
|
export interface ConfigStateAgents {
|
|
64
|
+
sessionGroups: SessionGroupItem[];
|
|
63
65
|
sessions: LobeSessions;
|
|
64
66
|
}
|
|
65
67
|
|
package/src/types/session.ts
CHANGED
|
@@ -7,19 +7,30 @@ export enum LobeSessionType {
|
|
|
7
7
|
Group = 'group',
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export type
|
|
10
|
+
export type SessionGroupId = SessionDefaultGroup | string;
|
|
11
11
|
|
|
12
|
-
export enum
|
|
12
|
+
export enum SessionDefaultGroup {
|
|
13
13
|
Default = 'default',
|
|
14
14
|
Pinned = 'pinned',
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export interface SessionGroupItem {
|
|
18
|
+
createdAt: number;
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
sort?: number;
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type SessionGroups = SessionGroupItem[];
|
|
26
|
+
|
|
17
27
|
/**
|
|
18
28
|
* Lobe Agent
|
|
19
29
|
*/
|
|
20
30
|
export interface LobeAgentSession extends BaseDataModel {
|
|
21
31
|
config: LobeAgentConfig;
|
|
22
|
-
group?:
|
|
32
|
+
group?: SessionGroupId;
|
|
33
|
+
pinned?: boolean;
|
|
23
34
|
type: LobeSessionType.Agent;
|
|
24
35
|
}
|
|
25
36
|
|
|
@@ -32,3 +43,16 @@ export interface LobeAgentSettings {
|
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
export type LobeSessions = LobeAgentSession[];
|
|
46
|
+
|
|
47
|
+
export interface CustomSessionGroup {
|
|
48
|
+
children: LobeSessions;
|
|
49
|
+
id: SessionGroupId;
|
|
50
|
+
name: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ChatSessionList {
|
|
54
|
+
all: LobeSessions;
|
|
55
|
+
customGroup: CustomSessionGroup[];
|
|
56
|
+
default: LobeSessions;
|
|
57
|
+
pinned: LobeSessions;
|
|
58
|
+
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { transform } from 'lodash-es';
|
|
2
|
-
|
|
3
|
-
import { SessionStore } from '@/store/session';
|
|
4
|
-
import { ConfigStateAgents, ConfigStateSessions } from '@/types/exportConfig';
|
|
5
|
-
import { LobeAgentSession, LobeSessions } from '@/types/session';
|
|
6
|
-
|
|
7
|
-
import { sessionHelpers } from '../helpers';
|
|
8
|
-
|
|
9
|
-
const exportSessions = (s: SessionStore): Pick<ConfigStateSessions, 'sessions'> => ({
|
|
10
|
-
sessions: s.sessions,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const exportAgents = (s: SessionStore): ConfigStateAgents => {
|
|
14
|
-
return {
|
|
15
|
-
sessions: transform(s.sessions, (result: LobeSessions, value, key) => {
|
|
16
|
-
// 移除 chats 和 topics
|
|
17
|
-
result[key] = { ...value, chats: {}, topics: {} } as LobeAgentSession;
|
|
18
|
-
}),
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const getExportAgent =
|
|
23
|
-
(id: string) =>
|
|
24
|
-
(s: SessionStore): LobeAgentSession =>
|
|
25
|
-
sessionHelpers.getSessionById(id, s.sessions);
|
|
26
|
-
|
|
27
|
-
export const sessionExportSelectors = {
|
|
28
|
-
exportAgents,
|
|
29
|
-
exportSessions,
|
|
30
|
-
getExportAgent,
|
|
31
|
-
};
|
|
File without changes
|
/package/docs/Development/{State-Management/State-Management-Intro.md → State-Management-Intro.md}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|