mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-11-17 22:43:42 +08:00
style: eslint 规则同步代码格式
This commit is contained in:
@@ -1,31 +1,31 @@
|
||||
import { getHeaders } from '../client/api';
|
||||
import { getClientConfig } from '../config/client';
|
||||
import {
|
||||
GoogleSafetySettingsThreshold,
|
||||
ServiceProvider,
|
||||
StoreKey,
|
||||
ApiPath,
|
||||
OPENAI_BASE_URL,
|
||||
ALIBABA_BASE_URL,
|
||||
ANTHROPIC_BASE_URL,
|
||||
GEMINI_BASE_URL,
|
||||
ApiPath,
|
||||
BAIDU_BASE_URL,
|
||||
BYTEDANCE_BASE_URL,
|
||||
ALIBABA_BASE_URL,
|
||||
TENCENT_BASE_URL,
|
||||
MOONSHOT_BASE_URL,
|
||||
STABILITY_BASE_URL,
|
||||
IFLYTEK_BASE_URL,
|
||||
XAI_BASE_URL,
|
||||
CHATGLM_BASE_URL,
|
||||
} from "../constant";
|
||||
import { getHeaders } from "../client/api";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import { ensure } from "../utils/clone";
|
||||
import { DEFAULT_CONFIG } from "./config";
|
||||
import { getModelProvider } from "../utils/model";
|
||||
GEMINI_BASE_URL,
|
||||
GoogleSafetySettingsThreshold,
|
||||
IFLYTEK_BASE_URL,
|
||||
MOONSHOT_BASE_URL,
|
||||
OPENAI_BASE_URL,
|
||||
ServiceProvider,
|
||||
STABILITY_BASE_URL,
|
||||
StoreKey,
|
||||
TENCENT_BASE_URL,
|
||||
XAI_BASE_URL,
|
||||
} from '../constant';
|
||||
import { ensure } from '../utils/clone';
|
||||
import { getModelProvider } from '../utils/model';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
import { DEFAULT_CONFIG } from './config';
|
||||
|
||||
let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
|
||||
|
||||
const isApp = getClientConfig()?.buildMode === "export";
|
||||
const isApp = getClientConfig()?.buildMode === 'export';
|
||||
|
||||
const DEFAULT_OPENAI_URL = isApp ? OPENAI_BASE_URL : ApiPath.OpenAI;
|
||||
|
||||
@@ -52,69 +52,69 @@ const DEFAULT_XAI_URL = isApp ? XAI_BASE_URL : ApiPath.XAI;
|
||||
const DEFAULT_CHATGLM_URL = isApp ? CHATGLM_BASE_URL : ApiPath.ChatGLM;
|
||||
|
||||
const DEFAULT_ACCESS_STATE = {
|
||||
accessCode: "",
|
||||
accessCode: '',
|
||||
useCustomConfig: false,
|
||||
|
||||
provider: ServiceProvider.OpenAI,
|
||||
|
||||
// openai
|
||||
openaiUrl: DEFAULT_OPENAI_URL,
|
||||
openaiApiKey: "",
|
||||
openaiApiKey: '',
|
||||
|
||||
// azure
|
||||
azureUrl: "",
|
||||
azureApiKey: "",
|
||||
azureApiVersion: "2023-08-01-preview",
|
||||
azureUrl: '',
|
||||
azureApiKey: '',
|
||||
azureApiVersion: '2023-08-01-preview',
|
||||
|
||||
// google ai studio
|
||||
googleUrl: DEFAULT_GOOGLE_URL,
|
||||
googleApiKey: "",
|
||||
googleApiVersion: "v1",
|
||||
googleApiKey: '',
|
||||
googleApiVersion: 'v1',
|
||||
googleSafetySettings: GoogleSafetySettingsThreshold.BLOCK_ONLY_HIGH,
|
||||
|
||||
// anthropic
|
||||
anthropicUrl: DEFAULT_ANTHROPIC_URL,
|
||||
anthropicApiKey: "",
|
||||
anthropicApiVersion: "2023-06-01",
|
||||
anthropicApiKey: '',
|
||||
anthropicApiVersion: '2023-06-01',
|
||||
|
||||
// baidu
|
||||
baiduUrl: DEFAULT_BAIDU_URL,
|
||||
baiduApiKey: "",
|
||||
baiduSecretKey: "",
|
||||
baiduApiKey: '',
|
||||
baiduSecretKey: '',
|
||||
|
||||
// bytedance
|
||||
bytedanceUrl: DEFAULT_BYTEDANCE_URL,
|
||||
bytedanceApiKey: "",
|
||||
bytedanceApiKey: '',
|
||||
|
||||
// alibaba
|
||||
alibabaUrl: DEFAULT_ALIBABA_URL,
|
||||
alibabaApiKey: "",
|
||||
alibabaApiKey: '',
|
||||
|
||||
// moonshot
|
||||
moonshotUrl: DEFAULT_MOONSHOT_URL,
|
||||
moonshotApiKey: "",
|
||||
moonshotApiKey: '',
|
||||
|
||||
//stability
|
||||
// stability
|
||||
stabilityUrl: DEFAULT_STABILITY_URL,
|
||||
stabilityApiKey: "",
|
||||
stabilityApiKey: '',
|
||||
|
||||
// tencent
|
||||
tencentUrl: DEFAULT_TENCENT_URL,
|
||||
tencentSecretKey: "",
|
||||
tencentSecretId: "",
|
||||
tencentSecretKey: '',
|
||||
tencentSecretId: '',
|
||||
|
||||
// iflytek
|
||||
iflytekUrl: DEFAULT_IFLYTEK_URL,
|
||||
iflytekApiKey: "",
|
||||
iflytekApiSecret: "",
|
||||
iflytekApiKey: '',
|
||||
iflytekApiSecret: '',
|
||||
|
||||
// xai
|
||||
xaiUrl: DEFAULT_XAI_URL,
|
||||
xaiApiKey: "",
|
||||
xaiApiKey: '',
|
||||
|
||||
// chatglm
|
||||
chatglmUrl: DEFAULT_CHATGLM_URL,
|
||||
chatglmApiKey: "",
|
||||
chatglmApiKey: '',
|
||||
|
||||
// server config
|
||||
needCode: true,
|
||||
@@ -122,11 +122,11 @@ const DEFAULT_ACCESS_STATE = {
|
||||
hideBalanceQuery: false,
|
||||
disableGPT4: false,
|
||||
disableFastLink: false,
|
||||
customModels: "",
|
||||
defaultModel: "",
|
||||
customModels: '',
|
||||
defaultModel: '',
|
||||
|
||||
// tts config
|
||||
edgeTTSVoiceName: "zh-CN-YunxiNeural",
|
||||
edgeTTSVoiceName: 'zh-CN-YunxiNeural',
|
||||
};
|
||||
|
||||
export const useAccessStore = createPersistStore(
|
||||
@@ -146,50 +146,50 @@ export const useAccessStore = createPersistStore(
|
||||
},
|
||||
|
||||
isValidOpenAI() {
|
||||
return ensure(get(), ["openaiApiKey"]);
|
||||
return ensure(get(), ['openaiApiKey']);
|
||||
},
|
||||
|
||||
isValidAzure() {
|
||||
return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
|
||||
return ensure(get(), ['azureUrl', 'azureApiKey', 'azureApiVersion']);
|
||||
},
|
||||
|
||||
isValidGoogle() {
|
||||
return ensure(get(), ["googleApiKey"]);
|
||||
return ensure(get(), ['googleApiKey']);
|
||||
},
|
||||
|
||||
isValidAnthropic() {
|
||||
return ensure(get(), ["anthropicApiKey"]);
|
||||
return ensure(get(), ['anthropicApiKey']);
|
||||
},
|
||||
|
||||
isValidBaidu() {
|
||||
return ensure(get(), ["baiduApiKey", "baiduSecretKey"]);
|
||||
return ensure(get(), ['baiduApiKey', 'baiduSecretKey']);
|
||||
},
|
||||
|
||||
isValidByteDance() {
|
||||
return ensure(get(), ["bytedanceApiKey"]);
|
||||
return ensure(get(), ['bytedanceApiKey']);
|
||||
},
|
||||
|
||||
isValidAlibaba() {
|
||||
return ensure(get(), ["alibabaApiKey"]);
|
||||
return ensure(get(), ['alibabaApiKey']);
|
||||
},
|
||||
|
||||
isValidTencent() {
|
||||
return ensure(get(), ["tencentSecretKey", "tencentSecretId"]);
|
||||
return ensure(get(), ['tencentSecretKey', 'tencentSecretId']);
|
||||
},
|
||||
|
||||
isValidMoonshot() {
|
||||
return ensure(get(), ["moonshotApiKey"]);
|
||||
return ensure(get(), ['moonshotApiKey']);
|
||||
},
|
||||
isValidIflytek() {
|
||||
return ensure(get(), ["iflytekApiKey"]);
|
||||
return ensure(get(), ['iflytekApiKey']);
|
||||
},
|
||||
|
||||
isValidXAI() {
|
||||
return ensure(get(), ["xaiApiKey"]);
|
||||
return ensure(get(), ['xaiApiKey']);
|
||||
},
|
||||
|
||||
isValidChatGLM() {
|
||||
return ensure(get(), ["chatglmApiKey"]);
|
||||
return ensure(get(), ['chatglmApiKey']);
|
||||
},
|
||||
|
||||
isAuthorized() {
|
||||
@@ -197,36 +197,37 @@ export const useAccessStore = createPersistStore(
|
||||
|
||||
// has token or has code or disabled access control
|
||||
return (
|
||||
this.isValidOpenAI() ||
|
||||
this.isValidAzure() ||
|
||||
this.isValidGoogle() ||
|
||||
this.isValidAnthropic() ||
|
||||
this.isValidBaidu() ||
|
||||
this.isValidByteDance() ||
|
||||
this.isValidAlibaba() ||
|
||||
this.isValidTencent() ||
|
||||
this.isValidMoonshot() ||
|
||||
this.isValidIflytek() ||
|
||||
this.isValidXAI() ||
|
||||
this.isValidChatGLM() ||
|
||||
!this.enabledAccessControl() ||
|
||||
(this.enabledAccessControl() && ensure(get(), ["accessCode"]))
|
||||
this.isValidOpenAI()
|
||||
|| this.isValidAzure()
|
||||
|| this.isValidGoogle()
|
||||
|| this.isValidAnthropic()
|
||||
|| this.isValidBaidu()
|
||||
|| this.isValidByteDance()
|
||||
|| this.isValidAlibaba()
|
||||
|| this.isValidTencent()
|
||||
|| this.isValidMoonshot()
|
||||
|| this.isValidIflytek()
|
||||
|| this.isValidXAI()
|
||||
|| this.isValidChatGLM()
|
||||
|| !this.enabledAccessControl()
|
||||
|| (this.enabledAccessControl() && ensure(get(), ['accessCode']))
|
||||
);
|
||||
},
|
||||
fetch() {
|
||||
if (fetchState > 0 || getClientConfig()?.buildMode === "export") return;
|
||||
if (fetchState > 0 || getClientConfig()?.buildMode === 'export')
|
||||
{ return; }
|
||||
fetchState = 1;
|
||||
fetch("/api/config", {
|
||||
method: "post",
|
||||
fetch('/api/config', {
|
||||
method: 'post',
|
||||
body: null,
|
||||
headers: {
|
||||
...getHeaders(),
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
const defaultModel = res.defaultModel ?? "";
|
||||
if (defaultModel !== "") {
|
||||
const defaultModel = res.defaultModel ?? '';
|
||||
if (defaultModel !== '') {
|
||||
const [model, providerName] = getModelProvider(defaultModel);
|
||||
DEFAULT_CONFIG.modelConfig.model = model;
|
||||
DEFAULT_CONFIG.modelConfig.providerName = providerName as any;
|
||||
@@ -235,11 +236,11 @@ export const useAccessStore = createPersistStore(
|
||||
return res;
|
||||
})
|
||||
.then((res: DangerConfig) => {
|
||||
console.log("[Config] got config from server", res);
|
||||
console.log('[Config] got config from server', res);
|
||||
set(() => ({ ...res }));
|
||||
})
|
||||
.catch(() => {
|
||||
console.error("[Config] failed to fetch config");
|
||||
console.error('[Config] failed to fetch config');
|
||||
})
|
||||
.finally(() => {
|
||||
fetchState = 2;
|
||||
@@ -258,7 +259,7 @@ export const useAccessStore = createPersistStore(
|
||||
googleApiKey: string;
|
||||
};
|
||||
state.openaiApiKey = state.token;
|
||||
state.azureApiVersion = "2023-08-01-preview";
|
||||
state.azureApiVersion = '2023-08-01-preview';
|
||||
}
|
||||
|
||||
return persistedState as any;
|
||||
|
||||
@@ -1,38 +1,39 @@
|
||||
import { getMessageTextContent, trimTopic } from "../utils";
|
||||
|
||||
import { indexedDBStorage } from "@/app/utils/indexedDB-storage";
|
||||
import { nanoid } from "nanoid";
|
||||
import type {
|
||||
ClientApi,
|
||||
MultimodalContent,
|
||||
RequestMessage,
|
||||
} from "../client/api";
|
||||
import { getClientApi } from "../client/api";
|
||||
import { ChatControllerPool } from "../client/controller";
|
||||
import { showToast } from "../components/ui-lib";
|
||||
} from '../client/api';
|
||||
|
||||
import type { ModelConfig, ModelType } from './config';
|
||||
import type { Mask } from './mask';
|
||||
import { indexedDBStorage } from '@/app/utils/indexedDB-storage';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { getClientApi } from '../client/api';
|
||||
import { ChatControllerPool } from '../client/controller';
|
||||
import { showToast } from '../components/ui-lib';
|
||||
import {
|
||||
DEFAULT_INPUT_TEMPLATE,
|
||||
DEFAULT_MODELS,
|
||||
DEFAULT_SYSTEM_TEMPLATE,
|
||||
GEMINI_SUMMARIZE_MODEL,
|
||||
KnowledgeCutOffDate,
|
||||
ServiceProvider,
|
||||
StoreKey,
|
||||
SUMMARIZE_MODEL,
|
||||
GEMINI_SUMMARIZE_MODEL,
|
||||
ServiceProvider,
|
||||
} from "../constant";
|
||||
import Locale, { getLang } from "../locales";
|
||||
import { isDalle3, safeLocalStorage } from "../utils";
|
||||
import { prettyObject } from "../utils/format";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import { estimateTokenLength } from "../utils/token";
|
||||
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
||||
import { useAccessStore } from "./access";
|
||||
import { collectModelsWithDefaultModel } from "../utils/model";
|
||||
import { createEmptyMask, Mask } from "./mask";
|
||||
} from '../constant';
|
||||
import Locale, { getLang } from '../locales';
|
||||
import { getMessageTextContent, isDalle3, safeLocalStorage, trimTopic } from '../utils';
|
||||
import { prettyObject } from '../utils/format';
|
||||
import { collectModelsWithDefaultModel } from '../utils/model';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
import { estimateTokenLength } from '../utils/token';
|
||||
import { useAccessStore } from './access';
|
||||
import { useAppConfig } from './config';
|
||||
import { createEmptyMask } from './mask';
|
||||
|
||||
const localStorage = safeLocalStorage();
|
||||
|
||||
export type ChatMessageTool = {
|
||||
export interface ChatMessageTool {
|
||||
id: string;
|
||||
index?: number;
|
||||
type?: string;
|
||||
@@ -43,7 +44,7 @@ export type ChatMessageTool = {
|
||||
content?: string;
|
||||
isError?: boolean;
|
||||
errorMsg?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type ChatMessage = RequestMessage & {
|
||||
date: string;
|
||||
@@ -59,8 +60,8 @@ export function createMessage(override: Partial<ChatMessage>): ChatMessage {
|
||||
return {
|
||||
id: nanoid(),
|
||||
date: new Date().toLocaleString(),
|
||||
role: "user",
|
||||
content: "",
|
||||
role: 'user',
|
||||
content: '',
|
||||
...override,
|
||||
};
|
||||
}
|
||||
@@ -87,7 +88,7 @@ export interface ChatSession {
|
||||
|
||||
export const DEFAULT_TOPIC = Locale.Store.DefaultTopic;
|
||||
export const BOT_HELLO: ChatMessage = createMessage({
|
||||
role: "assistant",
|
||||
role: 'assistant',
|
||||
content: Locale.Store.BotHello,
|
||||
});
|
||||
|
||||
@@ -95,7 +96,7 @@ function createEmptySession(): ChatSession {
|
||||
return {
|
||||
id: nanoid(),
|
||||
topic: DEFAULT_TOPIC,
|
||||
memoryPrompt: "",
|
||||
memoryPrompt: '',
|
||||
messages: [],
|
||||
stat: {
|
||||
tokenCount: 0,
|
||||
@@ -114,16 +115,16 @@ function getSummarizeModel(
|
||||
providerName: string,
|
||||
): string[] {
|
||||
// if it is using gpt-* models, force to use 4o-mini to summarize
|
||||
if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) {
|
||||
if (currentModel.startsWith('gpt') || currentModel.startsWith('chatgpt')) {
|
||||
const configStore = useAppConfig.getState();
|
||||
const accessStore = useAccessStore.getState();
|
||||
const allModel = collectModelsWithDefaultModel(
|
||||
configStore.models,
|
||||
[configStore.customModels, accessStore.customModels].join(","),
|
||||
[configStore.customModels, accessStore.customModels].join(','),
|
||||
accessStore.defaultModel,
|
||||
);
|
||||
const summarizeModel = allModel.find(
|
||||
(m) => m.name === SUMMARIZE_MODEL && m.available,
|
||||
m => m.name === SUMMARIZE_MODEL && m.available,
|
||||
);
|
||||
if (summarizeModel) {
|
||||
return [
|
||||
@@ -132,7 +133,7 @@ function getSummarizeModel(
|
||||
];
|
||||
}
|
||||
}
|
||||
if (currentModel.startsWith("gemini")) {
|
||||
if (currentModel.startsWith('gemini')) {
|
||||
return [GEMINI_SUMMARIZE_MODEL, ServiceProvider.Google];
|
||||
}
|
||||
return [currentModel, providerName];
|
||||
@@ -146,12 +147,12 @@ function countMessages(msgs: ChatMessage[]) {
|
||||
}
|
||||
|
||||
function fillTemplateWith(input: string, modelConfig: ModelConfig) {
|
||||
const cutoff =
|
||||
KnowledgeCutOffDate[modelConfig.model] ?? KnowledgeCutOffDate.default;
|
||||
const cutoff
|
||||
= KnowledgeCutOffDate[modelConfig.model] ?? KnowledgeCutOffDate.default;
|
||||
// Find the model in the DEFAULT_MODELS array that matches the modelConfig.model
|
||||
const modelInfo = DEFAULT_MODELS.find((m) => m.name === modelConfig.model);
|
||||
const modelInfo = DEFAULT_MODELS.find(m => m.name === modelConfig.model);
|
||||
|
||||
var serviceProvider = "OpenAI";
|
||||
let serviceProvider = 'OpenAI';
|
||||
if (modelInfo) {
|
||||
// TODO: auto detect the providerName from the modelConfig.model
|
||||
|
||||
@@ -165,24 +166,24 @@ function fillTemplateWith(input: string, modelConfig: ModelConfig) {
|
||||
model: modelConfig.model,
|
||||
time: new Date().toString(),
|
||||
lang: getLang(),
|
||||
input: input,
|
||||
input,
|
||||
};
|
||||
|
||||
let output = modelConfig.template ?? DEFAULT_INPUT_TEMPLATE;
|
||||
|
||||
// remove duplicate
|
||||
if (input.startsWith(output)) {
|
||||
output = "";
|
||||
output = '';
|
||||
}
|
||||
|
||||
// must contains {{input}}
|
||||
const inputVar = "{{input}}";
|
||||
const inputVar = '{{input}}';
|
||||
if (!output.includes(inputVar)) {
|
||||
output += "\n" + inputVar;
|
||||
output += `\n${inputVar}`;
|
||||
}
|
||||
|
||||
Object.entries(vars).forEach(([name, value]) => {
|
||||
const regex = new RegExp(`{{${name}}}`, "g");
|
||||
const regex = new RegExp(`{{${name}}}`, 'g');
|
||||
output = output.replace(regex, value.toString()); // Ensure value is a string
|
||||
});
|
||||
|
||||
@@ -192,7 +193,7 @@ function fillTemplateWith(input: string, modelConfig: ModelConfig) {
|
||||
const DEFAULT_CHAT_STATE = {
|
||||
sessions: [createEmptySession()],
|
||||
currentSessionIndex: 0,
|
||||
lastInput: "",
|
||||
lastInput: '',
|
||||
};
|
||||
|
||||
export const useChatStore = createPersistStore(
|
||||
@@ -209,7 +210,8 @@ export const useChatStore = createPersistStore(
|
||||
forkSession() {
|
||||
// 获取当前会话
|
||||
const currentSession = get().currentSession();
|
||||
if (!currentSession) return;
|
||||
if (!currentSession)
|
||||
{ return; }
|
||||
|
||||
const newSession = createEmptySession();
|
||||
|
||||
@@ -222,7 +224,7 @@ export const useChatStore = createPersistStore(
|
||||
},
|
||||
};
|
||||
|
||||
set((state) => ({
|
||||
set(state => ({
|
||||
currentSessionIndex: 0,
|
||||
sessions: [newSession, ...state.sessions],
|
||||
}));
|
||||
@@ -283,7 +285,7 @@ export const useChatStore = createPersistStore(
|
||||
session.topic = mask.name;
|
||||
}
|
||||
|
||||
set((state) => ({
|
||||
set(state => ({
|
||||
currentSessionIndex: 0,
|
||||
sessions: [session].concat(state.sessions),
|
||||
}));
|
||||
@@ -300,7 +302,8 @@ export const useChatStore = createPersistStore(
|
||||
const deletingLastSession = get().sessions.length === 1;
|
||||
const deletedSession = get().sessions.at(index);
|
||||
|
||||
if (!deletedSession) return;
|
||||
if (!deletedSession)
|
||||
{ return; }
|
||||
|
||||
const sessions = get().sessions.slice();
|
||||
sessions.splice(index, 1);
|
||||
@@ -367,29 +370,29 @@ export const useChatStore = createPersistStore(
|
||||
const modelConfig = session.mask.modelConfig;
|
||||
|
||||
const userContent = fillTemplateWith(content, modelConfig);
|
||||
console.log("[User Input] after template: ", userContent);
|
||||
console.log('[User Input] after template: ', userContent);
|
||||
|
||||
let mContent: string | MultimodalContent[] = userContent;
|
||||
|
||||
if (attachImages && attachImages.length > 0) {
|
||||
mContent = [
|
||||
...(userContent
|
||||
? [{ type: "text" as const, text: userContent }]
|
||||
? [{ type: 'text' as const, text: userContent }]
|
||||
: []),
|
||||
...attachImages.map((url) => ({
|
||||
type: "image_url" as const,
|
||||
...attachImages.map(url => ({
|
||||
type: 'image_url' as const,
|
||||
image_url: { url },
|
||||
})),
|
||||
];
|
||||
}
|
||||
|
||||
let userMessage: ChatMessage = createMessage({
|
||||
role: "user",
|
||||
const userMessage: ChatMessage = createMessage({
|
||||
role: 'user',
|
||||
content: mContent,
|
||||
});
|
||||
|
||||
const botMessage: ChatMessage = createMessage({
|
||||
role: "assistant",
|
||||
role: 'assistant',
|
||||
streaming: true,
|
||||
model: modelConfig.model,
|
||||
});
|
||||
@@ -442,7 +445,7 @@ export const useChatStore = createPersistStore(
|
||||
},
|
||||
onAfterTool(tool: ChatMessageTool) {
|
||||
botMessage?.tools?.forEach((t, i, tools) => {
|
||||
if (tool.id == t.id) {
|
||||
if (tool.id === t.id) {
|
||||
tools[i] = { ...tool };
|
||||
}
|
||||
});
|
||||
@@ -451,13 +454,13 @@ export const useChatStore = createPersistStore(
|
||||
});
|
||||
},
|
||||
onError(error) {
|
||||
const isAborted = error.message?.includes?.("aborted");
|
||||
botMessage.content +=
|
||||
"\n\n" +
|
||||
prettyObject({
|
||||
error: true,
|
||||
message: error.message,
|
||||
});
|
||||
const isAborted = error.message?.includes?.('aborted');
|
||||
botMessage.content
|
||||
+= `\n\n${
|
||||
prettyObject({
|
||||
error: true,
|
||||
message: error.message,
|
||||
})}`;
|
||||
botMessage.streaming = false;
|
||||
userMessage.isError = !isAborted;
|
||||
botMessage.isError = !isAborted;
|
||||
@@ -469,7 +472,7 @@ export const useChatStore = createPersistStore(
|
||||
botMessage.id ?? messageIndex,
|
||||
);
|
||||
|
||||
console.error("[Chat] failed ", error);
|
||||
console.error('[Chat] failed ', error);
|
||||
},
|
||||
onController(controller) {
|
||||
// collect controller for stop/retry
|
||||
@@ -487,9 +490,9 @@ export const useChatStore = createPersistStore(
|
||||
|
||||
if (session.memoryPrompt.length) {
|
||||
return {
|
||||
role: "system",
|
||||
role: 'system',
|
||||
content: Locale.Store.Prompt.History(session.memoryPrompt),
|
||||
date: "",
|
||||
date: '',
|
||||
} as ChatMessage;
|
||||
}
|
||||
},
|
||||
@@ -505,17 +508,17 @@ export const useChatStore = createPersistStore(
|
||||
const contextPrompts = session.mask.context.slice();
|
||||
|
||||
// system prompts, to get close to OpenAI Web ChatGPT
|
||||
const shouldInjectSystemPrompts =
|
||||
modelConfig.enableInjectSystemPrompts &&
|
||||
(session.mask.modelConfig.model.startsWith("gpt-") ||
|
||||
session.mask.modelConfig.model.startsWith("chatgpt-"));
|
||||
const shouldInjectSystemPrompts
|
||||
= modelConfig.enableInjectSystemPrompts
|
||||
&& (session.mask.modelConfig.model.startsWith('gpt-')
|
||||
|| session.mask.modelConfig.model.startsWith('chatgpt-'));
|
||||
|
||||
var systemPrompts: ChatMessage[] = [];
|
||||
let systemPrompts: ChatMessage[] = [];
|
||||
systemPrompts = shouldInjectSystemPrompts
|
||||
? [
|
||||
createMessage({
|
||||
role: "system",
|
||||
content: fillTemplateWith("", {
|
||||
role: 'system',
|
||||
content: fillTemplateWith('', {
|
||||
...modelConfig,
|
||||
template: DEFAULT_SYSTEM_TEMPLATE,
|
||||
}),
|
||||
@@ -524,19 +527,19 @@ export const useChatStore = createPersistStore(
|
||||
: [];
|
||||
if (shouldInjectSystemPrompts) {
|
||||
console.log(
|
||||
"[Global System Prompt] ",
|
||||
systemPrompts.at(0)?.content ?? "empty",
|
||||
'[Global System Prompt] ',
|
||||
systemPrompts.at(0)?.content ?? 'empty',
|
||||
);
|
||||
}
|
||||
const memoryPrompt = get().getMemoryPrompt();
|
||||
// long term memory
|
||||
const shouldSendLongTermMemory =
|
||||
modelConfig.sendMemory &&
|
||||
session.memoryPrompt &&
|
||||
session.memoryPrompt.length > 0 &&
|
||||
session.lastSummarizeIndex > clearContextIndex;
|
||||
const longTermMemoryPrompts =
|
||||
shouldSendLongTermMemory && memoryPrompt ? [memoryPrompt] : [];
|
||||
const shouldSendLongTermMemory
|
||||
= modelConfig.sendMemory
|
||||
&& session.memoryPrompt
|
||||
&& session.memoryPrompt.length > 0
|
||||
&& session.lastSummarizeIndex > clearContextIndex;
|
||||
const longTermMemoryPrompts
|
||||
= shouldSendLongTermMemory && memoryPrompt ? [memoryPrompt] : [];
|
||||
const longTermMemoryStartIndex = session.lastSummarizeIndex;
|
||||
|
||||
// short term memory
|
||||
@@ -566,7 +569,8 @@ export const useChatStore = createPersistStore(
|
||||
i -= 1
|
||||
) {
|
||||
const msg = messages[i];
|
||||
if (!msg || msg.isError) continue;
|
||||
if (!msg || msg.isError)
|
||||
{ continue; }
|
||||
tokenCount += estimateTokenLength(getMessageTextContent(msg));
|
||||
reversedRecentMessages.push(msg);
|
||||
}
|
||||
@@ -596,7 +600,7 @@ export const useChatStore = createPersistStore(
|
||||
resetSession(session: ChatSession) {
|
||||
get().updateTargetSession(session, (session) => {
|
||||
session.messages = [];
|
||||
session.memoryPrompt = "";
|
||||
session.memoryPrompt = '';
|
||||
});
|
||||
},
|
||||
|
||||
@@ -627,10 +631,10 @@ export const useChatStore = createPersistStore(
|
||||
// should summarize topic after chating more than 50 words
|
||||
const SUMMARIZE_MIN_LEN = 50;
|
||||
if (
|
||||
(config.enableAutoGenerateTitle &&
|
||||
session.topic === DEFAULT_TOPIC &&
|
||||
countMessages(messages) >= SUMMARIZE_MIN_LEN) ||
|
||||
refreshTitle
|
||||
(config.enableAutoGenerateTitle
|
||||
&& session.topic === DEFAULT_TOPIC
|
||||
&& countMessages(messages) >= SUMMARIZE_MIN_LEN)
|
||||
|| refreshTitle
|
||||
) {
|
||||
const startIndex = Math.max(
|
||||
0,
|
||||
@@ -643,7 +647,7 @@ export const useChatStore = createPersistStore(
|
||||
)
|
||||
.concat(
|
||||
createMessage({
|
||||
role: "user",
|
||||
role: 'user',
|
||||
content: Locale.Store.Prompt.Topic,
|
||||
}),
|
||||
);
|
||||
@@ -658,9 +662,9 @@ export const useChatStore = createPersistStore(
|
||||
if (responseRes?.status === 200) {
|
||||
get().updateTargetSession(
|
||||
session,
|
||||
(session) =>
|
||||
(session.topic =
|
||||
message.length > 0 ? trimTopic(message) : DEFAULT_TOPIC),
|
||||
session =>
|
||||
(session.topic
|
||||
= message.length > 0 ? trimTopic(message) : DEFAULT_TOPIC),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -671,7 +675,7 @@ export const useChatStore = createPersistStore(
|
||||
session.clearContextIndex ?? 0,
|
||||
);
|
||||
let toBeSummarizedMsgs = messages
|
||||
.filter((msg) => !msg.isError)
|
||||
.filter(msg => !msg.isError)
|
||||
.slice(summarizeIndex);
|
||||
|
||||
const historyMsgLength = countMessages(toBeSummarizedMsgs);
|
||||
@@ -691,26 +695,27 @@ export const useChatStore = createPersistStore(
|
||||
const lastSummarizeIndex = session.messages.length;
|
||||
|
||||
console.log(
|
||||
"[Chat History] ",
|
||||
'[Chat History] ',
|
||||
toBeSummarizedMsgs,
|
||||
historyMsgLength,
|
||||
modelConfig.compressMessageLengthThreshold,
|
||||
);
|
||||
|
||||
if (
|
||||
historyMsgLength > modelConfig.compressMessageLengthThreshold &&
|
||||
modelConfig.sendMemory
|
||||
historyMsgLength > modelConfig.compressMessageLengthThreshold
|
||||
&& modelConfig.sendMemory
|
||||
) {
|
||||
/** Destruct max_tokens while summarizing
|
||||
/**
|
||||
* Destruct max_tokens while summarizing
|
||||
* this param is just shit
|
||||
**/
|
||||
*/
|
||||
const { max_tokens, ...modelcfg } = modelConfig;
|
||||
api.llm.chat({
|
||||
messages: toBeSummarizedMsgs.concat(
|
||||
createMessage({
|
||||
role: "system",
|
||||
role: 'system',
|
||||
content: Locale.Store.Prompt.Summarize,
|
||||
date: "",
|
||||
date: '',
|
||||
}),
|
||||
),
|
||||
config: {
|
||||
@@ -724,7 +729,7 @@ export const useChatStore = createPersistStore(
|
||||
},
|
||||
onFinish(message, responseRes) {
|
||||
if (responseRes?.status === 200) {
|
||||
console.log("[Memory] ", message);
|
||||
console.log('[Memory] ', message);
|
||||
get().updateTargetSession(session, (session) => {
|
||||
session.lastSummarizeIndex = lastSummarizeIndex;
|
||||
session.memoryPrompt = message; // Update the memory prompt for stored it in local storage
|
||||
@@ -732,7 +737,7 @@ export const useChatStore = createPersistStore(
|
||||
}
|
||||
},
|
||||
onError(err) {
|
||||
console.error("[Summarize] ", err);
|
||||
console.error('[Summarize] ', err);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -749,8 +754,9 @@ export const useChatStore = createPersistStore(
|
||||
updater: (session: ChatSession) => void,
|
||||
) {
|
||||
const sessions = get().sessions;
|
||||
const index = sessions.findIndex((s) => s.id === targetSession.id);
|
||||
if (index < 0) return;
|
||||
const index = sessions.findIndex(s => s.id === targetSession.id);
|
||||
if (index < 0)
|
||||
{ return; }
|
||||
updater(sessions[index]);
|
||||
set(() => ({ sessions }));
|
||||
},
|
||||
@@ -796,7 +802,7 @@ export const useChatStore = createPersistStore(
|
||||
// migrate id to nanoid
|
||||
newState.sessions.forEach((s) => {
|
||||
s.id = nanoid();
|
||||
s.messages.forEach((m) => (m.id = nanoid()));
|
||||
s.messages.forEach(m => (m.id = nanoid()));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -806,13 +812,13 @@ export const useChatStore = createPersistStore(
|
||||
newState.sessions.forEach((s) => {
|
||||
if (
|
||||
// Exclude those already set by user
|
||||
!s.mask.modelConfig.hasOwnProperty("enableInjectSystemPrompts")
|
||||
!s.mask.modelConfig.hasOwnProperty('enableInjectSystemPrompts')
|
||||
) {
|
||||
// Because users may have changed this configuration,
|
||||
// the user's current configuration is used instead of the default
|
||||
const config = useAppConfig.getState();
|
||||
s.mask.modelConfig.enableInjectSystemPrompts =
|
||||
config.modelConfig.enableInjectSystemPrompts;
|
||||
s.mask.modelConfig.enableInjectSystemPrompts
|
||||
= config.modelConfig.enableInjectSystemPrompts;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -822,16 +828,16 @@ export const useChatStore = createPersistStore(
|
||||
newState.sessions.forEach((s) => {
|
||||
const config = useAppConfig.getState();
|
||||
s.mask.modelConfig.compressModel = config.modelConfig.compressModel;
|
||||
s.mask.modelConfig.compressProviderName =
|
||||
config.modelConfig.compressProviderName;
|
||||
s.mask.modelConfig.compressProviderName
|
||||
= config.modelConfig.compressProviderName;
|
||||
});
|
||||
}
|
||||
// revert default summarize model for every session
|
||||
if (version < 3.3) {
|
||||
newState.sessions.forEach((s) => {
|
||||
const config = useAppConfig.getState();
|
||||
s.mask.modelConfig.compressModel = "";
|
||||
s.mask.modelConfig.compressProviderName = "";
|
||||
s.mask.modelConfig.compressModel = '';
|
||||
s.mask.modelConfig.compressProviderName = '';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
import { LLMModel } from "../client/api";
|
||||
import { DalleSize, DalleQuality, DalleStyle } from "../typing";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import type { Voice } from 'rt-client';
|
||||
import type { LLMModel } from '../client/api';
|
||||
import type {
|
||||
DEFAULT_TTS_ENGINES,
|
||||
DEFAULT_TTS_MODELS,
|
||||
DEFAULT_TTS_VOICES,
|
||||
ServiceProvider,
|
||||
} from '../constant';
|
||||
import type { DalleQuality, DalleSize, DalleStyle } from '../typing';
|
||||
import { getClientConfig } from '../config/client';
|
||||
import {
|
||||
DEFAULT_INPUT_TEMPLATE,
|
||||
DEFAULT_MODELS,
|
||||
DEFAULT_SIDEBAR_WIDTH,
|
||||
DEFAULT_TTS_ENGINE,
|
||||
DEFAULT_TTS_ENGINES,
|
||||
DEFAULT_TTS_MODEL,
|
||||
DEFAULT_TTS_MODELS,
|
||||
DEFAULT_TTS_VOICE,
|
||||
DEFAULT_TTS_VOICES,
|
||||
StoreKey,
|
||||
ServiceProvider,
|
||||
} from "../constant";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import type { Voice } from "rt-client";
|
||||
} from '../constant';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
|
||||
export type ModelType = (typeof DEFAULT_MODELS)[number]["name"];
|
||||
export type ModelType = (typeof DEFAULT_MODELS)[number]['name'];
|
||||
export type TTSModelType = (typeof DEFAULT_TTS_MODELS)[number];
|
||||
export type TTSVoiceType = (typeof DEFAULT_TTS_VOICES)[number];
|
||||
export type TTSEngineType = (typeof DEFAULT_TTS_ENGINES)[number];
|
||||
|
||||
export enum SubmitKey {
|
||||
Enter = "Enter",
|
||||
CtrlEnter = "Ctrl + Enter",
|
||||
ShiftEnter = "Shift + Enter",
|
||||
AltEnter = "Alt + Enter",
|
||||
MetaEnter = "Meta + Enter",
|
||||
Enter = 'Enter',
|
||||
CtrlEnter = 'Ctrl + Enter',
|
||||
ShiftEnter = 'Shift + Enter',
|
||||
AltEnter = 'Alt + Enter',
|
||||
MetaEnter = 'Meta + Enter',
|
||||
}
|
||||
|
||||
export enum Theme {
|
||||
Auto = "auto",
|
||||
Dark = "dark",
|
||||
Light = "light",
|
||||
Auto = 'auto',
|
||||
Dark = 'dark',
|
||||
Light = 'light',
|
||||
}
|
||||
|
||||
const config = getClientConfig();
|
||||
@@ -42,9 +44,9 @@ export const DEFAULT_CONFIG = {
|
||||
lastUpdate: Date.now(), // timestamp, to merge state
|
||||
|
||||
submitKey: SubmitKey.Enter,
|
||||
avatar: "1f603",
|
||||
avatar: '1f603',
|
||||
fontSize: 14,
|
||||
fontFamily: "",
|
||||
fontFamily: '',
|
||||
theme: Theme.Auto as Theme,
|
||||
tightBorder: !!config?.isApp,
|
||||
sendPreviewBubble: true,
|
||||
@@ -60,12 +62,12 @@ export const DEFAULT_CONFIG = {
|
||||
dontShowMaskSplashScreen: false, // dont show splash screen when create chat
|
||||
hideBuiltinMasks: false, // dont add builtin masks
|
||||
|
||||
customModels: "",
|
||||
customModels: '',
|
||||
models: DEFAULT_MODELS as any as LLMModel[],
|
||||
|
||||
modelConfig: {
|
||||
model: "gpt-4o-mini" as ModelType,
|
||||
providerName: "OpenAI" as ServiceProvider,
|
||||
model: 'gpt-4o-mini' as ModelType,
|
||||
providerName: 'OpenAI' as ServiceProvider,
|
||||
temperature: 0.5,
|
||||
top_p: 1,
|
||||
max_tokens: 4000,
|
||||
@@ -74,13 +76,13 @@ export const DEFAULT_CONFIG = {
|
||||
sendMemory: true,
|
||||
historyMessageCount: 4,
|
||||
compressMessageLengthThreshold: 1000,
|
||||
compressModel: "",
|
||||
compressProviderName: "",
|
||||
compressModel: '',
|
||||
compressProviderName: '',
|
||||
enableInjectSystemPrompts: true,
|
||||
template: config?.template ?? DEFAULT_INPUT_TEMPLATE,
|
||||
size: "1024x1024" as DalleSize,
|
||||
quality: "standard" as DalleQuality,
|
||||
style: "vivid" as DalleStyle,
|
||||
size: '1024x1024' as DalleSize,
|
||||
quality: 'standard' as DalleQuality,
|
||||
style: 'vivid' as DalleStyle,
|
||||
},
|
||||
|
||||
ttsConfig: {
|
||||
@@ -94,23 +96,23 @@ export const DEFAULT_CONFIG = {
|
||||
|
||||
realtimeConfig: {
|
||||
enable: false,
|
||||
provider: "OpenAI" as ServiceProvider,
|
||||
model: "gpt-4o-realtime-preview-2024-10-01",
|
||||
apiKey: "",
|
||||
provider: 'OpenAI' as ServiceProvider,
|
||||
model: 'gpt-4o-realtime-preview-2024-10-01',
|
||||
apiKey: '',
|
||||
azure: {
|
||||
endpoint: "",
|
||||
deployment: "",
|
||||
endpoint: '',
|
||||
deployment: '',
|
||||
},
|
||||
temperature: 0.9,
|
||||
voice: "alloy" as Voice,
|
||||
voice: 'alloy' as Voice,
|
||||
},
|
||||
};
|
||||
|
||||
export type ChatConfig = typeof DEFAULT_CONFIG;
|
||||
|
||||
export type ModelConfig = ChatConfig["modelConfig"];
|
||||
export type TTSConfig = ChatConfig["ttsConfig"];
|
||||
export type RealtimeConfig = ChatConfig["realtimeConfig"];
|
||||
export type ModelConfig = ChatConfig['modelConfig'];
|
||||
export type TTSConfig = ChatConfig['ttsConfig'];
|
||||
export type RealtimeConfig = ChatConfig['realtimeConfig'];
|
||||
|
||||
export function limitNumber(
|
||||
x: number,
|
||||
@@ -199,16 +201,19 @@ export const useAppConfig = createPersistStore(
|
||||
|
||||
merge(persistedState, currentState) {
|
||||
const state = persistedState as ChatConfig | undefined;
|
||||
if (!state) return { ...currentState };
|
||||
if (!state)
|
||||
{ return { ...currentState }; }
|
||||
const models = currentState.models.slice();
|
||||
state.models.forEach((pModel) => {
|
||||
const idx = models.findIndex(
|
||||
(v) => v.name === pModel.name && v.provider === pModel.provider,
|
||||
v => v.name === pModel.name && v.provider === pModel.provider,
|
||||
);
|
||||
if (idx !== -1) models[idx] = pModel;
|
||||
else models.push(pModel);
|
||||
if (idx !== -1)
|
||||
{ models[idx] = pModel; }
|
||||
else { models.push(pModel);
|
||||
}
|
||||
});
|
||||
return { ...currentState, ...state, models: models };
|
||||
return { ...currentState, ...state, models };
|
||||
},
|
||||
|
||||
migrate(persistedState, version) {
|
||||
@@ -226,7 +231,7 @@ export const useAppConfig = createPersistStore(
|
||||
}
|
||||
|
||||
if (version < 3.5) {
|
||||
state.customModels = "claude,claude-100k";
|
||||
state.customModels = 'claude,claude-100k';
|
||||
}
|
||||
|
||||
if (version < 3.6) {
|
||||
@@ -242,17 +247,17 @@ export const useAppConfig = createPersistStore(
|
||||
}
|
||||
|
||||
if (version < 3.9) {
|
||||
state.modelConfig.template =
|
||||
state.modelConfig.template !== DEFAULT_INPUT_TEMPLATE
|
||||
state.modelConfig.template
|
||||
= state.modelConfig.template !== DEFAULT_INPUT_TEMPLATE
|
||||
? state.modelConfig.template
|
||||
: config?.template ?? DEFAULT_INPUT_TEMPLATE;
|
||||
}
|
||||
|
||||
if (version < 4.1) {
|
||||
state.modelConfig.compressModel =
|
||||
DEFAULT_CONFIG.modelConfig.compressModel;
|
||||
state.modelConfig.compressProviderName =
|
||||
DEFAULT_CONFIG.modelConfig.compressProviderName;
|
||||
state.modelConfig.compressModel
|
||||
= DEFAULT_CONFIG.modelConfig.compressModel;
|
||||
state.modelConfig.compressProviderName
|
||||
= DEFAULT_CONFIG.modelConfig.compressProviderName;
|
||||
}
|
||||
|
||||
return state as any;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * from "./chat";
|
||||
export * from "./update";
|
||||
export * from "./access";
|
||||
export * from "./config";
|
||||
export * from "./plugin";
|
||||
export * from './access';
|
||||
export * from './chat';
|
||||
export * from './config';
|
||||
export * from './plugin';
|
||||
export * from './update';
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
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";
|
||||
import type { Lang } from '../locales';
|
||||
import type { ChatMessage } from './chat';
|
||||
import type { ModelConfig } from './config';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { StoreKey } from '../constant';
|
||||
import { getLang } from '../locales';
|
||||
import { BUILTIN_MASKS } from '../masks';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
import { DEFAULT_TOPIC } from './chat';
|
||||
import { useAppConfig } from './config';
|
||||
|
||||
export type Mask = {
|
||||
export interface Mask {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
avatar: string;
|
||||
@@ -20,7 +23,7 @@ export type Mask = {
|
||||
plugin?: string[];
|
||||
enableArtifacts?: boolean;
|
||||
enableCodeFold?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const DEFAULT_MASK_STATE = {
|
||||
masks: {} as Record<string, Mask>,
|
||||
@@ -31,9 +34,9 @@ export type MaskState = typeof DEFAULT_MASK_STATE & {
|
||||
language?: Lang | undefined;
|
||||
};
|
||||
|
||||
export const DEFAULT_MASK_AVATAR = "gpt-bot";
|
||||
export const createEmptyMask = () =>
|
||||
({
|
||||
export const DEFAULT_MASK_AVATAR = 'gpt-bot';
|
||||
export function createEmptyMask() {
|
||||
return ({
|
||||
id: nanoid(),
|
||||
avatar: DEFAULT_MASK_AVATAR,
|
||||
name: DEFAULT_TOPIC,
|
||||
@@ -45,6 +48,7 @@ export const createEmptyMask = () =>
|
||||
createdAt: Date.now(),
|
||||
plugin: [],
|
||||
}) as Mask;
|
||||
}
|
||||
|
||||
export const useMaskStore = createPersistStore(
|
||||
{ ...DEFAULT_MASK_STATE },
|
||||
@@ -68,7 +72,8 @@ export const useMaskStore = createPersistStore(
|
||||
updateMask(id: string, updater: (mask: Mask) => void) {
|
||||
const masks = get().masks;
|
||||
const mask = masks[id];
|
||||
if (!mask) return;
|
||||
if (!mask)
|
||||
{ return; }
|
||||
const updateMask = { ...mask };
|
||||
updater(updateMask);
|
||||
masks[id] = updateMask;
|
||||
@@ -90,9 +95,10 @@ export const useMaskStore = createPersistStore(
|
||||
(a, b) => b.createdAt - a.createdAt,
|
||||
);
|
||||
const config = useAppConfig.getState();
|
||||
if (config.hideBuiltinMasks) return userMasks;
|
||||
if (config.hideBuiltinMasks)
|
||||
{ return userMasks; }
|
||||
const buildinMasks = BUILTIN_MASKS.map(
|
||||
(m) =>
|
||||
m =>
|
||||
({
|
||||
...m,
|
||||
modelConfig: {
|
||||
@@ -121,7 +127,7 @@ export const useMaskStore = createPersistStore(
|
||||
|
||||
// migrate mask id to nanoid
|
||||
if (version < 3) {
|
||||
Object.values(newState.masks).forEach((m) => (m.id = nanoid()));
|
||||
Object.values(newState.masks).forEach(m => (m.id = nanoid()));
|
||||
}
|
||||
|
||||
if (version < 3.1) {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import OpenAPIClientAxios from "openapi-client-axios";
|
||||
import { StoreKey } from "../constant";
|
||||
import { nanoid } from "nanoid";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import yaml from "js-yaml";
|
||||
import { adapter, getOperationId } from "../utils";
|
||||
import { useAccessStore } from "./access";
|
||||
import yaml from 'js-yaml';
|
||||
import { nanoid } from 'nanoid';
|
||||
import OpenAPIClientAxios from 'openapi-client-axios';
|
||||
import { getClientConfig } from '../config/client';
|
||||
import { StoreKey } from '../constant';
|
||||
import { adapter, getOperationId } from '../utils';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
import { useAccessStore } from './access';
|
||||
|
||||
const isApp = getClientConfig()?.isApp !== false;
|
||||
|
||||
export type Plugin = {
|
||||
export interface Plugin {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
title: string;
|
||||
@@ -20,49 +20,50 @@ export type Plugin = {
|
||||
authLocation?: string;
|
||||
authHeader?: string;
|
||||
authToken?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type FunctionToolItem = {
|
||||
export interface FunctionToolItem {
|
||||
type: string;
|
||||
function: {
|
||||
name: string;
|
||||
description?: string;
|
||||
parameters: Object;
|
||||
parameters: object;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
type FunctionToolServiceItem = {
|
||||
interface FunctionToolServiceItem {
|
||||
api: OpenAPIClientAxios;
|
||||
length: number;
|
||||
tools: FunctionToolItem[];
|
||||
funcs: Record<string, Function>;
|
||||
};
|
||||
}
|
||||
|
||||
export const FunctionToolService = {
|
||||
tools: {} as Record<string, FunctionToolServiceItem>,
|
||||
add(plugin: Plugin, replace = false) {
|
||||
if (!replace && this.tools[plugin.id]) return this.tools[plugin.id];
|
||||
if (!replace && this.tools[plugin.id])
|
||||
{ return this.tools[plugin.id]; }
|
||||
const headerName = (
|
||||
plugin?.authType == "custom" ? plugin?.authHeader : "Authorization"
|
||||
plugin?.authType === 'custom' ? plugin?.authHeader : 'Authorization'
|
||||
) as string;
|
||||
const tokenValue =
|
||||
plugin?.authType == "basic"
|
||||
const tokenValue
|
||||
= plugin?.authType === 'basic'
|
||||
? `Basic ${plugin?.authToken}`
|
||||
: plugin?.authType == "bearer"
|
||||
? `Bearer ${plugin?.authToken}`
|
||||
: plugin?.authToken;
|
||||
const authLocation = plugin?.authLocation || "header";
|
||||
: plugin?.authType === 'bearer'
|
||||
? `Bearer ${plugin?.authToken}`
|
||||
: plugin?.authToken;
|
||||
const authLocation = plugin?.authLocation || 'header';
|
||||
const definition = yaml.load(plugin.content) as any;
|
||||
const serverURL = definition?.servers?.[0]?.url;
|
||||
const baseURL = !isApp ? "/api/proxy" : serverURL;
|
||||
const baseURL = !isApp ? '/api/proxy' : serverURL;
|
||||
const headers: Record<string, string | undefined> = {
|
||||
"X-Base-URL": !isApp ? serverURL : undefined,
|
||||
'X-Base-URL': !isApp ? serverURL : undefined,
|
||||
};
|
||||
if (authLocation == "header") {
|
||||
if (authLocation === 'header') {
|
||||
headers[headerName] = tokenValue;
|
||||
}
|
||||
// try using openaiApiKey for Dalle3 Plugin.
|
||||
if (!tokenValue && plugin.id === "dalle3") {
|
||||
if (!tokenValue && plugin.id === 'dalle3') {
|
||||
const openaiApiKey = useAccessStore.getState().openaiApiKey;
|
||||
if (openaiApiKey) {
|
||||
headers[headerName] = `Bearer ${openaiApiKey}`;
|
||||
@@ -71,7 +72,7 @@ export const FunctionToolService = {
|
||||
const api = new OpenAPIClientAxios({
|
||||
definition: yaml.load(plugin.content) as any,
|
||||
axiosConfigDefaults: {
|
||||
adapter: (window.__TAURI__ ? adapter : ["xhr"]) as any,
|
||||
adapter: (window.__TAURI__ ? adapter : ['xhr']) as any,
|
||||
baseURL,
|
||||
headers,
|
||||
},
|
||||
@@ -85,22 +86,22 @@ export const FunctionToolService = {
|
||||
length: operations.length,
|
||||
tools: operations.map((o) => {
|
||||
// @ts-ignore
|
||||
const parameters = o?.requestBody?.content["application/json"]
|
||||
const parameters = o?.requestBody?.content['application/json']
|
||||
?.schema || {
|
||||
type: "object",
|
||||
type: 'object',
|
||||
properties: {},
|
||||
};
|
||||
if (!parameters["required"]) {
|
||||
parameters["required"] = [];
|
||||
if (!parameters.required) {
|
||||
parameters.required = [];
|
||||
}
|
||||
if (o.parameters instanceof Array) {
|
||||
if (Array.isArray(o.parameters)) {
|
||||
o.parameters.forEach((p) => {
|
||||
// @ts-ignore
|
||||
if (p?.in == "query" || p?.in == "path") {
|
||||
if (p?.in === 'query' || p?.in === 'path') {
|
||||
// const name = `${p.in}__${p.name}`
|
||||
// @ts-ignore
|
||||
const name = p?.name;
|
||||
parameters["properties"][name] = {
|
||||
parameters.properties[name] = {
|
||||
// @ts-ignore
|
||||
type: p.schema.type,
|
||||
// @ts-ignore
|
||||
@@ -108,17 +109,17 @@ export const FunctionToolService = {
|
||||
};
|
||||
// @ts-ignore
|
||||
if (p.required) {
|
||||
parameters["required"].push(name);
|
||||
parameters.required.push(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return {
|
||||
type: "function",
|
||||
type: 'function',
|
||||
function: {
|
||||
name: getOperationId(o),
|
||||
description: o.description || o.summary,
|
||||
parameters: parameters,
|
||||
parameters,
|
||||
},
|
||||
} as FunctionToolItem;
|
||||
}),
|
||||
@@ -126,7 +127,7 @@ export const FunctionToolService = {
|
||||
// @ts-ignore
|
||||
s[getOperationId(o)] = function (args) {
|
||||
const parameters: Record<string, any> = {};
|
||||
if (o.parameters instanceof Array) {
|
||||
if (Array.isArray(o.parameters)) {
|
||||
o.parameters.forEach((p) => {
|
||||
// @ts-ignore
|
||||
parameters[p?.name] = args[p?.name];
|
||||
@@ -134,9 +135,9 @@ export const FunctionToolService = {
|
||||
delete args[p?.name];
|
||||
});
|
||||
}
|
||||
if (authLocation == "query") {
|
||||
if (authLocation === 'query') {
|
||||
parameters[headerName] = tokenValue;
|
||||
} else if (authLocation == "body") {
|
||||
} else if (authLocation === 'body') {
|
||||
args[headerName] = tokenValue;
|
||||
}
|
||||
// @ts-ignore if o.operationId is null, then using o.path and o.method
|
||||
@@ -155,15 +156,16 @@ export const FunctionToolService = {
|
||||
},
|
||||
};
|
||||
|
||||
export const createEmptyPlugin = () =>
|
||||
({
|
||||
export function createEmptyPlugin() {
|
||||
return ({
|
||||
id: nanoid(),
|
||||
title: "",
|
||||
version: "1.0.0",
|
||||
content: "",
|
||||
title: '',
|
||||
version: '1.0.0',
|
||||
content: '',
|
||||
builtin: false,
|
||||
createdAt: Date.now(),
|
||||
}) as Plugin;
|
||||
}
|
||||
|
||||
export const DEFAULT_PLUGIN_STATE = {
|
||||
plugins: {} as Record<string, Plugin>,
|
||||
@@ -191,7 +193,8 @@ export const usePluginStore = createPersistStore(
|
||||
updatePlugin(id: string, updater: (plugin: Plugin) => void) {
|
||||
const plugins = get().plugins;
|
||||
const plugin = plugins[id];
|
||||
if (!plugin) return;
|
||||
if (!plugin)
|
||||
{ return; }
|
||||
const updatePlugin = { ...plugin };
|
||||
updater(updatePlugin);
|
||||
plugins[id] = updatePlugin;
|
||||
@@ -209,9 +212,9 @@ export const usePluginStore = createPersistStore(
|
||||
getAsTools(ids: string[]) {
|
||||
const plugins = get().plugins;
|
||||
const selected = (ids || [])
|
||||
.map((id) => plugins[id])
|
||||
.filter((i) => i)
|
||||
.map((p) => FunctionToolService.add(p));
|
||||
.map(id => plugins[id])
|
||||
.filter(i => i)
|
||||
.map(p => FunctionToolService.add(p));
|
||||
return [
|
||||
// @ts-ignore
|
||||
selected.reduce((s, i) => s.concat(i.tools), []),
|
||||
@@ -232,12 +235,12 @@ export const usePluginStore = createPersistStore(
|
||||
version: 1,
|
||||
onRehydrateStorage(state) {
|
||||
// Skip store rehydration on server side
|
||||
if (typeof window === "undefined") {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("./plugins.json")
|
||||
.then((res) => res.json())
|
||||
fetch('./plugins.json')
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
Promise.all(
|
||||
res.map((item: any) =>
|
||||
@@ -245,12 +248,12 @@ export const usePluginStore = createPersistStore(
|
||||
state.get(item.id)
|
||||
? item
|
||||
: fetch(item.schema)
|
||||
.then((res) => res.text())
|
||||
.then((content) => ({
|
||||
.then(res => res.text())
|
||||
.then(content => ({
|
||||
...item,
|
||||
content,
|
||||
}))
|
||||
.catch((e) => item),
|
||||
.catch(e => item),
|
||||
),
|
||||
).then((builtinPlugins: any) => {
|
||||
builtinPlugins
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Fuse from "fuse.js";
|
||||
import { nanoid } from "nanoid";
|
||||
import { StoreKey } from "../constant";
|
||||
import { getLang } from "../locales";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import Fuse from 'fuse.js';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { StoreKey } from '../constant';
|
||||
import { getLang } from '../locales';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
|
||||
export interface Prompt {
|
||||
id: string;
|
||||
@@ -14,8 +14,8 @@ export interface Prompt {
|
||||
|
||||
export const SearchService = {
|
||||
ready: false,
|
||||
builtinEngine: new Fuse<Prompt>([], { keys: ["title"] }),
|
||||
userEngine: new Fuse<Prompt>([], { keys: ["title"] }),
|
||||
builtinEngine: new Fuse<Prompt>([], { keys: ['title'] }),
|
||||
userEngine: new Fuse<Prompt>([], { keys: ['title'] }),
|
||||
count: {
|
||||
builtin: 0,
|
||||
},
|
||||
@@ -34,7 +34,7 @@ export const SearchService = {
|
||||
},
|
||||
|
||||
remove(id: string) {
|
||||
this.userEngine.remove((doc) => doc.id === id);
|
||||
this.userEngine.remove(doc => doc.id === id);
|
||||
},
|
||||
|
||||
add(prompt: Prompt) {
|
||||
@@ -44,7 +44,7 @@ export const SearchService = {
|
||||
search(text: string) {
|
||||
const userResults = this.userEngine.search(text);
|
||||
const builtinResults = this.builtinEngine.search(text);
|
||||
return userResults.concat(builtinResults).map((v) => v.item);
|
||||
return userResults.concat(builtinResults).map(v => v.item);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ export const usePromptStore = createPersistStore(
|
||||
prompts[prompt.id] = prompt;
|
||||
|
||||
set(() => ({
|
||||
prompts: prompts,
|
||||
prompts,
|
||||
}));
|
||||
|
||||
return prompt.id!;
|
||||
@@ -73,7 +73,7 @@ export const usePromptStore = createPersistStore(
|
||||
const targetPrompt = get().prompts[id];
|
||||
|
||||
if (!targetPrompt) {
|
||||
return SearchService.builtinPrompts.find((v) => v.id === id);
|
||||
return SearchService.builtinPrompts.find(v => v.id === id);
|
||||
}
|
||||
|
||||
return targetPrompt;
|
||||
@@ -109,8 +109,8 @@ export const usePromptStore = createPersistStore(
|
||||
|
||||
updatePrompt(id: string, updater: (prompt: Prompt) => void) {
|
||||
const prompt = get().prompts[id] ?? {
|
||||
title: "",
|
||||
content: "",
|
||||
title: '',
|
||||
content: '',
|
||||
id,
|
||||
};
|
||||
|
||||
@@ -140,7 +140,7 @@ export const usePromptStore = createPersistStore(
|
||||
};
|
||||
|
||||
if (version < 3) {
|
||||
Object.values(newState.prompts).forEach((p) => (p.id = nanoid()));
|
||||
Object.values(newState.prompts).forEach(p => (p.id = nanoid()));
|
||||
}
|
||||
|
||||
return newState as any;
|
||||
@@ -148,19 +148,19 @@ export const usePromptStore = createPersistStore(
|
||||
|
||||
onRehydrateStorage(state) {
|
||||
// Skip store rehydration on server side
|
||||
if (typeof window === "undefined") {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const PROMPT_URL = "./prompts.json";
|
||||
const PROMPT_URL = './prompts.json';
|
||||
|
||||
type PromptList = Array<[string, string]>;
|
||||
|
||||
fetch(PROMPT_URL)
|
||||
.then((res) => res.json())
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
let fetchPrompts = [res.en, res.tw, res.cn];
|
||||
if (getLang() === "cn") {
|
||||
if (getLang() === 'cn') {
|
||||
fetchPrompts = fetchPrompts.reverse();
|
||||
}
|
||||
const builtinPrompts = fetchPrompts.map((promptList: PromptList) => {
|
||||
@@ -179,9 +179,9 @@ export const usePromptStore = createPersistStore(
|
||||
|
||||
const allPromptsForSearch = builtinPrompts
|
||||
.reduce((pre, cur) => pre.concat(cur), [])
|
||||
.filter((v) => !!v.title && !!v.content);
|
||||
SearchService.count.builtin =
|
||||
res.en.length + res.cn.length + res.tw.length;
|
||||
.filter(v => !!v.title && !!v.content);
|
||||
SearchService.count.builtin
|
||||
= res.en.length + res.cn.length + res.tw.length;
|
||||
SearchService.init(allPromptsForSearch, userPrompts);
|
||||
});
|
||||
},
|
||||
|
||||
254
app/store/sd.ts
254
app/store/sd.ts
@@ -1,15 +1,15 @@
|
||||
import { getBearerToken } from '@/app/client/api';
|
||||
import { getModelParamBasicData, models } from '@/app/components/sd/sd-panel';
|
||||
import {
|
||||
Stability,
|
||||
StoreKey,
|
||||
ACCESS_CODE_PREFIX,
|
||||
ApiPath,
|
||||
} from "@/app/constant";
|
||||
import { getBearerToken } from "@/app/client/api";
|
||||
import { createPersistStore } from "@/app/utils/store";
|
||||
import { nanoid } from "nanoid";
|
||||
import { uploadImage, base64Image2Blob } from "@/app/utils/chat";
|
||||
import { models, getModelParamBasicData } from "@/app/components/sd/sd-panel";
|
||||
import { useAccessStore } from "./access";
|
||||
Stability,
|
||||
StoreKey,
|
||||
} from '@/app/constant';
|
||||
import { base64Image2Blob, uploadImage } from '@/app/utils/chat';
|
||||
import { createPersistStore } from '@/app/utils/store';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useAccessStore } from './access';
|
||||
|
||||
const defaultModel = {
|
||||
name: models[0].name,
|
||||
@@ -40,124 +40,124 @@ export const useSdStore = createPersistStore<
|
||||
setCurrentParams: (data: any) => void;
|
||||
}
|
||||
>(
|
||||
DEFAULT_SD_STATE,
|
||||
(set, _get) => {
|
||||
function get() {
|
||||
return {
|
||||
..._get(),
|
||||
...methods,
|
||||
};
|
||||
}
|
||||
DEFAULT_SD_STATE,
|
||||
(set, _get) => {
|
||||
function get() {
|
||||
return {
|
||||
..._get(),
|
||||
...methods,
|
||||
};
|
||||
}
|
||||
|
||||
const methods = {
|
||||
getNextId() {
|
||||
const id = ++_get().currentId;
|
||||
set({ currentId: id });
|
||||
return id;
|
||||
},
|
||||
sendTask(data: any, okCall?: Function) {
|
||||
data = { ...data, id: nanoid(), status: "running" };
|
||||
set({ draw: [data, ..._get().draw] });
|
||||
this.getNextId();
|
||||
this.stabilityRequestCall(data);
|
||||
okCall?.();
|
||||
},
|
||||
stabilityRequestCall(data: any) {
|
||||
const accessStore = useAccessStore.getState();
|
||||
let prefix: string = ApiPath.Stability as string;
|
||||
let bearerToken = "";
|
||||
if (accessStore.useCustomConfig) {
|
||||
prefix = accessStore.stabilityUrl || (ApiPath.Stability as string);
|
||||
bearerToken = getBearerToken(accessStore.stabilityApiKey);
|
||||
}
|
||||
if (!bearerToken && accessStore.enabledAccessControl()) {
|
||||
bearerToken = getBearerToken(
|
||||
ACCESS_CODE_PREFIX + accessStore.accessCode,
|
||||
);
|
||||
}
|
||||
const headers = {
|
||||
Accept: "application/json",
|
||||
Authorization: bearerToken,
|
||||
const methods = {
|
||||
getNextId() {
|
||||
const id = ++_get().currentId;
|
||||
set({ currentId: id });
|
||||
return id;
|
||||
},
|
||||
sendTask(data: any, okCall?: Function) {
|
||||
data = { ...data, id: nanoid(), status: 'running' };
|
||||
set({ draw: [data, ..._get().draw] });
|
||||
this.getNextId();
|
||||
this.stabilityRequestCall(data);
|
||||
okCall?.();
|
||||
},
|
||||
stabilityRequestCall(data: any) {
|
||||
const accessStore = useAccessStore.getState();
|
||||
let prefix: string = ApiPath.Stability as string;
|
||||
let bearerToken = '';
|
||||
if (accessStore.useCustomConfig) {
|
||||
prefix = accessStore.stabilityUrl || (ApiPath.Stability as string);
|
||||
bearerToken = getBearerToken(accessStore.stabilityApiKey);
|
||||
}
|
||||
if (!bearerToken && accessStore.enabledAccessControl()) {
|
||||
bearerToken = getBearerToken(
|
||||
ACCESS_CODE_PREFIX + accessStore.accessCode,
|
||||
);
|
||||
}
|
||||
const headers = {
|
||||
Accept: 'application/json',
|
||||
Authorization: bearerToken,
|
||||
};
|
||||
const path = `${prefix}/${Stability.GeneratePath}/${data.model}`;
|
||||
const formData = new FormData();
|
||||
for (const paramsKey in data.params) {
|
||||
formData.append(paramsKey, data.params[paramsKey]);
|
||||
}
|
||||
fetch(path, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: formData,
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then((resData) => {
|
||||
if (resData.errors && resData.errors.length > 0) {
|
||||
this.updateDraw({
|
||||
...data,
|
||||
status: 'error',
|
||||
error: resData.errors[0],
|
||||
});
|
||||
this.getNextId();
|
||||
return;
|
||||
}
|
||||
const self = this;
|
||||
if (resData.finish_reason === 'SUCCESS') {
|
||||
uploadImage(base64Image2Blob(resData.image, 'image/png'))
|
||||
.then((img_data) => {
|
||||
console.debug('uploadImage success', img_data, self);
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: 'success',
|
||||
img_data,
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('uploadImage error', e);
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: 'error',
|
||||
error: JSON.stringify(e),
|
||||
});
|
||||
});
|
||||
} else {
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: 'error',
|
||||
error: JSON.stringify(resData),
|
||||
});
|
||||
}
|
||||
this.getNextId();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.updateDraw({ ...data, status: 'error', error: error.message });
|
||||
console.error('Error:', error);
|
||||
this.getNextId();
|
||||
});
|
||||
},
|
||||
updateDraw(_draw: any) {
|
||||
const draw = _get().draw || [];
|
||||
draw.some((item, index) => {
|
||||
if (item.id === _draw.id) {
|
||||
draw[index] = _draw;
|
||||
set(() => ({ draw }));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
setCurrentModel(model: any) {
|
||||
set({ currentModel: model });
|
||||
},
|
||||
setCurrentParams(data: any) {
|
||||
set({
|
||||
currentParams: data,
|
||||
});
|
||||
},
|
||||
};
|
||||
const path = `${prefix}/${Stability.GeneratePath}/${data.model}`;
|
||||
const formData = new FormData();
|
||||
for (let paramsKey in data.params) {
|
||||
formData.append(paramsKey, data.params[paramsKey]);
|
||||
}
|
||||
fetch(path, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: formData,
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((resData) => {
|
||||
if (resData.errors && resData.errors.length > 0) {
|
||||
this.updateDraw({
|
||||
...data,
|
||||
status: "error",
|
||||
error: resData.errors[0],
|
||||
});
|
||||
this.getNextId();
|
||||
return;
|
||||
}
|
||||
const self = this;
|
||||
if (resData.finish_reason === "SUCCESS") {
|
||||
uploadImage(base64Image2Blob(resData.image, "image/png"))
|
||||
.then((img_data) => {
|
||||
console.debug("uploadImage success", img_data, self);
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: "success",
|
||||
img_data,
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("uploadImage error", e);
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: "error",
|
||||
error: JSON.stringify(e),
|
||||
});
|
||||
});
|
||||
} else {
|
||||
self.updateDraw({
|
||||
...data,
|
||||
status: "error",
|
||||
error: JSON.stringify(resData),
|
||||
});
|
||||
}
|
||||
this.getNextId();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.updateDraw({ ...data, status: "error", error: error.message });
|
||||
console.error("Error:", error);
|
||||
this.getNextId();
|
||||
});
|
||||
},
|
||||
updateDraw(_draw: any) {
|
||||
const draw = _get().draw || [];
|
||||
draw.some((item, index) => {
|
||||
if (item.id === _draw.id) {
|
||||
draw[index] = _draw;
|
||||
set(() => ({ draw }));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
setCurrentModel(model: any) {
|
||||
set({ currentModel: model });
|
||||
},
|
||||
setCurrentParams(data: any) {
|
||||
set({
|
||||
currentParams: data,
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return methods;
|
||||
},
|
||||
{
|
||||
name: StoreKey.SdList,
|
||||
version: 1.0,
|
||||
},
|
||||
);
|
||||
return methods;
|
||||
},
|
||||
{
|
||||
name: StoreKey.SdList,
|
||||
version: 1.0,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { ApiPath, STORAGE_KEY, StoreKey } from "../constant";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import {
|
||||
import type {
|
||||
AppState,
|
||||
getLocalAppState,
|
||||
GetStoreState,
|
||||
} from '../utils/sync';
|
||||
import { showToast } from '../components/ui-lib';
|
||||
import { getClientConfig } from '../config/client';
|
||||
import { ApiPath, STORAGE_KEY, StoreKey } from '../constant';
|
||||
import Locale from '../locales';
|
||||
import { downloadAs, readFromFile } from '../utils';
|
||||
import { createSyncClient, ProviderType } from '../utils/cloud';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
import {
|
||||
getLocalAppState,
|
||||
mergeAppState,
|
||||
setLocalAppState,
|
||||
} from "../utils/sync";
|
||||
import { downloadAs, readFromFile } from "../utils";
|
||||
import { showToast } from "../components/ui-lib";
|
||||
import Locale from "../locales";
|
||||
import { createSyncClient, ProviderType } from "../utils/cloud";
|
||||
} from '../utils/sync';
|
||||
|
||||
export interface WebDavConfig {
|
||||
server: string;
|
||||
@@ -28,19 +30,19 @@ const DEFAULT_SYNC_STATE = {
|
||||
proxyUrl: ApiPath.Cors as string,
|
||||
|
||||
webdav: {
|
||||
endpoint: "",
|
||||
username: "",
|
||||
password: "",
|
||||
endpoint: '',
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
|
||||
upstash: {
|
||||
endpoint: "",
|
||||
endpoint: '',
|
||||
username: STORAGE_KEY,
|
||||
apiKey: "",
|
||||
apiKey: '',
|
||||
},
|
||||
|
||||
lastSyncTime: 0,
|
||||
lastProvider: "",
|
||||
lastProvider: '',
|
||||
};
|
||||
|
||||
export const useSyncStore = createPersistStore(
|
||||
@@ -48,7 +50,7 @@ export const useSyncStore = createPersistStore(
|
||||
(set, get) => ({
|
||||
cloudSync() {
|
||||
const config = get()[get().provider];
|
||||
return Object.values(config).every((c) => c.toString().length > 0);
|
||||
return Object.values(config).every(c => c.toString().length > 0);
|
||||
},
|
||||
|
||||
markSyncTime() {
|
||||
@@ -58,9 +60,9 @@ export const useSyncStore = createPersistStore(
|
||||
export() {
|
||||
const state = getLocalAppState();
|
||||
const datePart = isApp
|
||||
? `${new Date().toLocaleDateString().replace(/\//g, "_")} ${new Date()
|
||||
.toLocaleTimeString()
|
||||
.replace(/:/g, "_")}`
|
||||
? `${new Date().toLocaleDateString().replace(/\//g, '_')} ${new Date()
|
||||
.toLocaleTimeString()
|
||||
.replace(/:/g, '_')}`
|
||||
: new Date().toLocaleString();
|
||||
|
||||
const fileName = `Backup-${datePart}.json`;
|
||||
@@ -77,7 +79,7 @@ export const useSyncStore = createPersistStore(
|
||||
setLocalAppState(localState);
|
||||
location.reload();
|
||||
} catch (e) {
|
||||
console.error("[Import]", e);
|
||||
console.error('[Import]', e);
|
||||
showToast(Locale.Settings.Sync.ImportFailed);
|
||||
}
|
||||
},
|
||||
@@ -96,10 +98,10 @@ export const useSyncStore = createPersistStore(
|
||||
|
||||
try {
|
||||
const remoteState = await client.get(config.username);
|
||||
if (!remoteState || remoteState === "") {
|
||||
if (!remoteState || remoteState === '') {
|
||||
await client.set(config.username, JSON.stringify(localState));
|
||||
console.log(
|
||||
"[Sync] Remote state is empty, using local state instead.",
|
||||
'[Sync] Remote state is empty, using local state instead.',
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
@@ -110,7 +112,7 @@ export const useSyncStore = createPersistStore(
|
||||
setLocalAppState(localState);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("[Sync] failed to get remote state", e);
|
||||
console.log('[Sync] failed to get remote state', e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -137,10 +139,10 @@ export const useSyncStore = createPersistStore(
|
||||
|
||||
if (version < 1.2) {
|
||||
if (
|
||||
(persistedState as typeof DEFAULT_SYNC_STATE).proxyUrl ===
|
||||
"/api/cors/"
|
||||
(persistedState as typeof DEFAULT_SYNC_STATE).proxyUrl
|
||||
=== '/api/cors/'
|
||||
) {
|
||||
newState.proxyUrl = "";
|
||||
newState.proxyUrl = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { ClientApi } from '../client/api';
|
||||
import { getClientConfig } from '../config/client';
|
||||
import {
|
||||
FETCH_COMMIT_URL,
|
||||
FETCH_TAG_URL,
|
||||
ModelProvider,
|
||||
StoreKey,
|
||||
} from "../constant";
|
||||
import { getClientConfig } from "../config/client";
|
||||
import { createPersistStore } from "../utils/store";
|
||||
import { clientUpdate } from "../utils";
|
||||
import ChatGptIcon from "../icons/chatgpt.png";
|
||||
import Locale from "../locales";
|
||||
import { ClientApi } from "../client/api";
|
||||
} from '../constant';
|
||||
import ChatGptIcon from '../icons/chatgpt.png';
|
||||
import Locale from '../locales';
|
||||
import { clientUpdate } from '../utils';
|
||||
import { createPersistStore } from '../utils/store';
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
const isApp = !!getClientConfig()?.isApp;
|
||||
@@ -22,15 +22,15 @@ function formatVersionDate(t: string) {
|
||||
|
||||
return [
|
||||
year.toString(),
|
||||
month.toString().padStart(2, "0"),
|
||||
day.toString().padStart(2, "0"),
|
||||
].join("");
|
||||
month.toString().padStart(2, '0'),
|
||||
day.toString().padStart(2, '0'),
|
||||
].join('');
|
||||
}
|
||||
|
||||
type VersionType = "date" | "tag";
|
||||
type VersionType = 'date' | 'tag';
|
||||
|
||||
async function getVersion(type: VersionType) {
|
||||
if (type === "date") {
|
||||
if (type === 'date') {
|
||||
const data = (await (await fetch(FETCH_COMMIT_URL)).json()) as {
|
||||
commit: {
|
||||
author: { name: string; date: string };
|
||||
@@ -40,7 +40,7 @@ async function getVersion(type: VersionType) {
|
||||
const remoteCommitTime = data[0].commit.author.date;
|
||||
const remoteId = new Date(remoteCommitTime).getTime().toString();
|
||||
return remoteId;
|
||||
} else if (type === "tag") {
|
||||
} else if (type === 'tag') {
|
||||
const data = (await (await fetch(FETCH_TAG_URL)).json()) as {
|
||||
commit: { sha: string; url: string };
|
||||
name: string;
|
||||
@@ -51,10 +51,10 @@ async function getVersion(type: VersionType) {
|
||||
|
||||
export const useUpdateStore = createPersistStore(
|
||||
{
|
||||
versionType: "tag" as VersionType,
|
||||
versionType: 'tag' as VersionType,
|
||||
lastUpdate: 0,
|
||||
version: "unknown",
|
||||
remoteVersion: "",
|
||||
version: 'unknown',
|
||||
remoteVersion: '',
|
||||
used: 0,
|
||||
subscription: 0,
|
||||
|
||||
@@ -62,7 +62,7 @@ export const useUpdateStore = createPersistStore(
|
||||
},
|
||||
(set, get) => ({
|
||||
formatVersion(version: string) {
|
||||
if (get().versionType === "date") {
|
||||
if (get().versionType === 'date') {
|
||||
version = formatVersionDate(version);
|
||||
}
|
||||
return version;
|
||||
@@ -70,15 +70,16 @@ export const useUpdateStore = createPersistStore(
|
||||
|
||||
async getLatestVersion(force = false) {
|
||||
const versionType = get().versionType;
|
||||
let version =
|
||||
versionType === "date"
|
||||
const version
|
||||
= versionType === 'date'
|
||||
? getClientConfig()?.commitDate
|
||||
: getClientConfig()?.version;
|
||||
|
||||
set(() => ({ version }));
|
||||
|
||||
const shouldCheck = Date.now() - get().lastUpdate > 2 * 60 * ONE_MINUTE;
|
||||
if (!force && !shouldCheck) return;
|
||||
if (!force && !shouldCheck)
|
||||
{ return; }
|
||||
|
||||
set(() => ({
|
||||
lastUpdate: Date.now(),
|
||||
@@ -93,32 +94,32 @@ export const useUpdateStore = createPersistStore(
|
||||
// Check if notification permission is granted
|
||||
await window.__TAURI__?.notification
|
||||
.isPermissionGranted()
|
||||
.then((granted) => {
|
||||
.then((granted: any) => {
|
||||
if (!granted) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
// Request permission to show notifications
|
||||
window.__TAURI__?.notification
|
||||
.requestPermission()
|
||||
.then((permission) => {
|
||||
if (permission === "granted") {
|
||||
.then((permission: any) => {
|
||||
if (permission === 'granted') {
|
||||
if (version === remoteId) {
|
||||
// Show a notification using Tauri
|
||||
window.__TAURI__?.notification.sendNotification({
|
||||
title: "NextChat",
|
||||
title: 'NextChat',
|
||||
body: `${Locale.Settings.Update.IsLatest}`,
|
||||
icon: `${ChatGptIcon.src}`,
|
||||
sound: "Default",
|
||||
sound: 'Default',
|
||||
});
|
||||
} else {
|
||||
const updateMessage =
|
||||
Locale.Settings.Update.FoundUpdate(`${remoteId}`);
|
||||
const updateMessage
|
||||
= Locale.Settings.Update.FoundUpdate(`${remoteId}`);
|
||||
// Show a notification for the new version using Tauri
|
||||
window.__TAURI__?.notification.sendNotification({
|
||||
title: "NextChat",
|
||||
title: 'NextChat',
|
||||
body: updateMessage,
|
||||
icon: `${ChatGptIcon.src}`,
|
||||
sound: "Default",
|
||||
sound: 'Default',
|
||||
});
|
||||
clientUpdate();
|
||||
}
|
||||
@@ -127,16 +128,17 @@ export const useUpdateStore = createPersistStore(
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log("[Got Upstream] ", remoteId);
|
||||
console.log('[Got Upstream] ', remoteId);
|
||||
} catch (error) {
|
||||
console.error("[Fetch Upstream Commit Id]", error);
|
||||
console.error('[Fetch Upstream Commit Id]', error);
|
||||
}
|
||||
},
|
||||
|
||||
async updateUsage(force = false) {
|
||||
// only support openai for now
|
||||
const overOneMinute = Date.now() - get().lastUpdateUsage >= ONE_MINUTE;
|
||||
if (!overOneMinute && !force) return;
|
||||
if (!overOneMinute && !force)
|
||||
{ return; }
|
||||
|
||||
set(() => ({
|
||||
lastUpdateUsage: Date.now(),
|
||||
|
||||
Reference in New Issue
Block a user