forked from XiaoMo/ChatGPT-Next-Web
129 lines
3.1 KiB
TypeScript
129 lines
3.1 KiB
TypeScript
import { BUILTIN_MASKS } from "../masks";
|
|
import { getLang, Lang } from "../locales";
|
|
import { DEFAULT_TOPIC, ChatMessage } from "./chat";
|
|
import { ModelConfig, useAppConfig } from "./config";
|
|
import { StoreKey } from "../constant";
|
|
import { nanoid } from "nanoid";
|
|
import { createPersistStore } from "../utils/store";
|
|
|
|
export type Mask = {
|
|
id: string;
|
|
createdAt: number;
|
|
avatar: string;
|
|
name: string;
|
|
hideContext?: boolean;
|
|
context: ChatMessage[];
|
|
syncGlobalConfig?: boolean;
|
|
modelConfig: ModelConfig;
|
|
lang: Lang;
|
|
builtin: boolean;
|
|
};
|
|
|
|
export const DEFAULT_MASK_STATE = {
|
|
masks: {} as Record<string, Mask>,
|
|
};
|
|
|
|
export type MaskState = typeof DEFAULT_MASK_STATE;
|
|
|
|
export const DEFAULT_MASK_AVATAR = "gpt-bot";
|
|
export const createEmptyMask = () =>
|
|
({
|
|
id: nanoid(),
|
|
avatar: DEFAULT_MASK_AVATAR,
|
|
name: DEFAULT_TOPIC,
|
|
context: [],
|
|
syncGlobalConfig: true, // use global config as default
|
|
modelConfig: { ...useAppConfig.getState().modelConfig },
|
|
lang: getLang(),
|
|
builtin: false,
|
|
createdAt: Date.now(),
|
|
}) as Mask;
|
|
|
|
export const useMaskStore = createPersistStore(
|
|
{ ...DEFAULT_MASK_STATE },
|
|
|
|
(set, get) => ({
|
|
...DEFAULT_MASK_STATE,
|
|
|
|
create(mask?: Partial<Mask>) {
|
|
const masks = get().masks;
|
|
const id = nanoid();
|
|
masks[id] = {
|
|
...createEmptyMask(),
|
|
...mask,
|
|
id,
|
|
builtin: false,
|
|
};
|
|
|
|
set(() => ({ masks }));
|
|
get().markUpdate();
|
|
|
|
return masks[id];
|
|
},
|
|
updateMask(id: string, updater: (mask: Mask) => void) {
|
|
const masks = get().masks;
|
|
const mask = masks[id];
|
|
if (!mask) return;
|
|
const updateMask = { ...mask };
|
|
updater(updateMask);
|
|
masks[id] = updateMask;
|
|
set(() => ({ masks }));
|
|
get().markUpdate();
|
|
},
|
|
delete(id: string) {
|
|
const masks = get().masks;
|
|
delete masks[id];
|
|
set(() => ({ masks }));
|
|
get().markUpdate();
|
|
},
|
|
|
|
get(id?: string) {
|
|
return get().masks[id ?? 1145141919810];
|
|
},
|
|
getAll() {
|
|
const userMasks = Object.values(get().masks).sort(
|
|
(a, b) => b.createdAt - a.createdAt,
|
|
);
|
|
const config = useAppConfig.getState();
|
|
if (config.hideBuiltinMasks) return userMasks;
|
|
const buildinMasks = BUILTIN_MASKS.map(
|
|
(m) =>
|
|
({
|
|
...m,
|
|
modelConfig: {
|
|
...config.modelConfig,
|
|
...m.modelConfig,
|
|
},
|
|
}) as Mask,
|
|
);
|
|
return userMasks.concat(buildinMasks);
|
|
},
|
|
search(text: string) {
|
|
return Object.values(get().masks);
|
|
},
|
|
}),
|
|
{
|
|
name: StoreKey.Mask,
|
|
version: 3.1,
|
|
|
|
migrate(state, version) {
|
|
const newState = JSON.parse(JSON.stringify(state)) as MaskState;
|
|
|
|
// migrate mask id to nanoid
|
|
if (version < 3) {
|
|
Object.values(newState.masks).forEach((m) => (m.id = nanoid()));
|
|
}
|
|
|
|
if (version < 3.1) {
|
|
const updatedMasks: Record<string, Mask> = {};
|
|
Object.values(newState.masks).forEach((m) => {
|
|
updatedMasks[m.id] = m;
|
|
});
|
|
newState.masks = updatedMasks;
|
|
}
|
|
|
|
return newState as any;
|
|
},
|
|
},
|
|
);
|