mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-09-03 22:06:54 +08:00
Compare commits
107 Commits
v2.8.4
...
suggestion
Author | SHA1 | Date | |
---|---|---|---|
|
f75b238ebe | ||
|
b55b01cb13 | ||
|
90d8f3117f | ||
|
c7e976c8c5 | ||
|
6014b765f4 | ||
|
ca295588c4 | ||
|
3432d4df29 | ||
|
05fcb96181 | ||
|
6bb27f90a4 | ||
|
c10e8382a9 | ||
|
6653a31eb7 | ||
|
42561d04de | ||
|
9a285ab935 | ||
|
81771568be | ||
|
795b43f174 | ||
|
52203b50eb | ||
|
0373b2c9dd | ||
|
fe2c1c4ec6 | ||
|
596b6542e8 | ||
|
6897bf1254 | ||
|
8a6a13e583 | ||
|
b718285125 | ||
|
e5ab918ef9 | ||
|
6c6a2d08db | ||
|
9e6617e3ca | ||
|
94a50f92e1 | ||
|
5c8be2a8f6 | ||
|
1dcf2d80b4 | ||
|
1197521921 | ||
|
3863cfe786 | ||
|
54bd07702c | ||
|
a75e2b0c0e | ||
|
29fd9b23fe | ||
|
089e3b8946 | ||
|
9c36fcec81 | ||
|
74fa065266 | ||
|
38f2495cf6 | ||
|
4131fccbe0 | ||
|
f2d748cfe4 | ||
|
197ec0c29c | ||
|
0a2af9335c | ||
|
a52fa28ed1 | ||
|
78ed24dbf6 | ||
|
cda074fe24 | ||
|
823032617d | ||
|
5963459499 | ||
|
0bc2c71b0c | ||
|
b4e350e189 | ||
|
941e46490f | ||
|
4df92e903a | ||
|
6ba02d0d50 | ||
|
2dc122831b | ||
|
f3f84e523a | ||
|
0cdee25b5b | ||
|
92b0314c14 | ||
|
ad2bc7da96 | ||
|
d8b606dc83 | ||
|
5ce53dbcf4 | ||
|
c5c1a9ab3c | ||
|
564709aa98 | ||
|
475158a145 | ||
|
829df56733 | ||
|
ee55f8790e | ||
|
6d19fb3909 | ||
|
9057712c8f | ||
|
5d6e7de667 | ||
|
8f6f70879c | ||
|
3120087992 | ||
|
0ec4cc223f | ||
|
60c7be31b6 | ||
|
2388f853c9 | ||
|
1e8d4763bb | ||
|
be4834688d | ||
|
3937dad6a6 | ||
|
463251dcc1 | ||
|
3adca26808 | ||
|
97a8bb52d6 | ||
|
7748a980f9 | ||
|
b044e274aa | ||
|
6c3d4a11cc | ||
|
98afd5516b | ||
|
ea6926cad3 | ||
|
3298961748 | ||
|
0140f771c6 | ||
|
64c4f512ce | ||
|
5b1d45c1a9 | ||
|
efbd1c15a9 | ||
|
bce74890dc | ||
|
eb93a43d13 | ||
|
1dd75b63de | ||
|
6caf79121b | ||
|
5cdd34a388 | ||
|
38c8ee8cd2 | ||
|
d5c33a1183 | ||
|
058e28911a | ||
|
25a3bb351d | ||
|
1607640bed | ||
|
5f0cda829f | ||
|
b003a374b8 | ||
|
5f7c262759 | ||
|
f3ab6b27c9 | ||
|
d62eb56886 | ||
|
c2724c6aad | ||
|
0cde1683b6 | ||
|
128f596f93 | ||
|
27fae8eed0 | ||
|
82ec4474c2 |
27
.github/workflows/app.yml
vendored
27
.github/workflows/app.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
create-release:
|
create-release:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
release_id: ${{ steps.create-release.outputs.result }}
|
release_id: ${{ steps.create-release.outputs.result }}
|
||||||
|
|
||||||
@@ -39,9 +39,21 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
platform: [macos-latest, ubuntu-20.04, windows-latest]
|
config:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
arch: x86_64
|
||||||
|
rust_target: x86_64-unknown-linux-gnu
|
||||||
|
- os: macos-latest
|
||||||
|
arch: x86_64
|
||||||
|
rust_target: x86_64-apple-darwin
|
||||||
|
- os: macos-latest
|
||||||
|
arch: aarch64
|
||||||
|
rust_target: aarch64-apple-darwin
|
||||||
|
- os: windows-latest
|
||||||
|
arch: x86_64
|
||||||
|
rust_target: x86_64-pc-windows-msvc
|
||||||
|
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.config.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: setup node
|
- name: setup node
|
||||||
@@ -50,8 +62,13 @@ jobs:
|
|||||||
node-version: 16
|
node-version: 16
|
||||||
- name: install Rust stable
|
- name: install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: ${{ matrix.config.rust_target }}
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
key: ${{ matrix.config.rust_target }}
|
||||||
- name: install dependencies (ubuntu only)
|
- name: install dependencies (ubuntu only)
|
||||||
if: matrix.platform == 'ubuntu-20.04'
|
if: matrix.config.os == 'ubuntu-latest'
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
|
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
|
||||||
@@ -68,7 +85,7 @@ jobs:
|
|||||||
publish-release:
|
publish-release:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
needs: [create-release, build-tauri]
|
needs: [create-release, build-tauri]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@@ -84,7 +84,7 @@ One-Click to get well-designed cross-platform ChatGPT web UI.
|
|||||||
- [x] 预制角色:使用预制角色快速定制新对话 [#993](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/993)
|
- [x] 预制角色:使用预制角色快速定制新对话 [#993](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/993)
|
||||||
- [x] 分享为图片,分享到 ShareGPT 链接 [#1741](https://github.com/Yidadaa/ChatGPT-Next-Web/pull/1741)
|
- [x] 分享为图片,分享到 ShareGPT 链接 [#1741](https://github.com/Yidadaa/ChatGPT-Next-Web/pull/1741)
|
||||||
- [x] 使用 tauri 打包桌面应用
|
- [x] 使用 tauri 打包桌面应用
|
||||||
- [x] 支持自部署的大语言模型:开箱即用 [RWKV-Runner](https://github.com/josStorer/RWKV-Runner) ,服务端部署 [LocalAI 项目](https://github.com/go-skynet/LocalAI) llama / gpt4all / rwkv / vicuna / koala / gpt4all-j / cerebras / falcon / dolly 等等
|
- [x] 支持自部署的大语言模型:开箱即用 [RWKV-Runner](https://github.com/josStorer/RWKV-Runner) ,服务端部署 [LocalAI 项目](https://github.com/go-skynet/LocalAI) llama / gpt4all / rwkv / vicuna / koala / gpt4all-j / cerebras / falcon / dolly 等等,或者使用 [api-for-open-llm](https://github.com/xusenlinzy/api-for-open-llm)
|
||||||
- [ ] 插件机制,支持联网搜索、计算器、调用其他平台 api [#165](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/165)
|
- [ ] 插件机制,支持联网搜索、计算器、调用其他平台 api [#165](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/165)
|
||||||
|
|
||||||
## 最新动态
|
## 最新动态
|
||||||
@@ -263,6 +263,10 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Translation
|
||||||
|
|
||||||
|
If you want to add a new translation, read this [document](./docs/translation.md).
|
||||||
|
|
||||||
## Donation
|
## Donation
|
||||||
|
|
||||||
[Buy Me a Coffee](https://www.buymeacoffee.com/yidadaa)
|
[Buy Me a Coffee](https://www.buymeacoffee.com/yidadaa)
|
||||||
@@ -294,6 +298,7 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s
|
|||||||
[@Sha1rholder](https://github.com/Sha1rholder)
|
[@Sha1rholder](https://github.com/Sha1rholder)
|
||||||
[@AnsonHyq](https://github.com/AnsonHyq)
|
[@AnsonHyq](https://github.com/AnsonHyq)
|
||||||
[@synwith](https://github.com/synwith)
|
[@synwith](https://github.com/synwith)
|
||||||
|
[@piksonGit](https://github.com/piksonGit)
|
||||||
|
|
||||||
### Contributor
|
### Contributor
|
||||||
|
|
||||||
|
@@ -121,7 +121,7 @@ BASE_URL=https://chatgpt1.nextweb.fun/api/proxy
|
|||||||
|
|
||||||
1. 安装 nodejs 18 和 yarn,具体细节请询问 ChatGPT;
|
1. 安装 nodejs 18 和 yarn,具体细节请询问 ChatGPT;
|
||||||
2. 执行 `yarn install && yarn dev` 即可。⚠️ 注意:此命令仅用于本地开发,不要用于部署!
|
2. 执行 `yarn install && yarn dev` 即可。⚠️ 注意:此命令仅用于本地开发,不要用于部署!
|
||||||
3. 如果你想本地部署,请使用 `yarn install && yarn start` 命令,你可以配合 pm2 来守护进程,防止被杀死,详情询问 ChatGPT。
|
3. 如果你想本地部署,请使用 `yarn install && yarn build && yarn start` 命令,你可以配合 pm2 来守护进程,防止被杀死,详情询问 ChatGPT。
|
||||||
|
|
||||||
## 部署
|
## 部署
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ const serverConfig = getServerSideConfig();
|
|||||||
const DANGER_CONFIG = {
|
const DANGER_CONFIG = {
|
||||||
needCode: serverConfig.needCode,
|
needCode: serverConfig.needCode,
|
||||||
hideUserApiKey: serverConfig.hideUserApiKey,
|
hideUserApiKey: serverConfig.hideUserApiKey,
|
||||||
enableGPT4: serverConfig.enableGPT4,
|
disableGPT4: serverConfig.disableGPT4,
|
||||||
hideBalanceQuery: serverConfig.hideBalanceQuery,
|
hideBalanceQuery: serverConfig.hideBalanceQuery,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import { type OpenAIListModelResponse } from "@/app/client/platforms/openai";
|
||||||
|
import { getServerSideConfig } from "@/app/config/server";
|
||||||
import { OpenaiPath } from "@/app/constant";
|
import { OpenaiPath } from "@/app/constant";
|
||||||
import { prettyObject } from "@/app/utils/format";
|
import { prettyObject } from "@/app/utils/format";
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
@@ -6,6 +8,18 @@ import { requestOpenai } from "../../common";
|
|||||||
|
|
||||||
const ALLOWD_PATH = new Set(Object.values(OpenaiPath));
|
const ALLOWD_PATH = new Set(Object.values(OpenaiPath));
|
||||||
|
|
||||||
|
function getModels(remoteModelRes: OpenAIListModelResponse) {
|
||||||
|
const config = getServerSideConfig();
|
||||||
|
|
||||||
|
if (config.disableGPT4) {
|
||||||
|
remoteModelRes.data = remoteModelRes.data.filter(
|
||||||
|
(m) => !m.id.startsWith("gpt-4"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return remoteModelRes;
|
||||||
|
}
|
||||||
|
|
||||||
async function handle(
|
async function handle(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
{ params }: { params: { path: string[] } },
|
{ params }: { params: { path: string[] } },
|
||||||
@@ -39,7 +53,18 @@ async function handle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await requestOpenai(req);
|
const response = await requestOpenai(req);
|
||||||
|
|
||||||
|
// list models
|
||||||
|
if (subpath === OpenaiPath.ListModelPath && response.status === 200) {
|
||||||
|
const resJson = (await response.json()) as OpenAIListModelResponse;
|
||||||
|
const availableModels = getModels(resJson);
|
||||||
|
return NextResponse.json(availableModels, {
|
||||||
|
status: response.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[OpenAI] ", e);
|
console.error("[OpenAI] ", e);
|
||||||
return NextResponse.json(prettyObject(e));
|
return NextResponse.json(prettyObject(e));
|
||||||
|
@@ -38,9 +38,15 @@ export interface LLMUsage {
|
|||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LLMModel {
|
||||||
|
name: string;
|
||||||
|
available: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export abstract class LLMApi {
|
export abstract class LLMApi {
|
||||||
abstract chat(options: ChatOptions): Promise<void>;
|
abstract chat(options: ChatOptions): Promise<void>;
|
||||||
abstract usage(): Promise<LLMUsage>;
|
abstract usage(): Promise<LLMUsage>;
|
||||||
|
abstract models(): Promise<LLMModel[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProviderName = "openai" | "azure" | "claude" | "palm";
|
type ProviderName = "openai" | "azure" | "claude" | "palm";
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
import { OpenaiPath, REQUEST_TIMEOUT_MS } from "@/app/constant";
|
import {
|
||||||
|
DEFAULT_API_HOST,
|
||||||
|
OpenaiPath,
|
||||||
|
REQUEST_TIMEOUT_MS,
|
||||||
|
} from "@/app/constant";
|
||||||
import { useAccessStore, useAppConfig, useChatStore } from "@/app/store";
|
import { useAccessStore, useAppConfig, useChatStore } from "@/app/store";
|
||||||
|
|
||||||
import { ChatOptions, getHeaders, LLMApi, LLMUsage } from "../api";
|
import { ChatOptions, getHeaders, LLMApi, LLMModel, LLMUsage } from "../api";
|
||||||
import Locale from "../../locales";
|
import Locale from "../../locales";
|
||||||
import {
|
import {
|
||||||
EventStreamContentType,
|
EventStreamContentType,
|
||||||
@@ -9,12 +13,27 @@ import {
|
|||||||
} from "@fortaine/fetch-event-source";
|
} from "@fortaine/fetch-event-source";
|
||||||
import { prettyObject } from "@/app/utils/format";
|
import { prettyObject } from "@/app/utils/format";
|
||||||
|
|
||||||
|
export interface OpenAIListModelResponse {
|
||||||
|
object: string;
|
||||||
|
data: Array<{
|
||||||
|
id: string;
|
||||||
|
object: string;
|
||||||
|
root: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
export class ChatGPTApi implements LLMApi {
|
export class ChatGPTApi implements LLMApi {
|
||||||
path(path: string): string {
|
path(path: string): string {
|
||||||
let openaiUrl = useAccessStore.getState().openaiUrl;
|
let openaiUrl = useAccessStore.getState().openaiUrl;
|
||||||
|
if (openaiUrl.length === 0) {
|
||||||
|
openaiUrl = DEFAULT_API_HOST;
|
||||||
|
}
|
||||||
if (openaiUrl.endsWith("/")) {
|
if (openaiUrl.endsWith("/")) {
|
||||||
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
|
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
|
||||||
}
|
}
|
||||||
|
if (!openaiUrl.startsWith("http") && !openaiUrl.startsWith("/api/openai")) {
|
||||||
|
openaiUrl = "https://" + openaiUrl;
|
||||||
|
}
|
||||||
return [openaiUrl, path].join("/");
|
return [openaiUrl, path].join("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +62,7 @@ export class ChatGPTApi implements LLMApi {
|
|||||||
temperature: modelConfig.temperature,
|
temperature: modelConfig.temperature,
|
||||||
presence_penalty: modelConfig.presence_penalty,
|
presence_penalty: modelConfig.presence_penalty,
|
||||||
frequency_penalty: modelConfig.frequency_penalty,
|
frequency_penalty: modelConfig.frequency_penalty,
|
||||||
|
top_p: modelConfig.top_p,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("[Request] openai payload: ", requestPayload);
|
console.log("[Request] openai payload: ", requestPayload);
|
||||||
@@ -224,5 +244,25 @@ export class ChatGPTApi implements LLMApi {
|
|||||||
total: total.hard_limit_usd,
|
total: total.hard_limit_usd,
|
||||||
} as LLMUsage;
|
} as LLMUsage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async models(): Promise<LLMModel[]> {
|
||||||
|
const res = await fetch(this.path(OpenaiPath.ListModelPath), {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
...getHeaders(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const resJson = (await res.json()) as OpenAIListModelResponse;
|
||||||
|
const chatModels = resJson.data?.filter((m) => m.id.startsWith("gpt-"));
|
||||||
|
console.log("[Models]", chatModels);
|
||||||
|
|
||||||
|
return (
|
||||||
|
chatModels?.map((m) => ({
|
||||||
|
name: m.id,
|
||||||
|
available: true,
|
||||||
|
})) || []
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export { OpenaiPath };
|
export { OpenaiPath };
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
import { useSearchParams } from "react-router-dom";
|
import { useSearchParams } from "react-router-dom";
|
||||||
import Locale from "./locales";
|
import Locale from "./locales";
|
||||||
|
|
||||||
@@ -11,21 +12,22 @@ interface Commands {
|
|||||||
export function useCommand(commands: Commands = {}) {
|
export function useCommand(commands: Commands = {}) {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
|
||||||
if (commands === undefined) return;
|
useEffect(() => {
|
||||||
|
let shouldUpdate = false;
|
||||||
|
searchParams.forEach((param, name) => {
|
||||||
|
const commandName = name as keyof Commands;
|
||||||
|
if (typeof commands[commandName] === "function") {
|
||||||
|
commands[commandName]!(param);
|
||||||
|
searchParams.delete(name);
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let shouldUpdate = false;
|
if (shouldUpdate) {
|
||||||
searchParams.forEach((param, name) => {
|
setSearchParams(searchParams);
|
||||||
const commandName = name as keyof Commands;
|
|
||||||
if (typeof commands[commandName] === "function") {
|
|
||||||
commands[commandName]!(param);
|
|
||||||
searchParams.delete(name);
|
|
||||||
shouldUpdate = true;
|
|
||||||
}
|
}
|
||||||
});
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [searchParams, commands]);
|
||||||
if (shouldUpdate) {
|
|
||||||
setSearchParams(searchParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ChatCommands {
|
interface ChatCommands {
|
||||||
|
@@ -27,6 +27,26 @@
|
|||||||
fill: white !important;
|
fill: white !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: rgba($color: red, $alpha: 0.8);
|
||||||
|
border-color: rgba($color: red, $alpha: 0.5);
|
||||||
|
background-color: rgba($color: red, $alpha: 0.05);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: red;
|
||||||
|
background-color: rgba($color: red, $alpha: 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
path {
|
||||||
|
fill: red !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shadow {
|
.shadow {
|
||||||
@@ -37,10 +57,6 @@
|
|||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button:hover {
|
|
||||||
border-color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-button-icon {
|
.icon-button-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@@ -56,9 +72,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-button-text {
|
.icon-button-text {
|
||||||
margin-left: 5px;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,16 +2,20 @@ import * as React from "react";
|
|||||||
|
|
||||||
import styles from "./button.module.scss";
|
import styles from "./button.module.scss";
|
||||||
|
|
||||||
|
export type ButtonType = "primary" | "danger" | null;
|
||||||
|
|
||||||
export function IconButton(props: {
|
export function IconButton(props: {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
icon?: JSX.Element;
|
icon?: JSX.Element;
|
||||||
type?: "primary" | "danger";
|
type?: ButtonType;
|
||||||
text?: string;
|
text?: string;
|
||||||
bordered?: boolean;
|
bordered?: boolean;
|
||||||
shadow?: boolean;
|
shadow?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
tabIndex?: number;
|
||||||
|
autoFocus?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
@@ -25,6 +29,8 @@ export function IconButton(props: {
|
|||||||
title={props.title}
|
title={props.title}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
role="button"
|
role="button"
|
||||||
|
tabIndex={props.tabIndex}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
>
|
>
|
||||||
{props.icon && (
|
{props.icon && (
|
||||||
<div
|
<div
|
||||||
|
@@ -17,6 +17,7 @@ import { Path } from "../constant";
|
|||||||
import { MaskAvatar } from "./mask";
|
import { MaskAvatar } from "./mask";
|
||||||
import { Mask } from "../store/mask";
|
import { Mask } from "../store/mask";
|
||||||
import { useRef, useEffect } from "react";
|
import { useRef, useEffect } from "react";
|
||||||
|
import { showConfirm } from "./ui-lib";
|
||||||
|
|
||||||
export function ChatItem(props: {
|
export function ChatItem(props: {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
@@ -139,8 +140,11 @@ export function ChatList(props: { narrow?: boolean }) {
|
|||||||
navigate(Path.Chat);
|
navigate(Path.Chat);
|
||||||
selectSession(i);
|
selectSession(i);
|
||||||
}}
|
}}
|
||||||
onDelete={() => {
|
onDelete={async () => {
|
||||||
if (!props.narrow || confirm(Locale.Home.DeleteChat)) {
|
if (
|
||||||
|
!props.narrow ||
|
||||||
|
(await showConfirm(Locale.Home.DeleteChat))
|
||||||
|
) {
|
||||||
chatStore.deleteSession(i);
|
chatStore.deleteSession(i);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
.chat-input-actions {
|
.chat-input-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
.chat-input-action {
|
.chat-input-action {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
@@ -213,13 +212,14 @@
|
|||||||
.chat-body {
|
.chat-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
position: relative;
|
position: relative;
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-body-title {
|
.chat-body-main-title {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -227,6 +227,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.chat-body-title {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.chat-message {
|
.chat-message {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -239,6 +245,34 @@
|
|||||||
.chat-message-user {
|
.chat-message-user {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
|
|
||||||
|
.chat-message-header {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message-header {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.chat-message-actions {
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 12px;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
transition: all ease 0.3s;
|
||||||
|
transform: scale(0.9) translateY(5px);
|
||||||
|
margin: 0 10px;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
|
.chat-input-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-container {
|
.chat-message-container {
|
||||||
@@ -246,6 +280,18 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.chat-message-edit {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message-actions {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
transform: scale(1) translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-user > .chat-message-container {
|
.chat-message-user > .chat-message-container {
|
||||||
@@ -253,7 +299,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-avatar {
|
.chat-message-avatar {
|
||||||
margin-top: 20px;
|
position: relative;
|
||||||
|
|
||||||
|
.chat-message-edit {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all ease 0.3s;
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-status {
|
.chat-message-status {
|
||||||
@@ -276,39 +338,20 @@
|
|||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all ease 0.3s;
|
transition: all ease 0.3s;
|
||||||
min-width: 0;
|
}
|
||||||
|
|
||||||
&:hover {
|
.chat-message-action-date {
|
||||||
min-width: 330px;
|
font-size: 12px;
|
||||||
|
opacity: 0.2;
|
||||||
.chat-message-actions {
|
white-space: nowrap;
|
||||||
height: 40px;
|
transition: all ease 0.6s;
|
||||||
opacity: 1;
|
color: var(--black);
|
||||||
transform: translateY(0px);
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
.chat-message-action-date {
|
box-sizing: border-box;
|
||||||
opacity: 0.3;
|
padding-right: 10px;
|
||||||
}
|
pointer-events: none;
|
||||||
}
|
z-index: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.chat-message-actions {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 12px;
|
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: space-between;
|
|
||||||
transition: all ease 0.3s;
|
|
||||||
transform: translateY(10px);
|
|
||||||
opacity: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-message-action-date {
|
|
||||||
color: var(--black);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-message-user > .chat-message-container > .chat-message-item {
|
.chat-message-user > .chat-message-container > .chat-message-item {
|
||||||
@@ -328,6 +371,12 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-top: var(--border-in-light);
|
border-top: var(--border-in-light);
|
||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
|
|
||||||
|
.chat-input-actions {
|
||||||
|
.chat-input-action {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin single-line {
|
@mixin single-line {
|
||||||
@@ -400,6 +449,8 @@
|
|||||||
padding: 10px 90px 10px 14px;
|
padding: 10px 90px 10px 14px;
|
||||||
resize: none;
|
resize: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: 68px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-input:focus {
|
.chat-input:focus {
|
||||||
@@ -424,3 +475,21 @@
|
|||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-suggestions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.chat-suggestion {
|
||||||
|
display: inline;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--black);
|
||||||
|
border: var(--border-in-light);
|
||||||
|
padding: 4px 10px;
|
||||||
|
animation: slide-in ease 0.3s;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import BreakIcon from "../icons/break.svg";
|
|||||||
import SettingsIcon from "../icons/chat-settings.svg";
|
import SettingsIcon from "../icons/chat-settings.svg";
|
||||||
import DeleteIcon from "../icons/clear.svg";
|
import DeleteIcon from "../icons/clear.svg";
|
||||||
import PinIcon from "../icons/pin.svg";
|
import PinIcon from "../icons/pin.svg";
|
||||||
|
import EditIcon from "../icons/rename.svg";
|
||||||
|
|
||||||
import LightIcon from "../icons/light.svg";
|
import LightIcon from "../icons/light.svg";
|
||||||
import DarkIcon from "../icons/dark.svg";
|
import DarkIcon from "../icons/dark.svg";
|
||||||
@@ -41,12 +42,11 @@ import {
|
|||||||
Theme,
|
Theme,
|
||||||
useAppConfig,
|
useAppConfig,
|
||||||
DEFAULT_TOPIC,
|
DEFAULT_TOPIC,
|
||||||
ALL_MODELS,
|
ModelType,
|
||||||
} from "../store";
|
} from "../store";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
copyToClipboard,
|
copyToClipboard,
|
||||||
downloadAs,
|
|
||||||
selectOrCopy,
|
selectOrCopy,
|
||||||
autoGrowTextArea,
|
autoGrowTextArea,
|
||||||
useMobileScreen,
|
useMobileScreen,
|
||||||
@@ -61,7 +61,14 @@ import Locale from "../locales";
|
|||||||
import { IconButton } from "./button";
|
import { IconButton } from "./button";
|
||||||
import styles from "./chat.module.scss";
|
import styles from "./chat.module.scss";
|
||||||
|
|
||||||
import { ListItem, Modal, showToast } from "./ui-lib";
|
import {
|
||||||
|
ListItem,
|
||||||
|
Modal,
|
||||||
|
Selector,
|
||||||
|
showConfirm,
|
||||||
|
showPrompt,
|
||||||
|
showToast,
|
||||||
|
} from "./ui-lib";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
|
import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
|
||||||
import { Avatar } from "./emoji";
|
import { Avatar } from "./emoji";
|
||||||
@@ -93,8 +100,8 @@ export function SessionConfigModel(props: { onClose: () => void }) {
|
|||||||
icon={<ResetIcon />}
|
icon={<ResetIcon />}
|
||||||
bordered
|
bordered
|
||||||
text={Locale.Chat.Config.Reset}
|
text={Locale.Chat.Config.Reset}
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
if (confirm(Locale.Memory.ResetConfirm)) {
|
if (await showConfirm(Locale.Memory.ResetConfirm)) {
|
||||||
chatStore.updateCurrentSession(
|
chatStore.updateCurrentSession(
|
||||||
(session) => (session.memoryPrompt = ""),
|
(session) => (session.memoryPrompt = ""),
|
||||||
);
|
);
|
||||||
@@ -172,10 +179,29 @@ function PromptToast(props: {
|
|||||||
function useSubmitHandler() {
|
function useSubmitHandler() {
|
||||||
const config = useAppConfig();
|
const config = useAppConfig();
|
||||||
const submitKey = config.submitKey;
|
const submitKey = config.submitKey;
|
||||||
|
const isComposing = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onCompositionStart = () => {
|
||||||
|
isComposing.current = true;
|
||||||
|
};
|
||||||
|
const onCompositionEnd = () => {
|
||||||
|
isComposing.current = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("compositionstart", onCompositionStart);
|
||||||
|
window.addEventListener("compositionend", onCompositionEnd);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("compositionstart", onCompositionStart);
|
||||||
|
window.removeEventListener("compositionend", onCompositionEnd);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const shouldSubmit = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
const shouldSubmit = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
if (e.key !== "Enter") return false;
|
if (e.key !== "Enter") return false;
|
||||||
if (e.key === "Enter" && e.nativeEvent.isComposing) return false;
|
if (e.key === "Enter" && (e.nativeEvent.isComposing || isComposing.current))
|
||||||
|
return false;
|
||||||
return (
|
return (
|
||||||
(config.submitKey === SubmitKey.AltEnter && e.altKey) ||
|
(config.submitKey === SubmitKey.AltEnter && e.altKey) ||
|
||||||
(config.submitKey === SubmitKey.CtrlEnter && e.ctrlKey) ||
|
(config.submitKey === SubmitKey.CtrlEnter && e.ctrlKey) ||
|
||||||
@@ -294,8 +320,8 @@ function ChatAction(props: {
|
|||||||
const iconRef = useRef<HTMLDivElement>(null);
|
const iconRef = useRef<HTMLDivElement>(null);
|
||||||
const textRef = useRef<HTMLDivElement>(null);
|
const textRef = useRef<HTMLDivElement>(null);
|
||||||
const [width, setWidth] = useState({
|
const [width, setWidth] = useState({
|
||||||
full: 20,
|
full: 16,
|
||||||
icon: 20,
|
icon: 16,
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateWidth() {
|
function updateWidth() {
|
||||||
@@ -309,10 +335,6 @@ function ChatAction(props: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
updateWidth();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${styles["chat-input-action"]} clickable`}
|
className={`${styles["chat-input-action"]} clickable`}
|
||||||
@@ -320,6 +342,8 @@ function ChatAction(props: {
|
|||||||
props.onClick();
|
props.onClick();
|
||||||
setTimeout(updateWidth, 1);
|
setTimeout(updateWidth, 1);
|
||||||
}}
|
}}
|
||||||
|
onMouseEnter={updateWidth}
|
||||||
|
onTouchStart={updateWidth}
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
"--icon-width": `${width.icon}px`,
|
"--icon-width": `${width.icon}px`,
|
||||||
@@ -387,16 +411,11 @@ export function ChatActions(props: {
|
|||||||
|
|
||||||
// switch model
|
// switch model
|
||||||
const currentModel = chatStore.currentSession().mask.modelConfig.model;
|
const currentModel = chatStore.currentSession().mask.modelConfig.model;
|
||||||
function nextModel() {
|
const models = useMemo(
|
||||||
const models = ALL_MODELS.filter((m) => m.available).map((m) => m.name);
|
() => config.models.filter((m) => m.available).map((m) => m.name),
|
||||||
const modelIndex = models.indexOf(currentModel);
|
[config.models],
|
||||||
const nextIndex = (modelIndex + 1) % models.length;
|
);
|
||||||
const nextModel = models[nextIndex];
|
const [showModelSelector, setShowModelSelector] = useState(false);
|
||||||
chatStore.updateCurrentSession((session) => {
|
|
||||||
session.mask.modelConfig.model = nextModel;
|
|
||||||
session.mask.syncGlobalConfig = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["chat-input-actions"]}>
|
<div className={styles["chat-input-actions"]}>
|
||||||
@@ -468,10 +487,28 @@ export function ChatActions(props: {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ChatAction
|
<ChatAction
|
||||||
onClick={nextModel}
|
onClick={() => setShowModelSelector(true)}
|
||||||
text={currentModel}
|
text={currentModel}
|
||||||
icon={<RobotIcon />}
|
icon={<RobotIcon />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{showModelSelector && (
|
||||||
|
<Selector
|
||||||
|
items={models.map((m) => ({
|
||||||
|
title: m,
|
||||||
|
value: m,
|
||||||
|
}))}
|
||||||
|
onClose={() => setShowModelSelector(false)}
|
||||||
|
onSelection={(s) => {
|
||||||
|
if (s.length === 0) return;
|
||||||
|
chatStore.updateCurrentSession((session) => {
|
||||||
|
session.mask.modelConfig.model = s[0] as ModelType;
|
||||||
|
session.mask.syncGlobalConfig = false;
|
||||||
|
});
|
||||||
|
showToast(s[0]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -515,14 +552,6 @@ export function Chat() {
|
|||||||
{ leading: true, trailing: true },
|
{ leading: true, trailing: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
const onPromptSelect = (prompt: Prompt) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
setPromptHints([]);
|
|
||||||
setUserInput(prompt.content);
|
|
||||||
inputRef.current?.focus();
|
|
||||||
}, 30);
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto grow input
|
// auto grow input
|
||||||
const [inputRows, setInputRows] = useState(2);
|
const [inputRows, setInputRows] = useState(2);
|
||||||
const measure = useDebouncedCallback(
|
const measure = useDebouncedCallback(
|
||||||
@@ -577,6 +606,8 @@ export function Chat() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [suggestions, setSuggestions] = useState<string[]>([]);
|
||||||
|
|
||||||
const doSubmit = (userInput: string) => {
|
const doSubmit = (userInput: string) => {
|
||||||
if (userInput.trim() === "") return;
|
if (userInput.trim() === "") return;
|
||||||
const matchCommand = chatCommands.match(userInput);
|
const matchCommand = chatCommands.match(userInput);
|
||||||
@@ -587,7 +618,13 @@ export function Chat() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
chatStore.onUserInput(userInput).then(() => setIsLoading(false));
|
setSuggestions([]);
|
||||||
|
chatStore.onUserInput(userInput).then(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
chatStore
|
||||||
|
.getSuggestions()
|
||||||
|
.then((suggestions) => setSuggestions(suggestions));
|
||||||
|
});
|
||||||
localStorage.setItem(LAST_INPUT_KEY, userInput);
|
localStorage.setItem(LAST_INPUT_KEY, userInput);
|
||||||
setUserInput("");
|
setUserInput("");
|
||||||
setPromptHints([]);
|
setPromptHints([]);
|
||||||
@@ -595,6 +632,23 @@ export function Chat() {
|
|||||||
setAutoScroll(true);
|
setAutoScroll(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onPromptSelect = (prompt: Prompt) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
setPromptHints([]);
|
||||||
|
|
||||||
|
const matchedChatCommand = chatCommands.match(prompt.content);
|
||||||
|
if (matchedChatCommand.matched) {
|
||||||
|
// if user is selecting a chat command, just trigger it
|
||||||
|
matchedChatCommand.invoke();
|
||||||
|
setUserInput("");
|
||||||
|
} else {
|
||||||
|
// or fill the prompt
|
||||||
|
setUserInput(prompt.content);
|
||||||
|
}
|
||||||
|
inputRef.current?.focus();
|
||||||
|
}, 30);
|
||||||
|
};
|
||||||
|
|
||||||
// stop response
|
// stop response
|
||||||
const onUserStop = (messageId: number) => {
|
const onUserStop = (messageId: number) => {
|
||||||
ChatControllerPool.stop(sessionIndex, messageId);
|
ChatControllerPool.stop(sessionIndex, messageId);
|
||||||
@@ -662,49 +716,46 @@ export function Chat() {
|
|||||||
let lastUserMessageIndex: number | null = null;
|
let lastUserMessageIndex: number | null = null;
|
||||||
for (let i = 0; i < session.messages.length; i += 1) {
|
for (let i = 0; i < session.messages.length; i += 1) {
|
||||||
const message = session.messages[i];
|
const message = session.messages[i];
|
||||||
if (message.id === messageId) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (message.role === "user") {
|
if (message.role === "user") {
|
||||||
lastUserMessageIndex = i;
|
lastUserMessageIndex = i;
|
||||||
}
|
}
|
||||||
|
if (message.id === messageId) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastUserMessageIndex;
|
return lastUserMessageIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteMessage = (userIndex: number) => {
|
const deleteMessage = (msgId?: number) => {
|
||||||
chatStore.updateCurrentSession((session) =>
|
chatStore.updateCurrentSession(
|
||||||
session.messages.splice(userIndex, 2),
|
(session) =>
|
||||||
|
(session.messages = session.messages.filter((m) => m.id !== msgId)),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDelete = (botMessageId: number) => {
|
const onDelete = (msgId: number) => {
|
||||||
const userIndex = findLastUserIndex(botMessageId);
|
deleteMessage(msgId);
|
||||||
if (userIndex === null) return;
|
|
||||||
deleteMessage(userIndex);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onResend = (botMessageId: number) => {
|
const onResend = (message: ChatMessage) => {
|
||||||
// find last user input message and resend
|
let content = message.content;
|
||||||
const userIndex = findLastUserIndex(botMessageId);
|
|
||||||
if (userIndex === null) return;
|
if (message.role === "assistant" && message.id) {
|
||||||
|
const userIndex = findLastUserIndex(message.id);
|
||||||
|
if (userIndex) {
|
||||||
|
content = session.messages.at(userIndex)?.content ?? content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const content = session.messages[userIndex].content;
|
|
||||||
deleteMessage(userIndex);
|
|
||||||
chatStore.onUserInput(content).then(() => setIsLoading(false));
|
chatStore.onUserInput(content).then(() => setIsLoading(false));
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPinMessage = (botMessage: ChatMessage) => {
|
const onPinMessage = (message: ChatMessage) => {
|
||||||
if (!botMessage.id) return;
|
|
||||||
const userMessageIndex = findLastUserIndex(botMessage.id);
|
|
||||||
if (!userMessageIndex) return;
|
|
||||||
|
|
||||||
const userMessage = session.messages[userMessageIndex];
|
|
||||||
chatStore.updateCurrentSession((session) =>
|
chatStore.updateCurrentSession((session) =>
|
||||||
session.mask.context.push(userMessage, botMessage),
|
session.mask.context.push(message),
|
||||||
);
|
);
|
||||||
|
|
||||||
showToast(Locale.Chat.Actions.PinToastContent, {
|
showToast(Locale.Chat.Actions.PinToastContent, {
|
||||||
@@ -771,10 +822,13 @@ export function Chat() {
|
|||||||
const [showPromptModal, setShowPromptModal] = useState(false);
|
const [showPromptModal, setShowPromptModal] = useState(false);
|
||||||
|
|
||||||
const renameSession = () => {
|
const renameSession = () => {
|
||||||
const newTopic = prompt(Locale.Chat.Rename, session.topic);
|
showPrompt(Locale.Chat.Rename, session.topic).then((newTopic) => {
|
||||||
if (newTopic && newTopic !== session.topic) {
|
if (newTopic && newTopic !== session.topic) {
|
||||||
chatStore.updateCurrentSession((session) => (session.topic = newTopic!));
|
chatStore.updateCurrentSession(
|
||||||
}
|
(session) => (session.topic = newTopic!),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const clientConfig = useMemo(() => getClientConfig(), []);
|
const clientConfig = useMemo(() => getClientConfig(), []);
|
||||||
@@ -795,9 +849,22 @@ export function Chat() {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.chat} key={session.id}>
|
<div className={styles.chat} key={session.id}>
|
||||||
<div className="window-header" data-tauri-drag-region>
|
<div className="window-header" data-tauri-drag-region>
|
||||||
<div className="window-header-title">
|
{isMobileScreen && (
|
||||||
|
<div className="window-actions">
|
||||||
|
<div className={"window-action-button"}>
|
||||||
|
<IconButton
|
||||||
|
icon={<ReturnIcon />}
|
||||||
|
bordered
|
||||||
|
title={Locale.Chat.Actions.ChatList}
|
||||||
|
onClick={() => navigate(Path.Home)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={`window-header-title ${styles["chat-body-title"]}`}>
|
||||||
<div
|
<div
|
||||||
className={`window-header-main-title " ${styles["chat-body-title"]}`}
|
className={`window-header-main-title ${styles["chat-body-main-title"]}`}
|
||||||
onClickCapture={renameSession}
|
onClickCapture={renameSession}
|
||||||
>
|
>
|
||||||
{!session.topic ? DEFAULT_TOPIC : session.topic}
|
{!session.topic ? DEFAULT_TOPIC : session.topic}
|
||||||
@@ -807,21 +874,15 @@ export function Chat() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="window-actions">
|
<div className="window-actions">
|
||||||
<div className={"window-action-button" + " " + styles.mobile}>
|
{!isMobileScreen && (
|
||||||
<IconButton
|
<div className="window-action-button">
|
||||||
icon={<ReturnIcon />}
|
<IconButton
|
||||||
bordered
|
icon={<RenameIcon />}
|
||||||
title={Locale.Chat.Actions.ChatList}
|
bordered
|
||||||
onClick={() => navigate(Path.Home)}
|
onClick={renameSession}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="window-action-button">
|
)}
|
||||||
<IconButton
|
|
||||||
icon={<RenameIcon />}
|
|
||||||
bordered
|
|
||||||
onClick={renameSession}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="window-action-button">
|
<div className="window-action-button">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<ExportIcon />}
|
icon={<ExportIcon />}
|
||||||
@@ -867,10 +928,11 @@ export function Chat() {
|
|||||||
>
|
>
|
||||||
{messages.map((message, i) => {
|
{messages.map((message, i) => {
|
||||||
const isUser = message.role === "user";
|
const isUser = message.role === "user";
|
||||||
|
const isContext = i < context.length;
|
||||||
const showActions =
|
const showActions =
|
||||||
!isUser &&
|
|
||||||
i > 0 &&
|
i > 0 &&
|
||||||
!(message.preview || message.content.length === 0);
|
!(message.preview || message.content.length === 0) &&
|
||||||
|
!isContext;
|
||||||
const showTyping = message.preview || message.streaming;
|
const showTyping = message.preview || message.streaming;
|
||||||
|
|
||||||
const shouldShowClearContextDivider = i === clearContextIndex - 1;
|
const shouldShowClearContextDivider = i === clearContextIndex - 1;
|
||||||
@@ -884,11 +946,72 @@ export function Chat() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className={styles["chat-message-container"]}>
|
<div className={styles["chat-message-container"]}>
|
||||||
<div className={styles["chat-message-avatar"]}>
|
<div className={styles["chat-message-header"]}>
|
||||||
{message.role === "user" ? (
|
<div className={styles["chat-message-avatar"]}>
|
||||||
<Avatar avatar={config.avatar} />
|
<div className={styles["chat-message-edit"]}>
|
||||||
) : (
|
<IconButton
|
||||||
<MaskAvatar mask={session.mask} />
|
icon={<EditIcon />}
|
||||||
|
onClick={async () => {
|
||||||
|
const newMessage = await showPrompt(
|
||||||
|
Locale.Chat.Actions.Edit,
|
||||||
|
message.content,
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
chatStore.updateCurrentSession((session) => {
|
||||||
|
const m = session.messages.find(
|
||||||
|
(m) => m.id === message.id,
|
||||||
|
);
|
||||||
|
if (m) {
|
||||||
|
m.content = newMessage;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
></IconButton>
|
||||||
|
</div>
|
||||||
|
{isUser ? (
|
||||||
|
<Avatar avatar={config.avatar} />
|
||||||
|
) : (
|
||||||
|
<MaskAvatar mask={session.mask} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showActions && (
|
||||||
|
<div className={styles["chat-message-actions"]}>
|
||||||
|
<div className={styles["chat-input-actions"]}>
|
||||||
|
{message.streaming ? (
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Stop}
|
||||||
|
icon={<StopIcon />}
|
||||||
|
onClick={() => onUserStop(message.id ?? i)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Retry}
|
||||||
|
icon={<ResetIcon />}
|
||||||
|
onClick={() => onResend(message)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Delete}
|
||||||
|
icon={<DeleteIcon />}
|
||||||
|
onClick={() => onDelete(message.id ?? i)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Pin}
|
||||||
|
icon={<PinIcon />}
|
||||||
|
onClick={() => onPinMessage(message)}
|
||||||
|
/>
|
||||||
|
<ChatAction
|
||||||
|
text={Locale.Chat.Actions.Copy}
|
||||||
|
icon={<CopyIcon />}
|
||||||
|
onClick={() => copyToClipboard(message.content)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showTyping && (
|
{showTyping && (
|
||||||
@@ -912,55 +1035,12 @@ export function Chat() {
|
|||||||
parentRef={scrollRef}
|
parentRef={scrollRef}
|
||||||
defaultShow={i >= messages.length - 10}
|
defaultShow={i >= messages.length - 10}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{showActions && (
|
<div className={styles["chat-message-action-date"]}>
|
||||||
<div className={styles["chat-message-actions"]}>
|
{isContext
|
||||||
<div
|
? Locale.Chat.IsContext
|
||||||
className={styles["chat-input-actions"]}
|
: message.date.toLocaleString()}
|
||||||
style={{
|
|
||||||
marginTop: 10,
|
|
||||||
marginBottom: 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{message.streaming ? (
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Stop}
|
|
||||||
icon={<StopIcon />}
|
|
||||||
onClick={() => onUserStop(message.id ?? i)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Delete}
|
|
||||||
icon={<DeleteIcon />}
|
|
||||||
onClick={() => onDelete(message.id ?? i)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Retry}
|
|
||||||
icon={<ResetIcon />}
|
|
||||||
onClick={() => onResend(message.id ?? i)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Pin}
|
|
||||||
icon={<PinIcon />}
|
|
||||||
onClick={() => onPinMessage(message)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<ChatAction
|
|
||||||
text={Locale.Chat.Actions.Copy}
|
|
||||||
icon={<CopyIcon />}
|
|
||||||
onClick={() => copyToClipboard(message.content)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles["chat-message-action-date"]}>
|
|
||||||
{message.date.toLocaleString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -989,6 +1069,25 @@ export function Chat() {
|
|||||||
onSearch("");
|
onSearch("");
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{suggestions.length > 0 && (
|
||||||
|
<div className={styles["chat-suggestions"]}>
|
||||||
|
{suggestions.map((s, i) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className={styles["chat-suggestion"] + " clickable"}
|
||||||
|
onClick={() => {
|
||||||
|
doSubmit(s);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{s}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className={styles["chat-input-panel-inner"]}>
|
<div className={styles["chat-input-panel-inner"]}>
|
||||||
<textarea
|
<textarea
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
@@ -5,6 +5,7 @@ import ResetIcon from "../icons/reload.svg";
|
|||||||
import { ISSUE_URL } from "../constant";
|
import { ISSUE_URL } from "../constant";
|
||||||
import Locale from "../locales";
|
import Locale from "../locales";
|
||||||
import { downloadAs } from "../utils";
|
import { downloadAs } from "../utils";
|
||||||
|
import { showConfirm } from "./ui-lib";
|
||||||
|
|
||||||
interface IErrorBoundaryState {
|
interface IErrorBoundaryState {
|
||||||
hasError: boolean;
|
hasError: boolean;
|
||||||
@@ -57,10 +58,11 @@ export class ErrorBoundary extends React.Component<any, IErrorBoundaryState> {
|
|||||||
<IconButton
|
<IconButton
|
||||||
icon={<ResetIcon />}
|
icon={<ResetIcon />}
|
||||||
text="Clear All Data"
|
text="Clear All Data"
|
||||||
onClick={() =>
|
onClick={async () => {
|
||||||
confirm(Locale.Settings.Actions.ConfirmClearAll) &&
|
if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
|
||||||
this.clearAndSaveData()
|
this.clearAndSaveData();
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
bordered
|
bordered
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -186,7 +186,7 @@
|
|||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
|
|
||||||
* {
|
*:not(li) {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,16 @@
|
|||||||
|
/* eslint-disable @next/next/no-img-element */
|
||||||
import { ChatMessage, useAppConfig, useChatStore } from "../store";
|
import { ChatMessage, useAppConfig, useChatStore } from "../store";
|
||||||
import Locale from "../locales";
|
import Locale from "../locales";
|
||||||
import styles from "./exporter.module.scss";
|
import styles from "./exporter.module.scss";
|
||||||
import { List, ListItem, Modal, Select, showToast } from "./ui-lib";
|
import {
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Modal,
|
||||||
|
Select,
|
||||||
|
showImageModal,
|
||||||
|
showModal,
|
||||||
|
showToast,
|
||||||
|
} from "./ui-lib";
|
||||||
import { IconButton } from "./button";
|
import { IconButton } from "./button";
|
||||||
import { copyToClipboard, downloadAs, useMobileScreen } from "../utils";
|
import { copyToClipboard, downloadAs, useMobileScreen } from "../utils";
|
||||||
|
|
||||||
@@ -23,6 +32,7 @@ import { DEFAULT_MASK_AVATAR } from "../store/mask";
|
|||||||
import { api } from "../client/api";
|
import { api } from "../client/api";
|
||||||
import { prettyObject } from "../utils/format";
|
import { prettyObject } from "../utils/format";
|
||||||
import { EXPORT_MESSAGE_CLASS_NAME } from "../constant";
|
import { EXPORT_MESSAGE_CLASS_NAME } from "../constant";
|
||||||
|
import { getClientConfig } from "../config/client";
|
||||||
|
|
||||||
const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
|
const Markdown = dynamic(async () => (await import("./markdown")).Markdown, {
|
||||||
loading: () => <LoadingIcon />,
|
loading: () => <LoadingIcon />,
|
||||||
@@ -369,6 +379,7 @@ export function ImagePreviewer(props: {
|
|||||||
const previewRef = useRef<HTMLDivElement>(null);
|
const previewRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const copy = () => {
|
const copy = () => {
|
||||||
|
showToast(Locale.Export.Image.Toast);
|
||||||
const dom = previewRef.current;
|
const dom = previewRef.current;
|
||||||
if (!dom) return;
|
if (!dom) return;
|
||||||
toBlob(dom).then((blob) => {
|
toBlob(dom).then((blob) => {
|
||||||
@@ -393,17 +404,15 @@ export function ImagePreviewer(props: {
|
|||||||
const isMobile = useMobileScreen();
|
const isMobile = useMobileScreen();
|
||||||
|
|
||||||
const download = () => {
|
const download = () => {
|
||||||
|
showToast(Locale.Export.Image.Toast);
|
||||||
const dom = previewRef.current;
|
const dom = previewRef.current;
|
||||||
if (!dom) return;
|
if (!dom) return;
|
||||||
toPng(dom)
|
toPng(dom)
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
if (!blob) return;
|
if (!blob) return;
|
||||||
|
|
||||||
if (isMobile) {
|
if (isMobile || getClientConfig()?.isApp) {
|
||||||
const image = new Image();
|
showImageModal(blob);
|
||||||
image.src = blob;
|
|
||||||
const win = window.open("");
|
|
||||||
win?.document.write(image.outerHTML);
|
|
||||||
} else {
|
} else {
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.download = `${props.topic}.png`;
|
link.download = `${props.topic}.png`;
|
||||||
|
@@ -27,6 +27,8 @@ import { SideBar } from "./sidebar";
|
|||||||
import { useAppConfig } from "../store/config";
|
import { useAppConfig } from "../store/config";
|
||||||
import { AuthPage } from "./auth";
|
import { AuthPage } from "./auth";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
import { api } from "../client/api";
|
||||||
|
import { useChatStore } from "../store";
|
||||||
|
|
||||||
export function Loading(props: { noLogo?: boolean }) {
|
export function Loading(props: { noLogo?: boolean }) {
|
||||||
return (
|
return (
|
||||||
@@ -113,6 +115,7 @@ function Screen() {
|
|||||||
const isHome = location.pathname === Path.Home;
|
const isHome = location.pathname === Path.Home;
|
||||||
const isAuth = location.pathname === Path.Auth;
|
const isAuth = location.pathname === Path.Auth;
|
||||||
const isMobileScreen = useMobileScreen();
|
const isMobileScreen = useMobileScreen();
|
||||||
|
const chat = useChatStore();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadAsyncGoogleFont();
|
loadAsyncGoogleFont();
|
||||||
@@ -152,8 +155,21 @@ function Screen() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useLoadData() {
|
||||||
|
const config = useAppConfig();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
const models = await api.llm.models();
|
||||||
|
config.mergeModels(models);
|
||||||
|
})();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
export function Home() {
|
export function Home() {
|
||||||
useSwitchTheme();
|
useSwitchTheme();
|
||||||
|
useLoadData();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("[Config] got config from build time", getClientConfig());
|
console.log("[Config] got config from build time", getClientConfig());
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
.input-range {
|
.input-range {
|
||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 5px 15px 5px 10px;
|
padding: 5px 10px 5px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
max-width: 40%;
|
max-width: 40%;
|
||||||
|
|
||||||
input[type="range"] {
|
input[type="range"] {
|
||||||
max-width: calc(100% - 50px);
|
max-width: calc(100% - 34px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ import mermaid from "mermaid";
|
|||||||
import LoadingIcon from "../icons/three-dots.svg";
|
import LoadingIcon from "../icons/three-dots.svg";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
|
import { useDebouncedCallback, useThrottledCallback } from "use-debounce";
|
||||||
|
import { showImageModal } from "./ui-lib";
|
||||||
|
|
||||||
export function Mermaid(props: { code: string }) {
|
export function Mermaid(props: { code: string }) {
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
@@ -37,11 +38,13 @@ export function Mermaid(props: { code: string }) {
|
|||||||
if (!svg) return;
|
if (!svg) return;
|
||||||
const text = new XMLSerializer().serializeToString(svg);
|
const text = new XMLSerializer().serializeToString(svg);
|
||||||
const blob = new Blob([text], { type: "image/svg+xml" });
|
const blob = new Blob([text], { type: "image/svg+xml" });
|
||||||
const url = URL.createObjectURL(blob);
|
console.log(blob);
|
||||||
const win = window.open(url);
|
// const url = URL.createObjectURL(blob);
|
||||||
if (win) {
|
// const win = window.open(url);
|
||||||
win.onload = () => URL.revokeObjectURL(url);
|
// if (win) {
|
||||||
}
|
// win.onload = () => URL.revokeObjectURL(url);
|
||||||
|
// }
|
||||||
|
showImageModal(URL.createObjectURL(blob));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
|
@@ -15,14 +15,22 @@ import CopyIcon from "../icons/copy.svg";
|
|||||||
import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "../store/mask";
|
import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "../store/mask";
|
||||||
import { ChatMessage, ModelConfig, useAppConfig, useChatStore } from "../store";
|
import { ChatMessage, ModelConfig, useAppConfig, useChatStore } from "../store";
|
||||||
import { ROLES } from "../client/api";
|
import { ROLES } from "../client/api";
|
||||||
import { Input, List, ListItem, Modal, Popover, Select } from "./ui-lib";
|
import {
|
||||||
|
Input,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Modal,
|
||||||
|
Popover,
|
||||||
|
Select,
|
||||||
|
showConfirm,
|
||||||
|
} from "./ui-lib";
|
||||||
import { Avatar, AvatarPicker } from "./emoji";
|
import { Avatar, AvatarPicker } from "./emoji";
|
||||||
import Locale, { AllLangs, ALL_LANG_OPTIONS, Lang } from "../locales";
|
import Locale, { AllLangs, ALL_LANG_OPTIONS, Lang } from "../locales";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import chatStyle from "./chat.module.scss";
|
import chatStyle from "./chat.module.scss";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { downloadAs, readFromFile } from "../utils";
|
import { copyToClipboard, downloadAs, readFromFile } from "../utils";
|
||||||
import { Updater } from "../typing";
|
import { Updater } from "../typing";
|
||||||
import { ModelConfigList } from "./model-config";
|
import { ModelConfigList } from "./model-config";
|
||||||
import { FileName, Path } from "../constant";
|
import { FileName, Path } from "../constant";
|
||||||
@@ -57,6 +65,11 @@ export function MaskConfig(props: {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyMaskLink = () => {
|
||||||
|
const maskLink = `${location.protocol}//${location.host}/#${Path.NewChat}?mask=${props.mask.id}`;
|
||||||
|
copyToClipboard(maskLink);
|
||||||
|
};
|
||||||
|
|
||||||
const globalConfig = useAppConfig();
|
const globalConfig = useAppConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -117,6 +130,20 @@ export function MaskConfig(props: {
|
|||||||
}}
|
}}
|
||||||
></input>
|
></input>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
|
{!props.shouldSyncFromGlobal ? (
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Mask.Config.Share.Title}
|
||||||
|
subTitle={Locale.Mask.Config.Share.SubTitle}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
icon={<CopyIcon />}
|
||||||
|
text={Locale.Mask.Config.Share.Action}
|
||||||
|
onClick={copyMaskLink}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{props.shouldSyncFromGlobal ? (
|
{props.shouldSyncFromGlobal ? (
|
||||||
<ListItem
|
<ListItem
|
||||||
title={Locale.Mask.Config.Sync.Title}
|
title={Locale.Mask.Config.Sync.Title}
|
||||||
@@ -125,15 +152,20 @@ export function MaskConfig(props: {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={props.mask.syncGlobalConfig}
|
checked={props.mask.syncGlobalConfig}
|
||||||
onChange={(e) => {
|
onChange={async (e) => {
|
||||||
|
const checked = e.currentTarget.checked;
|
||||||
if (
|
if (
|
||||||
e.currentTarget.checked &&
|
checked &&
|
||||||
confirm(Locale.Mask.Config.Sync.Confirm)
|
(await showConfirm(Locale.Mask.Config.Sync.Confirm))
|
||||||
) {
|
) {
|
||||||
props.updateMask((mask) => {
|
props.updateMask((mask) => {
|
||||||
mask.syncGlobalConfig = e.currentTarget.checked;
|
mask.syncGlobalConfig = checked;
|
||||||
mask.modelConfig = { ...globalConfig.modelConfig };
|
mask.modelConfig = { ...globalConfig.modelConfig };
|
||||||
});
|
});
|
||||||
|
} else if (!checked) {
|
||||||
|
props.updateMask((mask) => {
|
||||||
|
mask.syncGlobalConfig = checked;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
></input>
|
></input>
|
||||||
@@ -439,8 +471,8 @@ export function MaskPage() {
|
|||||||
<IconButton
|
<IconButton
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
text={Locale.Mask.Item.Delete}
|
text={Locale.Mask.Item.Delete}
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
if (confirm(Locale.Mask.Item.DeleteConfirm)) {
|
if (await showConfirm(Locale.Mask.Item.DeleteConfirm)) {
|
||||||
maskStore.delete(m.id);
|
maskStore.delete(m.id);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { ALL_MODELS, ModalConfigValidator, ModelConfig } from "../store";
|
import { ModalConfigValidator, ModelConfig, useAppConfig } from "../store";
|
||||||
|
|
||||||
import Locale from "../locales";
|
import Locale from "../locales";
|
||||||
import { InputRange } from "./input-range";
|
import { InputRange } from "./input-range";
|
||||||
@@ -8,6 +8,8 @@ export function ModelConfigList(props: {
|
|||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
updateConfig: (updater: (config: ModelConfig) => void) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const config = useAppConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ListItem title={Locale.Settings.Model}>
|
<ListItem title={Locale.Settings.Model}>
|
||||||
@@ -22,7 +24,7 @@ export function ModelConfigList(props: {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{ALL_MODELS.map((v) => (
|
{config.models.map((v) => (
|
||||||
<option value={v.name} key={v.name} disabled={!v.available}>
|
<option value={v.name} key={v.name} disabled={!v.available}>
|
||||||
{v.name}
|
{v.name}
|
||||||
</option>
|
</option>
|
||||||
@@ -48,6 +50,25 @@ export function ModelConfigList(props: {
|
|||||||
}}
|
}}
|
||||||
></InputRange>
|
></InputRange>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Settings.TopP.Title}
|
||||||
|
subTitle={Locale.Settings.TopP.SubTitle}
|
||||||
|
>
|
||||||
|
<InputRange
|
||||||
|
value={(props.modelConfig.top_p ?? 1).toFixed(1)}
|
||||||
|
min="0"
|
||||||
|
max="1"
|
||||||
|
step="0.1"
|
||||||
|
onChange={(e) => {
|
||||||
|
props.updateConfig(
|
||||||
|
(config) =>
|
||||||
|
(config.top_p = ModalConfigValidator.top_p(
|
||||||
|
e.currentTarget.valueAsNumber,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
></InputRange>
|
||||||
|
</ListItem>
|
||||||
<ListItem
|
<ListItem
|
||||||
title={Locale.Settings.MaxTokens.Title}
|
title={Locale.Settings.MaxTokens.Title}
|
||||||
subTitle={Locale.Settings.MaxTokens.SubTitle}
|
subTitle={Locale.Settings.MaxTokens.SubTitle}
|
||||||
|
@@ -14,6 +14,8 @@ import Locale from "../locales";
|
|||||||
import { useAppConfig, useChatStore } from "../store";
|
import { useAppConfig, useChatStore } from "../store";
|
||||||
import { MaskAvatar } from "./mask";
|
import { MaskAvatar } from "./mask";
|
||||||
import { useCommand } from "../command";
|
import { useCommand } from "../command";
|
||||||
|
import { showConfirm } from "./ui-lib";
|
||||||
|
import { BUILTIN_MASK_STORE } from "../masks";
|
||||||
|
|
||||||
function getIntersectionArea(aRect: DOMRect, bRect: DOMRect) {
|
function getIntersectionArea(aRect: DOMRect, bRect: DOMRect) {
|
||||||
const xmin = Math.max(aRect.x, bRect.x);
|
const xmin = Math.max(aRect.x, bRect.x);
|
||||||
@@ -92,14 +94,17 @@ export function NewChat() {
|
|||||||
const { state } = useLocation();
|
const { state } = useLocation();
|
||||||
|
|
||||||
const startChat = (mask?: Mask) => {
|
const startChat = (mask?: Mask) => {
|
||||||
chatStore.newSession(mask);
|
setTimeout(() => {
|
||||||
setTimeout(() => navigate(Path.Chat), 1);
|
chatStore.newSession(mask);
|
||||||
|
navigate(Path.Chat);
|
||||||
|
}, 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
useCommand({
|
useCommand({
|
||||||
mask: (id) => {
|
mask: (id) => {
|
||||||
try {
|
try {
|
||||||
const mask = maskStore.get(parseInt(id));
|
const intId = parseInt(id);
|
||||||
|
const mask = maskStore.get(intId) ?? BUILTIN_MASK_STORE.get(intId);
|
||||||
startChat(mask ?? undefined);
|
startChat(mask ?? undefined);
|
||||||
} catch {
|
} catch {
|
||||||
console.error("[New Chat] failed to create chat from mask id=", id);
|
console.error("[New Chat] failed to create chat from mask id=", id);
|
||||||
@@ -125,8 +130,8 @@ export function NewChat() {
|
|||||||
{!state?.fromHome && (
|
{!state?.fromHome && (
|
||||||
<IconButton
|
<IconButton
|
||||||
text={Locale.NewChat.NotShow}
|
text={Locale.NewChat.NotShow}
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
if (confirm(Locale.NewChat.ConfirmNoShow)) {
|
if (await showConfirm(Locale.NewChat.ConfirmNoShow)) {
|
||||||
startChat();
|
startChat();
|
||||||
config.update(
|
config.update(
|
||||||
(config) => (config.dontShowMaskSplashScreen = true),
|
(config) => (config.dontShowMaskSplashScreen = true),
|
||||||
|
@@ -18,6 +18,7 @@ import {
|
|||||||
PasswordInput,
|
PasswordInput,
|
||||||
Popover,
|
Popover,
|
||||||
Select,
|
Select,
|
||||||
|
showConfirm,
|
||||||
} from "./ui-lib";
|
} from "./ui-lib";
|
||||||
import { ModelConfigList } from "./model-config";
|
import { ModelConfigList } from "./model-config";
|
||||||
|
|
||||||
@@ -39,13 +40,14 @@ import Locale, {
|
|||||||
} from "../locales";
|
} from "../locales";
|
||||||
import { copyToClipboard } from "../utils";
|
import { copyToClipboard } from "../utils";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Path, UPDATE_URL } from "../constant";
|
import { Path, RELEASE_URL, UPDATE_URL } from "../constant";
|
||||||
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
|
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
|
||||||
import { ErrorBoundary } from "./error";
|
import { ErrorBoundary } from "./error";
|
||||||
import { InputRange } from "./input-range";
|
import { InputRange } from "./input-range";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { Avatar, AvatarPicker } from "./emoji";
|
import { Avatar, AvatarPicker } from "./emoji";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
import { useSyncStore } from "../store/sync";
|
||||||
|
|
||||||
function EditPromptModal(props: { id: number; onClose: () => void }) {
|
function EditPromptModal(props: { id: number; onClose: () => void }) {
|
||||||
const promptStore = usePromptStore();
|
const promptStore = usePromptStore();
|
||||||
@@ -198,17 +200,114 @@ function UserPromptModal(props: { onClose?: () => void }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatVersionDate(t: string) {
|
function DangerItems() {
|
||||||
const d = new Date(+t);
|
const chatStore = useChatStore();
|
||||||
const year = d.getUTCFullYear();
|
const appConfig = useAppConfig();
|
||||||
const month = d.getUTCMonth() + 1;
|
|
||||||
const day = d.getUTCDate();
|
|
||||||
|
|
||||||
return [
|
return (
|
||||||
year.toString(),
|
<List>
|
||||||
month.toString().padStart(2, "0"),
|
<ListItem
|
||||||
day.toString().padStart(2, "0"),
|
title={Locale.Settings.Danger.Reset.Title}
|
||||||
].join("");
|
subTitle={Locale.Settings.Danger.Reset.SubTitle}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
text={Locale.Settings.Danger.Reset.Action}
|
||||||
|
onClick={async () => {
|
||||||
|
if (await showConfirm(Locale.Settings.Danger.Reset.Confirm)) {
|
||||||
|
appConfig.reset();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
type="danger"
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Settings.Danger.Clear.Title}
|
||||||
|
subTitle={Locale.Settings.Danger.Clear.SubTitle}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
text={Locale.Settings.Danger.Clear.Action}
|
||||||
|
onClick={async () => {
|
||||||
|
if (await showConfirm(Locale.Settings.Danger.Clear.Confirm)) {
|
||||||
|
chatStore.clearAllData();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
type="danger"
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SyncItems() {
|
||||||
|
const syncStore = useSyncStore();
|
||||||
|
const webdav = syncStore.webDavConfig;
|
||||||
|
|
||||||
|
// not ready: https://github.com/Yidadaa/ChatGPT-Next-Web/issues/920#issuecomment-1609866332
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
<ListItem
|
||||||
|
title={"上次同步:" + new Date().toLocaleString()}
|
||||||
|
subTitle={"20 次对话,100 条消息,200 提示词,20 面具"}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
icon={<ResetIcon />}
|
||||||
|
text="同步"
|
||||||
|
onClick={() => {
|
||||||
|
syncStore.check().then(console.log);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
title={"本地备份"}
|
||||||
|
subTitle={"20 次对话,100 条消息,200 提示词,20 面具"}
|
||||||
|
></ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
title={"Web Dav Server"}
|
||||||
|
subTitle={Locale.Settings.AccessCode.SubTitle}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
value={webdav.server}
|
||||||
|
type="text"
|
||||||
|
placeholder={"https://example.com"}
|
||||||
|
onChange={(e) => {
|
||||||
|
syncStore.update(
|
||||||
|
(config) => (config.server = e.currentTarget.value),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem title="Web Dav User Name" subTitle="user name here">
|
||||||
|
<input
|
||||||
|
value={webdav.username}
|
||||||
|
type="text"
|
||||||
|
placeholder={"username"}
|
||||||
|
onChange={(e) => {
|
||||||
|
syncStore.update(
|
||||||
|
(config) => (config.username = e.currentTarget.value),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem title="Web Dav Password" subTitle="password here">
|
||||||
|
<input
|
||||||
|
value={webdav.password}
|
||||||
|
type="text"
|
||||||
|
placeholder={"password"}
|
||||||
|
onChange={(e) => {
|
||||||
|
syncStore.update(
|
||||||
|
(config) => (config.password = e.currentTarget.value),
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Settings() {
|
export function Settings() {
|
||||||
@@ -216,14 +315,14 @@ export function Settings() {
|
|||||||
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
||||||
const config = useAppConfig();
|
const config = useAppConfig();
|
||||||
const updateConfig = config.update;
|
const updateConfig = config.update;
|
||||||
const resetConfig = config.reset;
|
|
||||||
const chatStore = useChatStore();
|
const chatStore = useChatStore();
|
||||||
|
|
||||||
const updateStore = useUpdateStore();
|
const updateStore = useUpdateStore();
|
||||||
const [checkingUpdate, setCheckingUpdate] = useState(false);
|
const [checkingUpdate, setCheckingUpdate] = useState(false);
|
||||||
const currentVersion = formatVersionDate(updateStore.version);
|
const currentVersion = updateStore.formatVersion(updateStore.version);
|
||||||
const remoteId = formatVersionDate(updateStore.remoteVersion);
|
const remoteId = updateStore.formatVersion(updateStore.remoteVersion);
|
||||||
const hasNewVersion = currentVersion !== remoteId;
|
const hasNewVersion = currentVersion !== remoteId;
|
||||||
|
const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL;
|
||||||
|
|
||||||
function checkUpdate(force = false) {
|
function checkUpdate(force = false) {
|
||||||
setCheckingUpdate(true);
|
setCheckingUpdate(true);
|
||||||
@@ -231,14 +330,8 @@ export function Settings() {
|
|||||||
setCheckingUpdate(false);
|
setCheckingUpdate(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
console.log("[Update] local version ", updateStore.version);
|
||||||
"[Update] local version ",
|
console.log("[Update] remote version ", updateStore.remoteVersion);
|
||||||
new Date(+updateStore.version).toLocaleString(),
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"[Update] remote version ",
|
|
||||||
new Date(+updateStore.remoteVersion).toLocaleString(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const usage = {
|
const usage = {
|
||||||
@@ -247,6 +340,10 @@ export function Settings() {
|
|||||||
};
|
};
|
||||||
const [loadingUsage, setLoadingUsage] = useState(false);
|
const [loadingUsage, setLoadingUsage] = useState(false);
|
||||||
function checkUsage(force = false) {
|
function checkUsage(force = false) {
|
||||||
|
if (accessStore.hideBalanceQuery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setLoadingUsage(true);
|
setLoadingUsage(true);
|
||||||
updateStore.updateUsage(force).finally(() => {
|
updateStore.updateUsage(force).finally(() => {
|
||||||
setLoadingUsage(false);
|
setLoadingUsage(false);
|
||||||
@@ -301,36 +398,13 @@ export function Settings() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="window-actions">
|
<div className="window-actions">
|
||||||
<div className="window-action-button">
|
<div className="window-action-button"></div>
|
||||||
<IconButton
|
<div className="window-action-button"></div>
|
||||||
icon={<ClearIcon />}
|
|
||||||
onClick={() => {
|
|
||||||
if (confirm(Locale.Settings.Actions.ConfirmClearAll)) {
|
|
||||||
chatStore.clearAllData();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
bordered
|
|
||||||
title={Locale.Settings.Actions.ClearAll}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="window-action-button">
|
|
||||||
<IconButton
|
|
||||||
icon={<ResetIcon />}
|
|
||||||
onClick={() => {
|
|
||||||
if (confirm(Locale.Settings.Actions.ConfirmResetAll)) {
|
|
||||||
resetConfig();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
bordered
|
|
||||||
title={Locale.Settings.Actions.ResetAll}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="window-action-button">
|
<div className="window-action-button">
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<CloseIcon />}
|
icon={<CloseIcon />}
|
||||||
onClick={() => navigate(Path.Home)}
|
onClick={() => navigate(Path.Home)}
|
||||||
bordered
|
bordered
|
||||||
title={Locale.Settings.Actions.Close}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -372,7 +446,7 @@ export function Settings() {
|
|||||||
{checkingUpdate ? (
|
{checkingUpdate ? (
|
||||||
<LoadingIcon />
|
<LoadingIcon />
|
||||||
) : hasNewVersion ? (
|
) : hasNewVersion ? (
|
||||||
<Link href={UPDATE_URL} target="_blank" className="link">
|
<Link href={updateUrl} target="_blank" className="link">
|
||||||
{Locale.Settings.Update.GoToUpdate}
|
{Locale.Settings.Update.GoToUpdate}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
@@ -468,10 +542,12 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
></input>
|
></input>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
|
||||||
|
<List>
|
||||||
<ListItem
|
<ListItem
|
||||||
title={Locale.Settings.Mask.Title}
|
title={Locale.Settings.Mask.Splash.Title}
|
||||||
subTitle={Locale.Settings.Mask.SubTitle}
|
subTitle={Locale.Settings.Mask.Splash.SubTitle}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -485,6 +561,22 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
></input>
|
></input>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Settings.Mask.Builtin.Title}
|
||||||
|
subTitle={Locale.Settings.Mask.Builtin.SubTitle}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.hideBuiltinMasks}
|
||||||
|
onChange={(e) =>
|
||||||
|
updateConfig(
|
||||||
|
(config) =>
|
||||||
|
(config.hideBuiltinMasks = e.currentTarget.checked),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
></input>
|
||||||
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
@@ -507,19 +599,34 @@ export function Settings() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!accessStore.hideUserApiKey ? (
|
{!accessStore.hideUserApiKey ? (
|
||||||
<ListItem
|
<>
|
||||||
title={Locale.Settings.Token.Title}
|
<ListItem
|
||||||
subTitle={Locale.Settings.Token.SubTitle}
|
title={Locale.Settings.Endpoint.Title}
|
||||||
>
|
subTitle={Locale.Settings.Endpoint.SubTitle}
|
||||||
<PasswordInput
|
>
|
||||||
value={accessStore.token}
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={Locale.Settings.Token.Placeholder}
|
value={accessStore.openaiUrl}
|
||||||
onChange={(e) => {
|
placeholder="https://api.openai.com/"
|
||||||
accessStore.updateToken(e.currentTarget.value);
|
onChange={(e) =>
|
||||||
}}
|
accessStore.updateOpenAiUrl(e.currentTarget.value)
|
||||||
/>
|
}
|
||||||
</ListItem>
|
></input>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
title={Locale.Settings.Token.Title}
|
||||||
|
subTitle={Locale.Settings.Token.SubTitle}
|
||||||
|
>
|
||||||
|
<PasswordInput
|
||||||
|
value={accessStore.token}
|
||||||
|
type="text"
|
||||||
|
placeholder={Locale.Settings.Token.Placeholder}
|
||||||
|
onChange={(e) => {
|
||||||
|
accessStore.updateToken(e.currentTarget.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!accessStore.hideBalanceQuery ? (
|
{!accessStore.hideBalanceQuery ? (
|
||||||
@@ -547,21 +654,6 @@ export function Settings() {
|
|||||||
)}
|
)}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!accessStore.hideUserApiKey ? (
|
|
||||||
<ListItem
|
|
||||||
title={Locale.Settings.Endpoint.Title}
|
|
||||||
subTitle={Locale.Settings.Endpoint.SubTitle}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={accessStore.openaiUrl}
|
|
||||||
onChange={(e) =>
|
|
||||||
accessStore.updateOpenAiUrl(e.currentTarget.value)
|
|
||||||
}
|
|
||||||
></input>
|
|
||||||
</ListItem>
|
|
||||||
) : null}
|
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
@@ -596,6 +688,8 @@ export function Settings() {
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
|
<SyncItems />
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
<ModelConfigList
|
<ModelConfigList
|
||||||
modelConfig={config.modelConfig}
|
modelConfig={config.modelConfig}
|
||||||
@@ -610,6 +704,8 @@ export function Settings() {
|
|||||||
{shouldShowPromptModal && (
|
{shouldShowPromptModal && (
|
||||||
<UserPromptModal onClose={() => setShowPromptModal(false)} />
|
<UserPromptModal onClose={() => setShowPromptModal(false)} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<DangerItems />
|
||||||
</div>
|
</div>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
|
@@ -26,7 +26,7 @@ import {
|
|||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { useMobileScreen } from "../utils";
|
import { useMobileScreen } from "../utils";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { showToast } from "./ui-lib";
|
import { showConfirm, showToast } from "./ui-lib";
|
||||||
|
|
||||||
const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, {
|
const ChatList = dynamic(async () => (await import("./chat-list")).ChatList, {
|
||||||
loading: () => null,
|
loading: () => null,
|
||||||
@@ -37,7 +37,7 @@ function useHotKey() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onKeyDown = (e: KeyboardEvent) => {
|
const onKeyDown = (e: KeyboardEvent) => {
|
||||||
if (e.metaKey || e.altKey || e.ctrlKey) {
|
if (e.altKey || e.ctrlKey) {
|
||||||
if (e.key === "ArrowUp") {
|
if (e.key === "ArrowUp") {
|
||||||
chatStore.nextSession(-1);
|
chatStore.nextSession(-1);
|
||||||
} else if (e.key === "ArrowDown") {
|
} else if (e.key === "ArrowDown") {
|
||||||
@@ -160,8 +160,8 @@ export function SideBar(props: { className?: string }) {
|
|||||||
<div className={styles["sidebar-action"] + " " + styles.mobile}>
|
<div className={styles["sidebar-action"] + " " + styles.mobile}>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<CloseIcon />}
|
icon={<CloseIcon />}
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
if (confirm(Locale.Home.DeleteChat)) {
|
if (await showConfirm(Locale.Home.DeleteChat)) {
|
||||||
chatStore.deleteSession(chatStore.currentSessionIndex);
|
chatStore.deleteSession(chatStore.currentSessionIndex);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
animation: slide-in ease 0.3s;
|
animation: slide-in ease 0.3s;
|
||||||
|
background: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.list .list-item:last-child {
|
.list .list-item:last-child {
|
||||||
@@ -72,11 +73,26 @@
|
|||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
width: 60vw;
|
width: 80vw;
|
||||||
|
max-width: 900px;
|
||||||
|
min-width: 300px;
|
||||||
animation: slide-in ease 0.3s;
|
animation: slide-in ease 0.3s;
|
||||||
|
|
||||||
--modal-padding: 20px;
|
--modal-padding: 20px;
|
||||||
|
|
||||||
|
&-max {
|
||||||
|
width: 95vw;
|
||||||
|
max-width: unset;
|
||||||
|
height: 95vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
max-height: unset !important;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.modal-header {
|
.modal-header {
|
||||||
padding: var(--modal-padding);
|
padding: var(--modal-padding);
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -89,11 +105,19 @@
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close-btn {
|
.modal-header-actions {
|
||||||
cursor: pointer;
|
display: flex;
|
||||||
|
|
||||||
&:hover {
|
.modal-header-action {
|
||||||
filter: brightness(1.2);
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +231,7 @@
|
|||||||
.select-with-icon {
|
.select-with-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
|
|
||||||
.select-with-icon-select {
|
.select-with-icon-select {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: var(--border-in-light);
|
border: var(--border-in-light);
|
||||||
@@ -227,4 +251,55 @@
|
|||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-input {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: var(--border-in-light);
|
||||||
|
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.03);
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--black);
|
||||||
|
font-family: inherit;
|
||||||
|
padding: 10px;
|
||||||
|
resize: none;
|
||||||
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border: 1px solid var(--primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
.list {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--white);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
filter: brightness(0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,9 +1,16 @@
|
|||||||
|
/* eslint-disable @next/next/no-img-element */
|
||||||
import styles from "./ui-lib.module.scss";
|
import styles from "./ui-lib.module.scss";
|
||||||
import LoadingIcon from "../icons/three-dots.svg";
|
import LoadingIcon from "../icons/three-dots.svg";
|
||||||
import CloseIcon from "../icons/close.svg";
|
import CloseIcon from "../icons/close.svg";
|
||||||
import EyeIcon from "../icons/eye.svg";
|
import EyeIcon from "../icons/eye.svg";
|
||||||
import EyeOffIcon from "../icons/eye-off.svg";
|
import EyeOffIcon from "../icons/eye-off.svg";
|
||||||
import DownIcon from "../icons/down.svg";
|
import DownIcon from "../icons/down.svg";
|
||||||
|
import ConfirmIcon from "../icons/confirm.svg";
|
||||||
|
import CancelIcon from "../icons/cancel.svg";
|
||||||
|
import MaxIcon from "../icons/max.svg";
|
||||||
|
import MinIcon from "../icons/min.svg";
|
||||||
|
|
||||||
|
import Locale from "../locales";
|
||||||
|
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import React, { HTMLProps, useEffect, useState } from "react";
|
import React, { HTMLProps, useEffect, useState } from "react";
|
||||||
@@ -40,9 +47,13 @@ export function ListItem(props: {
|
|||||||
children?: JSX.Element | JSX.Element[];
|
children?: JSX.Element | JSX.Element[];
|
||||||
icon?: JSX.Element;
|
icon?: JSX.Element;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
onClick?: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={styles["list-item"] + ` ${props.className || ""}`}>
|
<div
|
||||||
|
className={styles["list-item"] + ` ${props.className || ""}`}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
<div className={styles["list-header"]}>
|
<div className={styles["list-header"]}>
|
||||||
{props.icon && <div className={styles["list-icon"]}>{props.icon}</div>}
|
{props.icon && <div className={styles["list-icon"]}>{props.icon}</div>}
|
||||||
<div className={styles["list-item-title"]}>
|
<div className={styles["list-item-title"]}>
|
||||||
@@ -87,8 +98,9 @@ export function Loading() {
|
|||||||
|
|
||||||
interface ModalProps {
|
interface ModalProps {
|
||||||
title: string;
|
title: string;
|
||||||
children?: JSX.Element | JSX.Element[];
|
children?: any;
|
||||||
actions?: JSX.Element[];
|
actions?: JSX.Element[];
|
||||||
|
defaultMax?: boolean;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
export function Modal(props: ModalProps) {
|
export function Modal(props: ModalProps) {
|
||||||
@@ -107,13 +119,30 @@ export function Modal(props: ModalProps) {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const [isMax, setMax] = useState(!!props.defaultMax);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles["modal-container"]}>
|
<div
|
||||||
|
className={
|
||||||
|
styles["modal-container"] + ` ${isMax && styles["modal-container-max"]}`
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className={styles["modal-header"]}>
|
<div className={styles["modal-header"]}>
|
||||||
<div className={styles["modal-title"]}>{props.title}</div>
|
<div className={styles["modal-title"]}>{props.title}</div>
|
||||||
|
|
||||||
<div className={styles["modal-close-btn"]} onClick={props.onClose}>
|
<div className={styles["modal-header-actions"]}>
|
||||||
<CloseIcon />
|
<div
|
||||||
|
className={styles["modal-header-action"]}
|
||||||
|
onClick={() => setMax(!isMax)}
|
||||||
|
>
|
||||||
|
{isMax ? <MinIcon /> : <MaxIcon />}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={styles["modal-header-action"]}
|
||||||
|
onClick={props.onClose}
|
||||||
|
>
|
||||||
|
<CloseIcon />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -262,3 +291,182 @@ export function Select(
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function showConfirm(content: any) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.className = "modal-mask";
|
||||||
|
document.body.appendChild(div);
|
||||||
|
|
||||||
|
const root = createRoot(div);
|
||||||
|
const closeModal = () => {
|
||||||
|
root.unmount();
|
||||||
|
div.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise<boolean>((resolve) => {
|
||||||
|
root.render(
|
||||||
|
<Modal
|
||||||
|
title={Locale.UI.Confirm}
|
||||||
|
actions={[
|
||||||
|
<IconButton
|
||||||
|
key="cancel"
|
||||||
|
text={Locale.UI.Cancel}
|
||||||
|
onClick={() => {
|
||||||
|
resolve(false);
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
icon={<CancelIcon />}
|
||||||
|
tabIndex={0}
|
||||||
|
bordered
|
||||||
|
shadow
|
||||||
|
></IconButton>,
|
||||||
|
<IconButton
|
||||||
|
key="confirm"
|
||||||
|
text={Locale.UI.Confirm}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
resolve(true);
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
icon={<ConfirmIcon />}
|
||||||
|
tabIndex={0}
|
||||||
|
autoFocus
|
||||||
|
bordered
|
||||||
|
shadow
|
||||||
|
></IconButton>,
|
||||||
|
]}
|
||||||
|
onClose={closeModal}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</Modal>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function PromptInput(props: {
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
rows?: number;
|
||||||
|
}) {
|
||||||
|
const [input, setInput] = useState(props.value);
|
||||||
|
const onInput = (value: string) => {
|
||||||
|
props.onChange(value);
|
||||||
|
setInput(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
className={styles["modal-input"]}
|
||||||
|
autoFocus
|
||||||
|
value={input}
|
||||||
|
onInput={(e) => onInput(e.currentTarget.value)}
|
||||||
|
rows={props.rows ?? 3}
|
||||||
|
></textarea>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showPrompt(content: any, value = "", rows = 3) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.className = "modal-mask";
|
||||||
|
document.body.appendChild(div);
|
||||||
|
|
||||||
|
const root = createRoot(div);
|
||||||
|
const closeModal = () => {
|
||||||
|
root.unmount();
|
||||||
|
div.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise<string>((resolve) => {
|
||||||
|
let userInput = "";
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<Modal
|
||||||
|
title={content}
|
||||||
|
actions={[
|
||||||
|
<IconButton
|
||||||
|
key="cancel"
|
||||||
|
text={Locale.UI.Cancel}
|
||||||
|
onClick={() => {
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
icon={<CancelIcon />}
|
||||||
|
bordered
|
||||||
|
shadow
|
||||||
|
tabIndex={0}
|
||||||
|
></IconButton>,
|
||||||
|
<IconButton
|
||||||
|
key="confirm"
|
||||||
|
text={Locale.UI.Confirm}
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
resolve(userInput);
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
icon={<ConfirmIcon />}
|
||||||
|
bordered
|
||||||
|
shadow
|
||||||
|
tabIndex={0}
|
||||||
|
></IconButton>,
|
||||||
|
]}
|
||||||
|
onClose={closeModal}
|
||||||
|
>
|
||||||
|
<PromptInput
|
||||||
|
onChange={(val) => (userInput = val)}
|
||||||
|
value={value}
|
||||||
|
rows={rows}
|
||||||
|
></PromptInput>
|
||||||
|
</Modal>,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showImageModal(img: string) {
|
||||||
|
showModal({
|
||||||
|
title: Locale.Export.Image.Modal,
|
||||||
|
children: (
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src={img}
|
||||||
|
alt="preview"
|
||||||
|
style={{
|
||||||
|
maxWidth: "100%",
|
||||||
|
}}
|
||||||
|
></img>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Selector<T>(props: {
|
||||||
|
items: Array<{
|
||||||
|
title: string;
|
||||||
|
subTitle?: string;
|
||||||
|
value: T;
|
||||||
|
}>;
|
||||||
|
onSelection?: (selection: T[]) => void;
|
||||||
|
onClose?: () => void;
|
||||||
|
multiple?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className={styles["selector"]} onClick={() => props.onClose?.()}>
|
||||||
|
<div className={styles["selector-content"]}>
|
||||||
|
<List>
|
||||||
|
{props.items.map((item, i) => {
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
className={styles["selector-item"]}
|
||||||
|
key={i}
|
||||||
|
title={item.title}
|
||||||
|
subTitle={item.subTitle}
|
||||||
|
onClick={() => {
|
||||||
|
props.onSelection?.([item.value]);
|
||||||
|
props.onClose?.();
|
||||||
|
}}
|
||||||
|
></ListItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
import tauriConfig from "../../src-tauri/tauri.conf.json";
|
||||||
|
|
||||||
export const getBuildConfig = () => {
|
export const getBuildConfig = () => {
|
||||||
if (typeof process === "undefined") {
|
if (typeof process === "undefined") {
|
||||||
throw Error(
|
throw Error(
|
||||||
@@ -5,23 +7,37 @@ export const getBuildConfig = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const COMMIT_ID: string = (() => {
|
const buildMode = process.env.BUILD_MODE ?? "standalone";
|
||||||
|
const isApp = !!process.env.BUILD_APP;
|
||||||
|
const version = "v" + tauriConfig.package.version;
|
||||||
|
|
||||||
|
const commitInfo = (() => {
|
||||||
try {
|
try {
|
||||||
const childProcess = require("child_process");
|
const childProcess = require("child_process");
|
||||||
return childProcess
|
const commitDate: string = childProcess
|
||||||
.execSync('git log -1 --format="%at000" --date=unix')
|
.execSync('git log -1 --format="%at000" --date=unix')
|
||||||
.toString()
|
.toString()
|
||||||
.trim();
|
.trim();
|
||||||
|
const commitHash: string = childProcess
|
||||||
|
.execSync('git log --pretty=format:"%H" -n 1')
|
||||||
|
.toString()
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
return { commitDate, commitHash };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("[Build Config] No git or not from git repo.");
|
console.error("[Build Config] No git or not from git repo.");
|
||||||
return "unknown";
|
return {
|
||||||
|
commitDate: "unknown",
|
||||||
|
commitHash: "unknown",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
commitId: COMMIT_ID,
|
version,
|
||||||
buildMode: process.env.BUILD_MODE ?? "standalone",
|
...commitInfo,
|
||||||
isApp: !!process.env.BUILD_APP,
|
buildMode,
|
||||||
|
isApp,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ export const getServerSideConfig = () => {
|
|||||||
proxyUrl: process.env.PROXY_URL,
|
proxyUrl: process.env.PROXY_URL,
|
||||||
isVercel: !!process.env.VERCEL,
|
isVercel: !!process.env.VERCEL,
|
||||||
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
|
||||||
enableGPT4: !process.env.DISABLE_GPT4,
|
disableGPT4: !!process.env.DISABLE_GPT4,
|
||||||
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
|
hideBalanceQuery: !!process.env.HIDE_BALANCE_QUERY,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -3,6 +3,7 @@ export const REPO = "ChatGPT-Next-Web";
|
|||||||
export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
|
export const REPO_URL = `https://github.com/${OWNER}/${REPO}`;
|
||||||
export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;
|
export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;
|
||||||
export const UPDATE_URL = `${REPO_URL}#keep-updated`;
|
export const UPDATE_URL = `${REPO_URL}#keep-updated`;
|
||||||
|
export const RELEASE_URL = `${REPO_URL}/releases`;
|
||||||
export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
|
export const FETCH_COMMIT_URL = `https://api.github.com/repos/${OWNER}/${REPO}/commits?per_page=1`;
|
||||||
export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
|
export const FETCH_TAG_URL = `https://api.github.com/repos/${OWNER}/${REPO}/tags?per_page=1`;
|
||||||
export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
|
export const RUNTIME_CONFIG_DOM = "danger-runtime-config";
|
||||||
@@ -33,6 +34,7 @@ export enum StoreKey {
|
|||||||
Mask = "mask-store",
|
Mask = "mask-store",
|
||||||
Prompt = "prompt-store",
|
Prompt = "prompt-store",
|
||||||
Update = "chat-update",
|
Update = "chat-update",
|
||||||
|
Sync = "sync",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MAX_SIDEBAR_WIDTH = 500;
|
export const MAX_SIDEBAR_WIDTH = 500;
|
||||||
@@ -51,6 +53,79 @@ export const OpenaiPath = {
|
|||||||
ChatPath: "v1/chat/completions",
|
ChatPath: "v1/chat/completions",
|
||||||
UsagePath: "dashboard/billing/usage",
|
UsagePath: "dashboard/billing/usage",
|
||||||
SubsPath: "dashboard/billing/subscription",
|
SubsPath: "dashboard/billing/subscription",
|
||||||
|
ListModelPath: "v1/models",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang
|
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
|
||||||
|
Current model: {{model}}
|
||||||
|
Current time: {{time}}`;
|
||||||
|
|
||||||
|
export const DEFAULT_MODELS = [
|
||||||
|
{
|
||||||
|
name: "gpt-4",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-0314",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k-0314",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-4-32k-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-0301",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-16k",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gpt-3.5-turbo-16k-0613",
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "qwen-v1", // 通义千问
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ernie", // 文心一言
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "spark", // 讯飞星火
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "llama", // llama
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "chatglm", // chatglm-6b
|
||||||
|
available: false,
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
6
app/global.d.ts
vendored
6
app/global.d.ts
vendored
@@ -9,3 +9,9 @@ declare module "*.scss" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.svg";
|
declare module "*.svg";
|
||||||
|
|
||||||
|
declare interface Window {
|
||||||
|
__TAURI__?: {
|
||||||
|
writeText(text: string): Promise<void>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
1
app/icons/cancel.svg
Normal file
1
app/icons/cancel.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><g opacity="1" transform="translate(0 0) rotate(0)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path id="路径 1" style="fill:#333333; opacity:1;" d="M13.9967,8.00337c0,-0.81625 -0.1569,-1.59615 -0.4707,-2.3397c-0.30307,-0.71824 -0.73117,-1.3542 -1.2843,-1.90789c-0.55287,-0.55348 -1.18783,-0.98185 -1.9049,-1.28512c-0.74182,-0.31375 -1.51963,-0.47062 -2.33343,-0.47062c-0.81634,0 -1.59621,0.15693 -2.3396,0.47079c-0.71828,0.30325 -1.35419,0.73165 -1.90774,1.2852c-0.55355,0.55354 -0.98195,1.18945 -1.2852,1.90774c-0.31386,0.74339 -0.47079,1.52326 -0.47079,2.3396c0,0.8138 0.15687,1.59161 0.47062,2.33343c0.30327,0.71707 0.73164,1.35203 1.28512,1.9049c0.55369,0.55313 1.18965,0.98123 1.90789,1.2843c0.74355,0.3138 1.52345,0.4707 2.3397,0.4707c0.81371,0 1.59155,-0.15683 2.33353,-0.4705c0.717,-0.30313 1.35203,-0.7312 1.9051,-1.2842c0.553,-0.55307 0.98107,-1.1881 1.2842,-1.9051c0.31367,-0.74198 0.4705,-1.51982 0.4705,-2.33353zM15.33,8.00337c0,0.99387 -0.1919,1.94478 -0.5757,2.85273c-0.37067,0.87673 -0.89383,1.65297 -1.5695,2.3287c-0.67573,0.67567 -1.45197,1.19883 -2.3287,1.5695c-0.90795,0.3838 -1.85886,0.5757 -2.85273,0.5757c-0.99612,0 -1.94882,-0.19183 -2.8581,-0.5755c-0.8781,-0.3706 -1.65537,-0.89377 -2.33181,-1.5695c-0.67631,-0.6756 -1.19992,-1.45187 -1.57081,-2.3288c-0.38396,-0.90784 -0.57594,-1.85878 -0.57594,-2.85283c0,-0.99629 0.19192,-1.94903 0.57577,-2.8582c0.37081,-0.87829 0.89439,-1.6556 1.57074,-2.33195c0.67635,-0.67635 1.45367,-1.19993 2.33195,-1.57074c0.90917,-0.38385 1.86191,-0.57577 2.8582,-0.57577c0.99405,0 1.94499,0.19198 2.85283,0.57594c0.87693,0.37089 1.6532,0.8945 2.3288,1.57081c0.67573,0.67644 1.1989,1.45371 1.5695,2.33181c0.38367,0.90928 0.5755,1.86198 0.5755,2.8581z"></path><path id="路径 2" style="fill:#333333; opacity:1;" d="M5.4714,4.5286l6,6c0.03093,0.03093 0.05857,0.0646 0.0829,0.101c0.02433,0.0364 0.04487,0.07483 0.0616,0.1153c0.01673,0.0404 0.0294,0.08207 0.038,0.125c0.00853,0.04293 0.0128,0.0863 0.0128,0.1301c0,0.0438 -0.00427,0.08717 -0.0128,0.1301c-0.0086,0.04293 -0.02127,0.0846 -0.038,0.125c-0.01673,0.04047 -0.03727,0.0789 -0.0616,0.1153c-0.02433,0.0364 -0.05197,0.07007 -0.0829,0.101c-0.03093,0.03093 -0.0646,0.05857 -0.101,0.0829c-0.0364,0.02433 -0.07483,0.04487 -0.1153,0.0616c-0.0404,0.01673 -0.08207,0.0294 -0.125,0.038c-0.04293,0.00853 -0.0863,0.0128 -0.1301,0.0128c-0.0438,0 -0.08717,-0.00427 -0.1301,-0.0128c-0.04293,-0.0086 -0.0846,-0.02127 -0.125,-0.038c-0.04047,-0.01673 -0.0789,-0.03727 -0.1153,-0.0616c-0.0364,-0.02433 -0.07007,-0.05197 -0.101,-0.0829l-6,-6c-0.03095,-0.03095 -0.05859,-0.06463 -0.08291,-0.10102c-0.02432,-0.0364 -0.04486,-0.07482 -0.06161,-0.11526c-0.01675,-0.04044 -0.0294,-0.08213 -0.03794,-0.12506c-0.00854,-0.04293 -0.01281,-0.08629 -0.01281,-0.13006c0,-0.04377 0.00427,-0.08713 0.01281,-0.13006c0.00854,-0.04293 0.02119,-0.08462 0.03794,-0.12506c0.01675,-0.04045 0.03729,-0.07887 0.06161,-0.11526c0.02432,-0.0364 0.05196,-0.07007 0.08291,-0.10102c0.03095,-0.03095 0.06462,-0.05859 0.10102,-0.08291c0.03639,-0.02432 0.07481,-0.04486 0.11526,-0.06161c0.04044,-0.01675 0.08213,-0.0294 0.12506,-0.03794c0.04293,-0.00854 0.08629,-0.01281 0.13006,-0.01281c0.04377,0 0.08713,0.00427 0.13006,0.01281c0.04293,0.00854 0.08462,0.02119 0.12506,0.03794c0.04044,0.01675 0.07886,0.03729 0.11526,0.06161c0.03639,0.02432 0.07007,0.05196 0.10102,0.08291z"></path></g></g><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs></svg>
|
After Width: | Height: | Size: 3.5 KiB |
1
app/icons/confirm.svg
Normal file
1
app/icons/confirm.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><g opacity="1" transform="translate(0 0) rotate(0)"><mask id="bg-mask-0" fill="white"><use xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path id="路径 1" style="fill:#333333; opacity:1;" d="M5.99607,12.8916c-0.03633,0.02413 -0.07466,0.04453 -0.11499,0.0612c-0.04034,0.01667 -0.08191,0.02923 -0.12471,0.0377c-0.04281,0.00853 -0.08603,0.0128 -0.12967,0.0128c-0.04364,0 -0.08686,-0.00423 -0.12966,-0.0127c-0.04281,-0.00847 -0.08438,-0.02103 -0.12472,-0.0377c-0.04034,-0.01667 -0.07867,-0.03707 -0.115,-0.0612c-0.03633,-0.0242 -0.06997,-0.0517 -0.1009,-0.0825l-3.96,-3.93998c-0.03103,-0.03087 -0.05876,-0.06448 -0.08317,-0.10081c-0.02441,-0.03634 -0.04505,-0.07471 -0.0619,-0.1151c-0.01685,-0.0404 -0.0296,-0.08206 -0.03825,-0.12497c-0.00865,-0.04291 -0.01303,-0.08626 -0.01314,-0.13003c-0.00011,-0.04377 0.00405,-0.08714 0.01248,-0.13009c0.00843,-0.04295 0.02097,-0.08467 0.03762,-0.12516c0.01665,-0.04048 0.03709,-0.07895 0.06132,-0.11541c0.02423,-0.03646 0.05178,-0.0702 0.08265,-0.10123c0.03087,-0.03103 0.06448,-0.05876 0.10081,-0.08317c0.03634,-0.02441 0.07471,-0.04505 0.11511,-0.0619c0.04039,-0.01685 0.08205,-0.0296 0.12496,-0.03825c0.04291,-0.00865 0.08626,-0.01303 0.13003,-0.01314c0.04377,-0.00011 0.08714,0.00405 0.13009,0.01248c0.04295,0.00843 0.08467,0.02097 0.12516,0.03762c0.04048,0.01665 0.07895,0.03709 0.11541,0.06132c0.03646,0.02423 0.07021,0.05178 0.10124,0.08265l3.48968,3.47207l8.23978,-8.20196c0.031,-0.03088 0.06473,-0.05844 0.1012,-0.08268c0.03647,-0.02423 0.07493,-0.04468 0.1154,-0.06134c0.04047,-0.01666 0.0822,-0.02921 0.1252,-0.03765c0.04293,-0.00844 0.0863,-0.01261 0.1301,-0.01251c0.04373,0.0001 0.08707,0.00447 0.13,0.01311c0.04293,0.00864 0.0846,0.02138 0.125,0.03822c0.0404,0.01685 0.07877,0.03747 0.1151,0.06188c0.03633,0.0244 0.06993,0.05211 0.1008,0.08314c0.0624,0.06265 0.1104,0.13486 0.144,0.21661c0.03367,0.08175 0.0504,0.16683 0.0502,0.25524c-0.0002,0.08841 -0.0173,0.17341 -0.0513,0.25501c-0.03407,0.08159 -0.08243,0.15357 -0.1451,0.21594l-8.70996,8.66999c-0.03093,0.0308 -0.06455,0.0583 -0.10087,0.0825z"></path></g></g><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs></svg>
|
After Width: | Height: | Size: 2.2 KiB |
@@ -100,13 +100,7 @@ const ar: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "الإعدادات",
|
Title: "الإعدادات",
|
||||||
SubTitle: "جميع الإعدادات",
|
SubTitle: "جميع الإعدادات",
|
||||||
Actions: {
|
|
||||||
ClearAll: "مسح جميع البيانات",
|
|
||||||
ResetAll: "إعادة تعيين جميع الإعدادات",
|
|
||||||
Close: "إغلاق",
|
|
||||||
ConfirmResetAll: "هل أنت متأكد من رغبتك في إعادة تعيين جميع الإعدادات؟",
|
|
||||||
ConfirmClearAll: "هل أنت متأكد من رغبتك في مسح جميع البيانات؟",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // تنبيه: إذا كنت ترغب في إضافة ترجمة جديدة، يرجى عدم ترجمة هذه القيمة وتركها "Language"
|
Name: "Language", // تنبيه: إذا كنت ترغب في إضافة ترجمة جديدة، يرجى عدم ترجمة هذه القيمة وتركها "Language"
|
||||||
All: "كل اللغات",
|
All: "كل اللغات",
|
||||||
@@ -136,8 +130,10 @@ const ar: PartialLocaleType = {
|
|||||||
SubTitle: "معاينة Markdown في فقاعة",
|
SubTitle: "معاينة Markdown في فقاعة",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "شاشة تظهر الأقنعة",
|
Splash: {
|
||||||
SubTitle: "عرض شاشة تظهر الأقنعة قبل بدء الدردشة الجديدة",
|
Title: "شاشة تظهر الأقنعة",
|
||||||
|
SubTitle: "عرض شاشة تظهر الأقنعة قبل بدء الدردشة الجديدة",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
338
app/locales/bn.ts
Normal file
338
app/locales/bn.ts
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
import { SubmitKey } from "../store/config";
|
||||||
|
import { PartialLocaleType } from "./index";
|
||||||
|
|
||||||
|
const bn: PartialLocaleType = {
|
||||||
|
WIP: "শীঘ্রই আসছে...",
|
||||||
|
Error: {
|
||||||
|
Unauthorized:
|
||||||
|
"অননুমোদিত অ্যাক্সেস, অনুগ্রহ করে [অথোরাইজশন](/#/auth) পৃষ্ঠায় অ্যাক্সেস কোড ইনপুট করুন।",
|
||||||
|
},
|
||||||
|
Auth: {
|
||||||
|
Title: "একটি অ্যাক্সেস কোড প্রয়োজন",
|
||||||
|
Tips: "নীচে অ্যাক্সেস কোড ইনপুট করুন",
|
||||||
|
Input: "অ্যাক্সেস কোড",
|
||||||
|
Confirm: "নিশ্চিত করুন",
|
||||||
|
Later: "পরে",
|
||||||
|
},
|
||||||
|
ChatItem: {
|
||||||
|
ChatItemCount: (count: number) => `${count} টি বার্তা`,
|
||||||
|
},
|
||||||
|
Chat: {
|
||||||
|
SubTitle: (count: number) => `${count} টি বার্তা`,
|
||||||
|
Actions: {
|
||||||
|
ChatList: "চ্যাট তালিকায় যান",
|
||||||
|
CompressedHistory: "সংক্ষিপ্ত ইতিহাস মেমোরি প্রম্পট",
|
||||||
|
Export: "সমস্ত বার্তা মার্কডাউন হিসাবে রপ্তানি করুন",
|
||||||
|
Copy: "কপি",
|
||||||
|
Stop: "বন্ধ করুন",
|
||||||
|
Retry: "পুনরায় চেষ্টা করুন",
|
||||||
|
Pin: "পিন করুন",
|
||||||
|
PinToastContent: "পিন করা হয়েছে ২টি বার্তা প্রম্পটে",
|
||||||
|
PinToastAction: "দেখুন",
|
||||||
|
Delete: "মুছে ফেলুন",
|
||||||
|
Edit: "সম্পাদন করুন",
|
||||||
|
},
|
||||||
|
Commands: {
|
||||||
|
new: "নতুন চ্যাট শুরু করুন",
|
||||||
|
newm: "মাস্ক সহ নতুন চ্যাট শুরু করুন",
|
||||||
|
next: "পরবর্তী চ্যাট",
|
||||||
|
prev: "পূর্ববর্তী চ্যাট",
|
||||||
|
clear: "সংশ্লিষ্টতাবদ্ধকরণ পরিষ্কার করুন",
|
||||||
|
del: "চ্যাট মুছুন",
|
||||||
|
},
|
||||||
|
InputActions: {
|
||||||
|
Stop: "বন্ধ করুন",
|
||||||
|
ToBottom: "সর্বশেষতম দিকে",
|
||||||
|
Theme: {
|
||||||
|
auto: "অটো",
|
||||||
|
light: "হালকা থিম",
|
||||||
|
dark: "ডার্ক থিম",
|
||||||
|
},
|
||||||
|
Prompt: "প্রম্পটগুলিতে",
|
||||||
|
Masks: "মাস্কগুলি",
|
||||||
|
Clear: "সংশ্লিষ্টতাবদ্ধকরণ পরিষ্কার করুন",
|
||||||
|
Settings: "সেটিংস",
|
||||||
|
},
|
||||||
|
Rename: "চ্যাট পুনঃনামকরণ করুন",
|
||||||
|
Typing: "টাইপিং...",
|
||||||
|
Input: (submitKey: string) => {
|
||||||
|
var inputHints = `${submitKey} to send`;
|
||||||
|
if (submitKey === String(SubmitKey.Enter)) {
|
||||||
|
inputHints += ", Shift + Enter to wrap";
|
||||||
|
}
|
||||||
|
return inputHints + ", / to search prompts, : to use commands";
|
||||||
|
},
|
||||||
|
Send: "প্রেরণ করুন",
|
||||||
|
Config: {
|
||||||
|
Reset: "ডিফল্টে রিসেট করুন",
|
||||||
|
SaveAs: "মাস্ক হিসাবে সংরক্ষণ করুন",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Export: {
|
||||||
|
Title: "বার্তা রপ্তানিকরণ",
|
||||||
|
Copy: "সমস্তটি কপি করুন",
|
||||||
|
Download: "ডাউনলোড করুন",
|
||||||
|
MessageFromYou: "আপনার বার্তা",
|
||||||
|
MessageFromChatGPT: "চ্যাটজিপিটির বার্তা",
|
||||||
|
Share: "শেয়ার করুন শেয়ারজিপিটি তে",
|
||||||
|
Format: {
|
||||||
|
Title: "রপ্তানি ফরম্যাট",
|
||||||
|
SubTitle: "মার্কডাউন বা পিএনজি চিত্র",
|
||||||
|
},
|
||||||
|
IncludeContext: {
|
||||||
|
Title: "মাস্ক অন্তর্ভুক্ত করুন",
|
||||||
|
SubTitle: "মাস্কগুলি সংরক্ষণ করবেন না কি",
|
||||||
|
},
|
||||||
|
Steps: {
|
||||||
|
Select: "নির্বাচন করুন",
|
||||||
|
Preview: "প্রিভিউ করুন",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Select: {
|
||||||
|
Search: "অনুসন্ধান করুন",
|
||||||
|
All: "সমস্তটি নির্বাচন করুন",
|
||||||
|
Latest: "সর্বশেষতমটি নির্বাচন করুন",
|
||||||
|
Clear: "পরিষ্কার করুন",
|
||||||
|
},
|
||||||
|
Memory: {
|
||||||
|
Title: "মেমোরি প্রম্পট",
|
||||||
|
EmptyContent: "এখনও কিছুই নেই।",
|
||||||
|
Send: "মেমোরি প্রেরণ করুন",
|
||||||
|
Copy: "মেমোরি কপি করুন",
|
||||||
|
Reset: "পুনরায় নিশ্চিত করুন",
|
||||||
|
ResetConfirm:
|
||||||
|
"রিসেট করলে বর্তমান চ্যাট ইতিহাস এবং ঐতিহাসিক মেমোরি মুছে যাবে। পুনরায় নির্দিষ্ট করতে চান তা নিশ্চিত করতে চান?",
|
||||||
|
},
|
||||||
|
Home: {
|
||||||
|
NewChat: "নতুন চ্যাট",
|
||||||
|
DeleteChat: "নির্বাচিত সংলাপটি মুছতে নিশ্চিত করুন?",
|
||||||
|
DeleteToast: "চ্যাটটি মুছেছেন",
|
||||||
|
Revert: "পুনরায়",
|
||||||
|
},
|
||||||
|
Settings: {
|
||||||
|
Title: "সেটিংস",
|
||||||
|
SubTitle: "সমস্ত সেটিংস",
|
||||||
|
Danger: {
|
||||||
|
Reset: {
|
||||||
|
Title: "সমস্ত সেটিংস পুনঃনির্দেশ দিন",
|
||||||
|
SubTitle: "সকল সেটিংস ডিফল্টে পুনঃনির্দেশ দিতে",
|
||||||
|
Action: "পুনঃনির্দেশ দিন",
|
||||||
|
Confirm: "সমস্ত সেটিংস ডিফল্টে পুনঃনির্দেশ করতে নিশ্চিত করতে?",
|
||||||
|
},
|
||||||
|
Clear: {
|
||||||
|
Title: "সমস্ত তথ্য মুছুন",
|
||||||
|
SubTitle: "সমস্ত বার্তা এবং সেটিংস মুছুন",
|
||||||
|
Action: "মুছুন",
|
||||||
|
Confirm: "সমস্ত বার্তা এবং সেটিংস মুছে ফেলতে নিশ্চিত করতে?",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Lang: {
|
||||||
|
Name: "বাংলা", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
|
All: "সমস্ত ভাষা",
|
||||||
|
},
|
||||||
|
Avatar: "অবতার",
|
||||||
|
FontSize: {
|
||||||
|
Title: "ফন্ট সাইজ",
|
||||||
|
SubTitle: "চ্যাট সামগ্রীর ফন্ট সাইজ সংশোধন করুন",
|
||||||
|
},
|
||||||
|
|
||||||
|
InputTemplate: {
|
||||||
|
Title: "ইনপুট টেমপ্লেট",
|
||||||
|
SubTitle: "নতুনতম বার্তা এই টেমপ্লেটে পূরণ হবে",
|
||||||
|
},
|
||||||
|
|
||||||
|
Update: {
|
||||||
|
Version: (x: string) => `Version: ${x}`,
|
||||||
|
IsLatest: "Latest version",
|
||||||
|
CheckUpdate: "Check Update",
|
||||||
|
IsChecking: "Checking update...",
|
||||||
|
FoundUpdate: (x: string) => `Found new version: ${x}`,
|
||||||
|
GoToUpdate: "Update",
|
||||||
|
},
|
||||||
|
SendKey: "প্রেরণ চাবি",
|
||||||
|
Theme: "থিম",
|
||||||
|
TightBorder: "সঙ্গতি সীমা",
|
||||||
|
SendPreviewBubble: {
|
||||||
|
Title: "প্রিভিউ বুলবুল প্রেরণ করুন",
|
||||||
|
SubTitle: "বুলবুলে মার্কডাউন প্রিভিউ করুন",
|
||||||
|
},
|
||||||
|
Mask: {
|
||||||
|
Splash: {
|
||||||
|
Title: "মাস্ক স্প্ল্যাশ স্ক্রিন",
|
||||||
|
SubTitle:
|
||||||
|
"নতুন চ্যাট শুরু করার আগে মাস্ক স্প্ল্যাশ স্ক্রিন প্রদর্শন করুন",
|
||||||
|
},
|
||||||
|
Builtin: {
|
||||||
|
Title: "মূলত মাস্ক গোপন করুন",
|
||||||
|
SubTitle: "মাস্ক তালিকা থেকে মূলত মাস্কগুলি লুকান",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Prompt: {
|
||||||
|
Disable: {
|
||||||
|
Title: "অটো-সম্পূর্ণতা নিষ্ক্রিয় করুন",
|
||||||
|
SubTitle: "অটো-সম্পূর্ণতা চালু করতে / ইনপুট করুন",
|
||||||
|
},
|
||||||
|
List: "প্রম্পট তালিকা",
|
||||||
|
ListCount: (builtin: number, custom: number) =>
|
||||||
|
`${builtin} built-in, ${custom} user-defined`,
|
||||||
|
Edit: "সম্পাদন করুন",
|
||||||
|
Modal: {
|
||||||
|
Title: "প্রম্পট তালিকা",
|
||||||
|
Add: "একটি যোগ করুন",
|
||||||
|
Search: "সন্ধান প্রম্পট",
|
||||||
|
},
|
||||||
|
EditModal: {
|
||||||
|
Title: "সম্পাদন করুন প্রম্পট",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HistoryCount: {
|
||||||
|
Title: "সংযুক্ত বার্তা সংখ্যা",
|
||||||
|
SubTitle: "প্রতি অনুরোধে প্রেরণ করা গেলে প্রেরণ করা হবে",
|
||||||
|
},
|
||||||
|
CompressThreshold: {
|
||||||
|
Title: "ইতিহাস সঙ্কুচিত করার সীমা",
|
||||||
|
SubTitle:
|
||||||
|
"নকুল বার্তা দৈর্ঘ্য সীমা অতিক্রান্ত হলে ঐ বার্তাটি সঙ্কুচিত হবে",
|
||||||
|
},
|
||||||
|
Token: {
|
||||||
|
Title: "অ্যাপি কী",
|
||||||
|
SubTitle: "অ্যাক্সেস কোড সীমা উপেক্ষা করতে আপনার কীটি ব্যবহার করুন",
|
||||||
|
Placeholder: "OpenAI API কী",
|
||||||
|
},
|
||||||
|
Usage: {
|
||||||
|
Title: "একাউন্ট ব্যালেন্স",
|
||||||
|
SubTitle(used: any, total: any) {
|
||||||
|
return `এই মাসে ব্যবহৃত $${used}, সাবস্ক্রিপশন $${total}`;
|
||||||
|
},
|
||||||
|
IsChecking: "চেক করা হচ্ছে...",
|
||||||
|
Check: "চেক",
|
||||||
|
NoAccess: "ব্যালেন্স চেক করতে অ্যাপি কী ইনপুট করুন",
|
||||||
|
},
|
||||||
|
AccessCode: {
|
||||||
|
Title: "অ্যাক্সেস কোড",
|
||||||
|
SubTitle: "অ্যাক্সেস নিয়ন্ত্রণ সক্রিয়",
|
||||||
|
Placeholder: "অ্যাক্সেস কোড প্রয়োজন",
|
||||||
|
},
|
||||||
|
Endpoint: {
|
||||||
|
Title: "ইনটারপয়েন্ট",
|
||||||
|
SubTitle: "কাস্টম এন্ডপয়েন্টটি হতে হবে http(s):// দিয়ে শুরু হতে হবে",
|
||||||
|
},
|
||||||
|
Model: "মডেল",
|
||||||
|
Temperature: {
|
||||||
|
Title: "তাপমাত্রা",
|
||||||
|
SubTitle: "আরতি মান বেশি করলে বেশি এলোমেলো আউটপুট হবে",
|
||||||
|
},
|
||||||
|
TopP: {
|
||||||
|
Title: "শীর্ষ পি",
|
||||||
|
SubTitle: "তাপমাত্রা সঙ্গে এই মান পরিবর্তন করবেন না",
|
||||||
|
},
|
||||||
|
MaxTokens: {
|
||||||
|
Title: "সর্বাধিক টোকেন",
|
||||||
|
SubTitle: "ইনপুট টোকেন এবং উৎপাদিত টোকেনের সর্বাধিক দৈর্ঘ্য",
|
||||||
|
},
|
||||||
|
PresencePenalty: {
|
||||||
|
Title: "উপস্থিতির জরিমানা",
|
||||||
|
SubTitle: "আরতি মান বেশি করলে নতুন বিষয়গুলি সম্ভাব্যতা বাড়াতে পারে",
|
||||||
|
},
|
||||||
|
FrequencyPenalty: {
|
||||||
|
Title: "ফ্রিকুয়েন্সি জরিমানা",
|
||||||
|
SubTitle:
|
||||||
|
"আরতি মান বাড়ালে একই লাইন পুনরায় ব্যাবহার করার সম্ভাবনা হ্রাস পায়",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Store: {
|
||||||
|
DefaultTopic: "নতুন সংলাপ",
|
||||||
|
BotHello: "হ্যালো! আজকে আপনাকে কিভাবে সাহায্য করতে পারি?",
|
||||||
|
Error: "কিছু নিয়ে ভুল হয়েছে, পরে আবার চেষ্টা করুন।",
|
||||||
|
Prompt: {
|
||||||
|
History: (content: string) =>
|
||||||
|
"এটি চ্যাট ইতিহাসের সংক্ষিপ্ত সংকলনের মতো: " + content,
|
||||||
|
Topic:
|
||||||
|
"আমাদের সংলাপটির চার থেকে পাঁচ শব্দের একটি শিরোনাম তৈরি করুন যা আমাদের আলাপের সংক্ষিপ্তসার হিসাবে যোগ হবে না, যেমন অভিবৃত্তি, বিন্যাস, উদ্ধৃতি, পূর্বচালক চিহ্ন, পূর্বরোবক্তির যেকোনো চিহ্ন বা অতিরিক্ত পাঠ। মেয়াদশেষ উদ্ধৃতি চেষ্টা করুন।",
|
||||||
|
Summarize:
|
||||||
|
"২০০ শব্দের লম্বা হয়ে মুহূর্তে আলোচনা সংক্ষেপের রপ্তানি করুন, যেটি ভবিষ্যতের প্রম্পট হিসাবে ব্যবহার করবেন।",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Copy: {
|
||||||
|
Success: "ক্লিপবোর্ডে কপি করা হয়েছে",
|
||||||
|
Failed: "কপি ব্যর্থ, অনুমতি প্রদান করার জন্য অনুমতি প্রদান করুন",
|
||||||
|
},
|
||||||
|
Context: {
|
||||||
|
Toast: (x: any) => `With ${x} contextual prompts`,
|
||||||
|
Edit: "বর্তমান চ্যাট সেটিংস",
|
||||||
|
Add: "একটি প্রম্পট যোগ করুন",
|
||||||
|
Clear: "সঙ্গতি পরিস্কার করুন",
|
||||||
|
Revert: "পূর্ববর্তী অবস্থানে ফিরে যান",
|
||||||
|
},
|
||||||
|
Plugin: {
|
||||||
|
Name: "প্লাগইন",
|
||||||
|
},
|
||||||
|
Mask: {
|
||||||
|
Name: "মাস্ক",
|
||||||
|
Page: {
|
||||||
|
Title: "প্রম্পট টেমপ্লেট",
|
||||||
|
SubTitle: (count: number) => `${count} টি প্রম্পট টেমপ্লেট`,
|
||||||
|
Search: "টেমপ্লেট অনুসন্ধান করুন",
|
||||||
|
Create: "তৈরি করুন",
|
||||||
|
},
|
||||||
|
Item: {
|
||||||
|
Info: (count: number) => `${count} প্রম্পট`,
|
||||||
|
Chat: "চ্যাট",
|
||||||
|
View: "দেখুন",
|
||||||
|
Edit: "সম্পাদন করুন",
|
||||||
|
Delete: "মুছে ফেলুন",
|
||||||
|
DeleteConfirm: "মুছে ফেলতে নিশ্চিত করুন?",
|
||||||
|
},
|
||||||
|
EditModal: {
|
||||||
|
Title: (readonly: boolean) =>
|
||||||
|
`প্রম্পট টেমপ্লেট সম্পাদন করুন ${readonly ? "(readonly)" : ""}`,
|
||||||
|
Download: "ডাউনলোড করুন",
|
||||||
|
Clone: "ক্লোন করুন",
|
||||||
|
},
|
||||||
|
Config: {
|
||||||
|
Avatar: "বট অবতার",
|
||||||
|
Name: "বটের নাম",
|
||||||
|
Sync: {
|
||||||
|
Title: "গ্লোবাল কনফিগ ব্যবহার করুন",
|
||||||
|
SubTitle: "এই চ্যাটে গ্লোবাল কনফিগ ব্যবহার করুন",
|
||||||
|
Confirm:
|
||||||
|
"গ্লোবাল কনফিগ দ্বারা কাস্টম কনফিগ ওভাররাইড করতে নিশ্চিত করতে?",
|
||||||
|
},
|
||||||
|
HideContext: {
|
||||||
|
Title: "সংশ্লিষ্টতা প্রম্পটগুলি লুকান",
|
||||||
|
SubTitle: "চ্যাটে সংশ্লিষ্টতা প্রম্পটগুলি দেখাবেন না",
|
||||||
|
},
|
||||||
|
Share: {
|
||||||
|
Title: "এই মাস্কটি শেয়ার করুন",
|
||||||
|
SubTitle: "এই মাস্কের একটি লিঙ্ক তৈরি করুন",
|
||||||
|
Action: "লিঙ্ক কপি করুন",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NewChat: {
|
||||||
|
Return: "ফিরে যান",
|
||||||
|
Skip: "শুরু করুন",
|
||||||
|
Title: "মাস্ক নির্বাচন করুন",
|
||||||
|
SubTitle: "মাস্কের পিছনে আত্মার সঙ্গে চ্যাট করুন",
|
||||||
|
More: "আরো খুঁজুন",
|
||||||
|
NotShow: "এখনও দেখাবেন না",
|
||||||
|
ConfirmNoShow:
|
||||||
|
"নিষ্ক্রিয় করতে নিশ্চিত করুন? পরে আপনি এটি সেটিংসে সক্ষম করতে পারবেন।",
|
||||||
|
},
|
||||||
|
|
||||||
|
UI: {
|
||||||
|
Confirm: "নিশ্চিত করুন",
|
||||||
|
Cancel: "বাতিল করুন",
|
||||||
|
Close: "বন্ধ করুন",
|
||||||
|
Create: "তৈরি করুন",
|
||||||
|
Edit: "সম্পাদন করুন",
|
||||||
|
},
|
||||||
|
Exporter: {
|
||||||
|
Model: "মডেল",
|
||||||
|
Messages: "বার্তা",
|
||||||
|
Topic: "টপিক",
|
||||||
|
Time: "সময়",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default bn;
|
@@ -17,7 +17,7 @@ const cn = {
|
|||||||
ChatItemCount: (count: number) => `${count} 条对话`,
|
ChatItemCount: (count: number) => `${count} 条对话`,
|
||||||
},
|
},
|
||||||
Chat: {
|
Chat: {
|
||||||
SubTitle: (count: number) => `与 ChatGPT 的 ${count} 条对话`,
|
SubTitle: (count: number) => `共 ${count} 条对话`,
|
||||||
Actions: {
|
Actions: {
|
||||||
ChatList: "查看消息列表",
|
ChatList: "查看消息列表",
|
||||||
CompressedHistory: "查看压缩后的历史 Prompt",
|
CompressedHistory: "查看压缩后的历史 Prompt",
|
||||||
@@ -26,9 +26,10 @@ const cn = {
|
|||||||
Stop: "停止",
|
Stop: "停止",
|
||||||
Retry: "重试",
|
Retry: "重试",
|
||||||
Pin: "固定",
|
Pin: "固定",
|
||||||
PinToastContent: "已将 2 条对话固定至预设提示词",
|
PinToastContent: "已将 1 条对话固定至预设提示词",
|
||||||
PinToastAction: "查看",
|
PinToastAction: "查看",
|
||||||
Delete: "删除",
|
Delete: "删除",
|
||||||
|
Edit: "编辑",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "新建聊天",
|
new: "新建聊天",
|
||||||
@@ -65,6 +66,7 @@ const cn = {
|
|||||||
Reset: "清除记忆",
|
Reset: "清除记忆",
|
||||||
SaveAs: "存为面具",
|
SaveAs: "存为面具",
|
||||||
},
|
},
|
||||||
|
IsContext: "预设提示词",
|
||||||
},
|
},
|
||||||
Export: {
|
Export: {
|
||||||
Title: "分享聊天记录",
|
Title: "分享聊天记录",
|
||||||
@@ -85,6 +87,10 @@ const cn = {
|
|||||||
Select: "选取",
|
Select: "选取",
|
||||||
Preview: "预览",
|
Preview: "预览",
|
||||||
},
|
},
|
||||||
|
Image: {
|
||||||
|
Toast: "正在生成截图",
|
||||||
|
Modal: "长按或右键保存图片",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Select: {
|
Select: {
|
||||||
Search: "搜索消息",
|
Search: "搜索消息",
|
||||||
@@ -108,13 +114,21 @@ const cn = {
|
|||||||
},
|
},
|
||||||
Settings: {
|
Settings: {
|
||||||
Title: "设置",
|
Title: "设置",
|
||||||
SubTitle: "设置选项",
|
SubTitle: "所有设置选项",
|
||||||
Actions: {
|
|
||||||
ClearAll: "清除所有数据",
|
Danger: {
|
||||||
ResetAll: "重置所有选项",
|
Reset: {
|
||||||
Close: "关闭",
|
Title: "重置所有设置",
|
||||||
ConfirmResetAll: "确认重置所有配置?",
|
SubTitle: "重置所有设置项回默认值",
|
||||||
ConfirmClearAll: "确认清除所有数据?",
|
Action: "立即重置",
|
||||||
|
Confirm: "确认重置所有设置?",
|
||||||
|
},
|
||||||
|
Clear: {
|
||||||
|
Title: "清除所有数据",
|
||||||
|
SubTitle: "清除所有聊天、设置数据",
|
||||||
|
Action: "立即清除",
|
||||||
|
Confirm: "确认清除所有聊天、设置数据?",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
@@ -147,8 +161,14 @@ const cn = {
|
|||||||
SubTitle: "在预览气泡中预览 Markdown 内容",
|
SubTitle: "在预览气泡中预览 Markdown 内容",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "面具启动页",
|
Splash: {
|
||||||
SubTitle: "新建聊天时,展示面具启动页",
|
Title: "面具启动页",
|
||||||
|
SubTitle: "新建聊天时,展示面具启动页",
|
||||||
|
},
|
||||||
|
Builtin: {
|
||||||
|
Title: "隐藏内置面具",
|
||||||
|
SubTitle: "在所有面具列表中隐藏内置面具",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
@@ -205,6 +225,10 @@ const cn = {
|
|||||||
Title: "随机性 (temperature)",
|
Title: "随机性 (temperature)",
|
||||||
SubTitle: "值越大,回复越随机",
|
SubTitle: "值越大,回复越随机",
|
||||||
},
|
},
|
||||||
|
TopP: {
|
||||||
|
Title: "核采样 (top_p)",
|
||||||
|
SubTitle: "与随机性类似,但不要和随机性一起更改",
|
||||||
|
},
|
||||||
MaxTokens: {
|
MaxTokens: {
|
||||||
Title: "单次回复限制 (max_tokens)",
|
Title: "单次回复限制 (max_tokens)",
|
||||||
SubTitle: "单次交互所用的最大 Token 数",
|
SubTitle: "单次交互所用的最大 Token 数",
|
||||||
@@ -278,6 +302,11 @@ const cn = {
|
|||||||
Title: "隐藏预设对话",
|
Title: "隐藏预设对话",
|
||||||
SubTitle: "隐藏后预设对话不会出现在聊天界面",
|
SubTitle: "隐藏后预设对话不会出现在聊天界面",
|
||||||
},
|
},
|
||||||
|
Share: {
|
||||||
|
Title: "分享此面具",
|
||||||
|
SubTitle: "生成此面具的直达链接",
|
||||||
|
Action: "复制链接",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
NewChat: {
|
NewChat: {
|
||||||
|
@@ -61,13 +61,7 @@ const cs: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Nastavení",
|
Title: "Nastavení",
|
||||||
SubTitle: "Všechna nastavení",
|
SubTitle: "Všechna nastavení",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Vymazat všechna data",
|
|
||||||
ResetAll: "Obnovit veškeré nastavení",
|
|
||||||
Close: "Zavřít",
|
|
||||||
ConfirmResetAll: "Jste si jisti, že chcete obnovit všechna nastavení?",
|
|
||||||
ConfirmClearAll: "Jste si jisti, že chcete smazat všechna data?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Všechny jazyky",
|
All: "Všechny jazyky",
|
||||||
@@ -93,8 +87,10 @@ const cs: PartialLocaleType = {
|
|||||||
SubTitle: "Zobrazit v náhledu bubliny",
|
SubTitle: "Zobrazit v náhledu bubliny",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Úvodní obrazovka Masek",
|
Splash: {
|
||||||
SubTitle: "Před zahájením nového chatu zobrazte úvodní obrazovku Masek",
|
Title: "Úvodní obrazovka Masek",
|
||||||
|
SubTitle: "Před zahájením nového chatu zobrazte úvodní obrazovku Masek",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,14 +61,7 @@ const de: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Einstellungen",
|
Title: "Einstellungen",
|
||||||
SubTitle: "Alle Einstellungen",
|
SubTitle: "Alle Einstellungen",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Alle Daten löschen",
|
|
||||||
ResetAll: "Alle Einstellungen zurücksetzen",
|
|
||||||
Close: "Schließen",
|
|
||||||
ConfirmResetAll:
|
|
||||||
"Möchten Sie wirklich alle Konfigurationen zurücksetzen?",
|
|
||||||
ConfirmClearAll: "Möchten Sie wirklich alle Chats zurücksetzen?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Alle Sprachen",
|
All: "Alle Sprachen",
|
||||||
@@ -94,8 +87,10 @@ const de: PartialLocaleType = {
|
|||||||
SubTitle: "Preview markdown in bubble",
|
SubTitle: "Preview markdown in bubble",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Show a mask splash screen before starting new chat",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Show a mask splash screen before starting new chat",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { SubmitKey } from "../store/config";
|
import { SubmitKey } from "../store/config";
|
||||||
import { LocaleType } from "./index";
|
import { LocaleType } from "./index";
|
||||||
|
|
||||||
|
// if you are adding a new translation, please use PartialLocaleType instead of LocaleType
|
||||||
const en: LocaleType = {
|
const en: LocaleType = {
|
||||||
WIP: "Coming Soon...",
|
WIP: "Coming Soon...",
|
||||||
Error: {
|
Error: {
|
||||||
@@ -18,7 +19,7 @@ const en: LocaleType = {
|
|||||||
ChatItemCount: (count: number) => `${count} messages`,
|
ChatItemCount: (count: number) => `${count} messages`,
|
||||||
},
|
},
|
||||||
Chat: {
|
Chat: {
|
||||||
SubTitle: (count: number) => `${count} messages with ChatGPT`,
|
SubTitle: (count: number) => `${count} messages`,
|
||||||
Actions: {
|
Actions: {
|
||||||
ChatList: "Go To Chat List",
|
ChatList: "Go To Chat List",
|
||||||
CompressedHistory: "Compressed History Memory Prompt",
|
CompressedHistory: "Compressed History Memory Prompt",
|
||||||
@@ -27,9 +28,10 @@ const en: LocaleType = {
|
|||||||
Stop: "Stop",
|
Stop: "Stop",
|
||||||
Retry: "Retry",
|
Retry: "Retry",
|
||||||
Pin: "Pin",
|
Pin: "Pin",
|
||||||
PinToastContent: "Pinned 2 messages to contextual prompts",
|
PinToastContent: "Pinned 1 messages to contextual prompts",
|
||||||
PinToastAction: "View",
|
PinToastAction: "View",
|
||||||
Delete: "Delete",
|
Delete: "Delete",
|
||||||
|
Edit: "Edit",
|
||||||
},
|
},
|
||||||
Commands: {
|
Commands: {
|
||||||
new: "Start a new chat",
|
new: "Start a new chat",
|
||||||
@@ -66,6 +68,7 @@ const en: LocaleType = {
|
|||||||
Reset: "Reset to Default",
|
Reset: "Reset to Default",
|
||||||
SaveAs: "Save as Mask",
|
SaveAs: "Save as Mask",
|
||||||
},
|
},
|
||||||
|
IsContext: "Contextual Prompt",
|
||||||
},
|
},
|
||||||
Export: {
|
Export: {
|
||||||
Title: "Export Messages",
|
Title: "Export Messages",
|
||||||
@@ -86,6 +89,10 @@ const en: LocaleType = {
|
|||||||
Select: "Select",
|
Select: "Select",
|
||||||
Preview: "Preview",
|
Preview: "Preview",
|
||||||
},
|
},
|
||||||
|
Image: {
|
||||||
|
Toast: "Capturing Image...",
|
||||||
|
Modal: "Long press or right click to save image",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Select: {
|
Select: {
|
||||||
Search: "Search",
|
Search: "Search",
|
||||||
@@ -111,12 +118,19 @@ const en: LocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Settings",
|
Title: "Settings",
|
||||||
SubTitle: "All Settings",
|
SubTitle: "All Settings",
|
||||||
Actions: {
|
Danger: {
|
||||||
ClearAll: "Clear All Data",
|
Reset: {
|
||||||
ResetAll: "Reset All Settings",
|
Title: "Reset All Settings",
|
||||||
Close: "Close",
|
SubTitle: "Reset all setting items to default",
|
||||||
ConfirmResetAll: "Are you sure you want to reset all configurations?",
|
Action: "Reset",
|
||||||
ConfirmClearAll: "Are you sure you want to reset all data?",
|
Confirm: "Confirm to reset all settings to default?",
|
||||||
|
},
|
||||||
|
Clear: {
|
||||||
|
Title: "Clear All Data",
|
||||||
|
SubTitle: "Clear all messages and settings",
|
||||||
|
Action: "Clear",
|
||||||
|
Confirm: "Confirm to clear all messages and settings?",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
@@ -149,8 +163,14 @@ const en: LocaleType = {
|
|||||||
SubTitle: "Preview markdown in bubble",
|
SubTitle: "Preview markdown in bubble",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Show a mask splash screen before starting new chat",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Show a mask splash screen before starting new chat",
|
||||||
|
},
|
||||||
|
Builtin: {
|
||||||
|
Title: "Hide Builtin Masks",
|
||||||
|
SubTitle: "Hide builtin masks in mask list",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
@@ -207,6 +227,10 @@ const en: LocaleType = {
|
|||||||
Title: "Temperature",
|
Title: "Temperature",
|
||||||
SubTitle: "A larger value makes the more random output",
|
SubTitle: "A larger value makes the more random output",
|
||||||
},
|
},
|
||||||
|
TopP: {
|
||||||
|
Title: "Top P",
|
||||||
|
SubTitle: "Do not alter this value together with temperature",
|
||||||
|
},
|
||||||
MaxTokens: {
|
MaxTokens: {
|
||||||
Title: "Max Tokens",
|
Title: "Max Tokens",
|
||||||
SubTitle: "Maximum length of input tokens and generated tokens",
|
SubTitle: "Maximum length of input tokens and generated tokens",
|
||||||
@@ -241,7 +265,7 @@ const en: LocaleType = {
|
|||||||
},
|
},
|
||||||
Context: {
|
Context: {
|
||||||
Toast: (x: any) => `With ${x} contextual prompts`,
|
Toast: (x: any) => `With ${x} contextual prompts`,
|
||||||
Edit: "Contextual and Memory Prompts",
|
Edit: "Current Chat Settings",
|
||||||
Add: "Add a Prompt",
|
Add: "Add a Prompt",
|
||||||
Clear: "Context Cleared",
|
Clear: "Context Cleared",
|
||||||
Revert: "Revert",
|
Revert: "Revert",
|
||||||
@@ -283,6 +307,11 @@ const en: LocaleType = {
|
|||||||
Title: "Hide Context Prompts",
|
Title: "Hide Context Prompts",
|
||||||
SubTitle: "Do not show in-context prompts in chat",
|
SubTitle: "Do not show in-context prompts in chat",
|
||||||
},
|
},
|
||||||
|
Share: {
|
||||||
|
Title: "Share This Mask",
|
||||||
|
SubTitle: "Generate a link to this mask",
|
||||||
|
Action: "Copy Link",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
NewChat: {
|
NewChat: {
|
||||||
|
@@ -61,13 +61,7 @@ const es: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Configuración",
|
Title: "Configuración",
|
||||||
SubTitle: "Todas las configuraciones",
|
SubTitle: "Todas las configuraciones",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Borrar todos los datos",
|
|
||||||
ResetAll: "Restablecer todas las configuraciones",
|
|
||||||
Close: "Cerrar",
|
|
||||||
ConfirmResetAll: "Are you sure you want to reset all configurations?",
|
|
||||||
ConfirmClearAll: "Are you sure you want to reset all chat?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Todos los idiomas",
|
All: "Todos los idiomas",
|
||||||
@@ -93,8 +87,10 @@ const es: PartialLocaleType = {
|
|||||||
SubTitle: "Preview markdown in bubble",
|
SubTitle: "Preview markdown in bubble",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Show a mask splash screen before starting new chat",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Show a mask splash screen before starting new chat",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,14 +61,7 @@ const fr: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Paramètres",
|
Title: "Paramètres",
|
||||||
SubTitle: "Toutes les configurations",
|
SubTitle: "Toutes les configurations",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Effacer toutes les données",
|
|
||||||
ResetAll: "Réinitialiser les configurations",
|
|
||||||
Close: "Fermer",
|
|
||||||
ConfirmResetAll:
|
|
||||||
"Êtes-vous sûr de vouloir réinitialiser toutes les configurations?",
|
|
||||||
ConfirmClearAll: "Êtes-vous sûr de vouloir supprimer toutes les données?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION : si vous souhaitez ajouter une nouvelle traduction, ne traduisez pas cette valeur, laissez-la sous forme de `Language`
|
Name: "Language", // ATTENTION : si vous souhaitez ajouter une nouvelle traduction, ne traduisez pas cette valeur, laissez-la sous forme de `Language`
|
||||||
All: "Toutes les langues",
|
All: "Toutes les langues",
|
||||||
@@ -95,9 +88,11 @@ const fr: PartialLocaleType = {
|
|||||||
SubTitle: "Aperçu du Markdown dans une bulle",
|
SubTitle: "Aperçu du Markdown dans une bulle",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Écran de masque",
|
Splash: {
|
||||||
SubTitle:
|
Title: "Écran de masque",
|
||||||
"Afficher un écran de masque avant de démarrer une nouvelle discussion",
|
SubTitle:
|
||||||
|
"Afficher un écran de masque avant de démarrer une nouvelle discussion",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -13,6 +13,7 @@ import no from "./no";
|
|||||||
import cs from "./cs";
|
import cs from "./cs";
|
||||||
import ko from "./ko";
|
import ko from "./ko";
|
||||||
import ar from "./ar";
|
import ar from "./ar";
|
||||||
|
import bn from "./bn";
|
||||||
import { merge } from "../utils/merge";
|
import { merge } from "../utils/merge";
|
||||||
|
|
||||||
import type { LocaleType } from "./cn";
|
import type { LocaleType } from "./cn";
|
||||||
@@ -34,6 +35,7 @@ const ALL_LANGS = {
|
|||||||
cs,
|
cs,
|
||||||
no,
|
no,
|
||||||
ar,
|
ar,
|
||||||
|
bn,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Lang = keyof typeof ALL_LANGS;
|
export type Lang = keyof typeof ALL_LANGS;
|
||||||
@@ -56,6 +58,7 @@ export const ALL_LANG_OPTIONS: Record<Lang, string> = {
|
|||||||
cs: "Čeština",
|
cs: "Čeština",
|
||||||
no: "Nynorsk",
|
no: "Nynorsk",
|
||||||
ar: "العربية",
|
ar: "العربية",
|
||||||
|
bn: "বাংলা",
|
||||||
};
|
};
|
||||||
|
|
||||||
const LANG_KEY = "lang";
|
const LANG_KEY = "lang";
|
||||||
|
@@ -61,13 +61,7 @@ const it: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Impostazioni",
|
Title: "Impostazioni",
|
||||||
SubTitle: "Tutte le impostazioni",
|
SubTitle: "Tutte le impostazioni",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Cancella tutti i dati",
|
|
||||||
ResetAll: "Resetta tutte le impostazioni",
|
|
||||||
Close: "Chiudi",
|
|
||||||
ConfirmResetAll: "Sei sicuro vuoi cancellare tutte le impostazioni?",
|
|
||||||
ConfirmClearAll: "Sei sicuro vuoi cancellare tutte le chat?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Tutte le lingue",
|
All: "Tutte le lingue",
|
||||||
@@ -93,8 +87,10 @@ const it: PartialLocaleType = {
|
|||||||
SubTitle: "Preview markdown in bubble",
|
SubTitle: "Preview markdown in bubble",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Show a mask splash screen before starting new chat",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Show a mask splash screen before starting new chat",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,12 +61,19 @@ const jp: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "設定",
|
Title: "設定",
|
||||||
SubTitle: "設定オプション",
|
SubTitle: "設定オプション",
|
||||||
Actions: {
|
Danger: {
|
||||||
ClearAll: "すべてのデータをクリア",
|
Reset: {
|
||||||
ResetAll: "すべてのオプションをリセット",
|
Title: "設定をリセット",
|
||||||
Close: "閉じる",
|
SubTitle: "すべての設定項目をデフォルトにリセットします",
|
||||||
ConfirmResetAll: "すべての設定をリセットしてもよろしいですか?",
|
Action: "今すぐリセットする",
|
||||||
ConfirmClearAll: "すべてのチャットをリセットしてもよろしいですか?",
|
Confirm: "すべての設定項目をリセットしてもよろしいですか?",
|
||||||
|
},
|
||||||
|
Clear: {
|
||||||
|
Title: "データを消去",
|
||||||
|
SubTitle: "すべてのチャット履歴と設定を消去します",
|
||||||
|
Action: "今すぐ消去する",
|
||||||
|
Confirm: "すべてのチャット履歴と設定を消去しますか?",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
@@ -77,7 +84,10 @@ const jp: PartialLocaleType = {
|
|||||||
Title: "フォントサイズ",
|
Title: "フォントサイズ",
|
||||||
SubTitle: "チャット内容のフォントサイズ",
|
SubTitle: "チャット内容のフォントサイズ",
|
||||||
},
|
},
|
||||||
|
InputTemplate: {
|
||||||
|
Title: "入力の前処理",
|
||||||
|
SubTitle: "新規入力がこのテンプレートに埋め込まれます",
|
||||||
|
},
|
||||||
Update: {
|
Update: {
|
||||||
Version: (x: string) => `現在のバージョン:${x}`,
|
Version: (x: string) => `現在のバージョン:${x}`,
|
||||||
IsLatest: "最新バージョンです",
|
IsLatest: "最新バージョンです",
|
||||||
@@ -94,8 +104,10 @@ const jp: PartialLocaleType = {
|
|||||||
SubTitle: "プレビューバブルでマークダウンコンテンツをプレビュー",
|
SubTitle: "プレビューバブルでマークダウンコンテンツをプレビュー",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "キャラクターページ",
|
Splash: {
|
||||||
SubTitle: "新規チャット作成時にキャラクターページを表示する",
|
Title: "キャラクターページ",
|
||||||
|
SubTitle: "新規チャット作成時にキャラクターページを表示する",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,13 +61,7 @@ const ko: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "설정",
|
Title: "설정",
|
||||||
SubTitle: "모든 설정",
|
SubTitle: "모든 설정",
|
||||||
Actions: {
|
|
||||||
ClearAll: "모든 데이터 지우기",
|
|
||||||
ResetAll: "모든 설정 초기화",
|
|
||||||
Close: "닫기",
|
|
||||||
ConfirmResetAll: "모든 설정을 초기화하시겠습니까?",
|
|
||||||
ConfirmClearAll: "모든 데이터를 지우시겠습니까?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "All Languages",
|
All: "All Languages",
|
||||||
@@ -93,8 +87,10 @@ const ko: PartialLocaleType = {
|
|||||||
SubTitle: "버블에서 마크다운 미리 보기",
|
SubTitle: "버블에서 마크다운 미리 보기",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "마스크 시작 화면",
|
Splash: {
|
||||||
SubTitle: "새로운 채팅 시작 전에 마스크 시작 화면 표시",
|
Title: "마스크 시작 화면",
|
||||||
|
SubTitle: "새로운 채팅 시작 전에 마스크 시작 화면 표시",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -56,11 +56,7 @@ const no: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Innstillinger",
|
Title: "Innstillinger",
|
||||||
SubTitle: "Alle innstillinger",
|
SubTitle: "Alle innstillinger",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Fjern alle data",
|
|
||||||
ResetAll: "Nullstill innstillinger",
|
|
||||||
Close: "Lukk",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
},
|
},
|
||||||
|
@@ -61,13 +61,7 @@ const ru: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Настройки",
|
Title: "Настройки",
|
||||||
SubTitle: "Все настройки",
|
SubTitle: "Все настройки",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Очистить все данные",
|
|
||||||
ResetAll: "Сбросить все настройки",
|
|
||||||
Close: "Закрыть",
|
|
||||||
ConfirmResetAll: "Вы уверены, что хотите сбросить все настройки?",
|
|
||||||
ConfirmClearAll: "Вы уверены, что хотите очистить все данные?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Все языки",
|
All: "Все языки",
|
||||||
@@ -93,8 +87,10 @@ const ru: PartialLocaleType = {
|
|||||||
SubTitle: "Предварительный просмотр markdown в пузыре",
|
SubTitle: "Предварительный просмотр markdown в пузыре",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Экран заставки маски",
|
Splash: {
|
||||||
SubTitle: "Показывать экран заставки маски перед началом нового чата",
|
Title: "Экран заставки маски",
|
||||||
|
SubTitle: "Показывать экран заставки маски перед началом нового чата",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,13 +61,7 @@ const tr: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Ayarlar",
|
Title: "Ayarlar",
|
||||||
SubTitle: "Tüm Ayarlar",
|
SubTitle: "Tüm Ayarlar",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Tüm Verileri Temizle",
|
|
||||||
ResetAll: "Tüm Ayarları Sıfırla",
|
|
||||||
Close: "Kapat",
|
|
||||||
ConfirmResetAll: "Tüm ayarları sıfırlamak istediğinizden emin misiniz?",
|
|
||||||
ConfirmClearAll: "Tüm sohbeti sıfırlamak istediğinizden emin misiniz?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Tüm Diller",
|
All: "Tüm Diller",
|
||||||
@@ -93,8 +87,10 @@ const tr: PartialLocaleType = {
|
|||||||
SubTitle: "Preview markdown in bubble",
|
SubTitle: "Preview markdown in bubble",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Show a mask splash screen before starting new chat",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Show a mask splash screen before starting new chat",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -59,13 +59,7 @@ const tw: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "設定",
|
Title: "設定",
|
||||||
SubTitle: "設定選項",
|
SubTitle: "設定選項",
|
||||||
Actions: {
|
|
||||||
ClearAll: "清除所有資料",
|
|
||||||
ResetAll: "重設所有設定",
|
|
||||||
Close: "關閉",
|
|
||||||
ConfirmResetAll: "您確定要重設所有設定嗎?",
|
|
||||||
ConfirmClearAll: "您確定要清除所有数据嗎?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "所有语言",
|
All: "所有语言",
|
||||||
@@ -91,8 +85,10 @@ const tw: PartialLocaleType = {
|
|||||||
SubTitle: "在预览气泡中预览 Markdown 内容",
|
SubTitle: "在预览气泡中预览 Markdown 内容",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "面具启动页",
|
Splash: {
|
||||||
SubTitle: "新建聊天时,展示面具启动页",
|
Title: "面具启动页",
|
||||||
|
SubTitle: "新建聊天时,展示面具启动页",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -61,13 +61,7 @@ const vi: PartialLocaleType = {
|
|||||||
Settings: {
|
Settings: {
|
||||||
Title: "Cài đặt",
|
Title: "Cài đặt",
|
||||||
SubTitle: "Tất cả cài đặt",
|
SubTitle: "Tất cả cài đặt",
|
||||||
Actions: {
|
|
||||||
ClearAll: "Xóa toàn bộ dữ liệu",
|
|
||||||
ResetAll: "Khôi phục cài đặt gốc",
|
|
||||||
Close: "Đóng",
|
|
||||||
ConfirmResetAll: "Bạn chắc chắn muốn thiết lập lại tất cả cài đặt?",
|
|
||||||
ConfirmClearAll: "Bạn chắc chắn muốn thiết lập lại tất cả dữ liệu?",
|
|
||||||
},
|
|
||||||
Lang: {
|
Lang: {
|
||||||
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
|
||||||
All: "Tất cả ngôn ngữ",
|
All: "Tất cả ngôn ngữ",
|
||||||
@@ -93,8 +87,10 @@ const vi: PartialLocaleType = {
|
|||||||
SubTitle: "Xem trước nội dung markdown bằng bong bóng",
|
SubTitle: "Xem trước nội dung markdown bằng bong bóng",
|
||||||
},
|
},
|
||||||
Mask: {
|
Mask: {
|
||||||
Title: "Mask Splash Screen",
|
Splash: {
|
||||||
SubTitle: "Chớp màn hình khi bắt đầu cuộc trò chuyện mới",
|
Title: "Mask Splash Screen",
|
||||||
|
SubTitle: "Chớp màn hình khi bắt đầu cuộc trò chuyện mới",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Prompt: {
|
Prompt: {
|
||||||
Disable: {
|
Disable: {
|
||||||
|
@@ -3,7 +3,6 @@ import { persist } from "zustand/middleware";
|
|||||||
import { DEFAULT_API_HOST, StoreKey } from "../constant";
|
import { DEFAULT_API_HOST, StoreKey } from "../constant";
|
||||||
import { getHeaders } from "../client/api";
|
import { getHeaders } from "../client/api";
|
||||||
import { BOT_HELLO } from "./chat";
|
import { BOT_HELLO } from "./chat";
|
||||||
import { ALL_MODELS } from "./config";
|
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
|
||||||
export interface AccessControlStore {
|
export interface AccessControlStore {
|
||||||
@@ -76,14 +75,6 @@ export const useAccessStore = create<AccessControlStore>()(
|
|||||||
console.log("[Config] got config from server", res);
|
console.log("[Config] got config from server", res);
|
||||||
set(() => ({ ...res }));
|
set(() => ({ ...res }));
|
||||||
|
|
||||||
if (!res.enableGPT4) {
|
|
||||||
ALL_MODELS.forEach((model) => {
|
|
||||||
if (model.name.startsWith("gpt-4")) {
|
|
||||||
(model as any).available = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res as any).botHello) {
|
if ((res as any).botHello) {
|
||||||
BOT_HELLO.content = (res as any).botHello;
|
BOT_HELLO.content = (res as any).botHello;
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,11 @@ import Locale, { getLang } from "../locales";
|
|||||||
import { showToast } from "../components/ui-lib";
|
import { showToast } from "../components/ui-lib";
|
||||||
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
import { ModelConfig, ModelType, useAppConfig } from "./config";
|
||||||
import { createEmptyMask, Mask } from "./mask";
|
import { createEmptyMask, Mask } from "./mask";
|
||||||
import { DEFAULT_INPUT_TEMPLATE, StoreKey } from "../constant";
|
import {
|
||||||
|
DEFAULT_INPUT_TEMPLATE,
|
||||||
|
DEFAULT_SYSTEM_TEMPLATE,
|
||||||
|
StoreKey,
|
||||||
|
} from "../constant";
|
||||||
import { api, RequestMessage } from "../client/api";
|
import { api, RequestMessage } from "../client/api";
|
||||||
import { ChatControllerPool } from "../client/controller";
|
import { ChatControllerPool } from "../client/controller";
|
||||||
import { prettyObject } from "../utils/format";
|
import { prettyObject } from "../utils/format";
|
||||||
@@ -99,6 +103,7 @@ interface ChatStore {
|
|||||||
resetSession: () => void;
|
resetSession: () => void;
|
||||||
getMessagesWithMemory: () => ChatMessage[];
|
getMessagesWithMemory: () => ChatMessage[];
|
||||||
getMemoryPrompt: () => ChatMessage;
|
getMemoryPrompt: () => ChatMessage;
|
||||||
|
getSuggestions: () => Promise<string[]>;
|
||||||
|
|
||||||
clearAllData: () => void;
|
clearAllData: () => void;
|
||||||
}
|
}
|
||||||
@@ -274,97 +279,99 @@ export const useChatStore = create<ChatStore>()(
|
|||||||
get().summarizeSession();
|
get().summarizeSession();
|
||||||
},
|
},
|
||||||
|
|
||||||
async onUserInput(content) {
|
onUserInput(content) {
|
||||||
const session = get().currentSession();
|
return new Promise((resolve) => {
|
||||||
const modelConfig = session.mask.modelConfig;
|
const session = get().currentSession();
|
||||||
|
const modelConfig = session.mask.modelConfig;
|
||||||
|
|
||||||
const userContent = fillTemplateWith(content, modelConfig);
|
const userContent = fillTemplateWith(content, modelConfig);
|
||||||
console.log("[User Input] fill with template: ", userContent);
|
console.log("[User Input] after template: ", userContent);
|
||||||
|
|
||||||
const userMessage: ChatMessage = createMessage({
|
const userMessage: ChatMessage = createMessage({
|
||||||
role: "user",
|
role: "user",
|
||||||
content: userContent,
|
content: userContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
const botMessage: ChatMessage = createMessage({
|
const botMessage: ChatMessage = createMessage({
|
||||||
role: "assistant",
|
role: "assistant",
|
||||||
streaming: true,
|
streaming: true,
|
||||||
id: userMessage.id! + 1,
|
id: userMessage.id! + 1,
|
||||||
model: modelConfig.model,
|
model: modelConfig.model,
|
||||||
});
|
});
|
||||||
|
|
||||||
// get recent messages
|
// get recent messages
|
||||||
const recentMessages = get().getMessagesWithMemory();
|
const recentMessages = get().getMessagesWithMemory();
|
||||||
const sendMessages = recentMessages.concat(userMessage);
|
const sendMessages = recentMessages.concat(userMessage);
|
||||||
const sessionIndex = get().currentSessionIndex;
|
const sessionIndex = get().currentSessionIndex;
|
||||||
const messageIndex = get().currentSession().messages.length + 1;
|
const messageIndex = get().currentSession().messages.length + 1;
|
||||||
|
|
||||||
// save user's and bot's message
|
// save user's and bot's message
|
||||||
get().updateCurrentSession((session) => {
|
get().updateCurrentSession((session) => {
|
||||||
const savedUserMessage = {
|
const savedUserMessage = {
|
||||||
...userMessage,
|
...userMessage,
|
||||||
content,
|
content,
|
||||||
};
|
};
|
||||||
session.messages = session.messages.concat([
|
session.messages = session.messages.concat([
|
||||||
savedUserMessage,
|
savedUserMessage,
|
||||||
botMessage,
|
botMessage,
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// make request
|
// make request
|
||||||
console.log("[User Input] ", sendMessages);
|
api.llm.chat({
|
||||||
api.llm.chat({
|
messages: sendMessages,
|
||||||
messages: sendMessages,
|
config: { ...modelConfig, stream: true },
|
||||||
config: { ...modelConfig, stream: true },
|
onUpdate(message) {
|
||||||
onUpdate(message) {
|
botMessage.streaming = true;
|
||||||
botMessage.streaming = true;
|
if (message) {
|
||||||
if (message) {
|
botMessage.content = message;
|
||||||
botMessage.content = message;
|
}
|
||||||
}
|
get().updateCurrentSession((session) => {
|
||||||
get().updateCurrentSession((session) => {
|
session.messages = session.messages.concat();
|
||||||
session.messages = session.messages.concat();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onFinish(message) {
|
|
||||||
botMessage.streaming = false;
|
|
||||||
if (message) {
|
|
||||||
botMessage.content = message;
|
|
||||||
get().onNewMessage(botMessage);
|
|
||||||
}
|
|
||||||
ChatControllerPool.remove(
|
|
||||||
sessionIndex,
|
|
||||||
botMessage.id ?? messageIndex,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onError(error) {
|
|
||||||
const isAborted = error.message.includes("aborted");
|
|
||||||
botMessage.content =
|
|
||||||
"\n\n" +
|
|
||||||
prettyObject({
|
|
||||||
error: true,
|
|
||||||
message: error.message,
|
|
||||||
});
|
});
|
||||||
botMessage.streaming = false;
|
},
|
||||||
userMessage.isError = !isAborted;
|
onFinish(message) {
|
||||||
botMessage.isError = !isAborted;
|
botMessage.streaming = false;
|
||||||
get().updateCurrentSession((session) => {
|
if (message) {
|
||||||
session.messages = session.messages.concat();
|
botMessage.content = message;
|
||||||
});
|
get().onNewMessage(botMessage);
|
||||||
ChatControllerPool.remove(
|
resolve();
|
||||||
sessionIndex,
|
}
|
||||||
botMessage.id ?? messageIndex,
|
ChatControllerPool.remove(
|
||||||
);
|
sessionIndex,
|
||||||
|
botMessage.id ?? messageIndex,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onError(error) {
|
||||||
|
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;
|
||||||
|
get().updateCurrentSession((session) => {
|
||||||
|
session.messages = session.messages.concat();
|
||||||
|
});
|
||||||
|
ChatControllerPool.remove(
|
||||||
|
sessionIndex,
|
||||||
|
botMessage.id ?? messageIndex,
|
||||||
|
);
|
||||||
|
|
||||||
console.error("[Chat] failed ", error);
|
console.error("[Chat] failed ", error);
|
||||||
},
|
},
|
||||||
onController(controller) {
|
onController(controller) {
|
||||||
// collect controller for stop/retry
|
// collect controller for stop/retry
|
||||||
ChatControllerPool.addController(
|
ChatControllerPool.addController(
|
||||||
sessionIndex,
|
sessionIndex,
|
||||||
botMessage.id ?? messageIndex,
|
botMessage.id ?? messageIndex,
|
||||||
controller,
|
controller,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -391,12 +398,33 @@ export const useChatStore = create<ChatStore>()(
|
|||||||
// in-context prompts
|
// in-context prompts
|
||||||
const contextPrompts = session.mask.context.slice();
|
const contextPrompts = session.mask.context.slice();
|
||||||
|
|
||||||
|
// system prompts, to get close to OpenAI Web ChatGPT
|
||||||
|
// only will be injected if user does not use a mask or set none context prompts
|
||||||
|
const shouldInjectSystemPrompts = contextPrompts.length === 0;
|
||||||
|
const systemPrompts = shouldInjectSystemPrompts
|
||||||
|
? [
|
||||||
|
createMessage({
|
||||||
|
role: "system",
|
||||||
|
content: fillTemplateWith("", {
|
||||||
|
...modelConfig,
|
||||||
|
template: DEFAULT_SYSTEM_TEMPLATE,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: [];
|
||||||
|
if (shouldInjectSystemPrompts) {
|
||||||
|
console.log(
|
||||||
|
"[Global System Prompt] ",
|
||||||
|
systemPrompts.at(0)?.content ?? "empty",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// long term memory
|
// long term memory
|
||||||
const shouldSendLongTermMemory =
|
const shouldSendLongTermMemory =
|
||||||
modelConfig.sendMemory &&
|
modelConfig.sendMemory &&
|
||||||
session.memoryPrompt &&
|
session.memoryPrompt &&
|
||||||
session.memoryPrompt.length > 0 &&
|
session.memoryPrompt.length > 0 &&
|
||||||
session.lastSummarizeIndex <= clearContextIndex;
|
session.lastSummarizeIndex > clearContextIndex;
|
||||||
const longTermMemoryPrompts = shouldSendLongTermMemory
|
const longTermMemoryPrompts = shouldSendLongTermMemory
|
||||||
? [get().getMemoryPrompt()]
|
? [get().getMemoryPrompt()]
|
||||||
: [];
|
: [];
|
||||||
@@ -409,6 +437,7 @@ export const useChatStore = create<ChatStore>()(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// lets concat send messages, including 4 parts:
|
// lets concat send messages, including 4 parts:
|
||||||
|
// 0. system prompt: to get close to OpenAI Web ChatGPT
|
||||||
// 1. long term memory: summarized memory messages
|
// 1. long term memory: summarized memory messages
|
||||||
// 2. pre-defined in-context prompts
|
// 2. pre-defined in-context prompts
|
||||||
// 3. short term memory: latest n messages
|
// 3. short term memory: latest n messages
|
||||||
@@ -435,6 +464,7 @@ export const useChatStore = create<ChatStore>()(
|
|||||||
|
|
||||||
// concat all messages
|
// concat all messages
|
||||||
const recentMessages = [
|
const recentMessages = [
|
||||||
|
...systemPrompts,
|
||||||
...longTermMemoryPrompts,
|
...longTermMemoryPrompts,
|
||||||
...contextPrompts,
|
...contextPrompts,
|
||||||
...reversedRecentMessages.reverse(),
|
...reversedRecentMessages.reverse(),
|
||||||
@@ -568,6 +598,62 @@ export const useChatStore = create<ChatStore>()(
|
|||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
location.reload();
|
location.reload();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getSuggestions() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// get last bot messages
|
||||||
|
const messages = get().currentSession().messages;
|
||||||
|
let lastBotMessage: ChatMessage | undefined = undefined;
|
||||||
|
|
||||||
|
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
||||||
|
if (messages[i].role === "assistant") {
|
||||||
|
lastBotMessage = messages[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const botMsg = lastBotMessage?.content;
|
||||||
|
|
||||||
|
if (!lastBotMessage || !botMsg) return resolve([]);
|
||||||
|
|
||||||
|
const prompt = `
|
||||||
|
here is bot's reponse:
|
||||||
|
'''
|
||||||
|
${botMsg}
|
||||||
|
'''
|
||||||
|
|
||||||
|
according to bot's reponse,
|
||||||
|
- according to the bot's message, generate three short user input suggestions
|
||||||
|
- detect the bot's language and response in detected language
|
||||||
|
- no other words, just response in pure json format:
|
||||||
|
{questions: string[]}";
|
||||||
|
`;
|
||||||
|
|
||||||
|
api.llm.chat({
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: prompt,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
config: {
|
||||||
|
model: "gpt-3.5-turbo",
|
||||||
|
},
|
||||||
|
onFinish(msg) {
|
||||||
|
try {
|
||||||
|
const msgJson = JSON.parse(msg) as {
|
||||||
|
questions: string[];
|
||||||
|
};
|
||||||
|
if (Array.isArray(msgJson.questions)) {
|
||||||
|
resolve(msgJson.questions);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
console.error("[Suggestions] failed to parse: ", msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: StoreKey.Chat,
|
name: StoreKey.Chat,
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
|
import { LLMModel } from "../client/api";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
import { DEFAULT_INPUT_TEMPLATE, StoreKey } from "../constant";
|
import { DEFAULT_INPUT_TEMPLATE, DEFAULT_MODELS, StoreKey } from "../constant";
|
||||||
|
|
||||||
|
export type ModelType = (typeof DEFAULT_MODELS)[number]["name"];
|
||||||
|
|
||||||
export enum SubmitKey {
|
export enum SubmitKey {
|
||||||
Enter = "Enter",
|
Enter = "Enter",
|
||||||
@@ -29,10 +32,14 @@ export const DEFAULT_CONFIG = {
|
|||||||
disablePromptHint: false,
|
disablePromptHint: false,
|
||||||
|
|
||||||
dontShowMaskSplashScreen: false, // dont show splash screen when create chat
|
dontShowMaskSplashScreen: false, // dont show splash screen when create chat
|
||||||
|
hideBuiltinMasks: false, // dont add builtin masks
|
||||||
|
|
||||||
|
models: DEFAULT_MODELS as any as LLMModel[],
|
||||||
|
|
||||||
modelConfig: {
|
modelConfig: {
|
||||||
model: "gpt-3.5-turbo" as ModelType,
|
model: "gpt-3.5-turbo" as ModelType,
|
||||||
temperature: 0.5,
|
temperature: 0.5,
|
||||||
|
top_p: 1,
|
||||||
max_tokens: 2000,
|
max_tokens: 2000,
|
||||||
presence_penalty: 0,
|
presence_penalty: 0,
|
||||||
frequency_penalty: 0,
|
frequency_penalty: 0,
|
||||||
@@ -48,81 +55,11 @@ export type ChatConfig = typeof DEFAULT_CONFIG;
|
|||||||
export type ChatConfigStore = ChatConfig & {
|
export type ChatConfigStore = ChatConfig & {
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
update: (updater: (config: ChatConfig) => void) => void;
|
update: (updater: (config: ChatConfig) => void) => void;
|
||||||
|
mergeModels: (newModels: LLMModel[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModelConfig = ChatConfig["modelConfig"];
|
export type ModelConfig = ChatConfig["modelConfig"];
|
||||||
|
|
||||||
const ENABLE_GPT4 = true;
|
|
||||||
|
|
||||||
export const ALL_MODELS = [
|
|
||||||
{
|
|
||||||
name: "gpt-4",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-0314",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-0613",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k-0314",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-4-32k-0613",
|
|
||||||
available: ENABLE_GPT4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-0301",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-0613",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-16k",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "gpt-3.5-turbo-16k-0613",
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "qwen-v1", // 通义千问
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ernie", // 文心一言
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "spark", // 讯飞星火
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "llama", // llama
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "chatglm", // chatglm-6b
|
|
||||||
available: false,
|
|
||||||
},
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type ModelType = (typeof ALL_MODELS)[number]["name"];
|
|
||||||
|
|
||||||
export function limitNumber(
|
export function limitNumber(
|
||||||
x: number,
|
x: number,
|
||||||
min: number,
|
min: number,
|
||||||
@@ -137,7 +74,8 @@ export function limitNumber(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function limitModel(name: string) {
|
export function limitModel(name: string) {
|
||||||
return ALL_MODELS.some((m) => m.name === name && m.available)
|
const allModels = useAppConfig.getState().models;
|
||||||
|
return allModels.some((m) => m.name === name && m.available)
|
||||||
? name
|
? name
|
||||||
: "gpt-3.5-turbo";
|
: "gpt-3.5-turbo";
|
||||||
}
|
}
|
||||||
@@ -158,6 +96,9 @@ export const ModalConfigValidator = {
|
|||||||
temperature(x: number) {
|
temperature(x: number) {
|
||||||
return limitNumber(x, 0, 1, 1);
|
return limitNumber(x, 0, 1, 1);
|
||||||
},
|
},
|
||||||
|
top_p(x: number) {
|
||||||
|
return limitNumber(x, 0, 1, 1);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useAppConfig = create<ChatConfigStore>()(
|
export const useAppConfig = create<ChatConfigStore>()(
|
||||||
@@ -174,22 +115,44 @@ export const useAppConfig = create<ChatConfigStore>()(
|
|||||||
updater(config);
|
updater(config);
|
||||||
set(() => config);
|
set(() => config);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mergeModels(newModels) {
|
||||||
|
const oldModels = get().models;
|
||||||
|
const modelMap: Record<string, LLMModel> = {};
|
||||||
|
|
||||||
|
for (const model of oldModels) {
|
||||||
|
model.available = false;
|
||||||
|
modelMap[model.name] = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const model of newModels) {
|
||||||
|
model.available = true;
|
||||||
|
modelMap[model.name] = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(() => ({
|
||||||
|
models: Object.values(modelMap),
|
||||||
|
}));
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: StoreKey.Config,
|
name: StoreKey.Config,
|
||||||
version: 3.1,
|
version: 3.4,
|
||||||
migrate(persistedState, version) {
|
migrate(persistedState, version) {
|
||||||
if (version === 3.1) return persistedState as any;
|
|
||||||
|
|
||||||
const state = persistedState as ChatConfig;
|
const state = persistedState as ChatConfig;
|
||||||
state.modelConfig.sendMemory = true;
|
|
||||||
state.modelConfig.historyMessageCount = 4;
|
|
||||||
state.modelConfig.compressMessageLengthThreshold = 1000;
|
|
||||||
state.modelConfig.frequency_penalty = 0;
|
|
||||||
state.modelConfig.template = DEFAULT_INPUT_TEMPLATE;
|
|
||||||
state.dontShowMaskSplashScreen = false;
|
|
||||||
|
|
||||||
return state;
|
if (version < 3.4) {
|
||||||
|
state.modelConfig.sendMemory = true;
|
||||||
|
state.modelConfig.historyMessageCount = 4;
|
||||||
|
state.modelConfig.compressMessageLengthThreshold = 1000;
|
||||||
|
state.modelConfig.frequency_penalty = 0;
|
||||||
|
state.modelConfig.top_p = 1;
|
||||||
|
state.modelConfig.template = DEFAULT_INPUT_TEMPLATE;
|
||||||
|
state.dontShowMaskSplashScreen = false;
|
||||||
|
state.hideBuiltinMasks = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state as any;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -90,6 +90,7 @@ export const useMaskStore = create<MaskStore>()(
|
|||||||
(a, b) => b.id - a.id,
|
(a, b) => b.id - a.id,
|
||||||
);
|
);
|
||||||
const config = useAppConfig.getState();
|
const config = useAppConfig.getState();
|
||||||
|
if (config.hideBuiltinMasks) return userMasks;
|
||||||
const buildinMasks = BUILTIN_MASKS.map(
|
const buildinMasks = BUILTIN_MASKS.map(
|
||||||
(m) =>
|
(m) =>
|
||||||
({
|
({
|
||||||
|
@@ -127,7 +127,7 @@ export const usePromptStore = create<PromptStore>()(
|
|||||||
search(text) {
|
search(text) {
|
||||||
if (text.length === 0) {
|
if (text.length === 0) {
|
||||||
// return all rompts
|
// return all rompts
|
||||||
return SearchService.allPrompts.concat([...get().getUserPrompts()]);
|
return get().getUserPrompts().concat(SearchService.builtinPrompts);
|
||||||
}
|
}
|
||||||
return SearchService.search(text) as Prompt[];
|
return SearchService.search(text) as Prompt[];
|
||||||
},
|
},
|
||||||
|
87
app/store/sync.ts
Normal file
87
app/store/sync.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { Updater } from "../typing";
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { persist } from "zustand/middleware";
|
||||||
|
import { StoreKey } from "../constant";
|
||||||
|
|
||||||
|
export interface WebDavConfig {
|
||||||
|
server: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SyncStore {
|
||||||
|
webDavConfig: WebDavConfig;
|
||||||
|
lastSyncTime: number;
|
||||||
|
|
||||||
|
update: Updater<WebDavConfig>;
|
||||||
|
check: () => Promise<boolean>;
|
||||||
|
|
||||||
|
path: (path: string) => string;
|
||||||
|
headers: () => { Authorization: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
const FILE = {
|
||||||
|
root: "/chatgpt-next-web/",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSyncStore = create<SyncStore>()(
|
||||||
|
persist(
|
||||||
|
(set, get) => ({
|
||||||
|
webDavConfig: {
|
||||||
|
server: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
lastSyncTime: 0,
|
||||||
|
|
||||||
|
update(updater) {
|
||||||
|
const config = { ...get().webDavConfig };
|
||||||
|
updater(config);
|
||||||
|
set({ webDavConfig: config });
|
||||||
|
},
|
||||||
|
|
||||||
|
async check() {
|
||||||
|
try {
|
||||||
|
const res = await fetch(this.path(""), {
|
||||||
|
method: "PROFIND",
|
||||||
|
headers: this.headers(),
|
||||||
|
});
|
||||||
|
console.log(res);
|
||||||
|
return res.status === 207;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[Sync] ", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
path(path: string) {
|
||||||
|
let url = get().webDavConfig.server;
|
||||||
|
|
||||||
|
if (!url.endsWith("/")) {
|
||||||
|
url += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return url + path;
|
||||||
|
},
|
||||||
|
|
||||||
|
headers() {
|
||||||
|
const auth = btoa(
|
||||||
|
[get().webDavConfig.username, get().webDavConfig.password].join(":"),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Authorization: `Basic ${auth}`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: StoreKey.Sync,
|
||||||
|
version: 1,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
@@ -1,48 +1,95 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
import { FETCH_COMMIT_URL, StoreKey } from "../constant";
|
import { FETCH_COMMIT_URL, FETCH_TAG_URL, StoreKey } from "../constant";
|
||||||
import { api } from "../client/api";
|
import { api } from "../client/api";
|
||||||
import { getClientConfig } from "../config/client";
|
import { getClientConfig } from "../config/client";
|
||||||
|
|
||||||
export interface UpdateStore {
|
export interface UpdateStore {
|
||||||
|
versionType: "date" | "tag";
|
||||||
lastUpdate: number;
|
lastUpdate: number;
|
||||||
|
version: string;
|
||||||
remoteVersion: string;
|
remoteVersion: string;
|
||||||
|
|
||||||
used?: number;
|
used?: number;
|
||||||
subscription?: number;
|
subscription?: number;
|
||||||
lastUpdateUsage: number;
|
lastUpdateUsage: number;
|
||||||
|
|
||||||
version: string;
|
|
||||||
getLatestVersion: (force?: boolean) => Promise<void>;
|
getLatestVersion: (force?: boolean) => Promise<void>;
|
||||||
updateUsage: (force?: boolean) => Promise<void>;
|
updateUsage: (force?: boolean) => Promise<void>;
|
||||||
|
|
||||||
|
formatVersion: (version: string) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ONE_MINUTE = 60 * 1000;
|
const ONE_MINUTE = 60 * 1000;
|
||||||
|
|
||||||
|
function formatVersionDate(t: string) {
|
||||||
|
const d = new Date(+t);
|
||||||
|
const year = d.getUTCFullYear();
|
||||||
|
const month = d.getUTCMonth() + 1;
|
||||||
|
const day = d.getUTCDate();
|
||||||
|
|
||||||
|
return [
|
||||||
|
year.toString(),
|
||||||
|
month.toString().padStart(2, "0"),
|
||||||
|
day.toString().padStart(2, "0"),
|
||||||
|
].join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVersion(type: "date" | "tag") {
|
||||||
|
if (type === "date") {
|
||||||
|
const data = (await (await fetch(FETCH_COMMIT_URL)).json()) as {
|
||||||
|
commit: {
|
||||||
|
author: { name: string; date: string };
|
||||||
|
};
|
||||||
|
sha: string;
|
||||||
|
}[];
|
||||||
|
const remoteCommitTime = data[0].commit.author.date;
|
||||||
|
const remoteId = new Date(remoteCommitTime).getTime().toString();
|
||||||
|
return remoteId;
|
||||||
|
} else if (type === "tag") {
|
||||||
|
const data = (await (await fetch(FETCH_TAG_URL)).json()) as {
|
||||||
|
commit: { sha: string; url: string };
|
||||||
|
name: string;
|
||||||
|
}[];
|
||||||
|
return data.at(0)?.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useUpdateStore = create<UpdateStore>()(
|
export const useUpdateStore = create<UpdateStore>()(
|
||||||
persist(
|
persist(
|
||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
|
versionType: "tag",
|
||||||
lastUpdate: 0,
|
lastUpdate: 0,
|
||||||
|
version: "unknown",
|
||||||
remoteVersion: "",
|
remoteVersion: "",
|
||||||
|
|
||||||
lastUpdateUsage: 0,
|
lastUpdateUsage: 0,
|
||||||
|
|
||||||
version: "unknown",
|
formatVersion(version: string) {
|
||||||
|
if (get().versionType === "date") {
|
||||||
|
version = formatVersionDate(version);
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
},
|
||||||
|
|
||||||
async getLatestVersion(force = false) {
|
async getLatestVersion(force = false) {
|
||||||
set(() => ({ version: getClientConfig()?.commitId ?? "unknown" }));
|
const versionType = get().versionType;
|
||||||
|
let version =
|
||||||
|
versionType === "date"
|
||||||
|
? getClientConfig()?.commitDate
|
||||||
|
: getClientConfig()?.version;
|
||||||
|
|
||||||
const overTenMins = Date.now() - get().lastUpdate > 10 * ONE_MINUTE;
|
set(() => ({ version }));
|
||||||
if (!force && !overTenMins) return;
|
|
||||||
|
const shouldCheck = Date.now() - get().lastUpdate > 2 * 60 * ONE_MINUTE;
|
||||||
|
if (!force && !shouldCheck) return;
|
||||||
|
|
||||||
set(() => ({
|
set(() => ({
|
||||||
lastUpdate: Date.now(),
|
lastUpdate: Date.now(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await (await fetch(FETCH_COMMIT_URL)).json();
|
const remoteId = await getVersion(versionType);
|
||||||
const remoteCommitTime = data[0].commit.committer.date;
|
|
||||||
const remoteId = new Date(remoteCommitTime).getTime().toString();
|
|
||||||
set(() => ({
|
set(() => ({
|
||||||
remoteVersion: remoteId,
|
remoteVersion: remoteId,
|
||||||
}));
|
}));
|
||||||
|
@@ -304,6 +304,9 @@ pre {
|
|||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(0.9);
|
filter: brightness(0.9);
|
||||||
}
|
}
|
||||||
|
&:focus {
|
||||||
|
filter: brightness(0.95);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
.window-header-sub-title {
|
.window-header-sub-title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: 5px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +31,6 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-action-button {
|
.window-action-button:not(:first-child) {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,12 @@ export function trimTopic(topic: string) {
|
|||||||
|
|
||||||
export async function copyToClipboard(text: string) {
|
export async function copyToClipboard(text: string) {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(text);
|
if (window.__TAURI__) {
|
||||||
|
window.__TAURI__.writeText(text);
|
||||||
|
} else {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
}
|
||||||
|
|
||||||
showToast(Locale.Copy.Success);
|
showToast(Locale.Copy.Success);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const textArea = document.createElement("textarea");
|
const textArea = document.createElement("textarea");
|
||||||
|
@@ -105,6 +105,23 @@ keepalive_timeout 300; # 设定keep-alive超时时间为65秒
|
|||||||
|
|
||||||
API KEY 有问题。余额不足。
|
API KEY 有问题。余额不足。
|
||||||
|
|
||||||
|
## 使用时遇到 "Error: Loading CSS chunk xxx failed..."
|
||||||
|
|
||||||
|
为了减少首屏白屏时间,默认启用了分块编译,技术原理见下:
|
||||||
|
|
||||||
|
- https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading
|
||||||
|
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4
|
||||||
|
- https://github.com/vercel/next.js/issues/38507
|
||||||
|
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4
|
||||||
|
|
||||||
|
然而 NextJS 的兼容性比较差,在比较老的浏览器上会导致此报错,可以在编译时关闭分块编译。
|
||||||
|
|
||||||
|
对于 Vercel 平台,在环境变量中增加 `DISABLE_CHUNK=1`,然后重新部署即可;
|
||||||
|
对于自行编译部署的项目,在构建时使用 `DISABLE_CHUNK=1 yarn build` 构建即可;
|
||||||
|
对于 Docker 用户,由于 Docker 打包时已经构建完毕,所以暂不支持关闭此特性。
|
||||||
|
|
||||||
|
注意,关闭此特性后,用户会在第一次访问网站时加载所有资源,如果用户网络状况较差,可能会引起较长时间的白屏,从而影响用户使用体验,所以自行考虑。
|
||||||
|
|
||||||
# 网络服务相关问题
|
# 网络服务相关问题
|
||||||
|
|
||||||
## Cloudflare 是什么?
|
## Cloudflare 是什么?
|
||||||
|
@@ -1,21 +1,26 @@
|
|||||||
# Frequently Asked Questions
|
# Frequently Asked Questions
|
||||||
|
|
||||||
## How to get help quickly?
|
## How to get help quickly?
|
||||||
|
|
||||||
1. Ask ChatGPT / Bing / Baidu / Google, etc.
|
1. Ask ChatGPT / Bing / Baidu / Google, etc.
|
||||||
2. Ask online friends. Please provide background information and a detailed description of the problem. High-quality questions are more likely to get useful answers.
|
2. Ask online friends. Please provide background information and a detailed description of the problem. High-quality questions are more likely to get useful answers.
|
||||||
|
|
||||||
# Deployment Related Questions
|
# Deployment Related Questions
|
||||||
|
|
||||||
## Why does the Docker deployment version always prompt for updates
|
## Why does the Docker deployment version always prompt for updates
|
||||||
|
|
||||||
The Docker version is equivalent to the stable version, and the latest Docker is always consistent with the latest release version. Currently, our release frequency is once every one to two days, so the Docker version will always be one to two days behind the latest commit, which is expected.
|
The Docker version is equivalent to the stable version, and the latest Docker is always consistent with the latest release version. Currently, our release frequency is once every one to two days, so the Docker version will always be one to two days behind the latest commit, which is expected.
|
||||||
|
|
||||||
## How to deploy on Vercel
|
## How to deploy on Vercel
|
||||||
|
|
||||||
1. Register a Github account and fork this project.
|
1. Register a Github account and fork this project.
|
||||||
2. Register Vercel (mobile phone verification required, Chinese number can be used), and connect your Github account.
|
2. Register Vercel (mobile phone verification required, Chinese number can be used), and connect your Github account.
|
||||||
3. Create a new project on Vercel, select the project you forked on Github, fill in the required environment variables, and start deploying. After deployment, you can access your project through the domain provided by Vercel. (Requires proxy in mainland China)
|
3. Create a new project on Vercel, select the project you forked on Github, fill in the required environment variables, and start deploying. After deployment, you can access your project through the domain provided by Vercel. (Requires proxy in mainland China)
|
||||||
* If you need to access it directly in China: At your DNS provider, add a CNAME record for the domain name, pointing to cname.vercel-dns.com. Then set up your domain access on Vercel.
|
|
||||||
|
- If you need to access it directly in China: At your DNS provider, add a CNAME record for the domain name, pointing to cname.vercel-dns.com. Then set up your domain access on Vercel.
|
||||||
|
|
||||||
## How to modify Vercel environment variables
|
## How to modify Vercel environment variables
|
||||||
|
|
||||||
- Enter the Vercel console page;
|
- Enter the Vercel console page;
|
||||||
- Select your chatgpt-next-web project;
|
- Select your chatgpt-next-web project;
|
||||||
- Click on the Settings option at the top of the page;
|
- Click on the Settings option at the top of the page;
|
||||||
@@ -23,14 +28,18 @@ The Docker version is equivalent to the stable version, and the latest Docker is
|
|||||||
- Modify the corresponding values as needed.
|
- Modify the corresponding values as needed.
|
||||||
|
|
||||||
## What is the environment variable CODE? Is it necessary to set it?
|
## What is the environment variable CODE? Is it necessary to set it?
|
||||||
|
|
||||||
This is your custom access password, you can choose:
|
This is your custom access password, you can choose:
|
||||||
|
|
||||||
1. Do not set it, delete the environment variable. Be cautious: anyone can access your project at this time.
|
1. Do not set it, delete the environment variable. Be cautious: anyone can access your project at this time.
|
||||||
2. When deploying the project, set the environment variable CODE (supports multiple passwords, separated by commas). After setting the access password, users need to enter the access password in the settings page to use it. See [related instructions](https://github.com/Yidadaa/ChatGPT-Next-Web#access-password)
|
2. When deploying the project, set the environment variable CODE (supports multiple passwords, separated by commas). After setting the access password, users need to enter the access password in the settings page to use it. See [related instructions](https://github.com/Yidadaa/ChatGPT-Next-Web#access-password)
|
||||||
|
|
||||||
## Why doesn't the version I deployed have streaming response
|
## Why doesn't the version I deployed have streaming response
|
||||||
|
|
||||||
> Related discussion: [#386](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/386)
|
> Related discussion: [#386](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/386)
|
||||||
|
|
||||||
If you use nginx reverse proxy, you need to add the following code to the configuration file:
|
If you use nginx reverse proxy, you need to add the following code to the configuration file:
|
||||||
|
|
||||||
```
|
```
|
||||||
# No caching, support streaming output
|
# No caching, support streaming output
|
||||||
proxy_cache off; # Turn off caching
|
proxy_cache off; # Turn off caching
|
||||||
@@ -44,89 +53,135 @@ keepalive_timeout 300; # Set keep-alive timeout to 65 seconds
|
|||||||
If you are deploying on netlify, this issue is still waiting to be resolved, please be patient.
|
If you are deploying on netlify, this issue is still waiting to be resolved, please be patient.
|
||||||
|
|
||||||
## I've deployed, but it's not accessible
|
## I've deployed, but it's not accessible
|
||||||
|
|
||||||
Please check and troubleshoot the following issues:
|
Please check and troubleshoot the following issues:
|
||||||
|
|
||||||
- Is the service started?
|
- Is the service started?
|
||||||
- Is the port correctly mapped?
|
- Is the port correctly mapped?
|
||||||
- Is the firewall port open?
|
- Is the firewall port open?
|
||||||
- Is the route to the server okay?
|
- Is the route to the server okay?
|
||||||
- Is the domain name resolved correctly?
|
- Is the domain name resolved correctly?
|
||||||
|
|
||||||
|
## You may encounter an "Error: Loading CSS chunk xxx failed..."
|
||||||
|
|
||||||
|
To reduce the initial white screen time, Next.js enables chunking by default. You can find the technical details here:
|
||||||
|
|
||||||
|
- https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading
|
||||||
|
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4
|
||||||
|
- https://github.com/vercel/next.js/issues/38507
|
||||||
|
- https://stackoverflow.com/questions/55993890/how-can-i-disable-chunkcode-splitting-with-webpack4
|
||||||
|
|
||||||
|
However, Next.js has limited compatibility with older browsers, which can result in this error.
|
||||||
|
|
||||||
|
You can disable chunking during building.
|
||||||
|
|
||||||
|
For Vercel platform, you can add `DISABLE_CHUNK=1` to the environment variables and redeploy.
|
||||||
|
For self-deployed projects, you can use `DISABLE_CHUNK=1 yarn build` during the build process.
|
||||||
|
For Docker users, as the build is already completed during packaging, disabling this feature is currently not supported.
|
||||||
|
|
||||||
|
Note that when you disable this feature, all resources will be loaded on the user's first visit. This may result in a longer white screen time if the user has a poor network connection, affecting the user experience. Please consider this when making a decision.
|
||||||
|
|
||||||
# Usage Related Questions
|
# Usage Related Questions
|
||||||
|
|
||||||
## Why does it always prompt "An error occurred, please try again later"
|
## Why does it always prompt "An error occurred, please try again later"
|
||||||
|
|
||||||
There could be many reasons, please check the following in order:
|
There could be many reasons, please check the following in order:
|
||||||
|
|
||||||
- First, check if your code version is the latest version, update to the latest version and try again;
|
- First, check if your code version is the latest version, update to the latest version and try again;
|
||||||
- Check if the api key is set correctly, the environment variable name must be uppercase with underscores;
|
- Check if the api key is set correctly, the environment variable name must be uppercase with underscores;
|
||||||
- Check if the api key is available;
|
- Check if the api key is available;
|
||||||
- If you still cannot determine the problem after going through the above steps, please submit a new issue in the issue area and attach the runtime log of vercel or the log of docker runtime.
|
- If you still cannot determine the problem after going through the above steps, please submit a new issue in the issue area and attach the runtime log of vercel or the log of docker runtime.
|
||||||
|
|
||||||
## Why does ChatGPT's reply get garbled
|
## Why does ChatGPT's reply get garbled
|
||||||
|
|
||||||
In the settings page - model settings, there is an item called `temperature`. If this value is greater than 1, it may cause garbled replies. Adjust it back to within 1.
|
In the settings page - model settings, there is an item called `temperature`. If this value is greater than 1, it may cause garbled replies. Adjust it back to within 1.
|
||||||
|
|
||||||
## It prompts "Now it's unauthorized, please enter the access password on the settings page" when using?
|
## It prompts "Now it's unauthorized, please enter the access password on the settings page" when using?
|
||||||
|
|
||||||
The project has set an access password through the environment variable CODE. When using it for the first time, you need to go to settings and enter the access code to use.
|
The project has set an access password through the environment variable CODE. When using it for the first time, you need to go to settings and enter the access code to use.
|
||||||
|
|
||||||
## It prompts "You exceeded your current quota, ..." when using?
|
## It prompts "You exceeded your current quota, ..." when using?
|
||||||
|
|
||||||
The API KEY is problematic. Insufficient balance.
|
The API KEY is problematic. Insufficient balance.
|
||||||
|
|
||||||
## What is a proxy and how to use it?
|
## What is a proxy and how to use it?
|
||||||
|
|
||||||
Due to IP restrictions of OpenAI, China and some other countries/regions cannot directly connect to OpenAI API and need to go through a proxy. You can use a proxy server (forward proxy) or a pre-configured OpenAI API reverse proxy.
|
Due to IP restrictions of OpenAI, China and some other countries/regions cannot directly connect to OpenAI API and need to go through a proxy. You can use a proxy server (forward proxy) or a pre-configured OpenAI API reverse proxy.
|
||||||
|
|
||||||
- Forward proxy example: VPN ladder. In the case of docker deployment, set the environment variable HTTP_PROXY to your proxy address (http://address:port).
|
- Forward proxy example: VPN ladder. In the case of docker deployment, set the environment variable HTTP_PROXY to your proxy address (http://address:port).
|
||||||
- Reverse proxy example: You can use someone else's proxy address or set it up for free through Cloudflare. Set the project environment variable BASE_URL to your proxy address.
|
- Reverse proxy example: You can use someone else's proxy address or set it up for free through Cloudflare. Set the project environment variable BASE_URL to your proxy address.
|
||||||
|
|
||||||
## Can I deploy it on a server in China?
|
## Can I deploy it on a server in China?
|
||||||
|
|
||||||
It is possible but there are issues to be addressed:
|
It is possible but there are issues to be addressed:
|
||||||
|
|
||||||
- Proxy is required to connect to websites such as Github and OpenAI;
|
- Proxy is required to connect to websites such as Github and OpenAI;
|
||||||
- Domain name resolution requires filing for servers in China;
|
- Domain name resolution requires filing for servers in China;
|
||||||
- Chinese policy restricts proxy access to foreign websites/ChatGPT-related applications, which may be blocked.
|
- Chinese policy restricts proxy access to foreign websites/ChatGPT-related applications, which may be blocked.
|
||||||
|
|
||||||
# Network Service Related Questions
|
# Network Service Related Questions
|
||||||
|
|
||||||
## What is Cloudflare?
|
## What is Cloudflare?
|
||||||
|
|
||||||
Cloudflare (CF) is a network service provider offering CDN, domain management, static page hosting, edge computing function deployment, and more. Common use cases: purchase and/or host your domain (resolution, dynamic domain, etc.), apply CDN to your server (can hide IP to avoid being blocked), deploy websites (CF Pages). CF offers most services for free.
|
Cloudflare (CF) is a network service provider offering CDN, domain management, static page hosting, edge computing function deployment, and more. Common use cases: purchase and/or host your domain (resolution, dynamic domain, etc.), apply CDN to your server (can hide IP to avoid being blocked), deploy websites (CF Pages). CF offers most services for free.
|
||||||
|
|
||||||
## What is Vercel?
|
## What is Vercel?
|
||||||
|
|
||||||
Vercel is a global cloud platform designed to help developers build and deploy modern web applications more quickly. This project and many web applications can be deployed on Vercel with a single click for free. No need to understand code, Linux, have a server, pay, or set up an OpenAI API proxy. The downside is that you need to bind a domain name to access it without restrictions in China.
|
Vercel is a global cloud platform designed to help developers build and deploy modern web applications more quickly. This project and many web applications can be deployed on Vercel with a single click for free. No need to understand code, Linux, have a server, pay, or set up an OpenAI API proxy. The downside is that you need to bind a domain name to access it without restrictions in China.
|
||||||
|
|
||||||
## How to obtain a domain name?
|
## How to obtain a domain name?
|
||||||
|
|
||||||
1. Register with a domain provider, such as Namesilo (supports Alipay) or Cloudflare for international providers, and Wanwang for domestic providers in China.
|
1. Register with a domain provider, such as Namesilo (supports Alipay) or Cloudflare for international providers, and Wanwang for domestic providers in China.
|
||||||
2. Free domain name providers: eu.org (second-level domain), etc.
|
2. Free domain name providers: eu.org (second-level domain), etc.
|
||||||
3. Ask friends for a free second-level domain.
|
3. Ask friends for a free second-level domain.
|
||||||
|
|
||||||
## How to obtain a server
|
## How to obtain a server
|
||||||
|
|
||||||
- Examples of international server providers: Amazon Web Services, Google Cloud, Vultr, Bandwagon, Hostdare, etc.
|
- Examples of international server providers: Amazon Web Services, Google Cloud, Vultr, Bandwagon, Hostdare, etc.
|
||||||
International server considerations: Server lines affect access speed in China; CN2 GIA and CN2 lines are recommended. If the server has difficulty accessing in China (serious packet loss, etc.), you can try using a CDN (from providers like Cloudflare).
|
International server considerations: Server lines affect access speed in China; CN2 GIA and CN2 lines are recommended. If the server has difficulty accessing in China (serious packet loss, etc.), you can try using a CDN (from providers like Cloudflare).
|
||||||
- Domestic server providers: Alibaba Cloud, Tencent, etc.
|
- Domestic server providers: Alibaba Cloud, Tencent, etc.
|
||||||
Domestic server considerations: Domain name resolution requires filing; domestic server bandwidth is relatively expensive; accessing foreign websites (Github, OpenAI, etc.) requires a proxy.
|
Domestic server considerations: Domain name resolution requires filing; domestic server bandwidth is relatively expensive; accessing foreign websites (Github, OpenAI, etc.) requires a proxy.
|
||||||
|
|
||||||
# OpenAI-related Questions
|
# OpenAI-related Questions
|
||||||
|
|
||||||
## How to register an OpenAI account?
|
## How to register an OpenAI account?
|
||||||
|
|
||||||
Go to chat.openai.com to register. You will need:
|
Go to chat.openai.com to register. You will need:
|
||||||
|
|
||||||
- A good VPN (OpenAI only allows native IP addresses of supported regions)
|
- A good VPN (OpenAI only allows native IP addresses of supported regions)
|
||||||
- A supported email (e.g., Gmail or a company/school email, not Outlook or QQ email)
|
- A supported email (e.g., Gmail or a company/school email, not Outlook or QQ email)
|
||||||
- A way to receive SMS verification (e.g., SMS-activate website)
|
- A way to receive SMS verification (e.g., SMS-activate website)
|
||||||
|
|
||||||
## How to activate OpenAI API? How to check API balance?
|
## How to activate OpenAI API? How to check API balance?
|
||||||
|
|
||||||
Official website (requires VPN): https://platform.openai.com/account/usage
|
Official website (requires VPN): https://platform.openai.com/account/usage
|
||||||
Some users have set up a proxy to check the balance without a VPN; ask online friends for access. Please verify the source is reliable to avoid API Key leakage.
|
Some users have set up a proxy to check the balance without a VPN; ask online friends for access. Please verify the source is reliable to avoid API Key leakage.
|
||||||
|
|
||||||
## Why doesn't my new OpenAI account have an API balance?
|
## Why doesn't my new OpenAI account have an API balance?
|
||||||
|
|
||||||
(Updated April 6th) Newly registered accounts usually display API balance within 24 hours. New accounts are currently given a $5 balance.
|
(Updated April 6th) Newly registered accounts usually display API balance within 24 hours. New accounts are currently given a $5 balance.
|
||||||
|
|
||||||
## How to recharge OpenAI API?
|
## How to recharge OpenAI API?
|
||||||
|
|
||||||
OpenAI only accepts credit cards from designated regions (Chinese credit cards cannot be used). If the credit cards from your region is not supported, some options include:
|
OpenAI only accepts credit cards from designated regions (Chinese credit cards cannot be used). If the credit cards from your region is not supported, some options include:
|
||||||
|
|
||||||
1. Depay virtual credit card
|
1. Depay virtual credit card
|
||||||
2. Apply for a foreign credit card
|
2. Apply for a foreign credit card
|
||||||
3. Find someone online to top up
|
3. Find someone online to top up
|
||||||
|
|
||||||
## How to access the GPT-4 API?
|
## How to access the GPT-4 API?
|
||||||
|
|
||||||
(Updated April 6th) Access to the GPT-4 API requires a separate application. Go to the following address and enter your information to join the waitlist (prepare your OpenAI organization ID): https://openai.com/waitlist/gpt-4-api
|
(Updated April 6th) Access to the GPT-4 API requires a separate application. Go to the following address and enter your information to join the waitlist (prepare your OpenAI organization ID): https://openai.com/waitlist/gpt-4-api
|
||||||
Wait for email updates afterwards.
|
Wait for email updates afterwards.
|
||||||
|
|
||||||
## How to use the Azure OpenAI interface
|
## How to use the Azure OpenAI interface
|
||||||
|
|
||||||
Please refer to: [#371](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/371)
|
Please refer to: [#371](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/371)
|
||||||
|
|
||||||
## Why is my Token consumed so fast?
|
## Why is my Token consumed so fast?
|
||||||
|
|
||||||
> Related discussion: [#518](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/518)
|
> Related discussion: [#518](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/518)
|
||||||
|
|
||||||
- If you have GPT-4 access and use GPT-4 API regularly, your bill will increase rapidly since GPT-4 pricing is about 15 times higher than GPT-3.5;
|
- If you have GPT-4 access and use GPT-4 API regularly, your bill will increase rapidly since GPT-4 pricing is about 15 times higher than GPT-3.5;
|
||||||
- If you are using GPT-3.5 and not using it frequently, but still find your bill increasing fast, please troubleshoot immediately using these steps:
|
- If you are using GPT-3.5 and not using it frequently, but still find your bill increasing fast, please troubleshoot immediately using these steps:
|
||||||
- Check your API key consumption record on the OpenAI website; if your token is consumed every hour and each time consumes tens of thousands of tokens, your key must have been leaked. Please delete it and regenerate it immediately. **Do not check your balance on random websites.**
|
- Check your API key consumption record on the OpenAI website; if your token is consumed every hour and each time consumes tens of thousands of tokens, your key must have been leaked. Please delete it and regenerate it immediately. **Do not check your balance on random websites.**
|
||||||
|
12
docs/translation.md
Normal file
12
docs/translation.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# How to add a new translation?
|
||||||
|
|
||||||
|
Assume that we are adding a new translation for `new`.
|
||||||
|
|
||||||
|
1. copy `app/locales/en.ts` to `app/locales/new.ts`;
|
||||||
|
2. edit `new.ts`, change `const en: LocaleType = ` to `const new: PartialLocaleType`, and `export default new;`;
|
||||||
|
3. edit `app/locales/index.ts`:
|
||||||
|
4. `import new from './new.ts'`;
|
||||||
|
5. add `new` to `ALL_LANGS`;
|
||||||
|
6. add `new: "new lang"` to `ALL_LANG_OPTIONS`;
|
||||||
|
7. translate the strings in `new.ts`;
|
||||||
|
8. submit a pull request, and the author will merge it.
|
@@ -1,6 +1,11 @@
|
|||||||
|
import webpack from "webpack";
|
||||||
|
|
||||||
const mode = process.env.BUILD_MODE ?? "standalone";
|
const mode = process.env.BUILD_MODE ?? "standalone";
|
||||||
console.log("[Next] build mode", mode);
|
console.log("[Next] build mode", mode);
|
||||||
|
|
||||||
|
const disableChunk = !!process.env.DISABLE_CHUNK || mode === "export";
|
||||||
|
console.log("[Next] build with chunk: ", !disableChunk);
|
||||||
|
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
webpack(config) {
|
webpack(config) {
|
||||||
@@ -9,6 +14,12 @@ const nextConfig = {
|
|||||||
use: ["@svgr/webpack"],
|
use: ["@svgr/webpack"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (disableChunk) {
|
||||||
|
config.plugins.push(
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
output: mode,
|
output: mode,
|
||||||
|
18
package.json
18
package.json
@@ -4,11 +4,11 @@
|
|||||||
"license": "mit",
|
"license": "mit",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "cross-env BUILD_MODE=standalone next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"export": "cross-env BUILD_MODE=export BUILD_APP=1 yarn build",
|
"export": "cross-env BUILD_MODE=export BUILD_APP=1 next build",
|
||||||
"export:dev": "cross-env BUILD_MODE=export BUILD_APP=1 yarn dev",
|
"export:dev": "cross-env BUILD_MODE=export BUILD_APP=1 next dev",
|
||||||
"app:dev": "yarn tauri dev",
|
"app:dev": "yarn tauri dev",
|
||||||
"app:build": "yarn tauri build",
|
"app:build": "yarn tauri build",
|
||||||
"prompts": "node ./scripts/fetch-prompts.mjs",
|
"prompts": "node ./scripts/fetch-prompts.mjs",
|
||||||
@@ -17,13 +17,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortaine/fetch-event-source": "^3.0.6",
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
"@hello-pangea/dnd": "^16.2.0",
|
"@hello-pangea/dnd": "^16.3.0",
|
||||||
"@svgr/webpack": "^6.5.1",
|
"@svgr/webpack": "^6.5.1",
|
||||||
"@vercel/analytics": "^0.1.11",
|
"@vercel/analytics": "^0.1.11",
|
||||||
"emoji-picker-react": "^4.4.7",
|
"emoji-picker-react": "^4.4.7",
|
||||||
"fuse.js": "^6.6.2",
|
"fuse.js": "^6.6.2",
|
||||||
"html-to-image": "^1.11.11",
|
"html-to-image": "^1.11.11",
|
||||||
"mermaid": "^10.2.3",
|
"mermaid": "^10.2.3",
|
||||||
|
"nanoid": "^4.0.2",
|
||||||
"next": "^13.4.6",
|
"next": "^13.4.6",
|
||||||
"node-fetch": "^3.3.1",
|
"node-fetch": "^3.3.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-router-dom": "^6.10.0",
|
"react-router-dom": "^6.10.0",
|
||||||
"rehype-highlight": "^6.0.0",
|
"rehype-highlight": "^6.0.0",
|
||||||
"rehype-katex": "^6.0.2",
|
"rehype-katex": "^6.0.3",
|
||||||
"remark-breaks": "^3.0.2",
|
"remark-breaks": "^3.0.2",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-math": "^5.1.1",
|
"remark-math": "^5.1.1",
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^1.3.1",
|
"@tauri-apps/cli": "^1.3.1",
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.3",
|
||||||
"@types/react": "^18.2.12",
|
"@types/react": "^18.2.12",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/react-katex": "^3.0.0",
|
"@types/react-katex": "^3.0.0",
|
||||||
@@ -54,8 +55,9 @@
|
|||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"husky": "^8.0.0",
|
"husky": "^8.0.0",
|
||||||
"lint-staged": "^13.2.2",
|
"lint-staged": "^13.2.2",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.8",
|
||||||
"typescript": "4.9.5"
|
"typescript": "4.9.5",
|
||||||
|
"webpack": "^5.88.1"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"lint-staged/yaml": "^2.2.2"
|
"lint-staged/yaml": "^2.2.2"
|
||||||
|
BIN
public/macos.png
Normal file
BIN
public/macos.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@@ -17,7 +17,7 @@ tauri-build = { version = "1.3.0", features = [] }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tauri = { version = "1.3.0", features = ["clipboard-all", "shell-open", "updater", "window-close", "window-hide", "window-maximize", "window-minimize", "window-set-icon", "window-set-ignore-cursor-events", "window-set-resizable", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
|
tauri = { version = "1.3.0", features = ["clipboard-all", "dialog-all", "shell-open", "updater", "window-close", "window-hide", "window-maximize", "window-minimize", "window-set-icon", "window-set-ignore-cursor-events", "window-set-resizable", "window-show", "window-start-dragging", "window-unmaximize", "window-unminimize"] }
|
||||||
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
Binary file not shown.
@@ -4,11 +4,12 @@
|
|||||||
"beforeBuildCommand": "yarn export",
|
"beforeBuildCommand": "yarn export",
|
||||||
"beforeDevCommand": "yarn export:dev",
|
"beforeDevCommand": "yarn export:dev",
|
||||||
"devPath": "http://localhost:3000",
|
"devPath": "http://localhost:3000",
|
||||||
"distDir": "../out"
|
"distDir": "../out",
|
||||||
|
"withGlobalTauri": true
|
||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "chatgpt-next-web",
|
"productName": "ChatGPT Next Web",
|
||||||
"version": "2.8.3"
|
"version": "2.8.8"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
@@ -17,8 +18,18 @@
|
|||||||
"all": false,
|
"all": false,
|
||||||
"open": true
|
"open": true
|
||||||
},
|
},
|
||||||
|
"dialog": {
|
||||||
|
"all": true,
|
||||||
|
"ask": true,
|
||||||
|
"confirm": true,
|
||||||
|
"message": true,
|
||||||
|
"open": true,
|
||||||
|
"save": true
|
||||||
|
},
|
||||||
"clipboard": {
|
"clipboard": {
|
||||||
"all": true
|
"all": true,
|
||||||
|
"writeText": true,
|
||||||
|
"readText": true
|
||||||
},
|
},
|
||||||
"window": {
|
"window": {
|
||||||
"all": false,
|
"all": false,
|
||||||
@@ -74,7 +85,7 @@
|
|||||||
"updater": {
|
"updater": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
"https://github.com/Yidadaa/ChatGPT-Next-Web/releases/download/{{current_version}}/latest.json"
|
"https://github.com/Yidadaa/ChatGPT-Next-Web/releases/latest/download/latest.json"
|
||||||
],
|
],
|
||||||
"dialog": false,
|
"dialog": false,
|
||||||
"windows": {
|
"windows": {
|
||||||
|
547
yarn.lock
547
yarn.lock
@@ -954,10 +954,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
|
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
|
||||||
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
|
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
|
||||||
|
|
||||||
"@babel/runtime@^7.12.1", "@babel/runtime@^7.19.4", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
"@babel/runtime@^7.12.1", "@babel/runtime@^7.20.7", "@babel/runtime@^7.22.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||||
version "7.21.0"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
|
||||||
integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
|
integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.11"
|
regenerator-runtime "^0.13.11"
|
||||||
|
|
||||||
@@ -1037,17 +1037,17 @@
|
|||||||
resolved "https://registry.npmmirror.com/@fortaine/fetch-event-source/-/fetch-event-source-3.0.6.tgz#b8552a2ca2c5202f5699b93a92be0188d422b06e"
|
resolved "https://registry.npmmirror.com/@fortaine/fetch-event-source/-/fetch-event-source-3.0.6.tgz#b8552a2ca2c5202f5699b93a92be0188d422b06e"
|
||||||
integrity sha512-621GAuLMvKtyZQ3IA6nlDWhV1V/7PGOTNIGLUifxt0KzM+dZIweJ6F3XvQF3QnqeNfS1N7WQ0Kil1Di/lhChEw==
|
integrity sha512-621GAuLMvKtyZQ3IA6nlDWhV1V/7PGOTNIGLUifxt0KzM+dZIweJ6F3XvQF3QnqeNfS1N7WQ0Kil1Di/lhChEw==
|
||||||
|
|
||||||
"@hello-pangea/dnd@^16.2.0":
|
"@hello-pangea/dnd@^16.3.0":
|
||||||
version "16.2.0"
|
version "16.3.0"
|
||||||
resolved "https://registry.npmmirror.com/@hello-pangea/dnd/-/dnd-16.2.0.tgz#58cbadeb56f8c7a381da696bb7aa3bfbb87876ec"
|
resolved "https://registry.yarnpkg.com/@hello-pangea/dnd/-/dnd-16.3.0.tgz#3776212f812df4e8e69c42831ec8ab7ff3a087d6"
|
||||||
integrity sha512-inACvMcvvLr34CG0P6+G/3bprVKhwswxjcsFUSJ+fpOGjhvDj9caiA9X3clby0lgJ6/ILIJjyedHZYECB7GAgA==
|
integrity sha512-RYQ/K8shtJoyNPvFWz0gfXIK7HF3P3mL9UZFGMuHB0ljRSXVgMjVFI/FxcZmakMzw6tO7NflWLriwTNBow/4vw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.19.4"
|
"@babel/runtime" "^7.22.5"
|
||||||
css-box-model "^1.2.1"
|
css-box-model "^1.2.1"
|
||||||
memoize-one "^6.0.0"
|
memoize-one "^6.0.0"
|
||||||
raf-schd "^4.0.3"
|
raf-schd "^4.0.3"
|
||||||
react-redux "^8.0.4"
|
react-redux "^8.1.1"
|
||||||
redux "^4.2.0"
|
redux "^4.2.1"
|
||||||
use-memo-one "^1.1.3"
|
use-memo-one "^1.1.3"
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.11.8":
|
"@humanwhocodes/config-array@^0.11.8":
|
||||||
@@ -1077,6 +1077,15 @@
|
|||||||
"@jridgewell/set-array" "^1.0.0"
|
"@jridgewell/set-array" "^1.0.0"
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping@^0.3.0":
|
||||||
|
version "0.3.3"
|
||||||
|
resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
|
||||||
|
integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/set-array" "^1.0.1"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
"@jridgewell/gen-mapping@^0.3.2":
|
"@jridgewell/gen-mapping@^0.3.2":
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||||
@@ -1096,6 +1105,14 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||||
|
|
||||||
|
"@jridgewell/source-map@^0.3.3":
|
||||||
|
version "0.3.3"
|
||||||
|
resolved "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda"
|
||||||
|
integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.0"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
|
"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
|
||||||
version "1.4.14"
|
version "1.4.14"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||||
@@ -1394,6 +1411,27 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/ms" "*"
|
"@types/ms" "*"
|
||||||
|
|
||||||
|
"@types/eslint-scope@^3.7.3":
|
||||||
|
version "3.7.4"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
|
||||||
|
integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==
|
||||||
|
dependencies:
|
||||||
|
"@types/eslint" "*"
|
||||||
|
"@types/estree" "*"
|
||||||
|
|
||||||
|
"@types/eslint@*":
|
||||||
|
version "8.40.2"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/eslint/-/eslint-8.40.2.tgz#2833bc112d809677864a4b0e7d1de4f04d7dac2d"
|
||||||
|
integrity sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "*"
|
||||||
|
"@types/json-schema" "*"
|
||||||
|
|
||||||
|
"@types/estree@*", "@types/estree@^1.0.0":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
|
||||||
|
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
||||||
|
|
||||||
"@types/hast@^2.0.0":
|
"@types/hast@^2.0.0":
|
||||||
version "2.3.4"
|
version "2.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
|
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
|
||||||
@@ -1409,6 +1447,11 @@
|
|||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
|
||||||
|
"@types/json-schema@*", "@types/json-schema@^7.0.8":
|
||||||
|
version "7.0.12"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
|
||||||
|
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
|
||||||
|
|
||||||
"@types/json5@^0.0.29":
|
"@types/json5@^0.0.29":
|
||||||
version "0.0.29"
|
version "0.0.29"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
@@ -1419,6 +1462,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5"
|
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5"
|
||||||
integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==
|
integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==
|
||||||
|
|
||||||
|
"@types/katex@^0.14.0":
|
||||||
|
version "0.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.14.0.tgz#b84c0afc3218069a5ad64fe2a95321881021b5fe"
|
||||||
|
integrity sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==
|
||||||
|
|
||||||
"@types/mdast@^3.0.0":
|
"@types/mdast@^3.0.0":
|
||||||
version "3.0.11"
|
version "3.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.11.tgz#dc130f7e7d9306124286f6d6cee40cf4d14a3dc0"
|
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.11.tgz#dc130f7e7d9306124286f6d6cee40cf4d14a3dc0"
|
||||||
@@ -1431,10 +1479,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
||||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||||
|
|
||||||
"@types/node@^20.3.1":
|
"@types/node@*", "@types/node@^20.3.3":
|
||||||
version "20.3.1"
|
version "20.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.3.tgz#329842940042d2b280897150e023e604d11657d6"
|
||||||
integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==
|
integrity sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==
|
||||||
|
|
||||||
"@types/parse-json@^4.0.0":
|
"@types/parse-json@^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
@@ -1538,11 +1586,152 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vercel/analytics/-/analytics-0.1.11.tgz#727a0ac655a4a89104cdea3e6925476470299428"
|
resolved "https://registry.yarnpkg.com/@vercel/analytics/-/analytics-0.1.11.tgz#727a0ac655a4a89104cdea3e6925476470299428"
|
||||||
integrity sha512-mj5CPR02y0BRs1tN3oZcBNAX9a8NxsIUl9vElDPcqxnMfP0RbRc9fI9Ud7+QDg/1Izvt5uMumsr+6YsmVHcyuw==
|
integrity sha512-mj5CPR02y0BRs1tN3oZcBNAX9a8NxsIUl9vElDPcqxnMfP0RbRc9fI9Ud7+QDg/1Izvt5uMumsr+6YsmVHcyuw==
|
||||||
|
|
||||||
|
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
|
||||||
|
integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/helper-numbers" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/floating-point-hex-parser@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
|
||||||
|
integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
|
||||||
|
|
||||||
|
"@webassemblyjs/helper-api-error@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
|
||||||
|
integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
|
||||||
|
|
||||||
|
"@webassemblyjs/helper-buffer@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
|
||||||
|
integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
|
||||||
|
|
||||||
|
"@webassemblyjs/helper-numbers@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
|
||||||
|
integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/floating-point-hex-parser" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-api-error" "1.11.6"
|
||||||
|
"@xtuc/long" "4.2.2"
|
||||||
|
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
|
||||||
|
integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
|
||||||
|
|
||||||
|
"@webassemblyjs/helper-wasm-section@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
|
||||||
|
integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/ieee754@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
|
||||||
|
integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
|
||||||
|
dependencies:
|
||||||
|
"@xtuc/ieee754" "^1.2.0"
|
||||||
|
|
||||||
|
"@webassemblyjs/leb128@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
|
||||||
|
integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
|
||||||
|
dependencies:
|
||||||
|
"@xtuc/long" "4.2.2"
|
||||||
|
|
||||||
|
"@webassemblyjs/utf8@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
|
||||||
|
integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
|
||||||
|
|
||||||
|
"@webassemblyjs/wasm-edit@^1.11.5":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
|
||||||
|
integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-section" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-opt" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-parser" "1.11.6"
|
||||||
|
"@webassemblyjs/wast-printer" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/wasm-gen@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
|
||||||
|
integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||||
|
"@webassemblyjs/ieee754" "1.11.6"
|
||||||
|
"@webassemblyjs/leb128" "1.11.6"
|
||||||
|
"@webassemblyjs/utf8" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/wasm-opt@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
|
||||||
|
integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||||
|
"@webassemblyjs/wasm-parser" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
|
||||||
|
integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-api-error" "1.11.6"
|
||||||
|
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||||
|
"@webassemblyjs/ieee754" "1.11.6"
|
||||||
|
"@webassemblyjs/leb128" "1.11.6"
|
||||||
|
"@webassemblyjs/utf8" "1.11.6"
|
||||||
|
|
||||||
|
"@webassemblyjs/wast-printer@1.11.6":
|
||||||
|
version "1.11.6"
|
||||||
|
resolved "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
|
||||||
|
integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
|
||||||
|
dependencies:
|
||||||
|
"@webassemblyjs/ast" "1.11.6"
|
||||||
|
"@xtuc/long" "4.2.2"
|
||||||
|
|
||||||
|
"@xtuc/ieee754@^1.2.0":
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||||
|
integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
|
||||||
|
|
||||||
|
"@xtuc/long@4.2.2":
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
|
||||||
|
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
|
||||||
|
|
||||||
|
acorn-import-assertions@^1.9.0:
|
||||||
|
version "1.9.0"
|
||||||
|
resolved "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
|
||||||
|
integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
|
||||||
|
|
||||||
acorn-jsx@^5.3.2:
|
acorn-jsx@^5.3.2:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
|
acorn@^8.7.1, acorn@^8.8.2:
|
||||||
|
version "8.9.0"
|
||||||
|
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59"
|
||||||
|
integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==
|
||||||
|
|
||||||
acorn@^8.8.0:
|
acorn@^8.8.0:
|
||||||
version "8.8.2"
|
version "8.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
||||||
@@ -1556,7 +1745,12 @@ aggregate-error@^3.0.0:
|
|||||||
clean-stack "^2.0.0"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
ajv@^6.10.0, ajv@^6.12.4:
|
ajv-keywords@^3.5.2:
|
||||||
|
version "3.5.2"
|
||||||
|
resolved "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
|
||||||
|
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
|
||||||
|
|
||||||
|
ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5:
|
||||||
version "6.12.6"
|
version "6.12.6"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||||
@@ -1763,6 +1957,16 @@ braces@^3.0.2, braces@~3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
browserslist@^4.14.5:
|
||||||
|
version "4.21.9"
|
||||||
|
resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635"
|
||||||
|
integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==
|
||||||
|
dependencies:
|
||||||
|
caniuse-lite "^1.0.30001503"
|
||||||
|
electron-to-chromium "^1.4.431"
|
||||||
|
node-releases "^2.0.12"
|
||||||
|
update-browserslist-db "^1.0.11"
|
||||||
|
|
||||||
browserslist@^4.21.3, browserslist@^4.21.5:
|
browserslist@^4.21.3, browserslist@^4.21.5:
|
||||||
version "4.21.5"
|
version "4.21.5"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
|
||||||
@@ -1773,6 +1977,11 @@ browserslist@^4.21.3, browserslist@^4.21.5:
|
|||||||
node-releases "^2.0.8"
|
node-releases "^2.0.8"
|
||||||
update-browserslist-db "^1.0.10"
|
update-browserslist-db "^1.0.10"
|
||||||
|
|
||||||
|
buffer-from@^1.0.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||||
|
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||||
|
|
||||||
busboy@1.6.0:
|
busboy@1.6.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
resolved "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
||||||
@@ -1803,6 +2012,11 @@ caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449:
|
|||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz#3859898b3cab65fc8905bb923df36ad35058153c"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz#3859898b3cab65fc8905bb923df36ad35058153c"
|
||||||
integrity sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==
|
integrity sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001503:
|
||||||
|
version "1.0.30001509"
|
||||||
|
resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz#2b7ad5265392d6d2de25cd8776d1ab3899570d14"
|
||||||
|
integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA==
|
||||||
|
|
||||||
ccount@^2.0.0:
|
ccount@^2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
|
resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5"
|
||||||
@@ -1850,6 +2064,11 @@ character-entities@^2.0.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
chrome-trace-event@^1.0.2:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
|
||||||
|
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
|
||||||
|
|
||||||
clean-stack@^2.0.0:
|
clean-stack@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||||
@@ -1932,7 +2151,12 @@ commander@^10.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.0.tgz#71797971162cd3cf65f0b9d24eb28f8d303acdf1"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.0.tgz#71797971162cd3cf65f0b9d24eb28f8d303acdf1"
|
||||||
integrity sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==
|
integrity sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==
|
||||||
|
|
||||||
commander@^8.0.0:
|
commander@^2.20.0:
|
||||||
|
version "2.20.3"
|
||||||
|
resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
|
||||||
|
commander@^8.0.0, commander@^8.3.0:
|
||||||
version "8.3.0"
|
version "8.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||||
@@ -2477,6 +2701,11 @@ electron-to-chromium@^1.4.284:
|
|||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.345.tgz#c90b7183b39245cddf0e990337469063bfced6f0"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.345.tgz#c90b7183b39245cddf0e990337469063bfced6f0"
|
||||||
integrity sha512-znGhOQK2TUYLICgS25uaM0a7pHy66rSxbre7l762vg9AUoCcJK+Bu+HCPWpjL/U/kK8/Hf+6E0szAUJSyVYb3Q==
|
integrity sha512-znGhOQK2TUYLICgS25uaM0a7pHy66rSxbre7l762vg9AUoCcJK+Bu+HCPWpjL/U/kK8/Hf+6E0szAUJSyVYb3Q==
|
||||||
|
|
||||||
|
electron-to-chromium@^1.4.431:
|
||||||
|
version "1.4.445"
|
||||||
|
resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.445.tgz#058d2c5f3a2981ab1a37440f5a5e42d15672aa6d"
|
||||||
|
integrity sha512-++DB+9VK8SBJwC+X1zlMfJ1tMA3F0ipi39GdEp+x3cV2TyBihqAgad8cNMWtLDEkbH39nlDQP7PfGrDr3Dr7HA==
|
||||||
|
|
||||||
elkjs@^0.8.2:
|
elkjs@^0.8.2:
|
||||||
version "0.8.2"
|
version "0.8.2"
|
||||||
resolved "https://registry.npmmirror.com/elkjs/-/elkjs-0.8.2.tgz#c37763c5a3e24e042e318455e0147c912a7c248e"
|
resolved "https://registry.npmmirror.com/elkjs/-/elkjs-0.8.2.tgz#c37763c5a3e24e042e318455e0147c912a7c248e"
|
||||||
@@ -2507,6 +2736,14 @@ enhanced-resolve@^5.12.0:
|
|||||||
graceful-fs "^4.2.4"
|
graceful-fs "^4.2.4"
|
||||||
tapable "^2.2.0"
|
tapable "^2.2.0"
|
||||||
|
|
||||||
|
enhanced-resolve@^5.15.0:
|
||||||
|
version "5.15.0"
|
||||||
|
resolved "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
|
||||||
|
integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
|
||||||
|
dependencies:
|
||||||
|
graceful-fs "^4.2.4"
|
||||||
|
tapable "^2.2.0"
|
||||||
|
|
||||||
entities@^2.0.0:
|
entities@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||||
@@ -2579,6 +2816,11 @@ es-get-iterator@^1.1.2:
|
|||||||
isarray "^2.0.5"
|
isarray "^2.0.5"
|
||||||
stop-iteration-iterator "^1.0.0"
|
stop-iteration-iterator "^1.0.0"
|
||||||
|
|
||||||
|
es-module-lexer@^1.2.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f"
|
||||||
|
integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==
|
||||||
|
|
||||||
es-set-tostringtag@^2.0.1:
|
es-set-tostringtag@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
|
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
|
||||||
@@ -2749,6 +2991,14 @@ eslint-plugin-react@^7.31.7:
|
|||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
string.prototype.matchall "^4.0.8"
|
string.prototype.matchall "^4.0.8"
|
||||||
|
|
||||||
|
eslint-scope@5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
||||||
|
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
|
||||||
|
dependencies:
|
||||||
|
esrecurse "^4.3.0"
|
||||||
|
estraverse "^4.1.1"
|
||||||
|
|
||||||
eslint-scope@^7.1.1:
|
eslint-scope@^7.1.1:
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
||||||
@@ -2831,6 +3081,11 @@ esrecurse@^4.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
estraverse "^5.2.0"
|
estraverse "^5.2.0"
|
||||||
|
|
||||||
|
estraverse@^4.1.1:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
|
||||||
|
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||||
|
|
||||||
estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
|
estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
|
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
|
||||||
@@ -2841,6 +3096,11 @@ esutils@^2.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||||
|
|
||||||
|
events@^3.2.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||||
|
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
|
||||||
|
|
||||||
execa@^7.0.0:
|
execa@^7.0.0:
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43"
|
resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43"
|
||||||
@@ -3137,7 +3397,7 @@ gopd@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
get-intrinsic "^1.1.3"
|
get-intrinsic "^1.1.3"
|
||||||
|
|
||||||
graceful-fs@^4.1.2, graceful-fs@^4.2.4:
|
graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
|
||||||
version "4.2.11"
|
version "4.2.11"
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||||
@@ -3193,6 +3453,35 @@ has@^1.0.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
|
|
||||||
|
hast-util-from-dom@^4.0.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz#25836ddecc3cc0849d32749c2a7aec03e94b59a7"
|
||||||
|
integrity sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==
|
||||||
|
dependencies:
|
||||||
|
hastscript "^7.0.0"
|
||||||
|
web-namespaces "^2.0.0"
|
||||||
|
|
||||||
|
hast-util-from-html-isomorphic@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz#592b2bea880d476665b76ca1cf7d1a94925c80ec"
|
||||||
|
integrity sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==
|
||||||
|
dependencies:
|
||||||
|
"@types/hast" "^2.0.0"
|
||||||
|
hast-util-from-dom "^4.0.0"
|
||||||
|
hast-util-from-html "^1.0.0"
|
||||||
|
unist-util-remove-position "^4.0.0"
|
||||||
|
|
||||||
|
hast-util-from-html@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz#2482fd701b2d8270b912b3909d6fb645d4a346cf"
|
||||||
|
integrity sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==
|
||||||
|
dependencies:
|
||||||
|
"@types/hast" "^2.0.0"
|
||||||
|
hast-util-from-parse5 "^7.0.0"
|
||||||
|
parse5 "^7.0.0"
|
||||||
|
vfile "^5.0.0"
|
||||||
|
vfile-message "^3.0.0"
|
||||||
|
|
||||||
hast-util-from-parse5@^7.0.0:
|
hast-util-from-parse5@^7.0.0:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz#aecfef73e3ceafdfa4550716443e4eb7b02e22b0"
|
resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz#aecfef73e3ceafdfa4550716443e4eb7b02e22b0"
|
||||||
@@ -3560,6 +3849,15 @@ isexe@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||||
|
|
||||||
|
jest-worker@^27.4.5:
|
||||||
|
version "27.5.1"
|
||||||
|
resolved "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
|
||||||
|
integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
merge-stream "^2.0.0"
|
||||||
|
supports-color "^8.0.0"
|
||||||
|
|
||||||
js-sdsl@^4.1.4:
|
js-sdsl@^4.1.4:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
|
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
|
||||||
@@ -3587,7 +3885,7 @@ jsesc@~0.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||||
integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
|
integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
|
||||||
|
|
||||||
json-parse-even-better-errors@^2.3.0:
|
json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||||
@@ -3629,12 +3927,12 @@ katex@^0.13.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
commander "^8.0.0"
|
commander "^8.0.0"
|
||||||
|
|
||||||
katex@^0.15.0:
|
katex@^0.16.0:
|
||||||
version "0.15.6"
|
version "0.16.8"
|
||||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.15.6.tgz#c4e2f6ced2ac4de1ef6f737fe7c67d3026baa0e5"
|
resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.8.tgz#89b453f40e8557f423f31a1009e9298dd99d5ceb"
|
||||||
integrity sha512-UpzJy4yrnqnhXvRPhjEuLA4lcPn6eRngixW7Q3TJErjg3Aw2PuLFBzTkdUb89UtumxjhHTqL3a5GDGETMSwgJA==
|
integrity sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==
|
||||||
dependencies:
|
dependencies:
|
||||||
commander "^8.0.0"
|
commander "^8.3.0"
|
||||||
|
|
||||||
khroma@^2.0.0:
|
khroma@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@@ -3719,6 +4017,11 @@ listr2@^5.0.7:
|
|||||||
through "^2.3.8"
|
through "^2.3.8"
|
||||||
wrap-ansi "^7.0.0"
|
wrap-ansi "^7.0.0"
|
||||||
|
|
||||||
|
loader-runner@^4.2.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
|
||||||
|
integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
|
||||||
|
|
||||||
locate-path@^6.0.0:
|
locate-path@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
|
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
|
||||||
@@ -4282,6 +4585,18 @@ micromatch@^4.0.4, micromatch@^4.0.5:
|
|||||||
braces "^3.0.2"
|
braces "^3.0.2"
|
||||||
picomatch "^2.3.1"
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
version "1.52.0"
|
||||||
|
resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
|
mime-types@^2.1.27:
|
||||||
|
version "2.1.35"
|
||||||
|
resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
|
dependencies:
|
||||||
|
mime-db "1.52.0"
|
||||||
|
|
||||||
mimic-fn@^2.1.0:
|
mimic-fn@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
@@ -4324,11 +4639,21 @@ nanoid@^3.3.4:
|
|||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||||
|
|
||||||
|
nanoid@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
|
||||||
|
integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==
|
||||||
|
|
||||||
natural-compare@^1.4.0:
|
natural-compare@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||||
|
|
||||||
|
neo-async@^2.6.2:
|
||||||
|
version "2.6.2"
|
||||||
|
resolved "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
|
|
||||||
next@^13.4.6:
|
next@^13.4.6:
|
||||||
version "13.4.6"
|
version "13.4.6"
|
||||||
resolved "https://registry.yarnpkg.com/next/-/next-13.4.6.tgz#ebe52f5c74d60176d45b45e73f25a51103713ea4"
|
resolved "https://registry.yarnpkg.com/next/-/next-13.4.6.tgz#ebe52f5c74d60176d45b45e73f25a51103713ea4"
|
||||||
@@ -4367,6 +4692,11 @@ node-fetch@^3.3.1:
|
|||||||
fetch-blob "^3.1.4"
|
fetch-blob "^3.1.4"
|
||||||
formdata-polyfill "^4.0.10"
|
formdata-polyfill "^4.0.10"
|
||||||
|
|
||||||
|
node-releases@^2.0.12:
|
||||||
|
version "2.0.12"
|
||||||
|
resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039"
|
||||||
|
integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==
|
||||||
|
|
||||||
node-releases@^2.0.8:
|
node-releases@^2.0.8:
|
||||||
version "2.0.10"
|
version "2.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
|
||||||
@@ -4544,10 +4874,12 @@ parse-json@^5.0.0:
|
|||||||
json-parse-even-better-errors "^2.3.0"
|
json-parse-even-better-errors "^2.3.0"
|
||||||
lines-and-columns "^1.1.6"
|
lines-and-columns "^1.1.6"
|
||||||
|
|
||||||
parse5@^6.0.0:
|
parse5@^7.0.0:
|
||||||
version "6.0.1"
|
version "7.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
|
resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32"
|
||||||
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
|
integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==
|
||||||
|
dependencies:
|
||||||
|
entities "^4.4.0"
|
||||||
|
|
||||||
path-exists@^4.0.0:
|
path-exists@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
@@ -4615,10 +4947,10 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^2.8.7:
|
prettier@^2.8.8:
|
||||||
version "2.8.7"
|
version "2.8.8"
|
||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
|
||||||
integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==
|
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
|
||||||
|
|
||||||
prop-types@^15.0.0, prop-types@^15.8.1:
|
prop-types@^15.0.0, prop-types@^15.8.1:
|
||||||
version "15.8.1"
|
version "15.8.1"
|
||||||
@@ -4649,6 +4981,13 @@ raf-schd@^4.0.3:
|
|||||||
resolved "https://registry.npmmirror.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
resolved "https://registry.npmmirror.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
||||||
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
||||||
|
|
||||||
|
randombytes@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||||
|
integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "^5.1.0"
|
||||||
|
|
||||||
react-dom@^18.2.0:
|
react-dom@^18.2.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||||
@@ -4688,10 +5027,10 @@ react-markdown@^8.0.7:
|
|||||||
unist-util-visit "^4.0.0"
|
unist-util-visit "^4.0.0"
|
||||||
vfile "^5.0.0"
|
vfile "^5.0.0"
|
||||||
|
|
||||||
react-redux@^8.0.4:
|
react-redux@^8.1.1:
|
||||||
version "8.0.5"
|
version "8.1.1"
|
||||||
resolved "https://registry.npmmirror.com/react-redux/-/react-redux-8.0.5.tgz#e5fb8331993a019b8aaf2e167a93d10af469c7bd"
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.1.1.tgz#8e740f3fd864a4cd0de5ba9cdc8ad39cc9e7c81a"
|
||||||
integrity sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==
|
integrity sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.12.1"
|
"@babel/runtime" "^7.12.1"
|
||||||
"@types/hoist-non-react-statics" "^3.3.1"
|
"@types/hoist-non-react-statics" "^3.3.1"
|
||||||
@@ -4729,9 +5068,9 @@ readdirp@~3.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch "^2.2.1"
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
redux@^4.2.0:
|
redux@^4.2.1:
|
||||||
version "4.2.1"
|
version "4.2.1"
|
||||||
resolved "https://registry.npmmirror.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
||||||
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
|
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
@@ -4799,30 +5138,18 @@ rehype-highlight@^6.0.0:
|
|||||||
unified "^10.0.0"
|
unified "^10.0.0"
|
||||||
unist-util-visit "^4.0.0"
|
unist-util-visit "^4.0.0"
|
||||||
|
|
||||||
rehype-katex@^6.0.2:
|
rehype-katex@^6.0.3:
|
||||||
version "6.0.2"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-6.0.2.tgz#20197bbc10bdf79f6b999bffa6689d7f17226c35"
|
resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-6.0.3.tgz#83e5b929b0967978e9491c02117f55be3594d7e1"
|
||||||
integrity sha512-C4gDAlS1+l0hJqctyiU64f9CvT00S03qV1T6HiMzbSuLBgWUtcqydWHY9OpKrm0SpkK16FNd62CDKyWLwV2ppg==
|
integrity sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/hast" "^2.0.0"
|
"@types/hast" "^2.0.0"
|
||||||
"@types/katex" "^0.11.0"
|
"@types/katex" "^0.14.0"
|
||||||
|
hast-util-from-html-isomorphic "^1.0.0"
|
||||||
hast-util-to-text "^3.1.0"
|
hast-util-to-text "^3.1.0"
|
||||||
katex "^0.15.0"
|
katex "^0.16.0"
|
||||||
rehype-parse "^8.0.0"
|
|
||||||
unified "^10.0.0"
|
|
||||||
unist-util-remove-position "^4.0.0"
|
|
||||||
unist-util-visit "^4.0.0"
|
unist-util-visit "^4.0.0"
|
||||||
|
|
||||||
rehype-parse@^8.0.0:
|
|
||||||
version "8.0.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-8.0.4.tgz#3d17c9ff16ddfef6bbcc8e6a25a99467b482d688"
|
|
||||||
integrity sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==
|
|
||||||
dependencies:
|
|
||||||
"@types/hast" "^2.0.0"
|
|
||||||
hast-util-from-parse5 "^7.0.0"
|
|
||||||
parse5 "^6.0.0"
|
|
||||||
unified "^10.0.0"
|
|
||||||
|
|
||||||
remark-breaks@^3.0.2:
|
remark-breaks@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-3.0.2.tgz#f466b9d3474d7323146c0149fc1496dabadd908e"
|
resolved "https://registry.yarnpkg.com/remark-breaks/-/remark-breaks-3.0.2.tgz#f466b9d3474d7323146c0149fc1496dabadd908e"
|
||||||
@@ -4950,6 +5277,11 @@ sade@^1.7.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mri "^1.1.0"
|
mri "^1.1.0"
|
||||||
|
|
||||||
|
safe-buffer@^5.1.0:
|
||||||
|
version "5.2.1"
|
||||||
|
resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
safe-regex-test@^1.0.0:
|
safe-regex-test@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
|
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
|
||||||
@@ -4980,6 +5312,15 @@ scheduler@^0.23.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
schema-utils@^3.1.1, schema-utils@^3.2.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
|
||||||
|
integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
|
||||||
|
dependencies:
|
||||||
|
"@types/json-schema" "^7.0.8"
|
||||||
|
ajv "^6.12.5"
|
||||||
|
ajv-keywords "^3.5.2"
|
||||||
|
|
||||||
semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
@@ -4992,6 +5333,13 @@ semver@^7.3.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^6.0.0"
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
|
serialize-javascript@^6.0.1:
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c"
|
||||||
|
integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==
|
||||||
|
dependencies:
|
||||||
|
randombytes "^2.1.0"
|
||||||
|
|
||||||
shebang-command@^2.0.0:
|
shebang-command@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||||
@@ -5059,7 +5407,15 @@ slice-ansi@^5.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||||
|
|
||||||
source-map@^0.6.1:
|
source-map-support@~0.5.20:
|
||||||
|
version "0.5.21"
|
||||||
|
resolved "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||||
|
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
source-map "^0.6.0"
|
||||||
|
|
||||||
|
source-map@^0.6.0, source-map@^0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
@@ -5217,6 +5573,13 @@ supports-color@^7.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
supports-color@^8.0.0:
|
||||||
|
version "8.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||||
|
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@^1.0.0:
|
supports-preserve-symlinks-flag@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
@@ -5248,11 +5611,32 @@ synckit@^0.8.5:
|
|||||||
"@pkgr/utils" "^2.3.1"
|
"@pkgr/utils" "^2.3.1"
|
||||||
tslib "^2.5.0"
|
tslib "^2.5.0"
|
||||||
|
|
||||||
tapable@^2.2.0:
|
tapable@^2.1.1, tapable@^2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||||
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
||||||
|
|
||||||
|
terser-webpack-plugin@^5.3.7:
|
||||||
|
version "5.3.9"
|
||||||
|
resolved "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"
|
||||||
|
integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
|
jest-worker "^27.4.5"
|
||||||
|
schema-utils "^3.1.1"
|
||||||
|
serialize-javascript "^6.0.1"
|
||||||
|
terser "^5.16.8"
|
||||||
|
|
||||||
|
terser@^5.16.8:
|
||||||
|
version "5.18.2"
|
||||||
|
resolved "https://registry.npmmirror.com/terser/-/terser-5.18.2.tgz#ff3072a0faf21ffd38f99acc9a0ddf7b5f07b948"
|
||||||
|
integrity sha512-Ah19JS86ypbJzTzvUCX7KOsEIhDaRONungA4aYBjEP3JZRf4ocuDzTg4QWZnPn9DEMiMYGJPiSOy7aykoCc70w==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/source-map" "^0.3.3"
|
||||||
|
acorn "^8.8.2"
|
||||||
|
commander "^2.20.0"
|
||||||
|
source-map-support "~0.5.20"
|
||||||
|
|
||||||
text-table@^0.2.0:
|
text-table@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
@@ -5474,6 +5858,14 @@ update-browserslist-db@^1.0.10:
|
|||||||
escalade "^3.1.1"
|
escalade "^3.1.1"
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
|
update-browserslist-db@^1.0.11:
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
|
||||||
|
integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
|
||||||
|
dependencies:
|
||||||
|
escalade "^3.1.1"
|
||||||
|
picocolors "^1.0.0"
|
||||||
|
|
||||||
uri-js@^4.2.2:
|
uri-js@^4.2.2:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||||
@@ -5537,7 +5929,7 @@ vfile@^5.0.0:
|
|||||||
unist-util-stringify-position "^3.0.0"
|
unist-util-stringify-position "^3.0.0"
|
||||||
vfile-message "^3.0.0"
|
vfile-message "^3.0.0"
|
||||||
|
|
||||||
watchpack@2.4.0:
|
watchpack@2.4.0, watchpack@^2.4.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
|
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
|
||||||
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
|
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
|
||||||
@@ -5560,6 +5952,41 @@ web-worker@^1.2.0:
|
|||||||
resolved "https://registry.npmmirror.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da"
|
resolved "https://registry.npmmirror.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da"
|
||||||
integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
|
integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
|
||||||
|
|
||||||
|
webpack-sources@^3.2.3:
|
||||||
|
version "3.2.3"
|
||||||
|
resolved "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
|
||||||
|
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
||||||
|
|
||||||
|
webpack@^5.88.1:
|
||||||
|
version "5.88.1"
|
||||||
|
resolved "https://registry.npmmirror.com/webpack/-/webpack-5.88.1.tgz#21eba01e81bd5edff1968aea726e2fbfd557d3f8"
|
||||||
|
integrity sha512-FROX3TxQnC/ox4N+3xQoWZzvGXSuscxR32rbzjpXgEzWudJFEJBpdlkkob2ylrv5yzzufD1zph1OoFsLtm6stQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/eslint-scope" "^3.7.3"
|
||||||
|
"@types/estree" "^1.0.0"
|
||||||
|
"@webassemblyjs/ast" "^1.11.5"
|
||||||
|
"@webassemblyjs/wasm-edit" "^1.11.5"
|
||||||
|
"@webassemblyjs/wasm-parser" "^1.11.5"
|
||||||
|
acorn "^8.7.1"
|
||||||
|
acorn-import-assertions "^1.9.0"
|
||||||
|
browserslist "^4.14.5"
|
||||||
|
chrome-trace-event "^1.0.2"
|
||||||
|
enhanced-resolve "^5.15.0"
|
||||||
|
es-module-lexer "^1.2.1"
|
||||||
|
eslint-scope "5.1.1"
|
||||||
|
events "^3.2.0"
|
||||||
|
glob-to-regexp "^0.4.1"
|
||||||
|
graceful-fs "^4.2.9"
|
||||||
|
json-parse-even-better-errors "^2.3.1"
|
||||||
|
loader-runner "^4.2.0"
|
||||||
|
mime-types "^2.1.27"
|
||||||
|
neo-async "^2.6.2"
|
||||||
|
schema-utils "^3.2.0"
|
||||||
|
tapable "^2.1.1"
|
||||||
|
terser-webpack-plugin "^5.3.7"
|
||||||
|
watchpack "^2.4.0"
|
||||||
|
webpack-sources "^3.2.3"
|
||||||
|
|
||||||
which-boxed-primitive@^1.0.2:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||||
|
Reference in New Issue
Block a user