mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-11-26 02:36:48 +08:00
Merge branch 'Yidadaa:main' into main
This commit is contained in:
111
app/store/app.ts
111
app/store/app.ts
@@ -7,16 +7,28 @@ import {
|
||||
requestChatStream,
|
||||
requestWithPrompt,
|
||||
} from "../requests";
|
||||
import { trimTopic } from "../utils";
|
||||
import { isMobileScreen, trimTopic } from "../utils";
|
||||
|
||||
import Locale from "../locales";
|
||||
import { showToast } from "../components/ui-lib";
|
||||
|
||||
export type Message = ChatCompletionResponseMessage & {
|
||||
date: string;
|
||||
streaming?: boolean;
|
||||
isError?: boolean;
|
||||
id?: number;
|
||||
};
|
||||
|
||||
export function createMessage(override: Partial<Message>): Message {
|
||||
return {
|
||||
id: Date.now(),
|
||||
date: new Date().toLocaleString(),
|
||||
role: "user",
|
||||
content: "",
|
||||
...override,
|
||||
};
|
||||
}
|
||||
|
||||
export enum SubmitKey {
|
||||
Enter = "Enter",
|
||||
CtrlEnter = "Ctrl + Enter",
|
||||
@@ -149,6 +161,7 @@ export interface ChatStat {
|
||||
export interface ChatSession {
|
||||
id: number;
|
||||
topic: string;
|
||||
sendMemory: boolean;
|
||||
memoryPrompt: string;
|
||||
context: Message[];
|
||||
messages: Message[];
|
||||
@@ -158,11 +171,10 @@ export interface ChatSession {
|
||||
}
|
||||
|
||||
const DEFAULT_TOPIC = Locale.Store.DefaultTopic;
|
||||
export const BOT_HELLO: Message = {
|
||||
export const BOT_HELLO: Message = createMessage({
|
||||
role: "assistant",
|
||||
content: Locale.Store.BotHello,
|
||||
date: "",
|
||||
};
|
||||
});
|
||||
|
||||
function createEmptySession(): ChatSession {
|
||||
const createDate = new Date().toLocaleString();
|
||||
@@ -170,6 +182,7 @@ function createEmptySession(): ChatSession {
|
||||
return {
|
||||
id: Date.now(),
|
||||
topic: DEFAULT_TOPIC,
|
||||
sendMemory: true,
|
||||
memoryPrompt: "",
|
||||
context: [],
|
||||
messages: [],
|
||||
@@ -189,8 +202,10 @@ interface ChatStore {
|
||||
currentSessionIndex: number;
|
||||
clearSessions: () => void;
|
||||
removeSession: (index: number) => void;
|
||||
moveSession: (from: number, to: number) => void;
|
||||
selectSession: (index: number) => void;
|
||||
newSession: () => void;
|
||||
deleteSession: () => void;
|
||||
currentSession: () => ChatSession;
|
||||
onNewMessage: (message: Message) => void;
|
||||
onUserInput: (content: string) => Promise<void>;
|
||||
@@ -202,6 +217,7 @@ interface ChatStore {
|
||||
messageIndex: number,
|
||||
updater: (message?: Message) => void,
|
||||
) => void;
|
||||
resetSession: () => void;
|
||||
getMessagesWithMemory: () => Message[];
|
||||
getMemoryPrompt: () => Message;
|
||||
|
||||
@@ -278,6 +294,31 @@ export const useChatStore = create<ChatStore>()(
|
||||
});
|
||||
},
|
||||
|
||||
moveSession(from: number, to: number) {
|
||||
set((state) => {
|
||||
const { sessions, currentSessionIndex: oldIndex } = state;
|
||||
|
||||
// move the session
|
||||
const newSessions = [...sessions];
|
||||
const session = newSessions[from];
|
||||
newSessions.splice(from, 1);
|
||||
newSessions.splice(to, 0, session);
|
||||
|
||||
// modify current session id
|
||||
let newIndex = oldIndex === from ? to : oldIndex;
|
||||
if (oldIndex > from && oldIndex <= to) {
|
||||
newIndex -= 1;
|
||||
} else if (oldIndex < from && oldIndex >= to) {
|
||||
newIndex += 1;
|
||||
}
|
||||
|
||||
return {
|
||||
currentSessionIndex: newIndex,
|
||||
sessions: newSessions,
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
newSession() {
|
||||
set((state) => ({
|
||||
currentSessionIndex: 0,
|
||||
@@ -285,6 +326,26 @@ export const useChatStore = create<ChatStore>()(
|
||||
}));
|
||||
},
|
||||
|
||||
deleteSession() {
|
||||
const deletedSession = get().currentSession();
|
||||
const index = get().currentSessionIndex;
|
||||
const isLastSession = get().sessions.length === 1;
|
||||
if (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) {
|
||||
get().removeSession(index);
|
||||
}
|
||||
showToast(Locale.Home.DeleteToast, {
|
||||
text: Locale.Home.Revert,
|
||||
onClick() {
|
||||
set((state) => ({
|
||||
sessions: state.sessions
|
||||
.slice(0, index)
|
||||
.concat([deletedSession])
|
||||
.concat(state.sessions.slice(index + Number(isLastSession))),
|
||||
}));
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
currentSession() {
|
||||
let index = get().currentSessionIndex;
|
||||
const sessions = get().sessions;
|
||||
@@ -308,18 +369,15 @@ export const useChatStore = create<ChatStore>()(
|
||||
},
|
||||
|
||||
async onUserInput(content) {
|
||||
const userMessage: Message = {
|
||||
const userMessage: Message = createMessage({
|
||||
role: "user",
|
||||
content,
|
||||
date: new Date().toLocaleString(),
|
||||
};
|
||||
});
|
||||
|
||||
const botMessage: Message = {
|
||||
content: "",
|
||||
const botMessage: Message = createMessage({
|
||||
role: "assistant",
|
||||
date: new Date().toLocaleString(),
|
||||
streaming: true,
|
||||
};
|
||||
});
|
||||
|
||||
// get recent messages
|
||||
const recentMessages = get().getMessagesWithMemory();
|
||||
@@ -342,7 +400,10 @@ export const useChatStore = create<ChatStore>()(
|
||||
botMessage.streaming = false;
|
||||
botMessage.content = content;
|
||||
get().onNewMessage(botMessage);
|
||||
ControllerPool.remove(sessionIndex, messageIndex);
|
||||
ControllerPool.remove(
|
||||
sessionIndex,
|
||||
botMessage.id ?? messageIndex,
|
||||
);
|
||||
} else {
|
||||
botMessage.content = content;
|
||||
set(() => ({}));
|
||||
@@ -358,13 +419,13 @@ export const useChatStore = create<ChatStore>()(
|
||||
userMessage.isError = true;
|
||||
botMessage.isError = true;
|
||||
set(() => ({}));
|
||||
ControllerPool.remove(sessionIndex, messageIndex);
|
||||
ControllerPool.remove(sessionIndex, botMessage.id ?? messageIndex);
|
||||
},
|
||||
onController(controller) {
|
||||
// collect controller for stop/retry
|
||||
ControllerPool.addController(
|
||||
sessionIndex,
|
||||
messageIndex,
|
||||
botMessage.id ?? messageIndex,
|
||||
controller,
|
||||
);
|
||||
},
|
||||
@@ -391,7 +452,11 @@ export const useChatStore = create<ChatStore>()(
|
||||
|
||||
const context = session.context.slice();
|
||||
|
||||
if (session.memoryPrompt && session.memoryPrompt.length > 0) {
|
||||
if (
|
||||
session.sendMemory &&
|
||||
session.memoryPrompt &&
|
||||
session.memoryPrompt.length > 0
|
||||
) {
|
||||
const memoryPrompt = get().getMemoryPrompt();
|
||||
context.push(memoryPrompt);
|
||||
}
|
||||
@@ -415,6 +480,13 @@ export const useChatStore = create<ChatStore>()(
|
||||
set(() => ({ sessions }));
|
||||
},
|
||||
|
||||
resetSession() {
|
||||
get().updateCurrentSession((session) => {
|
||||
session.messages = [];
|
||||
session.memoryPrompt = "";
|
||||
});
|
||||
},
|
||||
|
||||
summarizeSession() {
|
||||
const session = get().currentSession();
|
||||
|
||||
@@ -427,7 +499,8 @@ export const useChatStore = create<ChatStore>()(
|
||||
requestWithPrompt(session.messages, Locale.Store.Prompt.Topic).then(
|
||||
(res) => {
|
||||
get().updateCurrentSession(
|
||||
(session) => (session.topic = trimTopic(res)),
|
||||
(session) =>
|
||||
(session.topic = res ? trimTopic(res) : DEFAULT_TOPIC),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -506,7 +579,7 @@ export const useChatStore = create<ChatStore>()(
|
||||
}),
|
||||
{
|
||||
name: LOCAL_KEY,
|
||||
version: 1.1,
|
||||
version: 1.2,
|
||||
migrate(persistedState, version) {
|
||||
const state = persistedState as ChatStore;
|
||||
|
||||
@@ -514,6 +587,10 @@ export const useChatStore = create<ChatStore>()(
|
||||
state.sessions.forEach((s) => (s.context = []));
|
||||
}
|
||||
|
||||
if (version < 1.2) {
|
||||
state.sessions.forEach((s) => (s.sendMemory = true));
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user