Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'up/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/store/chat.ts
ahzmr committed Sep 12, 2024
2 parents 9551f5d + 35f77f4 commit 35f5288
Showing 19 changed files with 126 additions and 40 deletions.
4 changes: 3 additions & 1 deletion app/api/openai.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,9 @@ function getModels(remoteModelRes: OpenAIListModelResponse) {

if (config.disableGPT4) {
remoteModelRes.data = remoteModelRes.data.filter(
(m) => !m.id.startsWith("gpt-4") || m.id.startsWith("gpt-4o-mini"),
(m) =>
!(m.id.startsWith("gpt-4") || m.id.startsWith("chatgpt-4o")) ||
m.id.startsWith("gpt-4o-mini"),
);
}

2 changes: 1 addition & 1 deletion app/client/platforms/anthropic.ts
Original file line number Diff line number Diff line change
@@ -203,7 +203,7 @@ export class ClaudeApi implements LLMApi {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin as string[],
useChatStore.getState().currentSession().mask?.plugin || [],
);
return stream(
path,
2 changes: 1 addition & 1 deletion app/client/platforms/moonshot.ts
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ export class MoonshotApi implements LLMApi {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin as string[],
useChatStore.getState().currentSession().mask?.plugin || [],
);
return stream(
chatPath,
6 changes: 4 additions & 2 deletions app/client/platforms/openai.ts
Original file line number Diff line number Diff line change
@@ -244,7 +244,7 @@ export class ChatGPTApi implements LLMApi {
const [tools, funcs] = usePluginStore
.getState()
.getAsTools(
useChatStore.getState().currentSession().mask?.plugin as string[],
useChatStore.getState().currentSession().mask?.plugin || [],
);
// console.log("getAsTools", tools, funcs);
stream(
@@ -407,7 +407,9 @@ export class ChatGPTApi implements LLMApi {
});

const resJson = (await res.json()) as OpenAIListModelResponse;
const chatModels = resJson.data?.filter((m) => m.id.startsWith("gpt-"));
const chatModels = resJson.data?.filter(
(m) => m.id.startsWith("gpt-") || m.id.startsWith("chatgpt-"),
);
console.log("[Models]", chatModels);

if (!chatModels) {
7 changes: 5 additions & 2 deletions app/components/chat.tsx
Original file line number Diff line number Diff line change
@@ -68,6 +68,7 @@ import {
isDalle3,
removeOutdatedEntries,
showPlugins,
safeLocalStorage,
} from "../utils";

import { uploadImage as uploadImageRemote } from "@/app/utils/chat";
@@ -110,6 +111,8 @@ import { getClientConfig } from "../config/client";
import { useAllModels } from "../utils/hooks";
import { MultimodalContent } from "../client/api";

const localStorage = safeLocalStorage();

const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
loading: () => <LoadingIcon />,
});
@@ -943,7 +946,7 @@ function _Chat() {
.onUserInput(userInput, attachImages)
.then(() => setIsLoading(false));
setAttachImages([]);
localStorage.setItem(LAST_INPUT_KEY, userInput);
chatStore.setLastInput(userInput);
setUserInput("");
setPromptHints([]);
if (!isMobileScreen) inputRef.current?.focus();
@@ -1009,7 +1012,7 @@ function _Chat() {
userInput.length <= 0 &&
!(e.metaKey || e.altKey || e.ctrlKey)
) {
setUserInput(localStorage.getItem(LAST_INPUT_KEY) ?? "");
setUserInput(chatStore.lastInput ?? "");
e.preventDefault();
return;
}
3 changes: 2 additions & 1 deletion app/components/emoji.tsx
Original file line number Diff line number Diff line change
@@ -36,7 +36,8 @@ export function Avatar(props: { model?: ModelType; avatar?: string }) {
if (props.model) {
return (
<div className="no-dark">
{props.model?.startsWith("gpt-4") ? (
{props.model?.startsWith("gpt-4") ||
props.model?.startsWith("chatgpt-4o") ? (
<BlackBotIcon className="user-avatar" />
) : (
<BotIcon className="user-avatar" />
4 changes: 2 additions & 2 deletions app/components/error.tsx
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import { ISSUE_URL } from "../constant";
import Locale from "../locales";
import { showConfirm } from "./ui-lib";
import { useSyncStore } from "../store/sync";
import { useChatStore } from "../store/chat";

interface IErrorBoundaryState {
hasError: boolean;
@@ -30,8 +31,7 @@ export class ErrorBoundary extends React.Component<any, IErrorBoundaryState> {
try {
useSyncStore.getState().export();
} finally {
localStorage.clear();
location.reload();
useChatStore.getState().clearAllData();
}
}

3 changes: 2 additions & 1 deletion app/components/markdown.tsx
Original file line number Diff line number Diff line change
@@ -163,7 +163,7 @@ export function PreCode(props: { children: any }) {
);
}

function CustomCode(props: { children: any }) {
function CustomCode(props: { children: any; className?: string }) {
const ref = useRef<HTMLPreElement>(null);
const [collapsed, setCollapsed] = useState(true);
const [showToggle, setShowToggle] = useState(false);
@@ -182,6 +182,7 @@ function CustomCode(props: { children: any }) {
return (
<>
<code
className={props?.className}
ref={ref}
style={{
maxHeight: collapsed ? "400px" : "none",
15 changes: 3 additions & 12 deletions app/components/mask.tsx
Original file line number Diff line number Diff line change
@@ -426,16 +426,7 @@ export function MaskPage() {
const maskStore = useMaskStore();
const chatStore = useChatStore();

const [filterLang, setFilterLang] = useState<Lang | undefined>(
() => localStorage.getItem("Mask-language") as Lang | undefined,
);
useEffect(() => {
if (filterLang) {
localStorage.setItem("Mask-language", filterLang);
} else {
localStorage.removeItem("Mask-language");
}
}, [filterLang]);
const filterLang = maskStore.language;

const allMasks = maskStore
.getAll()
@@ -542,9 +533,9 @@ export function MaskPage() {
onChange={(e) => {
const value = e.currentTarget.value;
if (value === Locale.Settings.Lang.All) {
setFilterLang(undefined);
maskStore.setLanguage(undefined);
} else {
setFilterLang(value as Lang);
maskStore.setLanguage(value as Lang);
}
}}
>
7 changes: 5 additions & 2 deletions app/config/server.ts
Original file line number Diff line number Diff line change
@@ -120,12 +120,15 @@ export const getServerSideConfig = () => {
if (disableGPT4) {
if (customModels) customModels += ",";
customModels += DEFAULT_MODELS.filter(
(m) => m.name.startsWith("gpt-4") && !m.name.startsWith("gpt-4o-mini"),
(m) =>
(m.name.startsWith("gpt-4") || m.name.startsWith("chatgpt-4o")) &&
!m.name.startsWith("gpt-4o-mini"),
)
.map((m) => "-" + m.name)
.join(",");
if (
defaultModel.startsWith("gpt-4") &&
(defaultModel.startsWith("gpt-4") ||
defaultModel.startsWith("chatgpt-4o")) &&
!defaultModel.startsWith("gpt-4o-mini")
)
defaultModel = "";
2 changes: 2 additions & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
@@ -246,6 +246,7 @@ export const KnowledgeCutOffDate: Record<string, string> = {
"gpt-4o": "2023-10",
"gpt-4o-2024-05-13": "2023-10",
"gpt-4o-2024-08-06": "2023-10",
"chatgpt-4o-latest": "2023-10",
"gpt-4o-mini": "2023-10",
"gpt-4o-mini-2024-07-18": "2023-10",
"gpt-4-vision-preview": "2023-04",
@@ -268,6 +269,7 @@ const openaiModels = [
"gpt-4o",
"gpt-4o-2024-05-13",
"gpt-4o-2024-08-06",
"chatgpt-4o-latest",
"gpt-4o-mini",
"gpt-4o-mini-2024-07-18",
"gpt-4-vision-preview",
6 changes: 5 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
@@ -41,7 +41,11 @@ export default function RootLayout({
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link rel="manifest" href="/site.webmanifest"></link>
<link
rel="manifest"
href="/site.webmanifest"
crossOrigin="use-credentials"
></link>
<script src="/serviceWorkerRegister.js" defer></script>
</head>
<body>
13 changes: 5 additions & 8 deletions app/locales/index.ts
Original file line number Diff line number Diff line change
@@ -18,10 +18,13 @@ import ar from "./ar";
import bn from "./bn";
import sk from "./sk";
import { merge } from "../utils/merge";
import { safeLocalStorage } from "@/app/utils";

import type { LocaleType } from "./cn";
export type { LocaleType, PartialLocaleType } from "./cn";

const localStorage = safeLocalStorage();

const ALL_LANGS = {
cn,
en,
@@ -82,17 +85,11 @@ merge(fallbackLang, targetLang);
export default fallbackLang as LocaleType;

function getItem(key: string) {
try {
return localStorage.getItem(key);
} catch {
return null;
}
return localStorage.getItem(key);
}

function setItem(key: string, value: string) {
try {
localStorage.setItem(key, value);
} catch {}
localStorage.setItem(key, value);
}

function getLanguage() {
15 changes: 12 additions & 3 deletions app/store/chat.ts
Original file line number Diff line number Diff line change
@@ -30,10 +30,12 @@ import { nanoid } from "nanoid";
import { createPersistStore } from "../utils/store";
import { collectModelsWithDefaultModel } from "../utils/model";
import { useAccessStore } from "./access";
import { isDalle3, safeLocalStorage } from "../utils";
import { useSyncStore } from "./sync";
import { isDalle3 } from "../utils";
import { indexedDBStorage } from "@/app/utils/indexedDB-storage";

const localStorage = safeLocalStorage();

export type ChatMessageTool = {
id: string;
index?: number;
@@ -113,7 +115,7 @@ function createEmptySession(): ChatSession {

function getSummarizeModel(currentModel: string) {
// if it is using gpt-* models, force to use 4o-mini to summarize
if (currentModel.startsWith("gpt")) {
if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) {
const configStore = useAppConfig.getState();
const accessStore = useAccessStore.getState();
const allModel = collectModelsWithDefaultModel(
@@ -196,6 +198,7 @@ const DEFAULT_CHAT_STATE = {
sessions: [createEmptySession()],
currentSessionIndex: 0,
deletedSessionIds: {} as Record<string, number>,
lastInput: "",
};

export const useChatStore = createPersistStore(
@@ -551,7 +554,8 @@ export const useChatStore = createPersistStore(
// system prompts, to get close to OpenAI Web ChatGPT
const shouldInjectSystemPrompts =
modelConfig.enableInjectSystemPrompts &&
session.mask.modelConfig.model.startsWith("gpt-");
(session.mask.modelConfig.model.startsWith("gpt-") ||
session.mask.modelConfig.model.startsWith("chatgpt-"));

var systemPrompts: ChatMessage[] = [];
systemPrompts = shouldInjectSystemPrompts
@@ -775,6 +779,11 @@ export const useChatStore = createPersistStore(
localStorage.clear();
location.reload();
},
setLastInput(lastInput: string) {
set({
lastInput,
});
},
};

return methods;
10 changes: 9 additions & 1 deletion app/store/mask.ts
Original file line number Diff line number Diff line change
@@ -23,9 +23,12 @@ export type Mask = {

export const DEFAULT_MASK_STATE = {
masks: {} as Record<string, Mask>,
language: undefined as Lang | undefined,
};

export type MaskState = typeof DEFAULT_MASK_STATE;
export type MaskState = typeof DEFAULT_MASK_STATE & {
language?: Lang | undefined;
};

export const DEFAULT_MASK_AVATAR = "gpt-bot";
export const createEmptyMask = () =>
@@ -102,6 +105,11 @@ export const useMaskStore = createPersistStore(
search(text: string) {
return Object.values(get().masks);
},
setLanguage(language: Lang | undefined) {
set({
language,
});
},
}),
{
name: StoreKey.Mask,
2 changes: 1 addition & 1 deletion app/store/plugin.ts
Original file line number Diff line number Diff line change
@@ -199,7 +199,7 @@ export const usePluginStore = createPersistStore(

getAsTools(ids: string[]) {
const plugins = get().plugins;
const selected = ids
const selected = (ids || [])
.map((id) => plugins[id])
.filter((i) => i)
.map((p) => FunctionToolService.add(p));
60 changes: 60 additions & 0 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -331,3 +331,63 @@ export function adapter(config: Record<string, unknown>) {
: path;
return fetch(fetchUrl as string, { ...rest, responseType: "text" });
}

export function safeLocalStorage(): {
getItem: (key: string) => string | null;
setItem: (key: string, value: string) => void;
removeItem: (key: string) => void;
clear: () => void;
} {
let storage: Storage | null;

try {
if (typeof window !== "undefined" && window.localStorage) {
storage = window.localStorage;
} else {
storage = null;
}
} catch (e) {
console.error("localStorage is not available:", e);
storage = null;
}

return {
getItem(key: string): string | null {
if (storage) {
return storage.getItem(key);
} else {
console.warn(
`Attempted to get item "${key}" from localStorage, but localStorage is not available.`,
);
return null;
}
},
setItem(key: string, value: string): void {
if (storage) {
storage.setItem(key, value);
} else {
console.warn(
`Attempted to set item "${key}" in localStorage, but localStorage is not available.`,
);
}
},
removeItem(key: string): void {
if (storage) {
storage.removeItem(key);
} else {
console.warn(
`Attempted to remove item "${key}" from localStorage, but localStorage is not available.`,
);
}
},
clear(): void {
if (storage) {
storage.clear();
} else {
console.warn(
"Attempted to clear localStorage, but localStorage is not available.",
);
}
},
};
}
3 changes: 3 additions & 0 deletions app/utils/indexedDB-storage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { StateStorage } from "zustand/middleware";
import { get, set, del, clear } from "idb-keyval";
import { safeLocalStorage } from "@/app/utils";

const localStorage = safeLocalStorage();

class IndexedDBStorage implements StateStorage {
public async getItem(name: string): Promise<string | null> {
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
},
"package": {
"productName": "NextChat",
"version": "2.14.2"
"version": "2.15.1"
},
"tauri": {
"allowlist": {

0 comments on commit 35f5288

Please sign in to comment.