{
},
{
key: 'role',
- label: '角色设定',
+ label: '系统角色',
},
{
key: 'voice',
diff --git a/src/store/dance/slices/playlist.ts b/src/store/dance/slices/playlist.ts
index 23d53068..2a54f594 100644
--- a/src/store/dance/slices/playlist.ts
+++ b/src/store/dance/slices/playlist.ts
@@ -15,7 +15,7 @@ export interface PlayListStore {
/**
* Add a dance to the playlist.
*/
- addPlayItem: (dance: Dance) => void;
+ addToPlayList: (dance: Dance) => void;
/**
* Clear the playlist.
*/
@@ -64,6 +64,10 @@ export const createPlayListStore: StateCreator<
PlayListStore
> = (set, get) => {
return {
+ /**
+ * Add a dance to the playlist and play it. add to the first.
+ * @param dance
+ */
addAndPlayItem: (dance) => {
const { playlist, playItem } = get();
@@ -71,6 +75,9 @@ export const createPlayListStore: StateCreator<
const index = draftState.findIndex((item) => item.name === dance.name);
if (index === -1) {
draftState.unshift(dance);
+ } else {
+ draftState.splice(index, 1);
+ draftState.unshift(dance);
}
});
@@ -78,13 +85,17 @@ export const createPlayListStore: StateCreator<
playItem(dance);
},
- addPlayItem: (dance) => {
+ /**
+ * Add a dance to the playlist. add to the last.
+ * @param dance
+ */
+ addToPlayList: (dance) => {
const { playlist } = get();
const nextPlayList = produce(playlist, (draftState) => {
const index = draftState.findIndex((item) => item.name === dance.name);
if (index === -1) {
- draftState.unshift(dance);
+ draftState.push(dance);
}
});
diff --git a/src/store/global.ts b/src/store/global.ts
new file mode 100644
index 00000000..3e72a312
--- /dev/null
+++ b/src/store/global.ts
@@ -0,0 +1,31 @@
+import { shallow } from 'zustand/shallow';
+import { createWithEqualityFn } from 'zustand/traditional';
+
+interface GlobalStore {
+ setChatSidebar: (show: boolean) => void;
+ setSessionList: (show: boolean) => void;
+ showChatSidebar: boolean;
+ showSessionList: boolean;
+ toggleChatSideBar: () => void;
+ toggleSessionList: () => void;
+}
+
+export const useGlobalStore = createWithEqualityFn()(
+ (set) => ({
+ setChatSidebar: (show) => {
+ set({ showChatSidebar: show });
+ },
+ toggleChatSideBar: () => {
+ set((state) => ({ showChatSidebar: !state.showChatSidebar }));
+ },
+ showChatSidebar: true,
+ showSessionList: true,
+ setSessionList: (show) => {
+ set({ showSessionList: show });
+ },
+ toggleSessionList: () => {
+ set((state) => ({ showSessionList: !state.showSessionList }));
+ },
+ }),
+ shallow,
+);
diff --git a/src/store/session/index.ts b/src/store/session/index.ts
index 1602dfd0..2110b6df 100644
--- a/src/store/session/index.ts
+++ b/src/store/session/index.ts
@@ -7,6 +7,7 @@ import { shallow } from 'zustand/shallow';
import { createWithEqualityFn } from 'zustand/traditional';
import { StateCreator } from 'zustand/vanilla';
+import { LOBE_VIDOL_DEFAULT_AGENT_ID } from '@/constants/agent';
import { LOADING_FLAG } from '@/constants/common';
import { chatCompletion, handleSpeakAi } from '@/services/chat';
import { Agent } from '@/types/agent';
@@ -48,6 +49,10 @@ export interface SessionStore {
* @returns
*/
createSession: (agent: Agent) => void;
+ /**
+ * 默认会话
+ */
+ defaultSession: Session;
/**
* 删除消息
*/
@@ -351,6 +356,10 @@ export const createSessonStore: StateCreator {
const { sessionList } = get();
+ if (agentId === LOBE_VIDOL_DEFAULT_AGENT_ID) {
+ set({ activeId: agentId });
+ return;
+ }
const targetSession = sessionList.find((session) => session.agentId === agentId);
if (!targetSession) {
const session = {
@@ -386,13 +395,20 @@ export const createSessonStore: StateCreator {
- const { sessionList, activeId } = get();
- const sessions = produce(sessionList, (draft) => {
- const index = draft.findIndex((session) => session.agentId === activeId);
- if (index === -1) return;
- draft[index].messages = messages;
- });
- set({ sessionList: sessions });
+ const { sessionList, activeId, defaultSession } = get();
+ if (activeId === LOBE_VIDOL_DEFAULT_AGENT_ID) {
+ const mergeSession = produce(defaultSession, (draft) => {
+ draft.messages = messages;
+ });
+ set({ defaultSession: mergeSession });
+ } else {
+ const sessions = produce(sessionList, (draft) => {
+ const index = draft.findIndex((session) => session.agentId === activeId);
+ if (index === -1) return;
+ draft[index].messages = messages;
+ });
+ set({ sessionList: sessions });
+ }
},
});
diff --git a/src/store/session/initialState.ts b/src/store/session/initialState.ts
index f969ffaa..4e2f6049 100644
--- a/src/store/session/initialState.ts
+++ b/src/store/session/initialState.ts
@@ -1,17 +1,18 @@
-import { DEFAULT_AGENT, V_CHAT_DEFAULT_AGENT_ID } from '@/constants/agent';
+import { LOBE_VIDOL_DEFAULT_AGENT_ID } from '@/constants/agent';
import { Session } from '@/types/session';
const defaultSession: Session = {
- agentId: V_CHAT_DEFAULT_AGENT_ID,
+ agentId: LOBE_VIDOL_DEFAULT_AGENT_ID,
messages: [],
};
const initialState = {
activeId: defaultSession.agentId,
chatLoadingId: undefined,
- localAgentList: [DEFAULT_AGENT],
+ localAgentList: [],
messageInput: '',
- sessionList: [defaultSession],
+ sessionList: [],
+ defaultSession: defaultSession,
viewerMode: false,
voiceOn: true,
};
diff --git a/src/store/session/selectors.ts b/src/store/session/selectors.ts
index 353c1e6b..3a21f887 100644
--- a/src/store/session/selectors.ts
+++ b/src/store/session/selectors.ts
@@ -1,4 +1,4 @@
-import { V_CHAT_DEFAULT_AGENT_ID } from '@/constants/agent';
+import { DEFAULT_VIDOL_AGENT, LOBE_VIDOL_DEFAULT_AGENT_ID } from '@/constants/agent';
import { DEFAULT_USER_AVATAR } from '@/constants/common';
import { Agent } from '@/types/agent';
import { ChatMessage } from '@/types/chat';
@@ -7,7 +7,10 @@ import { Session } from '@/types/session';
import { SessionStore } from './index';
const currentSession = (s: SessionStore): Session | undefined => {
- const { activeId, sessionList } = s;
+ const { activeId, sessionList, defaultSession } = s;
+ if (activeId === LOBE_VIDOL_DEFAULT_AGENT_ID) {
+ return defaultSession;
+ }
return sessionList.find((item) => item.agentId === activeId);
};
@@ -16,14 +19,11 @@ const sessionListIds = (s: SessionStore): string[] => {
return sessionList.map((item) => item.agentId);
};
-const currentChatIDs = (s: SessionStore): string[] => {
- const session = currentSession(s);
- if (!session) return [];
- return session.messages.map((item) => item.id);
-};
-
const currentAgent = (s: SessionStore): Agent | undefined => {
const { activeId, localAgentList } = s;
+ if (activeId === LOBE_VIDOL_DEFAULT_AGENT_ID) {
+ return DEFAULT_VIDOL_AGENT;
+ }
return localAgentList.find((item) => item.agentId === activeId);
};
@@ -47,6 +47,38 @@ const currentChats = (s: SessionStore): ChatMessage[] => {
});
};
+const currentChatsWithGreetingMessage = (s: SessionStore): ChatMessage[] => {
+ const data = currentChats(s);
+
+ const isBrandNewChat = data.length === 0;
+
+ if (!isBrandNewChat) return data;
+
+ const agent = currentAgent(s);
+
+ const initTime = Date.now();
+
+ const emptyGuideMessage = {
+ content: agent?.greeting || `你好,我是${agent?.meta.name},有什么可以帮助你的吗?`,
+ createdAt: initTime,
+ id: 'default',
+ meta: {
+ avatar: agent?.meta.avatar,
+ title: agent?.meta.name,
+ description: agent?.meta.description,
+ },
+ role: 'assistant',
+ updatedAt: initTime,
+ } as ChatMessage;
+
+ return [emptyGuideMessage];
+};
+
+const currentChatIDsWithGreetingMessage = (s: SessionStore): string[] => {
+ const currentChats = currentChatsWithGreetingMessage(s);
+ return currentChats.map((item) => item.id);
+};
+
const previousChats = (s: SessionStore, id: string): ChatMessage[] => {
const chatList = currentChats(s);
const index = chatList.findIndex((item) => item.id === id);
@@ -87,20 +119,27 @@ const currentChatMessage = (s: SessionStore): ChatMessage | undefined => {
const getAgentById = (s: SessionStore) => {
const { localAgentList } = s;
- return (id: string): Agent | undefined => localAgentList.find((item) => item.agentId === id);
+ return (id: string): Agent | undefined => {
+ if (id === LOBE_VIDOL_DEFAULT_AGENT_ID) {
+ return DEFAULT_VIDOL_AGENT;
+ } else {
+ return localAgentList.find((item) => item.agentId === id);
+ }
+ };
};
const isDefaultAgent = (s: SessionStore) => {
return (id: string): boolean => {
const agent = getAgentById(s)(id);
- return agent?.agentId === V_CHAT_DEFAULT_AGENT_ID;
+ return agent?.agentId === LOBE_VIDOL_DEFAULT_AGENT_ID;
};
};
export const sessionSelectors = {
+ currentChatsWithGreetingMessage,
currentAgent,
currentAgentModel,
- currentChatIDs,
+ currentChatIDsWithGreetingMessage,
isDefaultAgent,
currentChatMessage,
currentChats,
diff --git a/src/types/agent.ts b/src/types/agent.ts
index 1fa31263..b4724f75 100644
--- a/src/types/agent.ts
+++ b/src/types/agent.ts
@@ -1,11 +1,29 @@
import { TouchActionConfig } from './touch';
import { TTS } from './tts';
+/**
+ * Category Enum, 当前包括 Anime, Game, Realistic, VTuber, Book, History, Movie, Animal, Vroid
+ */
+export enum CategoryEnum {
+ ANIMAL = 'Animal',
+ ANIME = 'Anime',
+ BOOK = 'Book',
+ GAME = 'Game',
+ HISTORY = 'History',
+ MOVIE = 'Movie',
+ REALISTIC = 'Realistic',
+ VROID = 'Vroid',
+ VTUBER = 'VTuber',
+}
export interface AgentMeta {
/**
* 头像图片路径
*/
avatar: string;
+ /**
+ * 模型分类
+ */
+ category?: CategoryEnum;
/**
* 封面图片路径
*/
@@ -37,11 +55,26 @@ export interface Agent {
* 角色 ID,为本地文件目录
*/
agentId: string;
+ /**
+ * 作者名
+ */
+ author: string;
+ /**
+ * 创建时间
+ */
+ createAt: string;
+ /**
+ * 问候语,角色在每次聊天开始时说的第一句话
+ */
+ greeting: string;
+ /**
+ * 作者主页
+ */
+ homepage: string;
/**
* 角色元数据
*/
meta: AgentMeta;
-
/**
* 角色设定
*/
diff --git a/src/types/dance.ts b/src/types/dance.ts
index 4f09aa43..805b0028 100644
--- a/src/types/dance.ts
+++ b/src/types/dance.ts
@@ -3,6 +3,10 @@ export interface Dance {
* 音频文件
*/
audio: string;
+ /**
+ * 作者名
+ */
+ author: string;
/**
* 封面图片
*/
@@ -15,6 +19,10 @@ export interface Dance {
* 舞蹈 ID
*/
danceId: string;
+ /**
+ * 作者主页
+ */
+ homepage: string;
/**
* 舞蹈名
*/