mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-10-11 20:43:42 +08:00
Merge branch 'main' of https://github.com/Yidadaa/ChatGPT-Next-Web
This commit is contained in:
@@ -11,6 +11,7 @@ const DANGER_CONFIG = {
|
||||
hideUserApiKey: serverConfig.hideUserApiKey,
|
||||
disableGPT4: serverConfig.disableGPT4,
|
||||
hideBalanceQuery: serverConfig.hideBalanceQuery,
|
||||
disableFastLink: serverConfig.disableFastLink,
|
||||
};
|
||||
|
||||
declare global {
|
||||
|
@@ -12,11 +12,16 @@ import { getClientConfig } from "../config/client";
|
||||
|
||||
export function AuthPage() {
|
||||
const navigate = useNavigate();
|
||||
const access = useAccessStore();
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
const goHome = () => navigate(Path.Home);
|
||||
const goChat = () => navigate(Path.Chat);
|
||||
const resetAccessCode = () => { access.updateCode(""); access.updateToken(""); }; // Reset access code to empty string
|
||||
const resetAccessCode = () => {
|
||||
accessStore.update((access) => {
|
||||
access.token = "";
|
||||
access.accessCode = "";
|
||||
});
|
||||
}; // Reset access code to empty string
|
||||
|
||||
useEffect(() => {
|
||||
if (getClientConfig()?.isApp) {
|
||||
@@ -38,21 +43,25 @@ export function AuthPage() {
|
||||
className={styles["auth-input"]}
|
||||
type="password"
|
||||
placeholder={Locale.Auth.Input}
|
||||
value={access.accessCode}
|
||||
value={accessStore.accessCode}
|
||||
onChange={(e) => {
|
||||
access.updateCode(e.currentTarget.value);
|
||||
accessStore.update(
|
||||
(access) => (access.accessCode = e.currentTarget.value),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{!access.hideUserApiKey ? (
|
||||
{!accessStore.hideUserApiKey ? (
|
||||
<>
|
||||
<div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div>
|
||||
<input
|
||||
className={styles["auth-input"]}
|
||||
type="password"
|
||||
placeholder={Locale.Settings.Token.Placeholder}
|
||||
value={access.token}
|
||||
value={accessStore.token}
|
||||
onChange={(e) => {
|
||||
access.updateToken(e.currentTarget.value);
|
||||
accessStore.update(
|
||||
(access) => (access.token = e.currentTarget.value),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@@ -73,11 +73,10 @@ import {
|
||||
showPrompt,
|
||||
showToast,
|
||||
} from "./ui-lib";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
CHAT_PAGE_SIZE,
|
||||
LAST_INPUT_KEY,
|
||||
MAX_RENDER_MSG_COUNT,
|
||||
Path,
|
||||
REQUEST_TIMEOUT_MS,
|
||||
UNFINISHED_INPUT,
|
||||
@@ -976,14 +975,17 @@ function _Chat() {
|
||||
doSubmit(text);
|
||||
},
|
||||
code: (text) => {
|
||||
if (accessStore.disableFastLink) return;
|
||||
console.log("[Command] got code from url: ", text);
|
||||
showConfirm(Locale.URLCommand.Code + `code = ${text}`).then((res) => {
|
||||
if (res) {
|
||||
accessStore.updateCode(text);
|
||||
accessStore.update((access) => (access.accessCode = text));
|
||||
}
|
||||
});
|
||||
},
|
||||
settings: (text) => {
|
||||
if (accessStore.disableFastLink) return;
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(text) as {
|
||||
key?: string;
|
||||
@@ -999,10 +1001,10 @@ function _Chat() {
|
||||
).then((res) => {
|
||||
if (!res) return;
|
||||
if (payload.key) {
|
||||
accessStore.updateToken(payload.key);
|
||||
accessStore.update((access) => (access.token = payload.key!));
|
||||
}
|
||||
if (payload.url) {
|
||||
accessStore.updateOpenAiUrl(payload.url);
|
||||
accessStore.update((access) => (access.openaiUrl = payload.url!));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -50,7 +50,13 @@ import Locale, {
|
||||
} from "../locales";
|
||||
import { copyToClipboard } from "../utils";
|
||||
import Link from "next/link";
|
||||
import { Path, RELEASE_URL, STORAGE_KEY, UPDATE_URL } from "../constant";
|
||||
import {
|
||||
OPENAI_BASE_URL,
|
||||
Path,
|
||||
RELEASE_URL,
|
||||
STORAGE_KEY,
|
||||
UPDATE_URL,
|
||||
} from "../constant";
|
||||
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
|
||||
import { ErrorBoundary } from "./error";
|
||||
import { InputRange } from "./input-range";
|
||||
@@ -571,13 +577,19 @@ export function Settings() {
|
||||
console.log("[Update] remote version ", updateStore.remoteVersion);
|
||||
}
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
const shouldHideBalanceQuery = useMemo(() => {
|
||||
const isOpenAiUrl = accessStore.openaiUrl.includes(OPENAI_BASE_URL);
|
||||
return accessStore.hideBalanceQuery || isOpenAiUrl;
|
||||
}, [accessStore.hideBalanceQuery, accessStore.openaiUrl]);
|
||||
|
||||
const usage = {
|
||||
used: updateStore.used,
|
||||
subscription: updateStore.subscription,
|
||||
};
|
||||
const [loadingUsage, setLoadingUsage] = useState(false);
|
||||
function checkUsage(force = false) {
|
||||
if (accessStore.hideBalanceQuery) {
|
||||
if (shouldHideBalanceQuery) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,7 +599,6 @@ export function Settings() {
|
||||
});
|
||||
}
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
const enabledAccessControl = useMemo(
|
||||
() => accessStore.enabledAccessControl(),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -877,7 +888,9 @@ export function Settings() {
|
||||
type="text"
|
||||
placeholder={Locale.Settings.AccessCode.Placeholder}
|
||||
onChange={(e) => {
|
||||
accessStore.updateCode(e.currentTarget.value);
|
||||
accessStore.update(
|
||||
(access) => (access.accessCode = e.currentTarget.value),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
@@ -896,7 +909,9 @@ export function Settings() {
|
||||
value={accessStore.openaiUrl}
|
||||
placeholder="https://api.openai.com/"
|
||||
onChange={(e) =>
|
||||
accessStore.updateOpenAiUrl(e.currentTarget.value)
|
||||
accessStore.update(
|
||||
(access) => (access.openaiUrl = e.currentTarget.value),
|
||||
)
|
||||
}
|
||||
></input>
|
||||
</ListItem>
|
||||
@@ -909,14 +924,16 @@ export function Settings() {
|
||||
type="text"
|
||||
placeholder={Locale.Settings.Token.Placeholder}
|
||||
onChange={(e) => {
|
||||
accessStore.updateToken(e.currentTarget.value);
|
||||
accessStore.update(
|
||||
(access) => (access.token = e.currentTarget.value),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</ListItem>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
{!accessStore.hideBalanceQuery ? (
|
||||
{!shouldHideBalanceQuery ? (
|
||||
<ListItem
|
||||
title={Locale.Settings.Usage.Title}
|
||||
subTitle={
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useCallback } from "react";
|
||||
import { useEffect, useRef, useCallback, useMemo } from "react";
|
||||
|
||||
import styles from "./home.module.scss";
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from "../constant";
|
||||
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { useMobileScreen } from "../utils";
|
||||
import { isIOS, useMobileScreen } from "../utils";
|
||||
import dynamic from "next/dynamic";
|
||||
import { showConfirm, showToast } from "./ui-lib";
|
||||
|
||||
@@ -134,6 +134,11 @@ export function SideBar(props: { className?: string }) {
|
||||
const { onDragStart, shouldNarrow } = useDragSideBar();
|
||||
const navigate = useNavigate();
|
||||
const config = useAppConfig();
|
||||
const isMobileScreen = useMobileScreen();
|
||||
const isIOSMobile = useMemo(
|
||||
() => isIOS() && isMobileScreen,
|
||||
[isMobileScreen],
|
||||
);
|
||||
|
||||
useHotKey();
|
||||
|
||||
@@ -142,6 +147,10 @@ export function SideBar(props: { className?: string }) {
|
||||
className={`${styles.sidebar} ${props.className} ${
|
||||
shouldNarrow && styles["narrow-sidebar"]
|
||||
}`}
|
||||
style={{
|
||||
// #3016 disable transition on ios mobile screen
|
||||
transition: isMobileScreen && isIOSMobile ? "none" : undefined,
|
||||
}}
|
||||
>
|
||||
<div className={styles["sidebar-header"]} data-tauri-drag-region>
|
||||
<div className={styles["sidebar-title"]} data-tauri-drag-region>
|
||||
|
@@ -12,7 +12,8 @@ declare global {
|
||||
DISABLE_GPT4?: string; // allow user to use gpt-4 or not
|
||||
BUILD_MODE?: "standalone" | "export";
|
||||
BUILD_APP?: string; // is building desktop app
|
||||
HIDE_BALANCE_QUERY?: string; // allow user to query balance or not
|
||||
ENABLE_BALANCE_QUERY?: string; // allow user to query balance or not
|
||||
DISABLE_FAST_LINK?: string; // disallow parse settings from url or not
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +48,7 @@ export const getServerSideConfig = () => {
|
||||
isVercel: !!process.env.VERCEL,
|
||||
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
||||
disableGPT4: !!process.env.DISABLE_GPT4,
|
||||
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
|
||||
hideBalanceQuery: !process.env.ENABLE_BALANCE_QUERY,
|
||||
disableFastLink: !!process.env.DISABLE_FAST_LINK,
|
||||
};
|
||||
};
|
||||
|
@@ -10,6 +10,7 @@ export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
|
||||
|
||||
export const DEFAULT_CORS_HOST = "https://ab.nextweb.fun";
|
||||
export const DEFAULT_API_HOST = `${DEFAULT_CORS_HOST}/api/proxy`;
|
||||
export const OPENAI_BASE_URL = "https://api.openai.com";
|
||||
|
||||
export enum Path {
|
||||
Home = "/",
|
||||
@@ -69,12 +70,20 @@ export const OpenaiPath = {
|
||||
export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang
|
||||
export const DEFAULT_SYSTEM_TEMPLATE = `
|
||||
You are ChatGPT, a large language model trained by OpenAI.
|
||||
Knowledge cutoff: 2021-09
|
||||
Knowledge cutoff: {{cutoff}}
|
||||
Current model: {{model}}
|
||||
Current time: {{time}}`;
|
||||
Current time: {{time}}
|
||||
`;
|
||||
|
||||
export const SUMMARIZE_MODEL = "gpt-3.5-turbo";
|
||||
|
||||
export const KnowledgeCutOffDate: Record<string, string> = {
|
||||
default: "2021-09",
|
||||
"gpt-3.5-turbo-1106": "2023-04",
|
||||
"gpt-4-1106-preview": "2023-04",
|
||||
"gpt-4-vision-preview": "2023-04",
|
||||
};
|
||||
|
||||
export const DEFAULT_MODELS = [
|
||||
{
|
||||
name: "gpt-4",
|
||||
@@ -100,6 +109,14 @@ export const DEFAULT_MODELS = [
|
||||
name: "gpt-4-32k-0613",
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
name: "gpt-4-1106-preview",
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
name: "gpt-4-vision-preview",
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
name: "gpt-3.5-turbo",
|
||||
available: true,
|
||||
@@ -112,6 +129,10 @@ export const DEFAULT_MODELS = [
|
||||
name: "gpt-3.5-turbo-0613",
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
name: "gpt-3.5-turbo-1106",
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
name: "gpt-3.5-turbo-16k",
|
||||
available: true,
|
||||
|
@@ -16,6 +16,7 @@ const DEFAULT_ACCESS_STATE = {
|
||||
hideUserApiKey: false,
|
||||
hideBalanceQuery: false,
|
||||
disableGPT4: false,
|
||||
disableFastLink: false,
|
||||
|
||||
openaiUrl: DEFAULT_OPENAI_URL,
|
||||
};
|
||||
@@ -29,15 +30,6 @@ export const useAccessStore = createPersistStore(
|
||||
|
||||
return get().needCode;
|
||||
},
|
||||
updateCode(code: string) {
|
||||
set(() => ({ accessCode: code?.trim() }));
|
||||
},
|
||||
updateToken(token: string) {
|
||||
set(() => ({ token: token?.trim() }));
|
||||
},
|
||||
updateOpenAiUrl(url: string) {
|
||||
set(() => ({ openaiUrl: url?.trim() }));
|
||||
},
|
||||
isAuthorized() {
|
||||
this.fetch();
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import { createEmptyMask, Mask } from "./mask";
|
||||
import {
|
||||
DEFAULT_INPUT_TEMPLATE,
|
||||
DEFAULT_SYSTEM_TEMPLATE,
|
||||
KnowledgeCutOffDate,
|
||||
StoreKey,
|
||||
SUMMARIZE_MODEL,
|
||||
} from "../constant";
|
||||
@@ -116,7 +117,11 @@ function countMessages(msgs: ChatMessage[]) {
|
||||
}
|
||||
|
||||
function fillTemplateWith(input: string, modelConfig: ModelConfig) {
|
||||
let cutoff =
|
||||
KnowledgeCutOffDate[modelConfig.model] ?? KnowledgeCutOffDate.default;
|
||||
|
||||
const vars = {
|
||||
cutoff,
|
||||
model: modelConfig.model,
|
||||
time: new Date().toLocaleString(),
|
||||
lang: getLang(),
|
||||
|
@@ -133,7 +133,9 @@ export const useAppConfig = createPersistStore(
|
||||
.customModels.split(",")
|
||||
.filter((v) => !!v && v.length > 0)
|
||||
.map((m) => ({ name: m, available: true }));
|
||||
return get().models.concat(customModels);
|
||||
const allModels = get().models.concat(customModels);
|
||||
allModels.sort((a, b) => (a.name < b.name ? -1 : 1));
|
||||
return allModels;
|
||||
},
|
||||
}),
|
||||
{
|
||||
|
Reference in New Issue
Block a user