Compare commits

..

130 Commits

Author SHA1 Message Date
Yifei Zhang
50eb7a5f98 Update tauri.conf.json 2023-08-18 18:47:54 +08:00
Yifei Zhang
484d1e7396 Merge pull request #2649 from pichuang/zh-tw 2023-08-18 18:40:30 +08:00
Yifei Zhang
a632e13334 Merge pull request #2653 from Algorithm5838/Algorithm5838-patch-1 2023-08-18 18:40:18 +08:00
Algorithm5838
35b0bd76f8 Update markdown.tsx 2023-08-18 08:12:27 +03:00
Phil Huang
1d7286c161 Improve the text in tw.ts
Adoption of text that is more closely aligned with the usage of zh-tw
2023-08-17 23:50:38 +08:00
Yifei Zhang
5a7ec38ecd Update README.md 2023-08-16 11:22:51 +08:00
Yifei Zhang
ada4e3cdcd Merge pull request #2641 from Yidadaa/bugfix-0815 2023-08-15 23:09:15 +08:00
Yidadaa
ed62c87156 feat: close #2638 hide auth page and use better unauth tips 2023-08-15 22:50:42 +08:00
Yidadaa
840277f584 fix: #2566 click avatar to edit context messages 2023-08-15 22:42:55 +08:00
Yifei Zhang
ffddb7fb2b Merge pull request #2636 from wangwentong-lunaon/main 2023-08-15 22:09:14 +08:00
wangwentong
b380421fd5 support json export 2023-08-15 13:32:34 +08:00
Yifei Zhang
20882a7598 Merge pull request #2629 from Yidadaa/bugfix-0814 2023-08-14 22:13:56 +08:00
Yifei Zhang
9d3dff47d2 Merge pull request #2627 from imldy/dev_title-generation-checkbox 2023-08-14 22:12:26 +08:00
Yidadaa
db5c7aba78 fix: #2615 scrollbar jitter under certain message counts 2023-08-14 22:11:38 +08:00
Yidadaa
e8e01aa60d feat: close #2618 use correct html lang attr 2023-08-14 21:55:18 +08:00
Yidadaa
ae8226907f feat: close #2621 use better default api url 2023-08-14 21:36:29 +08:00
imldy
803b66ae9d chore: Concise description 2023-08-14 20:47:02 +08:00
imldy
20a508e2d6 feat: add autoGenerateTitle option
(cherry picked from commit 656ab94a9c4edfee820616b8cfc39f5ee9952a3a)
2023-08-14 20:42:09 +08:00
Yifei Zhang
25ada1eae9 Merge pull request #2617 from Yidadaa/rtl-fix 2023-08-14 11:13:56 +08:00
Yifei Zhang
808e4b38a3 fixup 2023-08-14 11:10:02 +08:00
Yifei Zhang
a496bc5a63 fix: #2614 better rtl detecting algo 2023-08-14 10:57:24 +08:00
Yifei Zhang
c94713475f Update globals.scss 2023-08-13 02:47:07 +08:00
Yifei Zhang
d45c61109f Merge pull request #2607 from eltociear/add_ja-docs 2023-08-13 00:07:37 +08:00
Ikko Eltociear Ashimine
99220d72da Add faq-ja.md 2023-08-11 20:28:18 +09:00
Ikko Eltociear Ashimine
887eaef1aa Add vercel-ja.md 2023-08-11 19:58:54 +09:00
Ikko Eltociear Ashimine
836a00e104 Add cloudflare-pages-ja.md 2023-08-11 19:49:36 +09:00
Ikko Eltociear Ashimine
8ee5061046 Add Japanese README 2023-08-11 19:34:21 +09:00
Yifei Zhang
61852b4021 Merge pull request #2598 from Yidadaa/Yidadaa-patch-1 2023-08-10 10:49:16 +08:00
Yifei Zhang
0b7de6f7b2 fix: #2594 trim the / 2023-08-10 10:47:06 +08:00
Yifei Zhang
9834a67cbd Update tauri.conf.json 2023-08-09 15:37:13 +08:00
Yifei Zhang
d85a4a0c9f Merge pull request #2590 from ZhangYichi-ZYc/ZhangYichi-ZYc-patch-1 2023-08-09 15:29:46 +08:00
Yifei Zhang
67c8ec6d7e chore: change ACCESS_CODE_PREFIX to nk- 2023-08-09 15:27:08 +08:00
Yifei Zhang
2a2dd7ea19 Merge pull request #2588 from eltociear/eltociear-patch-1
Fix typo in README.md
2023-08-09 09:17:55 +08:00
Ikko Eltociear Ashimine
153e7ac7e4 Fix typo in README.md
notifictions -> notifications
2023-08-09 01:22:48 +09:00
Yifei Zhang
9420fd4946 Merge pull request #2585 from Yidadaa/bugfix-0808 2023-08-08 21:38:42 +08:00
Yidadaa
b14c5cd89c fix: #2485 one-time-use body 2023-08-08 21:36:37 +08:00
Yidadaa
4ab9141429 fix: #2564 should not clear message when error 2023-08-08 21:24:45 +08:00
Yidadaa
769c2f9f49 feat: close #2583 do not summarize with gpt-4 2023-08-08 21:22:41 +08:00
Yifei Zhang
c41c498a9c Merge pull request #2573 from 7lsu/main 2023-08-08 16:00:45 +08:00
7lsu
d1096582a5 font family display enhance 2023-08-07 17:44:32 +08:00
Yifei Zhang
543989151f Update constant.ts 2023-08-04 19:24:10 +08:00
Yifei Zhang
7da83987e4 chore: use bigger page size and render msg count 2023-08-04 15:45:16 +08:00
Yidadaa
523d553dac fix: clear btn should display in correct place 2023-08-04 02:58:02 +08:00
Yifei Zhang
ff6f0e9546 Merge pull request #2557 from Yidadaa/bugfix-0804
feat: disable auto focus on mobile screen
2023-08-04 02:45:19 +08:00
Yidadaa
3e63f6ba34 feat: disable auto focus on mobile screen 2023-08-04 02:43:55 +08:00
Yifei Zhang
811b92d24e Merge pull request #2556 from Yidadaa/bugfix-0804
fixup: improve auto scroll algo
2023-08-04 02:40:34 +08:00
Yidadaa
bc5ddc4541 fixup: improve auto scroll algo 2023-08-04 02:39:32 +08:00
Yifei Zhang
44e43729bf Merge pull request #2555 from Yidadaa/bugfix-0804
feat: close #2545 improve lazy load message list
2023-08-04 02:18:55 +08:00
Yidadaa
203067c936 feat: close #2545 improve lazy load message list 2023-08-04 02:16:44 +08:00
Zhang Yichi
f3b508c088 Update Model Pricing.md
OpenAI has updated their model prices, reducing the input of GPT-3.5 to $0.0015/1000 tokens
2023-08-03 23:52:18 +08:00
Yifei Zhang
081d84f848 Update tauri.conf.json 2023-08-03 10:41:45 +08:00
Yifei Zhang
e381add944 Merge pull request #2542 from Yidadaa/yifei-bugfix-0802
chore: smaller auto scroll interval
2023-08-02 23:54:19 +08:00
Yidadaa
75d4eca722 chore: smaller auto scroll interval 2023-08-02 23:51:01 +08:00
Yifei Zhang
56904ad6b2 Merge pull request #2541 from Yidadaa/yifei-bugfix-0802
feat: improve chat action, auto scroll and edit model title
2023-08-02 23:40:50 +08:00
Yidadaa
b5ef552c25 feat: improve auto scroll ux and edit model title 2023-08-02 23:35:51 +08:00
Yidadaa
cbabb9392c feat: improve ChatAction ux 2023-08-02 22:53:36 +08:00
Yifei Zhang
531b3dcf9e Merge pull request #2531 from LeviBorodenko/main
Add link to authentication page to i18n
2023-08-02 15:35:05 +08:00
Levi Borodenko
d975daf3f0 locale: add link to authentication page in i18n 2023-08-01 16:17:26 +02:00
Yifei Zhang
6137d551fe Merge pull request #2525 from 7lsu/main
typo fix
2023-08-01 15:17:26 +08:00
7lsu
cf625e3542 typo fix 2023-08-01 10:16:36 +08:00
Yifei Zhang
e354fca4a4 Merge pull request #2524 from Yidadaa/bugfix-0731
fix: #2514 should not clear the message after editing message
2023-07-31 22:23:11 +08:00
Yidadaa
129e7afc16 fix: #2514 should not clear the message after editing message 2023-07-31 22:20:39 +08:00
Yifei Zhang
e83e0f6a33 Merge pull request #2486 from fernandoxu/main
fix(typo): ngnix -> nginx
2023-07-26 17:13:46 +08:00
fernandoxu
cf4f928b25 fix(typo): ngnix -> nginx 2023-07-26 10:06:06 +08:00
Yifei Zhang
e4d955e3f9 Merge pull request #2483 from Yidadaa/bugfix-0725
fix: #2393 try to fix chat list lag
2023-07-25 23:01:46 +08:00
Yidadaa
13576087f4 fix: #2393 try to fix chat list lag 2023-07-25 22:59:21 +08:00
Yifei Zhang
e74f6f3183 Merge pull request #2469 from Yidadaa/dependabot/npm_and_yarn/types/react-dom-18.2.7
chore(deps-dev): bump @types/react-dom from 18.0.11 to 18.2.7
2023-07-24 22:06:40 +08:00
dependabot[bot]
8302d1d3c1 chore(deps-dev): bump @types/react-dom from 18.0.11 to 18.2.7
Bumps [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) from 18.0.11 to 18.2.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-24 10:33:12 +00:00
Yifei Zhang
b7320e6834 Update tauri.conf.json 2023-07-21 00:37:38 +08:00
Yifei Zhang
3193fe0235 Merge pull request #2452 from Yidadaa/bugfix-0720
feat: close #2449 edit / insert / delete messages modal
2023-07-21 00:25:33 +08:00
Yidadaa
7c2fa9f8a4 feat: close #2449 edit / insert / delete messages modal 2023-07-21 00:24:26 +08:00
Yidadaa
e5f6133127 feat: close #2447 pre-fill key/code/url 2023-07-20 23:17:58 +08:00
Yidadaa
0198c5b781 feat: close #2445 switch to mit license 2023-07-20 22:51:49 +08:00
Yifei Zhang
f535073ae4 Merge pull request #2431 from Hopelwj/main
设置页面-参数过滤空格
2023-07-19 20:14:13 +08:00
Hopelwj
b9895ecadd Merge branch 'Yidadaa:main' into main 2023-07-18 19:39:59 +08:00
liuweijie
322eb66fdf fix: useAccessStore filter spaces 2023-07-18 19:38:16 +08:00
Yifei Zhang
f0abdc80eb Update tauri.conf.json 2023-07-18 10:50:44 +08:00
Yifei Zhang
70a4f94c81 Update home.tsx 2023-07-17 11:33:19 +08:00
Yifei Zhang
f7e4b36746 Merge pull request #2412 from Yidadaa/fix-2409
fix: #2409 empty prompt id cause crash
2023-07-17 11:03:33 +08:00
Yifei Zhang
4e6b71ace5 Merge pull request #2410 from Lantianyou/feature/typing-metadata
Feature/typing-metadata
2023-07-17 11:01:39 +08:00
Yifei Zhang
c916cd1a87 Update mask.tsx 2023-07-17 11:00:45 +08:00
兰天游
442a529a72 feat: add type for import 2023-07-16 21:35:13 +08:00
兰天游
e1243f3d59 feat: add typings for metadata 2023-07-16 21:34:01 +08:00
Yifei Zhang
62f8cd1db6 Merge pull request #2406 from Yidadaa/bugfix-0716
feat: close #2376 add babel polyfill
2023-07-16 16:34:45 +08:00
Yidadaa
af5f67d459 feat: close #2376 add babel polyfill 2023-07-16 16:32:22 +08:00
Yifei Zhang
13424a893e Merge pull request #2405 from Yidadaa/bugfix-0716
fix: #2367 do not copy in async callback after sharing to ShareGPT
2023-07-16 16:17:40 +08:00
Yidadaa
30473ec41e fix: #2367 do not copy in async callback after sharing to ShareGPT 2023-07-16 16:14:57 +08:00
Yifei Zhang
24d382c70d Merge pull request #2404 from Yidadaa/bugfix-0716
feat: improve dnd icon
2023-07-16 16:14:25 +08:00
Yidadaa
3ddedc903e feat: improve dnd icon 2023-07-16 15:49:15 +08:00
Yifei Zhang
e3c279b8be Merge pull request #2389 from MarkShawn2020/fix-default-openai-url
fixed openai base url if empty
2023-07-16 15:20:26 +08:00
Yifei Zhang
d909b676c5 Update README.md 2023-07-16 15:08:53 +08:00
Yifei Zhang
08a8ac9971 Merge pull request #2388 from yikayiyo/feat-drag-prompts
feat: #2297 drag and drop in contextual prompts
2023-07-16 14:30:49 +08:00
Yifei Zhang
7073fd2f3b Merge pull request #2392 from imldy/dev_SetInjectSystemPrompts
fix: enable `enableInjectSystemPrompts` attribute for old sessions
2023-07-16 14:29:50 +08:00
imldy
a9f67a48a1 dev: use current inject configuration 2023-07-15 02:48:47 +08:00
imldy
fd058cc693 fix: enable enableInjectSystemPrompts attribute for old sessions 2023-07-15 01:32:39 +08:00
Yifei Zhang
c98df33003 Merge pull request #2390 from MarkShawn2020/fix-react-key
fixed react key
2023-07-15 01:28:56 +08:00
markshawn2020
3f8b14f5f8 fixed react key 2023-07-14 21:15:34 +08:00
markshawn2020
1c335a68e0 fixed openai base url if empty 2023-07-14 21:03:32 +08:00
legao
fb98050d9f feat: drag and drop in contextual prompts 2023-07-14 18:08:03 +08:00
Yifei Zhang
91cb7aa13d Merge pull request #2372 from Yidadaa/dependabot/npm_and_yarn/semver-6.3.1
chore(deps): bump semver from 6.3.0 to 6.3.1
2023-07-13 16:46:00 +08:00
dependabot[bot]
ab0f7cc0c9 chore(deps): bump semver from 6.3.0 to 6.3.1
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-13 01:58:09 +00:00
Yifei Zhang
b51f7f9a25 Merge pull request #2370 from Yidadaa/bugfix-0712
fix: sharegpt roles
2023-07-12 23:21:22 +08:00
Yidadaa
d275e32e70 fix: sharegpt roles 2023-07-12 23:19:46 +08:00
Yifei Zhang
22cf78d506 Merge pull request #2355 from fyl080801/main
fix: cloudflare headers
2023-07-11 23:57:03 +08:00
Yifei Zhang
c7c318b31e Merge pull request #2360 from imldy/fix_can't_edit_old_mask
fix: 迁移面具对象的key以解决无法编辑旧面具的问题
2023-07-11 23:48:02 +08:00
imldy
a4d012828c fix: migrated mask object key 2023-07-11 21:02:09 +08:00
yuanliang feng
72cfebd2bc Merge pull request #3 from fyl080801/deploy
Deploy
2023-07-11 17:08:50 +08:00
yuanliang feng
a832cfb343 Update common.ts 2023-07-11 15:46:40 +08:00
yuanliang feng
9ef680db57 Merge pull request #2 from fyl080801/main
update
2023-07-10 23:35:19 +08:00
yuanliang feng
2c09f4ef90 Merge pull request #1 from fyl080801/main
update
2023-07-10 23:23:20 +08:00
Yifei Zhang
c44454bf74 Merge pull request #2346 from Yidadaa/bugfix-0710
fix: #2336 resending message should delete origional messages
2023-07-10 23:22:53 +08:00
Yidadaa
ad1b9b7f6d fixup 2023-07-10 23:21:22 +08:00
Yidadaa
15e063e1b5 feat: #2330 disable /list/models 2023-07-10 23:19:43 +08:00
Yidadaa
c00a63e4c3 fix: #2336 resending message should delete origional messages 2023-07-10 22:59:12 +08:00
Yifei Zhang
dbda27b1d6 Merge pull request #2343 from Yidadaa/dependabot/npm_and_yarn/next-13.4.9
chore(deps): bump next from 13.4.6 to 13.4.9
2023-07-10 21:52:19 +08:00
Yifei Zhang
9eef879dbe Merge pull request #2342 from Yidadaa/dependabot/npm_and_yarn/tauri-apps/cli-1.4.0
chore(deps-dev): bump @tauri-apps/cli from 1.3.1 to 1.4.0
2023-07-10 21:52:08 +08:00
Yifei Zhang
cb29423636 Merge pull request #2341 from Yidadaa/dependabot/npm_and_yarn/types/react-18.2.14
chore(deps-dev): bump @types/react from 18.2.12 to 18.2.14
2023-07-10 21:51:56 +08:00
Yifei Zhang
d754eecf07 Merge pull request #2340 from Yidadaa/dependabot/npm_and_yarn/eslint-8.44.0
chore(deps-dev): bump eslint from 8.37.0 to 8.44.0
2023-07-10 21:51:45 +08:00
Yifei Zhang
1e308782ee Merge pull request #2339 from Yidadaa/dependabot/npm_and_yarn/react-router-dom-6.14.1
chore(deps): bump react-router-dom from 6.10.0 to 6.14.1
2023-07-10 21:51:32 +08:00
Yifei Zhang
69139cd85b Merge pull request #2344 from imldy/dev_SetInjectSystemPrompts
Dev: 给是否注入全局系统prompt提供一个开关
2023-07-10 21:51:06 +08:00
imldy
f59235bd5a feat: 翻译InjectSystemPrompts配置项为其他语言 2023-07-10 20:14:10 +08:00
imldy
2930ba0457 fix: 修改InjectSystemPrompts.SubTitle使其更符合系统行为 2023-07-10 20:12:51 +08:00
imldy
1513881eed fix: 修改是否应该注入System Prompt的判断规则为根据设置项 2023-07-10 18:57:54 +08:00
imldy
5e361f6748 dev: 增加模型设置项:是否启用注入全局 System Prompt 功能 2023-07-10 18:56:22 +08:00
dependabot[bot]
b182543a21 chore(deps): bump next from 13.4.6 to 13.4.9
Bumps [next](https://github.com/vercel/next.js) from 13.4.6 to 13.4.9.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v13.4.6...v13.4.9)

---
updated-dependencies:
- dependency-name: next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:51:20 +00:00
dependabot[bot]
cbce8b444f chore(deps-dev): bump @tauri-apps/cli from 1.3.1 to 1.4.0
Bumps [@tauri-apps/cli](https://github.com/tauri-apps/tauri) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/cli.js-v1.3.1...@tauri-apps/cli-v1.4.0)

---
updated-dependencies:
- dependency-name: "@tauri-apps/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:48:41 +00:00
dependabot[bot]
38e92cfc62 chore(deps-dev): bump @types/react from 18.2.12 to 18.2.14
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.12 to 18.2.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:47:57 +00:00
dependabot[bot]
a7764dc6d5 chore(deps-dev): bump eslint from 8.37.0 to 8.44.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.37.0 to 8.44.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.37.0...v8.44.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:47:33 +00:00
dependabot[bot]
c74552c4c5 chore(deps): bump react-router-dom from 6.10.0 to 6.14.1
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.10.0 to 6.14.1.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.14.1/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:46:56 +00:00
yuanliang feng
7a0b437626 Update common.ts 2023-07-10 17:26:28 +08:00
56 changed files with 1695 additions and 632 deletions

14
.babelrc Normal file
View File

@@ -0,0 +1,14 @@
{
"presets": [
[
"next/babel",
{
"preset-env": {
"targets": {
"browsers": ["> 0.25%, not dead"]
}
}
}
]
]
}

88
LICENSE
View File

@@ -1,75 +1,21 @@
版权所有c<2023><Zhang Yifei>
MIT License
反996许可证版本1.0
Copyright (c) 2023 Zhang Yifei
在符合下列条件的情况下,
特此免费向任何得到本授权作品的副本(包括源代码、文件和/或相关内容,以下统称为“授权作品”
)的个人和法人实体授权:被授权个人或法人实体有权以任何目的处置授权作品,包括但不限于使
用、复制,修改,衍生利用、散布,发布和再许可:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
1. 个人或法人实体必须在许可作品的每个再散布或衍生副本上包含以上版权声明和本许可证,不
得自行修改。
2. 个人或法人实体必须严格遵守与个人实际所在地或个人出生地或归化地、或法人实体注册地或
经营地(以较严格者为准)的司法管辖区所有适用的与劳动和就业相关法律、法规、规则和
标准。如果该司法管辖区没有此类法律、法规、规章和标准或其法律、法规、规章和标准不可
执行,则个人或法人实体必须遵守国际劳工标准的核心公约。
3. 个人或法人不得以任何方式诱导或强迫其全职或兼职员工或其独立承包人以口头或书面形式同
意直接或间接限制、削弱或放弃其所拥有的,受相关与劳动和就业有关的法律、法规、规则和
标准保护的权利或补救措施,无论该等书面或口头协议是否被该司法管辖区的法律所承认,该
等个人或法人实体也不得以任何方法限制其雇员或独立承包人向版权持有人或监督许可证合规
情况的有关当局报告或投诉上述违反许可证的行为的权利。
该授权作品是"按原样"提供,不做任何明示或暗示的保证,包括但不限于对适销性、特定用途适用
性和非侵权性的保证。在任何情况下,无论是在合同诉讼、侵权诉讼或其他诉讼中,版权持有人均
不承担因本软件或本软件的使用或其他交易而产生、引起或与之相关的任何索赔、损害或其他责任。
------------------------- ENGLISH ------------------------------
Copyright (c) <2023> <Zhang Yifei>
Anti 996 License Version 1.0 (Draft)
Permission is hereby granted to any individual or legal entity obtaining a copy
of this licensed work (including the source code, documentation and/or related
items, hereinafter collectively referred to as the "licensed work"), free of
charge, to deal with the licensed work for any purpose, including without
limitation, the rights to use, reproduce, modify, prepare derivative works of,
publish, distribute and sublicense the licensed work, subject to the following
conditions:
1. The individual or the legal entity must conspicuously display, without
modification, this License on each redistributed or derivative copy of the
Licensed Work.
2. The individual or the legal entity must strictly comply with all applicable
laws, regulations, rules and standards of the jurisdiction relating to
labor and employment where the individual is physically located or where
the individual was born or naturalized; or where the legal entity is
registered or is operating (whichever is stricter). In case that the
jurisdiction has no such laws, regulations, rules and standards or its
laws, regulations, rules and standards are unenforceable, the individual
or the legal entity are required to comply with Core International Labor
Standards.
3. The individual or the legal entity shall not induce or force its
employee(s), whether full-time or part-time, or its independent
contractor(s), in any methods, to agree in oral or written form,
to directly or indirectly restrict, weaken or relinquish his or
her rights or remedies under such laws, regulations, rules and
standards relating to labor and employment as mentioned above,
no matter whether such written or oral agreement are enforceable
under the laws of the said jurisdiction, nor shall such individual
or the legal entity limit, in any methods, the rights of its employee(s)
or independent contractor(s) from reporting or complaining to the copyright
holder or relevant authorities monitoring the compliance of the license
about its violation(s) of the said license.
THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT
HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION
WITH THE LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -3,7 +3,7 @@
<h1 align="center">ChatGPT Next Web</h1>
English / [简体中文](./README_CN.md)
English / [简体中文](./README_CN.md) / [日本語](./README_JA.md)
One-Click to get well-designed cross-platform ChatGPT web UI.
@@ -14,7 +14,7 @@ One-Click to get well-designed cross-platform ChatGPT web UI.
[![MacOS][MacOS-image]][download-url]
[![Linux][Linux-image]][download-url]
[Web App](https://chatgpt.nextweb.fun/) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Buy Me a Coffee](https://www.buymeacoffee.com/yidadaa)
[Web App](https://chatgpt.nextweb.fun/) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Discord](https://discord.gg/YCkeafCafC) / [Twitter](https://twitter.com/mortiest_ricky) / [Buy Me a Coffee](https://www.buymeacoffee.com/yidadaa)
[网页版](https://chatgpt.nextweb.fun/) / [客户端](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [反馈](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [QQ 群](https://github.com/Yidadaa/ChatGPT-Next-Web/discussions/1724) / [打赏开发者](https://user-images.githubusercontent.com/16968934/227772541-5bcd52d8-61b7-488c-a203-0330d8006e2b.jpg)
@@ -135,7 +135,7 @@ After forking the project, due to the limitations imposed by GitHub, you need to
If you want to update instantly, you can check out the [GitHub documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) to learn how to synchronize a forked project with upstream code.
You can star or watch this project or follow author to get release notifictions in time.
You can star or watch this project or follow author to get release notifications in time.
## Access Password
@@ -306,4 +306,4 @@ If you want to add a new translation, read this [document](./docs/translation.md
## LICENSE
[Anti 996 License](https://github.com/kattgu7/Anti-996-License/blob/master/LICENSE_CN_EN)
[MIT](https://opensource.org/license/mit/)

View File

@@ -181,6 +181,4 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s
## 开源协议
> 反对 996从我开始。
[Anti 996 License](https://github.com/kattgu7/Anti-996-License/blob/master/LICENSE_CN_EN)
[MIT](https://opensource.org/license/mit/)

View File

@@ -7,7 +7,7 @@ Implemente su aplicación web privada ChatGPT de forma gratuita con un solo clic
[Demo demo](https://chat-gpt-next-web.vercel.app/) / [Problemas de comentarios](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Únete a Discord](https://discord.gg/zrhvHCr79N) / [Grupo QQ](https://user-images.githubusercontent.com/16968934/228190818-7dd00845-e9b9-4363-97e5-44c507ac76da.jpeg) / [Desarrolladores de consejos](https://user-images.githubusercontent.com/16968934/227772541-5bcd52d8-61b7-488c-a203-0330d8006e2b.jpg) / [Donar](#捐赠-donate-usdt)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web\&env=OPENAI_API_KEY\&env=CODE\&project-name=chatgpt-next-web\&repository-name=ChatGPT-Next-Web)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=chatgpt-next-web&repository-name=ChatGPT-Next-Web)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)
@@ -19,7 +19,7 @@ Implemente su aplicación web privada ChatGPT de forma gratuita con un solo clic
1. Prepara el tuyo [Clave API OpenAI](https://platform.openai.com/account/api-keys);
2. Haga clic en el botón de la derecha para iniciar la implementación:
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web\&env=OPENAI_API_KEY\&env=CODE\&project-name=chatgpt-next-web\&repository-name=ChatGPT-Next-Web), inicie sesión directamente con su cuenta de Github y recuerde completar la clave API y la suma en la página de variables de entorno[Contraseña de acceso a la página](#配置页面访问密码) CÓDIGO;
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=chatgpt-next-web&repository-name=ChatGPT-Next-Web), inicie sesión directamente con su cuenta de Github y recuerde completar la clave API y la suma en la página de variables de entorno[Contraseña de acceso a la página](#配置页面访问密码) CÓDIGO;
3. Una vez implementado, puede comenzar;
4. (Opcional)[Enlazar un nombre de dominio personalizado](https://vercel.com/docs/concepts/projects/domains/add-a-domain): El nombre de dominio DNS asignado por Vercel está contaminado en algunas regiones y puede conectarse directamente enlazando un nombre de dominio personalizado.
@@ -28,9 +28,9 @@ Implemente su aplicación web privada ChatGPT de forma gratuita con un solo clic
Si sigue los pasos anteriores para implementar su proyecto con un solo clic, es posible que siempre diga "La actualización existe" porque Vercel creará un nuevo proyecto para usted de forma predeterminada en lugar de bifurcar el proyecto, lo que evitará que la actualización se detecte correctamente.
Le recomendamos que siga estos pasos para volver a implementar:
* Eliminar el repositorio original;
* Utilice el botón de bifurcación en la esquina superior derecha de la página para bifurcar este proyecto;
* En Vercel, vuelva a seleccionar e implementar,[Echa un vistazo al tutorial detallado](./docs/vercel-cn.md#如何新建项目)。
- Eliminar el repositorio original;
- Utilice el botón de bifurcación en la esquina superior derecha de la página para bifurcar este proyecto;
- En Vercel, vuelva a seleccionar e implementar,[Echa un vistazo al tutorial detallado](./docs/vercel-cn.md#如何新建项目)。
### Activar actualizaciones automáticas
@@ -170,6 +170,4 @@ bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/s
## Licencia de código abierto
> Contra 996, empezando por mí.
[Licencia Anti 996](https://github.com/kattgu7/Anti-996-License/blob/master/LICENSE_CN_EN)
[MIT](https://opensource.org/license/mit/)

275
README_JA.md Normal file
View File

@@ -0,0 +1,275 @@
<div align="center">
<img src="./docs/images/icon.svg" alt="icon"/>
<h1 align="center">ChatGPT Next Web</h1>
[English](./README.md) / [简体中文](./README_CN.md) / 日本語
ワンクリックで、クロスプラットフォーム ChatGPT ウェブ UI が表示されます。
[![Web][Web-image]][web-url]
[![Windows][Windows-image]][download-url]
[![MacOS][MacOS-image]][download-url]
[![Linux][Linux-image]][download-url]
[Web App](https://chatgpt.nextweb.fun/) / [Desktop App](https://github.com/Yidadaa/ChatGPT-Next-Web/releases) / [Issues](https://github.com/Yidadaa/ChatGPT-Next-Web/issues) / [Discord](https://discord.gg/YCkeafCafC) / [コーヒーをおごる](https://www.buymeacoffee.com/yidadaa) / [QQ グループ](https://github.com/Yidadaa/ChatGPT-Next-Web/discussions/1724) / [開発者への報酬](https://user-images.githubusercontent.com/16968934/227772541-5bcd52d8-61b7-488c-a203-0330d8006e2b.jpg)
[web-url]: https://chatgpt.nextweb.fun
[download-url]: https://github.com/Yidadaa/ChatGPT-Next-Web/releases
[Web-image]: https://img.shields.io/badge/Web-PWA-orange?logo=microsoftedge
[Windows-image]: https://img.shields.io/badge/-Windows-blue?logo=windows
[MacOS-image]: https://img.shields.io/badge/-MacOS-black?logo=apple
[Linux-image]: https://img.shields.io/badge/-Linux-333?logo=ubuntu
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=chatgpt-next-web&repository-name=ChatGPT-Next-Web)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)
![cover](./docs/images/cover.png)
</div>
## 特徴
- Vercel で 1 分以内に**ワンクリックで無料デプロイ**。
- コンパクトなクライアント (~5MB) on Linux/Windows/MacOS、[今すぐダウンロード](https://github.com/Yidadaa/ChatGPT-Next-Web/releases)
- [RWKV-Runner](https://github.com/josStorer/RWKV-Runner) または [LocalAI](https://github.com/go-skynet/LocalAI) との使用をお勧めします
- プライバシー第一、すべてのデータはブラウザにローカルに保存されます
- マークダウンのサポート: LaTex、マーメイド、コードハイライトなど
- レスポンシブデザイン、ダークモード、PWA
- 最初の画面読み込み速度が速い(~100kb)、ストリーミングレスポンスをサポート
- v2 の新機能:プロンプトテンプレート(マスク)でチャットツールを作成、共有、デバッグ
- [awesome-chatgpt-prompts-zh](https://github.com/PlexPt/awesome-chatgpt-prompts-zh) と [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts) による素晴らしいプロンプト
- トークンを保存しながら、長い会話をサポートするために自動的にチャット履歴を圧縮します
- 国際化: English、简体中文、繁体中文、日本語、Français、Español、Italiano、Türkçe、Deutsch、Tiếng Việt、Русский、Čeština、한국어
## ロードマップ
- [x] システムプロンプト: ユーザー定義のプロンプトをシステムプロンプトとして固定 [#138](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/138)
- [x] ユーザープロンプト: ユーザはカスタムプロンプトを編集し、プロンプトリストに保存することができます。
- [x] プロンプトテンプレート: 事前に定義されたインコンテキストプロンプトで新しいチャットを作成 [#993](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/993)
- [x] イメージとして共有、ShareGPT への共有 [#1741](https://github.com/Yidadaa/ChatGPT-Next-Web/pull/1741)
- [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 など
- [ ] プラグイン: ネットワーク検索、計算機、その他のAPIなどをサポート [#165](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/165)
## 新機能
- 🚀 v2.0 がリリースされ、プロンプト・テンプレートが作成できるようになりました!こちらをお読みください: [ChatGPT プロンプトエンジニアリング Tips: ゼロ、一発、数発プロンプト](https://www.allabtai.com/prompt-engineering-tips-zero-one-and-few-shot-prompting/)。
- 💡 このプロジェクトをいつでもどこでも簡単に使いたいですか?このデスクトッププラグインをお試しください: https://github.com/mushan0x0/AI0x0.com
- 🚀 v2.7 では、会話を画像として共有したり、ShareGPT に共有することができます!
- 🚀 v2.8 全てのプラットフォームで動作するクライアントができました!
## 始める
> [簡体字中国語 > 始め方](./README_CN.md#开始使用)
1. [OpenAI API Key](https://platform.openai.com/account/api-keys) を取得する;
2. クリック
[![Vercel でデプロイ](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FYidadaa%2FChatGPT-Next-Web&env=OPENAI_API_KEY&env=CODE&project-name=chatgpt-next-web&repository-name=ChatGPT-Next-Web)をクリックします。`CODE` はあなたのページのパスワードであることを忘れないでください;
3. お楽しみください :)
## FAQ
[簡体字中国語 > よくある質問](./docs/faq-cn.md)
[English > FAQ](./docs/faq-en.md)
## 更新を継続する
> [簡体字中国語 > コードを最新の状態に保つ方法](./README_CN.md#保持更新)
上記の手順に沿ってワンクリックで自分のプロジェクトをデプロイした場合、"Updates Available" が常に表示される問題に遭遇するかもしれません。これは、Vercel がこのプロジェクトをフォークする代わりに、デフォルトで新しいプロジェクトを作成するため、アップデートを正しく検出できないためです。
以下の手順で再デプロイすることをお勧めします:
- 元のリポジトリを削除してください;
- ページの右上にあるフォークボタンを使って、このプロジェクトをフォークする;
- Vercel を選択し、再度デプロイする。[詳しいチュートリアルを参照](./docs/vercel-cn.md)。
### 自動アップデートを有効にする
> Upstream Sync の実行に失敗した場合は、手動で一度フォークしてください。
プロジェクトをフォークした後、GitHub の制限により、フォークしたプロジェクトの Actions ページで Workflows と Upstream Sync Action を手動で有効にする必要があります。有効にすると、1 時間ごとに自動更新がスケジュールされます:
![Automatic Updates](./docs/images/enable-actions.jpg)
![Enable Automatic Updates](./docs/images/enable-actions-sync.jpg)
### 手動でコードを更新する
すぐに更新したい場合は、[GitHub ドキュメント](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) をチェックして、フォークしたプロジェクトを上流のコードと同期させる方法を学んでください。
このプロジェクトにスターをつけたり、ウォッチしたり、作者をフォローすることで、リリースの通知を受け取ることができます。
## アクセスパスワード
> [簡体字中国語 > アクセスパスワードを増やす方法](./README_CN.md#配置页面访问密码)
このプロジェクトではアクセス制御を制限しています。vercel の環境変数のページに `CODE` という環境変数を追加してください。その値は次のようにカンマで区切られたパスワードでなければなりません:
```
code1,code2,code3
```
この環境変数を追加または変更した後は、変更を有効にするためにプロジェクトを再デプロイしてください。
## 環境変数
> [簡体字中国語 > API キー、アクセスパスワード、インターフェイスプロキシ設定方法](./README_CN.md#环境变量)
### `OPENAI_API_KEY` (必須)
OpenAI の api キー。
### `CODE` (オプション)
カンマで区切られたアクセスパスワード。
### `BASE_URL` (オプション)
> デフォルト: `https://api.openai.com`
> 例: `http://your-openai-proxy.com`
OpenAI api のリクエストベースの url をオーバーライドします。
### `OPENAI_ORG_ID` (オプション)
OpenAI の組織 ID を指定します。
### `HIDE_USER_API_KEY` (オプション)
> デフォルト: 空
ユーザーに自分の API キーを入力させたくない場合は、この値を 1 に設定する。
### `DISABLE_GPT4` (オプション)
> デフォルト: 空
ユーザーに GPT-4 を使用させたくない場合は、この値を 1 に設定する。
### `HIDE_BALANCE_QUERY` (オプション)
> デフォルト: 空
ユーザーに残高を照会させたくない場合は、この値を 1 に設定する。
## 必要条件
NodeJS >= 18、Docker >= 20
## Development
> [簡体字中国語 > 二次開発の進め方](./README_CN.md#开发)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/Yidadaa/ChatGPT-Next-Web)
開発を始める前に、プロジェクトのルートに新しい `.env.local` ファイルを作成し、そこに api キーを置く必要があります:
```
OPENAI_API_KEY=<your api key here>
# OpenAI サービスにアクセスできない場合は、この BASE_URL を使用してください
BASE_URL=https://chatgpt1.nextweb.fun/api/proxy
```
### ローカルデプロイ
```shell
# 1. nodejs と yarn をまずインストールする
# 2. `.env.local` にローカルの env vars を設定する
# 3. 実行
yarn install
yarn dev
```
## デプロイ
> [簡体字中国語 > プライベートサーバーへのデプロイ方法](./README_CN.md#部署)
### Docker (推奨)
```shell
docker pull yidadaa/chatgpt-next-web
docker run -d -p 3000:3000 \
-e OPENAI_API_KEY="sk-xxxx" \
-e CODE="your-password" \
yidadaa/chatgpt-next-web
```
プロキシの後ろでサービスを開始することができる:
```shell
docker run -d -p 3000:3000 \
-e OPENAI_API_KEY="sk-xxxx" \
-e CODE="your-password" \
-e PROXY_URL="http://localhost:7890" \
yidadaa/chatgpt-next-web
```
プロキシにパスワードが必要な場合:
```shell
-e PROXY_URL="http://127.0.0.1:7890 user pass"
```
### シェル
```shell
bash <(curl -s https://raw.githubusercontent.com/Yidadaa/ChatGPT-Next-Web/main/scripts/setup.sh)
```
## スクリーンショット
![Settings](./docs/images/settings.png)
![More](./docs/images/more.png)
## 翻訳
新しい翻訳を追加したい場合は、この[ドキュメント](./docs/translation.md)をお読みください。
## 寄付
[コーヒーをおごる](https://www.buymeacoffee.com/yidadaa)
## スペシャルサンクス
### スポンサー
> 寄付金額が 100 元以上のユーザーのみリストアップしています
[@mushan0x0](https://github.com/mushan0x0)
[@ClarenceDan](https://github.com/ClarenceDan)
[@zhangjia](https://github.com/zhangjia)
[@hoochanlon](https://github.com/hoochanlon)
[@relativequantum](https://github.com/relativequantum)
[@desenmeng](https://github.com/desenmeng)
[@webees](https://github.com/webees)
[@chazzhou](https://github.com/chazzhou)
[@hauy](https://github.com/hauy)
[@Corwin006](https://github.com/Corwin006)
[@yankunsong](https://github.com/yankunsong)
[@ypwhs](https://github.com/ypwhs)
[@fxxxchao](https://github.com/fxxxchao)
[@hotic](https://github.com/hotic)
[@WingCH](https://github.com/WingCH)
[@jtung4](https://github.com/jtung4)
[@micozhu](https://github.com/micozhu)
[@jhansion](https://github.com/jhansion)
[@Sha1rholder](https://github.com/Sha1rholder)
[@AnsonHyq](https://github.com/AnsonHyq)
[@synwith](https://github.com/synwith)
[@piksonGit](https://github.com/piksonGit)
### コントリビューター
[コントリビューター達](https://github.com/Yidadaa/ChatGPT-Next-Web/graphs/contributors)
## ライセンス
[MIT](https://opensource.org/license/mit/)

View File

@@ -2,8 +2,8 @@ import { NextRequest, NextResponse } from "next/server";
export const OPENAI_URL = "api.openai.com";
const DEFAULT_PROTOCOL = "https";
const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL;
const BASE_URL = process.env.BASE_URL ?? OPENAI_URL;
const PROTOCOL = process.env.PROTOCOL || DEFAULT_PROTOCOL;
const BASE_URL = process.env.BASE_URL || OPENAI_URL;
const DISABLE_GPT4 = !!process.env.DISABLE_GPT4;
export async function requestOpenai(req: NextRequest) {
@@ -20,6 +20,10 @@ export async function requestOpenai(req: NextRequest) {
baseUrl = `${PROTOCOL}://${baseUrl}`;
}
if (baseUrl.endsWith('/')) {
baseUrl = baseUrl.slice(0, -1);
}
console.log("[Proxy] ", openaiPath);
console.log("[Base Url]", baseUrl);
@@ -35,14 +39,16 @@ export async function requestOpenai(req: NextRequest) {
const fetchOptions: RequestInit = {
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-store",
Authorization: authValue,
...(process.env.OPENAI_ORG_ID && {
"OpenAI-Organization": process.env.OPENAI_ORG_ID,
}),
},
cache: "no-store",
method: req.method,
body: req.body,
// to fix #2485: https://stackoverflow.com/questions/55920957/cloudflare-worker-typeerror-one-time-use-body
redirect: "manual",
// @ts-ignore
duplex: "half",
signal: controller.signal,

View File

@@ -99,7 +99,7 @@ export class ClientApi {
// 敬告二开开发者们,为了开源大模型的发展,请不要修改上述消息,此消息用于后续数据清洗使用
// Please do not modify this message
console.log("[Share]", msgs);
console.log("[Share]", messages, msgs);
const clientConfig = getClientConfig();
const proxyUrl = "/sharegpt";
const rawUrl = "https://sharegpt.com/api/conversations";

View File

@@ -1,5 +1,6 @@
import {
DEFAULT_API_HOST,
DEFAULT_MODELS,
OpenaiPath,
REQUEST_TIMEOUT_MS,
} from "@/app/constant";
@@ -12,6 +13,7 @@ import {
fetchEventSource,
} from "@fortaine/fetch-event-source";
import { prettyObject } from "@/app/utils/format";
import { getClientConfig } from "@/app/config/client";
export interface OpenAIListModelResponse {
object: string;
@@ -23,15 +25,20 @@ export interface OpenAIListModelResponse {
}
export class ChatGPTApi implements LLMApi {
private disableListModels = true;
path(path: string): string {
let openaiUrl = useAccessStore.getState().openaiUrl;
const apiPath = "/api/openai";
if (openaiUrl.length === 0) {
openaiUrl = DEFAULT_API_HOST;
const isApp = !!getClientConfig()?.isApp;
openaiUrl = isApp ? DEFAULT_API_HOST : apiPath;
}
if (openaiUrl.endsWith("/")) {
openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1);
}
if (!openaiUrl.startsWith("http") && !openaiUrl.startsWith("/api/openai")) {
if (!openaiUrl.startsWith("http") && !openaiUrl.startsWith(apiPath)) {
openaiUrl = "https://" + openaiUrl;
}
return [openaiUrl, path].join("/");
@@ -175,7 +182,7 @@ export class ChatGPTApi implements LLMApi {
options.onFinish(message);
}
} catch (e) {
console.log("[Request] failed to make a chat reqeust", e);
console.log("[Request] failed to make a chat request", e);
options.onError?.(e as Error);
}
}
@@ -246,6 +253,10 @@ export class ChatGPTApi implements LLMApi {
}
async models(): Promise<LLMModel[]> {
if (this.disableListModels) {
return DEFAULT_MODELS.slice();
}
const res = await fetch(this.path(OpenaiPath.ListModelPath), {
method: "GET",
headers: {

View File

@@ -7,6 +7,8 @@ interface Commands {
fill?: Command;
submit?: Command;
mask?: Command;
code?: Command;
settings?: Command;
}
export function useCommand(commands: Commands = {}) {

View File

@@ -7,6 +7,8 @@ import { useAccessStore } from "../store";
import Locale from "../locales";
import BotIcon from "../icons/bot.svg";
import { useEffect } from "react";
import { getClientConfig } from "../config/client";
export function AuthPage() {
const navigate = useNavigate();
@@ -14,6 +16,13 @@ export function AuthPage() {
const goHome = () => navigate(Path.Home);
useEffect(() => {
if (getClientConfig()?.isApp) {
navigate(Path.Settings);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className={styles["auth-page"]}>
<div className={`no-dark ${styles["auth-logo"]}`}>

View File

@@ -14,10 +14,11 @@
padding: 4px 10px;
animation: slide-in ease 0.3s;
box-shadow: var(--card-shadow);
transition: all ease 0.3s;
transition: width ease 0.3s;
align-items: center;
height: 16px;
width: var(--icon-width);
overflow: hidden;
&:not(:last-child) {
margin-right: 5px;
@@ -29,14 +30,16 @@
opacity: 0;
transform: translateX(-5px);
transition: all ease 0.3s;
transition-delay: 0.1s;
pointer-events: none;
}
&:hover {
--delay: 0.5s;
width: var(--full-width);
transition-delay: var(--delay);
.text {
transition-delay: var(--delay);
opacity: 1;
transform: translate(0);
}
@@ -95,11 +98,41 @@
}
.context-prompt {
.context-prompt-insert {
display: flex;
justify-content: center;
padding: 4px;
opacity: 0.2;
transition: all ease 0.3s;
background-color: rgba(0, 0, 0, 0);
cursor: pointer;
border-radius: 4px;
margin-top: 4px;
margin-bottom: 4px;
&:hover {
opacity: 1;
background-color: rgba(0, 0, 0, 0.05);
}
}
.context-prompt-row {
display: flex;
justify-content: center;
width: 100%;
margin-bottom: 10px;
&:hover {
.context-drag {
opacity: 1;
}
}
.context-drag {
display: flex;
align-items: center;
opacity: 0.5;
transition: all ease 0.3s;
}
.context-role {
margin-right: 10px;

View File

@@ -5,6 +5,7 @@ import React, {
useEffect,
useMemo,
useCallback,
Fragment,
} from "react";
import SendWhiteIcon from "../icons/send-white.svg";
@@ -24,6 +25,8 @@ import SettingsIcon from "../icons/chat-settings.svg";
import DeleteIcon from "../icons/clear.svg";
import PinIcon from "../icons/pin.svg";
import EditIcon from "../icons/rename.svg";
import ConfirmIcon from "../icons/confirm.svg";
import CancelIcon from "../icons/cancel.svg";
import LightIcon from "../icons/light.svg";
import DarkIcon from "../icons/dark.svg";
@@ -62,6 +65,7 @@ import { IconButton } from "./button";
import styles from "./chat.module.scss";
import {
List,
ListItem,
Modal,
Selector,
@@ -70,9 +74,15 @@ import {
showToast,
} from "./ui-lib";
import { useLocation, useNavigate } from "react-router-dom";
import { LAST_INPUT_KEY, Path, REQUEST_TIMEOUT_MS } from "../constant";
import {
CHAT_PAGE_SIZE,
LAST_INPUT_KEY,
MAX_RENDER_MSG_COUNT,
Path,
REQUEST_TIMEOUT_MS,
} from "../constant";
import { Avatar } from "./emoji";
import { MaskAvatar, MaskConfig } from "./mask";
import { ContextPrompts, MaskAvatar, MaskConfig } from "./mask";
import { useMaskStore } from "../store/mask";
import { ChatCommandPrefix, useChatCommand, useCommand } from "../command";
import { prettyObject } from "../utils/format";
@@ -367,23 +377,29 @@ function useScrollToBottom() {
// for auto-scroll
const scrollRef = useRef<HTMLDivElement>(null);
const [autoScroll, setAutoScroll] = useState(true);
const scrollToBottom = useCallback(() => {
function scrollDomToBottom() {
const dom = scrollRef.current;
if (dom) {
requestAnimationFrame(() => dom.scrollTo(0, dom.scrollHeight));
requestAnimationFrame(() => {
setAutoScroll(true);
dom.scrollTo(0, dom.scrollHeight);
});
}
}
}, []);
// auto scroll
useEffect(() => {
autoScroll && scrollToBottom();
if (autoScroll) {
scrollDomToBottom();
}
});
return {
scrollRef,
autoScroll,
setAutoScroll,
scrollToBottom,
scrollDomToBottom,
};
}
@@ -500,6 +516,7 @@ export function ChatActions(props: {
{showModelSelector && (
<Selector
defaultSelectedValue={currentModel}
items={models.map((m) => ({
title: m,
value: m,
@@ -519,14 +536,73 @@ export function ChatActions(props: {
);
}
export function Chat() {
export function EditMessageModal(props: { onClose: () => void }) {
const chatStore = useChatStore();
const session = chatStore.currentSession();
const [messages, setMessages] = useState(session.messages.slice());
return (
<div className="modal-mask">
<Modal
title={Locale.Chat.EditMessage.Title}
onClose={props.onClose}
actions={[
<IconButton
text={Locale.UI.Cancel}
icon={<CancelIcon />}
key="cancel"
onClick={() => {
props.onClose();
}}
/>,
<IconButton
type="primary"
text={Locale.UI.Confirm}
icon={<ConfirmIcon />}
key="ok"
onClick={() => {
chatStore.updateCurrentSession(
(session) => (session.messages = messages),
);
props.onClose();
}}
/>,
]}
>
<List>
<ListItem
title={Locale.Chat.EditMessage.Topic.Title}
subTitle={Locale.Chat.EditMessage.Topic.SubTitle}
>
<input
type="text"
value={session.topic}
onInput={(e) =>
chatStore.updateCurrentSession(
(session) => (session.topic = e.currentTarget.value),
)
}
></input>
</ListItem>
</List>
<ContextPrompts
context={messages}
updateContext={(updater) => {
const newMessages = messages.slice();
updater(newMessages);
setMessages(newMessages);
}}
/>
</Modal>
</div>
);
}
function _Chat() {
type RenderMessage = ChatMessage & { preview?: boolean };
const chatStore = useChatStore();
const [session, sessionIndex] = useChatStore((state) => [
state.currentSession(),
state.currentSessionIndex,
]);
const session = chatStore.currentSession();
const config = useAppConfig();
const fontSize = config.fontSize;
@@ -536,16 +612,11 @@ export function Chat() {
const [userInput, setUserInput] = useState("");
const [isLoading, setIsLoading] = useState(false);
const { submitKey, shouldSubmit } = useSubmitHandler();
const { scrollRef, setAutoScroll, scrollToBottom } = useScrollToBottom();
const { scrollRef, setAutoScroll, scrollDomToBottom } = useScrollToBottom();
const [hitBottom, setHitBottom] = useState(true);
const isMobileScreen = useMobileScreen();
const navigate = useNavigate();
const onChatBodyScroll = (e: HTMLElement) => {
const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 10;
setHitBottom(isTouchBottom);
};
// prompt hints
const promptStore = usePromptStore();
const [promptHints, setPromptHints] = useState<RenderPompt[]>([]);
@@ -709,22 +780,6 @@ export function Chat() {
}
};
const findLastUserIndex = (messageId: string) => {
// find last user input message and resend
let lastUserMessageIndex: number | null = null;
for (let i = 0; i < session.messages.length; i += 1) {
const message = session.messages[i];
if (message.role === "user") {
lastUserMessageIndex = i;
}
if (message.id === messageId) {
break;
}
}
return lastUserMessageIndex;
};
const deleteMessage = (msgId?: string) => {
chatStore.updateCurrentSession(
(session) =>
@@ -737,17 +792,56 @@ export function Chat() {
};
const onResend = (message: ChatMessage) => {
let content = message.content;
// when it is resending a message
// 1. for a user's message, find the next bot response
// 2. for a bot's message, find the last user's input
// 3. delete original user input and bot's message
// 4. resend the user's input
if (message.role === "assistant" && message.id) {
const userIndex = findLastUserIndex(message.id);
if (userIndex) {
content = session.messages.at(userIndex)?.content ?? content;
const resendingIndex = session.messages.findIndex(
(m) => m.id === message.id,
);
if (resendingIndex <= 0 || resendingIndex >= session.messages.length) {
console.error("[Chat] failed to find resending message", message);
return;
}
let userMessage: ChatMessage | undefined;
let botMessage: ChatMessage | undefined;
if (message.role === "assistant") {
// if it is resending a bot's message, find the user input for it
botMessage = message;
for (let i = resendingIndex; i >= 0; i -= 1) {
if (session.messages[i].role === "user") {
userMessage = session.messages[i];
break;
}
}
} else if (message.role === "user") {
// if it is resending a user's input, find the bot's response
userMessage = message;
for (let i = resendingIndex; i < session.messages.length; i += 1) {
if (session.messages[i].role === "assistant") {
botMessage = session.messages[i];
break;
}
}
}
if (userMessage === undefined) {
console.error("[Chat] failed to resend", message);
return;
}
// delete the original messages
deleteMessage(userMessage.id);
deleteMessage(botMessage?.id);
// resend the message
setIsLoading(true);
chatStore.onUserInput(content).then(() => setIsLoading(false));
chatStore.onUserInput(userMessage.content).then(() => setIsLoading(false));
inputRef.current?.focus();
};
@@ -764,10 +858,9 @@ export function Chat() {
});
};
const context: RenderMessage[] = session.mask.hideContext
? []
: session.mask.context.slice();
const context: RenderMessage[] = useMemo(() => {
return session.mask.hideContext ? [] : session.mask.context.slice();
}, [session.mask.context, session.mask.hideContext]);
const accessStore = useAccessStore();
if (
@@ -781,14 +874,9 @@ export function Chat() {
context.push(copiedHello);
}
// clear context index = context length + index in messages
const clearContextIndex =
(session.clearContextIndex ?? -1) >= 0
? session.clearContextIndex! + context.length
: -1;
// preview messages
const messages = context
const renderMessages = useMemo(() => {
return context
.concat(session.messages as RenderMessage[])
.concat(
isLoading
@@ -816,25 +904,68 @@ export function Chat() {
]
: [],
);
}, [
config.sendPreviewBubble,
context,
isLoading,
session.messages,
userInput,
]);
const [msgRenderIndex, _setMsgRenderIndex] = useState(
Math.max(0, renderMessages.length - CHAT_PAGE_SIZE),
);
function setMsgRenderIndex(newIndex: number) {
newIndex = Math.min(renderMessages.length - CHAT_PAGE_SIZE, newIndex);
newIndex = Math.max(0, newIndex);
_setMsgRenderIndex(newIndex);
}
const messages = useMemo(() => {
const endRenderIndex = Math.min(
msgRenderIndex + 3 * CHAT_PAGE_SIZE,
renderMessages.length,
);
return renderMessages.slice(msgRenderIndex, endRenderIndex);
}, [msgRenderIndex, renderMessages]);
const onChatBodyScroll = (e: HTMLElement) => {
const bottomHeight = e.scrollTop + e.clientHeight;
const edgeThreshold = e.clientHeight;
const isTouchTopEdge = e.scrollTop <= edgeThreshold;
const isTouchBottomEdge = bottomHeight >= e.scrollHeight - edgeThreshold;
const isHitBottom = bottomHeight >= e.scrollHeight - 10;
const prevPageMsgIndex = msgRenderIndex - CHAT_PAGE_SIZE;
const nextPageMsgIndex = msgRenderIndex + CHAT_PAGE_SIZE;
if (isTouchTopEdge && !isTouchBottomEdge) {
setMsgRenderIndex(prevPageMsgIndex);
} else if (isTouchBottomEdge) {
setMsgRenderIndex(nextPageMsgIndex);
}
setHitBottom(isHitBottom);
setAutoScroll(isHitBottom);
};
function scrollToBottom() {
setMsgRenderIndex(renderMessages.length - CHAT_PAGE_SIZE);
scrollDomToBottom();
}
// clear context index = context length + index in messages
const clearContextIndex =
(session.clearContextIndex ?? -1) >= 0
? session.clearContextIndex! + context.length - msgRenderIndex
: -1;
const [showPromptModal, setShowPromptModal] = useState(false);
const renameSession = () => {
showPrompt(Locale.Chat.Rename, session.topic).then((newTopic) => {
if (newTopic && newTopic !== session.topic) {
chatStore.updateCurrentSession(
(session) => (session.topic = newTopic!),
);
}
});
};
const clientConfig = useMemo(() => getClientConfig(), []);
const location = useLocation();
const isChat = location.pathname === Path.Chat;
const autoFocus = !isMobileScreen || isChat; // only focus in chat page
const autoFocus = !isMobileScreen; // wont auto focus on mobile screen
const showMaxIcon = !isMobileScreen && !clientConfig?.isApp;
useCommand({
@@ -842,7 +973,45 @@ export function Chat() {
submit: (text) => {
doSubmit(text);
},
code: (text) => {
console.log("[Command] got code from url: ", text);
showConfirm(Locale.URLCommand.Code + `code = ${text}`).then((res) => {
if (res) {
accessStore.updateCode(text);
}
});
},
settings: (text) => {
try {
const payload = JSON.parse(text) as {
key?: string;
url?: string;
};
console.log("[Command] got settings from url: ", payload);
if (payload.key || payload.url) {
showConfirm(
Locale.URLCommand.Settings +
`\n${JSON.stringify(payload, null, 4)}`,
).then((res) => {
if (!res) return;
if (payload.key) {
accessStore.updateToken(payload.key);
}
if (payload.url) {
accessStore.updateOpenAiUrl(payload.url);
}
});
}
} catch {
console.error("[Command] failed to get settings from url: ", text);
}
},
});
// edit / insert message modal
const [isEditingMessage, setIsEditingMessage] = useState(false);
return (
<div className={styles.chat} key={session.id}>
@@ -863,7 +1032,7 @@ export function Chat() {
<div className={`window-header-title ${styles["chat-body-title"]}`}>
<div
className={`window-header-main-title ${styles["chat-body-main-title"]}`}
onClickCapture={renameSession}
onClickCapture={() => setIsEditingMessage(true)}
>
{!session.topic ? DEFAULT_TOPIC : session.topic}
</div>
@@ -877,7 +1046,7 @@ export function Chat() {
<IconButton
icon={<RenameIcon />}
bordered
onClick={renameSession}
onClick={() => setIsEditingMessage(true)}
/>
</div>
)}
@@ -918,7 +1087,6 @@ export function Chat() {
ref={scrollRef}
onScroll={(e) => onChatBodyScroll(e.currentTarget)}
onMouseDown={() => inputRef.current?.blur()}
onWheel={(e) => setAutoScroll(hitBottom && e.deltaY > 0)}
onTouchStart={() => {
inputRef.current?.blur();
setAutoScroll(false);
@@ -936,9 +1104,8 @@ export function Chat() {
const shouldShowClearContextDivider = i === clearContextIndex - 1;
return (
<>
<Fragment key={message.id}>
<div
key={i}
className={
isUser ? styles["chat-message-user"] : styles["chat-message"]
}
@@ -956,9 +1123,9 @@ export function Chat() {
10,
);
chatStore.updateCurrentSession((session) => {
const m = session.messages.find(
(m) => m.id === message.id,
);
const m = session.mask.context
.concat(session.messages)
.find((m) => m.id === message.id);
if (m) {
m.content = newMessage;
}
@@ -1021,7 +1188,8 @@ export function Chat() {
<Markdown
content={message.content}
loading={
(message.preview || message.content.length === 0) &&
(message.preview || message.streaming) &&
message.content.length === 0 &&
!isUser
}
onContextMenu={(e) => onRightClick(e, message)}
@@ -1031,7 +1199,7 @@ export function Chat() {
}}
fontSize={fontSize}
parentRef={scrollRef}
defaultShow={i >= messages.length - 10}
defaultShow={i >= messages.length - 6}
/>
</div>
@@ -1043,7 +1211,7 @@ export function Chat() {
</div>
</div>
{shouldShowClearContextDivider && <ClearContextDivider />}
</>
</Fragment>
);
})}
</div>
@@ -1075,8 +1243,8 @@ export function Chat() {
onInput={(e) => onInput(e.currentTarget.value)}
value={userInput}
onKeyDown={onInputKeyDown}
onFocus={() => setAutoScroll(true)}
onBlur={() => setAutoScroll(false)}
onFocus={scrollToBottom}
onClick={scrollToBottom}
rows={inputRows}
autoFocus={autoFocus}
style={{
@@ -1096,6 +1264,20 @@ export function Chat() {
{showExport && (
<ExportMessageModal onClose={() => setShowExport(false)} />
)}
{isEditingMessage && (
<EditMessageModal
onClose={() => {
setIsEditingMessage(false);
}}
/>
)}
</div>
);
}
export function Chat() {
const chatStore = useChatStore();
const sessionIndex = chatStore.currentSessionIndex;
return <_Chat key={sessionIndex}></_Chat>;
}

View File

@@ -8,6 +8,7 @@ import {
Modal,
Select,
showImageModal,
showModal,
showToast,
} from "./ui-lib";
import { IconButton } from "./button";
@@ -126,7 +127,7 @@ export function MessageExporter() {
];
const { currentStep, setCurrentStepIndex, currentStepIndex } =
useSteps(steps);
const formats = ["text", "image"] as const;
const formats = ["text", "image", "json"] as const;
type ExportFormat = (typeof formats)[number];
const [exportConfig, setExportConfig] = useState({
@@ -156,7 +157,21 @@ export function MessageExporter() {
session.mask.context,
selection,
]);
function preview() {
if (exportConfig.format === "text") {
return (
<MarkdownPreviewer messages={selectedMessages} topic={session.topic} />
);
} else if (exportConfig.format === "json") {
return (
<JsonPreviewer messages={selectedMessages} topic={session.topic} />
);
} else {
return (
<ImagePreviewer messages={selectedMessages} topic={session.topic} />
);
}
}
return (
<>
<Steps
@@ -211,16 +226,7 @@ export function MessageExporter() {
/>
</div>
{currentStep.value === "preview" && (
<div className={styles["message-exporter-body"]}>
{exportConfig.format === "text" ? (
<MarkdownPreviewer
messages={selectedMessages}
topic={session.topic}
/>
) : (
<ImagePreviewer messages={selectedMessages} topic={session.topic} />
)}
</div>
<div className={styles["message-exporter-body"]}>{preview()}</div>
)}
</>
);
@@ -244,11 +250,11 @@ export function RenderExport(props: {
}
const renderMsgs = messages.map((v, i) => {
const [_, role] = v.id.split(":");
const [role, _] = v.id.split(":");
return {
id: i.toString(),
role: role as any,
content: v.innerHTML,
content: role === "user" ? v.textContent ?? "" : v.innerHTML,
date: "",
};
});
@@ -287,7 +293,30 @@ export function PreviewActions(props: {
.share(msgs)
.then((res) => {
if (!res) return;
copyToClipboard(res);
showModal({
title: Locale.Export.Share,
children: [
<input
type="text"
value={res}
key="input"
style={{
width: "100%",
maxWidth: "unset",
}}
readOnly
onClick={(e) => e.currentTarget.select()}
></input>,
],
actions: [
<IconButton
icon={<CopyIcon />}
text={Locale.Chat.Actions.Copy}
key="copy"
onClick={() => copyToClipboard(res)}
/>,
],
});
setTimeout(() => {
window.open(res, "_blank");
}, 800);
@@ -521,12 +550,44 @@ export function MarkdownPreviewer(props: {
const download = () => {
downloadAs(mdText, `${props.topic}.md`);
};
return (
<>
<PreviewActions
copy={copy}
download={download}
showCopy={true}
messages={props.messages}
/>
<div className="markdown-body">
<pre className={styles["export-content"]}>{mdText}</pre>
</div>
</>
);
}
export function JsonPreviewer(props: {
messages: ChatMessage[];
topic: string;
}) {
const msgs = props.messages.map((m) => ({
role: m.role,
content: m.content,
}));
const mdText = "\n" + JSON.stringify(msgs, null, 2) + "\n";
const copy = () => {
copyToClipboard(JSON.stringify(msgs, null, 2));
};
const download = () => {
downloadAs(JSON.stringify(msgs, null, 2), `${props.topic}.json`);
};
return (
<>
<PreviewActions
copy={copy}
download={download}
showCopy={true}
messages={props.messages}
/>
<div className="markdown-body">

View File

@@ -61,24 +61,36 @@
}
}
}
&:hover,
&:active {
.sidebar-drag {
background-color: rgba($color: #000000, $alpha: 0.01);
svg {
opacity: 0.2;
}
}
}
}
.sidebar-drag {
$width: 10px;
$width: 14px;
position: absolute;
top: 0;
right: 0;
height: 100%;
width: $width;
background-color: var(--black);
background-color: rgba($color: #000000, $alpha: 0);
cursor: ew-resize;
opacity: 0;
transition: all ease 0.3s;
display: flex;
align-items: center;
&:hover,
&:active {
opacity: 0.2;
svg {
opacity: 0;
margin-left: -2px;
}
}
@@ -162,6 +174,7 @@
user-select: none;
border: 2px solid transparent;
position: relative;
content-visibility: auto;
}
.chat-item:hover {

View File

@@ -15,7 +15,7 @@ import dynamic from "next/dynamic";
import { Path, SlotID } from "../constant";
import { ErrorBoundary } from "./error";
import { getLang } from "../locales";
import { getISOLang, getLang } from "../locales";
import {
HashRouter as Router,
@@ -28,6 +28,7 @@ import { useAppConfig } from "../store/config";
import { AuthPage } from "./auth";
import { getClientConfig } from "../config/client";
import { api } from "../client/api";
import { useAccessStore } from "../store";
export function Loading(props: { noLogo?: boolean }) {
return (
@@ -85,6 +86,17 @@ export function useSwitchTheme() {
}, [config.theme]);
}
function useHtmlLang() {
useEffect(() => {
const lang = getISOLang();
const htmlLang = document.documentElement.lang;
if (lang !== htmlLang) {
document.documentElement.lang = lang;
}
}, []);
}
const useHasHydrated = () => {
const [hasHydrated, setHasHydrated] = useState<boolean>(false);
@@ -103,8 +115,7 @@ const loadAsyncGoogleFont = () => {
getClientConfig()?.buildMode === "export" ? remoteFontUrl : proxyFontUrl;
linkEl.rel = "stylesheet";
linkEl.href =
googleFontUrl +
"/css2?family=Noto+Sans+SC:wght@300;400;700;900&display=swap";
googleFontUrl + "/css2?family=Noto+Sans:wght@300;400;700;900&display=swap";
document.head.appendChild(linkEl);
};
@@ -168,9 +179,11 @@ export function useLoadData() {
export function Home() {
useSwitchTheme();
useLoadData();
useHtmlLang();
useEffect(() => {
console.log("[Config] got config from build time", getClientConfig());
useAccessStore.getState().fetch();
}, []);
if (!useHasHydrated()) {

View File

@@ -38,12 +38,6 @@ export function Mermaid(props: { code: string }) {
if (!svg) return;
const text = new XMLSerializer().serializeToString(svg);
const blob = new Blob([text], { type: "image/svg+xml" });
console.log(blob);
// const url = URL.createObjectURL(blob);
// const win = window.open(url);
// if (win) {
// win.onload = () => URL.revokeObjectURL(url);
// }
showImageModal(URL.createObjectURL(blob));
}
@@ -121,6 +115,7 @@ function _MarkDownContent(props: { content: string }) {
]}
components={{
pre: PreCode,
p: (pProps) => <p {...pProps} dir="auto" />,
a: (aProps) => {
const href = aProps.href || "";
const isInternal = /^\/#/i.test(href);
@@ -146,70 +141,22 @@ export function Markdown(
} & React.DOMAttributes<HTMLDivElement>,
) {
const mdRef = useRef<HTMLDivElement>(null);
const renderedHeight = useRef(0);
const renderedWidth = useRef(0);
const inView = useRef(!!props.defaultShow);
const [_, triggerRender] = useState(0);
const checkInView = useThrottledCallback(
() => {
const parent = props.parentRef?.current;
const md = mdRef.current;
if (parent && md && !props.defaultShow) {
const parentBounds = parent.getBoundingClientRect();
const twoScreenHeight = Math.max(500, parentBounds.height * 2);
const mdBounds = md.getBoundingClientRect();
const parentTop = parentBounds.top - twoScreenHeight;
const parentBottom = parentBounds.bottom + twoScreenHeight;
const isOverlap =
Math.max(parentTop, mdBounds.top) <=
Math.min(parentBottom, mdBounds.bottom);
inView.current = isOverlap;
triggerRender(Date.now());
}
if (inView.current && md) {
const rect = md.getBoundingClientRect();
renderedHeight.current = Math.max(renderedHeight.current, rect.height);
renderedWidth.current = Math.max(renderedWidth.current, rect.width);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
},
300,
{
leading: true,
trailing: true,
},
);
useEffect(() => {
props.parentRef?.current?.addEventListener("scroll", checkInView);
checkInView();
return () =>
props.parentRef?.current?.removeEventListener("scroll", checkInView);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const getSize = (x: number) => (!inView.current && x > 0 ? x : "auto");
return (
<div
className="markdown-body"
style={{
fontSize: `${props.fontSize ?? 14}px`,
height: getSize(renderedHeight.current),
width: getSize(renderedWidth.current),
direction: /[\u0600-\u06FF]/.test(props.content) ? "rtl" : "ltr",
}}
ref={mdRef}
onContextMenu={props.onContextMenu}
onDoubleClickCapture={props.onDoubleClickCapture}
>
{inView.current &&
(props.loading ? (
{props.loading ? (
<LoadingIcon />
) : (
<MarkdownContent content={props.content} />
))}
)}
</div>
);
}

View File

@@ -11,6 +11,7 @@ import CloseIcon from "../icons/close.svg";
import DeleteIcon from "../icons/delete.svg";
import EyeIcon from "../icons/eye.svg";
import CopyIcon from "../icons/copy.svg";
import DragIcon from "../icons/drag.svg";
import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "../store/mask";
import {
@@ -42,6 +43,20 @@ import { ModelConfigList } from "./model-config";
import { FileName, Path } from "../constant";
import { BUILTIN_MASK_STORE } from "../masks";
import { nanoid } from "nanoid";
import {
DragDropContext,
Droppable,
Draggable,
OnDragEndResponder,
} from "@hello-pangea/dnd";
// drag and drop helper function
function reorder<T>(list: T[], startIndex: number, endIndex: number): T[] {
const result = [...list];
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
}
export function MaskAvatar(props: { mask: Mask }) {
return props.mask.avatar !== DEFAULT_MASK_AVATAR ? (
@@ -192,6 +207,7 @@ export function MaskConfig(props: {
}
function ContextPromptItem(props: {
index: number;
prompt: ChatMessage;
update: (prompt: ChatMessage) => void;
remove: () => void;
@@ -201,6 +217,10 @@ function ContextPromptItem(props: {
return (
<div className={chatStyle["context-prompt-row"]}>
{!focusingInput && (
<>
<div className={chatStyle["context-drag"]}>
<DragIcon />
</div>
<Select
value={props.prompt.role}
className={chatStyle["context-role"]}
@@ -217,6 +237,7 @@ function ContextPromptItem(props: {
</option>
))}
</Select>
</>
)}
<Input
value={props.prompt.content}
@@ -255,8 +276,8 @@ export function ContextPrompts(props: {
}) {
const context = props.context;
const addContextPrompt = (prompt: ChatMessage) => {
props.updateContext((context) => context.push(prompt));
const addContextPrompt = (prompt: ChatMessage, i: number) => {
props.updateContext((context) => context.splice(i, 0, prompt));
};
const removeContextPrompt = (i: number) => {
@@ -267,18 +288,71 @@ export function ContextPrompts(props: {
props.updateContext((context) => (context[i] = prompt));
};
const onDragEnd: OnDragEndResponder = (result) => {
if (!result.destination) {
return;
}
const newContext = reorder(
context,
result.source.index,
result.destination.index,
);
props.updateContext((context) => {
context.splice(0, context.length, ...newContext);
});
};
return (
<>
<div className={chatStyle["context-prompt"]} style={{ marginBottom: 20 }}>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="context-prompt-list">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{context.map((c, i) => (
<Draggable
draggableId={c.id || i.toString()}
index={i}
key={c.id}
>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<ContextPromptItem
key={i}
index={i}
prompt={c}
update={(prompt) => updateContextPrompt(i, prompt)}
remove={() => removeContextPrompt(i)}
/>
<div
className={chatStyle["context-prompt-insert"]}
onClick={() => {
addContextPrompt(
createMessage({
role: "user",
content: "",
date: new Date().toLocaleString(),
}),
i + 1,
);
}}
>
<AddIcon />
</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
{props.context.length === 0 && (
<div className={chatStyle["context-prompt-row"]}>
<IconButton
icon={<AddIcon />}
@@ -292,10 +366,12 @@ export function ContextPrompts(props: {
content: "",
date: "",
}),
props.context.length,
)
}
/>
</div>
)}
</div>
</>
);

View File

@@ -76,7 +76,7 @@ export function ModelConfigList(props: {
<input
type="number"
min={100}
max={32000}
max={100000}
value={props.modelConfig.max_tokens}
onChange={(e) =>
props.updateConfig(
@@ -130,6 +130,22 @@ export function ModelConfigList(props: {
></InputRange>
</ListItem>
<ListItem
title={Locale.Settings.InjectSystemPrompts.Title}
subTitle={Locale.Settings.InjectSystemPrompts.SubTitle}
>
<input
type="checkbox"
checked={props.modelConfig.enableInjectSystemPrompts}
onChange={(e) =>
props.updateConfig(
(config) =>
(config.enableInjectSystemPrompts = e.currentTarget.checked),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.InputTemplate.Title}
subTitle={Locale.Settings.InputTemplate.SubTitle}
@@ -153,7 +169,7 @@ export function ModelConfigList(props: {
title={props.modelConfig.historyMessageCount.toString()}
value={props.modelConfig.historyMessageCount}
min="0"
max="32"
max="64"
step="1"
onChange={(e) =>
props.updateConfig(

View File

@@ -529,6 +529,22 @@ export function Settings() {
></InputRange>
</ListItem>
<ListItem
title={Locale.Settings.AutoGenerateTitle.Title}
subTitle={Locale.Settings.AutoGenerateTitle.SubTitle}
>
<input
type="checkbox"
checked={config.enableAutoGenerateTitle}
onChange={(e) =>
updateConfig(
(config) =>
(config.enableAutoGenerateTitle = e.currentTarget.checked),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.SendPreviewBubble.Title}
subTitle={Locale.Settings.SendPreviewBubble.SubTitle}

View File

@@ -10,6 +10,7 @@ import AddIcon from "../icons/add.svg";
import CloseIcon from "../icons/close.svg";
import MaskIcon from "../icons/mask.svg";
import PluginIcon from "../icons/plugin.svg";
import DragIcon from "../icons/drag.svg";
import Locale from "../locales";
@@ -198,7 +199,9 @@ export function SideBar(props: { className?: string }) {
<div
className={styles["sidebar-drag"]}
onMouseDown={(e) => onDragMouseDown(e as any)}
></div>
>
<DragIcon />
</div>
</div>
);
}

View File

@@ -377,7 +377,7 @@ export function showPrompt(content: any, value = "", rows = 3) {
};
return new Promise<string>((resolve) => {
let userInput = "";
let userInput = value;
root.render(
<Modal
@@ -443,6 +443,7 @@ export function Selector<T>(props: {
subTitle?: string;
value: T;
}>;
defaultSelectedValue?: T;
onSelection?: (selection: T[]) => void;
onClose?: () => void;
multiple?: boolean;
@@ -452,6 +453,7 @@ export function Selector<T>(props: {
<div className={styles["selector-content"]}>
<List>
{props.items.map((item, i) => {
const selected = props.defaultSelectedValue === item.value;
return (
<ListItem
className={styles["selector-item"]}
@@ -462,7 +464,20 @@ export function Selector<T>(props: {
props.onSelection?.([item.value]);
props.onClose?.();
}}
></ListItem>
>
{selected ? (
<div
style={{
height: 10,
width: 10,
backgroundColor: "var(--primary)",
borderRadius: 10,
}}
></div>
) : (
<></>
)}
</ListItem>
);
})}
</List>

View File

@@ -41,7 +41,7 @@ export const MAX_SIDEBAR_WIDTH = 500;
export const MIN_SIDEBAR_WIDTH = 230;
export const NARROW_SIDEBAR_WIDTH = 100;
export const ACCESS_CODE_PREFIX = "ak-";
export const ACCESS_CODE_PREFIX = "nk-";
export const LAST_INPUT_KEY = "last-input";
@@ -108,24 +108,7 @@ export const DEFAULT_MODELS = [
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 const CHAT_PAGE_SIZE = 15;
export const MAX_RENDER_MSG_COUNT = 45;

1
app/icons/drag.svg Normal file
View 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 transform="translate(0 0) rotate(0)" xlink:href="#path_0"></use></mask><g mask="url(#bg-mask-0)" ><path id="路径 1" fill-rule="evenodd" style="fill:#333333" opacity="1" d="M6.33663,3.33c0,0.74 -0.6,1.34 -1.34,1.34c-0.73,0 -1.33,-0.6 -1.33,-1.34c0,-0.73 0.6,-1.33 1.33,-1.33c0.74,0 1.34,0.6 1.34,1.33zM4.99663,9.33c-0.73,0 -1.33,-0.59 -1.33,-1.33c0,-0.74 0.6,-1.33 1.33,-1.33c0.74,0 1.34,0.59 1.34,1.33c0,0.74 -0.6,1.33 -1.34,1.33zM4.99663,14c-0.73,0 -1.33,-0.6 -1.33,-1.33c0,-0.74 0.6,-1.34 1.33,-1.34c0.74,0 1.34,0.6 1.34,1.34c0,0.73 -0.6,1.33 -1.34,1.33z"></path><path id="路径 2" fill-rule="evenodd" style="fill:#333333" opacity="1" d="M12.3366,3.33c0,0.74 -0.6,1.34 -1.34,1.34c-0.73,0 -1.32997,-0.6 -1.32997,-1.34c0,-0.73 0.59997,-1.33 1.32997,-1.33c0.74,0 1.34,0.6 1.34,1.33zM10.9966,9.33c-0.73,0 -1.32997,-0.59 -1.32997,-1.33c0,-0.74 0.59997,-1.33 1.32997,-1.33c0.74,0 1.34,0.59 1.34,1.33c0,0.74 -0.6,1.33 -1.34,1.33zM10.9966,14c-0.73,0 -1.32997,-0.6 -1.32997,-1.33c0,-0.74 0.59997,-1.34 1.32997,-1.34c0.74,0 1.34,0.6 1.34,1.34c0,0.73 -0.6,1.33 -1.34,1.33z"></path></g></g><defs><rect id="path_0" x="0" y="0" width="16" height="16" /></defs></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -3,8 +3,9 @@ import "./styles/globals.scss";
import "./styles/markdown.scss";
import "./styles/highlight.scss";
import { getClientConfig } from "./config/client";
import { type Metadata } from "next";
export const metadata = {
export const metadata: Metadata = {
title: "ChatGPT Next Web",
description: "Your personal ChatGPT Chat Bot.",
viewport: {

View File

@@ -110,6 +110,11 @@ const ar: PartialLocaleType = {
Title: "حجم الخط",
SubTitle: "ضبط حجم الخط لمحتوى الدردشة",
},
InjectSystemPrompts: {
Title: "حقن تلميحات النظام",
SubTitle:
"قم بإضافة تلميحة نظام محاكاة ChatGPT إلى بداية قائمة الرسائل المُطلَبة في كل طلب",
},
InputTemplate: {
Title: "نموذج الإدخال",
SubTitle: "سيتم ملء أحدث رسالة في هذا النموذج",

View File

@@ -135,7 +135,11 @@ const bn: PartialLocaleType = {
Title: "ফন্ট সাইজ",
SubTitle: "চ্যাট সামগ্রীর ফন্ট সাইজ সংশোধন করুন",
},
InjectSystemPrompts: {
Title: "حقن تلميحات النظام",
SubTitle:
"قم بإضافة تلميحة نظام محاكاة ChatGPT إلى بداية قائمة الرسائل المُطلَبة في كل طلب",
},
InputTemplate: {
Title: "ইনপুট টেমপ্লেট",
SubTitle: "নতুনতম বার্তা এই টেমপ্লেটে পূরণ হবে",

View File

@@ -1,10 +1,14 @@
import { getClientConfig } from "../config/client";
import { SubmitKey } from "../store/config";
const isApp = !!getClientConfig()?.isApp;
const cn = {
WIP: "该功能仍在开发中……",
Error: {
Unauthorized:
"访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码,或者在[设置](/#/settings)页填入你自己的 OpenAI API Key。",
Unauthorized: isApp
? "检测到无效 API Key请前往[设置](/#/settings)页检查 API Key 是否配置正确。"
: "访问密码不正确或为空,请前往[登录](/#/auth)页输入正确的访问密码,或者在[设置](/#/settings)页填入你自己的 OpenAI API Key。",
},
Auth: {
Title: "需要密码",
@@ -18,6 +22,13 @@ const cn = {
},
Chat: {
SubTitle: (count: number) => `${count} 条对话`,
EditMessage: {
Title: "编辑消息记录",
Topic: {
Title: "聊天主题",
SubTitle: "更改当前聊天主题",
},
},
Actions: {
ChatList: "查看消息列表",
CompressedHistory: "查看压缩后的历史 Prompt",
@@ -139,7 +150,10 @@ const cn = {
Title: "字体大小",
SubTitle: "聊天内容的字体大小",
},
InjectSystemPrompts: {
Title: "注入系统级提示信息",
SubTitle: "强制给每次请求的消息列表开头添加一个模拟 ChatGPT 的系统提示",
},
InputTemplate: {
Title: "用户输入预处理",
SubTitle: "用户最新的一条消息会填充到此模板",
@@ -160,6 +174,10 @@ const cn = {
Title: "预览气泡",
SubTitle: "在预览气泡中预览 Markdown 内容",
},
AutoGenerateTitle: {
Title: "自动生成标题",
SubTitle: "根据对话内容生成合适的标题",
},
Mask: {
Splash: {
Title: "面具启动页",
@@ -265,7 +283,7 @@ const cn = {
Context: {
Toast: (x: any) => `包含 ${x} 条预设提示词`,
Edit: "当前对话设置",
Add: "新增预设对话",
Add: "新增一条对话",
Clear: "上下文已清除",
Revert: "恢复上下文",
},
@@ -323,6 +341,11 @@ const cn = {
More: "查看全部",
},
URLCommand: {
Code: "检测到链接中已经包含访问码,是否自动填入?",
Settings: "检测到链接中包含了预制设置,是否自动填入?",
},
UI: {
Confirm: "确认",
Cancel: "取消",

View File

@@ -5,7 +5,7 @@ const cs: PartialLocaleType = {
WIP: "V přípravě...",
Error: {
Unauthorized:
"Neoprávněný přístup, zadejte přístupový kód na stránce nastavení.",
"Neoprávněný přístup, zadejte přístupový kód na [stránce](/#/auth) nastavení.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} zpráv`,
@@ -71,6 +71,11 @@ const cs: PartialLocaleType = {
Title: "Velikost písma",
SubTitle: "Nastavení velikosti písma obsahu chatu",
},
InjectSystemPrompts: {
Title: "Vložit systémové prompty",
SubTitle:
"Vynutit přidání simulovaného systémového promptu ChatGPT na začátek seznamu zpráv každého požadavku",
},
Update: {
Version: (x: string) => `Verze: ${x}`,
IsLatest: "Aktuální verze",

View File

@@ -5,7 +5,7 @@ const de: PartialLocaleType = {
WIP: "In Bearbeitung...",
Error: {
Unauthorized:
"Unbefugter Zugriff, bitte geben Sie den Zugangscode auf der Einstellungsseite ein.",
"Unbefugter Zugriff, bitte geben Sie den Zugangscode auf der [Einstellungsseite](/#/auth) ein.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} Nachrichten`,
@@ -71,6 +71,11 @@ const de: PartialLocaleType = {
Title: "Schriftgröße",
SubTitle: "Schriftgröße des Chat-Inhalts anpassen",
},
InjectSystemPrompts: {
Title: "System-Prompts einfügen",
SubTitle:
"Erzwingt das Hinzufügen eines simulierten systemweiten Prompts von ChatGPT am Anfang der Nachrichtenliste bei jeder Anfrage",
},
Update: {
Version: (x: string) => `Version: ${x}`,
IsLatest: "Neueste Version",

View File

@@ -1,12 +1,16 @@
import { getClientConfig } from "../config/client";
import { SubmitKey } from "../store/config";
import { LocaleType } from "./index";
// if you are adding a new translation, please use PartialLocaleType instead of LocaleType
const isApp = !!getClientConfig()?.isApp;
const en: LocaleType = {
WIP: "Coming Soon...",
Error: {
Unauthorized:
"Unauthorized access, please enter access code in [auth](/#/auth) page.",
Unauthorized: isApp
? "Invalid API Key, please check it in [Settings](/#/settings) page."
: "Unauthorized access, please enter access code in [auth](/#/auth) page, or enter your OpenAI API Key.",
},
Auth: {
Title: "Need Access Code",
@@ -20,6 +24,13 @@ const en: LocaleType = {
},
Chat: {
SubTitle: (count: number) => `${count} messages`,
EditMessage: {
Title: "Edit All Messages",
Topic: {
Title: "Topic",
SubTitle: "Change the current topic",
},
},
Actions: {
ChatList: "Go To Chat List",
CompressedHistory: "Compressed History Memory Prompt",
@@ -141,7 +152,10 @@ const en: LocaleType = {
Title: "Font Size",
SubTitle: "Adjust font size of chat content",
},
InjectSystemPrompts: {
Title: "Inject System Prompts",
SubTitle: "Inject a global system prompt for every request",
},
InputTemplate: {
Title: "Input Template",
SubTitle: "Newest message will be filled to this template",
@@ -162,6 +176,10 @@ const en: LocaleType = {
Title: "Send Preview Bubble",
SubTitle: "Preview markdown in bubble",
},
AutoGenerateTitle: {
Title: "Auto Generate Title",
SubTitle: "Generate a suitable title based on the conversation content",
},
Mask: {
Splash: {
Title: "Mask Splash Screen",
@@ -341,6 +359,11 @@ const en: LocaleType = {
Topic: "Topic",
Time: "Time",
},
URLCommand: {
Code: "Detected access code from url, confirm to apply? ",
Settings: "Detected settings from url, confirm to apply?",
},
};
export default en;

View File

@@ -5,7 +5,7 @@ const es: PartialLocaleType = {
WIP: "En construcción...",
Error: {
Unauthorized:
"Acceso no autorizado, por favor ingrese el código de acceso en la página de configuración.",
"Acceso no autorizado, por favor ingrese el código de acceso en la [página](/#/auth) de configuración.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} mensajes`,
@@ -71,6 +71,11 @@ const es: PartialLocaleType = {
Title: "Tamaño de fuente",
SubTitle: "Ajustar el tamaño de fuente del contenido del chat",
},
InjectSystemPrompts: {
Title: "Inyectar Prompts del Sistema",
SubTitle:
"Agregar forzosamente un prompt de sistema simulado de ChatGPT al comienzo de la lista de mensajes en cada solicitud",
},
Update: {
Version: (x: string) => `Versión: ${x}`,
IsLatest: "Última versión",

View File

@@ -5,7 +5,7 @@ const fr: PartialLocaleType = {
WIP: "Prochainement...",
Error: {
Unauthorized:
"Accès non autorisé, veuillez saisir le code d'accès dans la page des paramètres.",
"Accès non autorisé, veuillez saisir le code d'accès dans la [page](/#/auth) des paramètres.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} messages en total`,
@@ -111,6 +111,11 @@ const fr: PartialLocaleType = {
Title: "Taille des polices",
SubTitle: "Ajuste la taille de police du contenu de la conversation",
},
InjectSystemPrompts: {
Title: "Injecter des invites système",
SubTitle:
"Ajoute de force une invite système simulée de ChatGPT au début de la liste des messages pour chaque demande",
},
InputTemplate: {
Title: "Template",
SubTitle: "Le message le plus récent sera ajouté à ce template.",

View File

@@ -116,3 +116,13 @@ export function changeLang(lang: Lang) {
setItem(LANG_KEY, lang);
location.reload();
}
export function getISOLang() {
const isoLangString: Record<string, string> = {
cn: "zh-Hans",
tw: "zh-Hant",
};
const lang = getLang();
return isoLangString[lang] ?? lang;
}

View File

@@ -5,7 +5,7 @@ const it: PartialLocaleType = {
WIP: "Work in progress...",
Error: {
Unauthorized:
"Accesso non autorizzato, inserire il codice di accesso nella pagina delle impostazioni.",
"Accesso non autorizzato, inserire il codice di accesso nella [pagina](/#/auth) delle impostazioni.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} messaggi`,
@@ -71,6 +71,11 @@ const it: PartialLocaleType = {
Title: "Dimensione carattere",
SubTitle: "Regolare la dimensione dei caratteri del contenuto della chat",
},
InjectSystemPrompts: {
Title: "Inserisci Prompts di Sistema",
SubTitle:
"Aggiungi forzatamente un prompt di sistema simulato di ChatGPT all'inizio della lista dei messaggi per ogni richiesta",
},
Update: {
Version: (x: string) => `Versione: ${x}`,
IsLatest: "Ultima versione",

View File

@@ -84,6 +84,11 @@ const jp: PartialLocaleType = {
Title: "フォントサイズ",
SubTitle: "チャット内容のフォントサイズ",
},
InjectSystemPrompts: {
Title: "システムプロンプトの挿入",
SubTitle:
"各リクエストのメッセージリストの先頭に、ChatGPTのシステムプロンプトを強制的に追加します",
},
InputTemplate: {
Title: "入力の前処理",
SubTitle: "新規入力がこのテンプレートに埋め込まれます",

View File

@@ -5,7 +5,8 @@ import type { PartialLocaleType } from "./index";
const ko: PartialLocaleType = {
WIP: "곧 출시 예정...",
Error: {
Unauthorized: "권한이 없습니다. 설정 페이지에서 액세스 코드를 입력하세요.",
Unauthorized:
"권한이 없습니다. 설정 페이지에서 액세스 코드를 [입력하세요](/#/auth).",
},
ChatItem: {
ChatItemCount: (count: number) => `${count}개의 메시지`,
@@ -71,6 +72,11 @@ const ko: PartialLocaleType = {
Title: "글꼴 크기",
SubTitle: "채팅 내용의 글꼴 크기 조정",
},
InjectSystemPrompts: {
Title: "시스템 프롬프트 주입",
SubTitle:
"각 요청의 메시지 목록의 시작에 ChatGPT 시스템 프롬프트를 강제로 추가합니다",
},
Update: {
Version: (x: string) => `버전: ${x}`,
IsLatest: "최신 버전",

View File

@@ -4,7 +4,8 @@ import type { PartialLocaleType } from "./index";
const no: PartialLocaleType = {
WIP: "Arbeid pågår ...",
Error: {
Unauthorized: "Du har ikke tilgang. Vennlig oppgi tildelt adgangskode.",
Unauthorized:
"Du har ikke tilgang. [Vennlig oppgi tildelt adgangskode](/#/auth).",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} meldinger`,
@@ -65,6 +66,11 @@ const no: PartialLocaleType = {
Title: "Fontstørrelsen",
SubTitle: "Juster fontstørrelsen for samtaleinnholdet.",
},
InjectSystemPrompts: {
Title: "Sett inn systemprompter",
SubTitle:
"Tving tillegg av en simulert ChatGPT-systemprompt i begynnelsen av meldingslisten for hver forespørsel",
},
Update: {
Version: (x: string) => `Versjon: ${x}`,
IsLatest: "Siste versjon",

View File

@@ -5,7 +5,7 @@ const ru: PartialLocaleType = {
WIP: "Скоро...",
Error: {
Unauthorized:
"Несанкционированный доступ. Пожалуйста, введите код доступа на странице настроек.",
"Несанкционированный доступ. Пожалуйста, введите код доступа на [странице](/#/auth) настроек.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} сообщений`,
@@ -71,6 +71,11 @@ const ru: PartialLocaleType = {
Title: "Размер шрифта",
SubTitle: "Настроить размер шрифта контента чата",
},
InjectSystemPrompts: {
Title: "Вставить системные подсказки",
SubTitle:
"Принудительно добавить симулированную системную подсказку ChatGPT в начало списка сообщений для каждого запроса",
},
Update: {
Version: (x: string) => `Версия: ${x}`,
IsLatest: "Последняя версия",

View File

@@ -5,7 +5,7 @@ const tr: PartialLocaleType = {
WIP: "Çalışma devam ediyor...",
Error: {
Unauthorized:
"Yetkisiz erişim, lütfen erişim kodunu ayarlar sayfasından giriniz.",
"Yetkisiz erişim, lütfen erişim kodunu ayarlar [sayfasından](/#/auth) giriniz.",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} mesaj`,
@@ -71,6 +71,11 @@ const tr: PartialLocaleType = {
Title: "Yazı Boyutu",
SubTitle: "Sohbet içeriğinin yazı boyutunu ayarlayın",
},
InjectSystemPrompts: {
Title: "Sistem İpucu Ekleyin",
SubTitle:
"Her istek için ileti listesinin başına simüle edilmiş bir ChatGPT sistem ipucu ekleyin",
},
Update: {
Version: (x: string) => `Sürüm: ${x}`,
IsLatest: "En son sürüm",

View File

@@ -4,7 +4,7 @@ import type { PartialLocaleType } from "./index";
const tw: PartialLocaleType = {
WIP: "該功能仍在開發中……",
Error: {
Unauthorized: "目前您的狀態是未授權,請前往設定頁面輸入授權碼。",
Unauthorized: "目前您的狀態是未授權,請前往[設定頁面](/#/auth)輸入授權碼。",
},
ChatItem: {
ChatItemCount: (count: number) => `${count} 條對話`,
@@ -20,7 +20,7 @@ const tw: PartialLocaleType = {
Retry: "重試",
Delete: "刪除",
},
Rename: "重命名對話",
Rename: "重命名對話",
Typing: "正在輸入…",
Input: (submitKey: string) => {
var inputHints = `輸入訊息後,按下 ${submitKey} 鍵即可發送`;
@@ -31,8 +31,8 @@ const tw: PartialLocaleType = {
},
Send: "發送",
Config: {
Reset: "重置默认",
SaveAs: "另存为面具",
Reset: "重置預設",
SaveAs: "另存新檔",
},
},
Export: {
@@ -62,13 +62,17 @@ const tw: PartialLocaleType = {
Lang: {
Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language`
All: "所有言",
All: "所有言",
},
Avatar: "大頭貼",
FontSize: {
Title: "字型大小",
SubTitle: "聊天內容的字型大小",
},
InjectSystemPrompts: {
Title: "匯入系統提示",
SubTitle: "強制在每個請求的訊息列表開頭添加一個模擬 ChatGPT 的系統提示",
},
Update: {
Version: (x: string) => `當前版本:${x}`,
IsLatest: "已是最新版本",
@@ -82,12 +86,12 @@ const tw: PartialLocaleType = {
TightBorder: "緊湊邊框",
SendPreviewBubble: {
Title: "預覽氣泡",
SubTitle: "在预览气泡中预览 Markdown 内容",
SubTitle: "在預覽氣泡中預覽 Markdown 内容",
},
Mask: {
Splash: {
Title: "面具启动页",
SubTitle: "新聊天时,展示面具启动页",
Title: "面具啟動頁面",
SubTitle: "新聊天時,呈現面具啟動頁面",
},
},
Prompt: {
@@ -105,7 +109,7 @@ const tw: PartialLocaleType = {
Search: "搜尋提示詞",
},
EditModal: {
Title: "编辑提示",
Title: "編輯提示",
},
},
HistoryCount: {
@@ -175,53 +179,53 @@ const tw: PartialLocaleType = {
Edit: "前置上下文和歷史記憶",
Add: "新增一條",
},
Plugin: { Name: "插件" },
Plugin: { Name: "外掛" },
Mask: {
Name: "面具",
Page: {
Title: "预设角色面具",
SubTitle: (count: number) => `${count} 个预设角色定`,
Search: "搜角色面具",
Create: "新",
Title: "預設角色面具",
SubTitle: (count: number) => `${count} 個預設角色定`,
Search: "搜角色面具",
Create: "新",
},
Item: {
Info: (count: number) => `包含 ${count} 条预设对话`,
Chat: "对话",
Info: (count: number) => `包含 ${count} 條預設對話`,
Chat: "對話",
View: "查看",
Edit: "编辑",
Edit: "編輯",
Delete: "删除",
DeleteConfirm: "确认删除?",
DeleteConfirm: "確認删除?",
},
EditModal: {
Title: (readonly: boolean) =>
`编辑预设面具 ${readonly ? "(只读)" : ""}`,
Download: "下载预设",
Clone: "克隆预设",
`編輯預設面具 ${readonly ? "(只读)" : ""}`,
Download: "下載預設",
Clone: "克隆預設",
},
Config: {
Avatar: "角色像",
Name: "角色名",
Avatar: "角色像",
Name: "角色名",
},
},
NewChat: {
Return: "返回",
Skip: "跳",
Title: "挑选一个面具",
SubTitle: "现在开始,面具背后的灵魂思碰撞",
More: "搜更多",
NotShow: "不再展示",
ConfirmNoShow: "确认禁用?禁用可以随时在设置中重新用。",
Skip: "跳",
Title: "挑選一個面具",
SubTitle: "現在開始,面具背後的靈魂思碰撞",
More: "搜更多",
NotShow: "不再呈現",
ConfirmNoShow: "確認禁用?禁用可以随時在設定中重新用。",
},
UI: {
Confirm: "确认",
Confirm: "確認",
Cancel: "取消",
Close: "关闭",
Create: "新",
Edit: "编辑",
Close: "關閉",
Create: "新",
Edit: "編輯",
},
Exporter: {
Model: "模型",
Messages: "息",
Messages: "息",
Topic: "主題",
Time: "時間",
},

View File

@@ -71,6 +71,11 @@ const vi: PartialLocaleType = {
Title: "Font chữ",
SubTitle: "Thay đổi font chữ của nội dung trò chuyện",
},
InjectSystemPrompts: {
Title: "Tiêm Prompt Hệ thống",
SubTitle:
"Bắt buộc thêm một prompt hệ thống giả lập ChatGPT ở đầu danh sách tin nhắn cho mỗi yêu cầu",
},
Update: {
Version: (x: string) => `Phiên bản: ${x}`,
IsLatest: "Phiên bản mới nhất",

View File

@@ -1,6 +1,6 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
import { DEFAULT_API_HOST, StoreKey } from "../constant";
import { DEFAULT_API_HOST, DEFAULT_MODELS, StoreKey } from "../constant";
import { getHeaders } from "../client/api";
import { BOT_HELLO } from "./chat";
import { getClientConfig } from "../config/client";
@@ -11,8 +11,10 @@ export interface AccessControlStore {
needCode: boolean;
hideUserApiKey: boolean;
openaiUrl: string;
hideBalanceQuery: boolean;
disableGPT4: boolean;
openaiUrl: string;
updateToken: (_: string) => void;
updateCode: (_: string) => void;
@@ -35,8 +37,10 @@ export const useAccessStore = create<AccessControlStore>()(
accessCode: "",
needCode: true,
hideUserApiKey: false,
openaiUrl: DEFAULT_OPENAI_URL,
hideBalanceQuery: false,
disableGPT4: false,
openaiUrl: DEFAULT_OPENAI_URL,
enabledAccessControl() {
get().fetch();
@@ -44,13 +48,13 @@ export const useAccessStore = create<AccessControlStore>()(
return get().needCode;
},
updateCode(code: string) {
set(() => ({ accessCode: code }));
set(() => ({ accessCode: code?.trim() }));
},
updateToken(token: string) {
set(() => ({ token }));
set(() => ({ token: token?.trim() }));
},
updateOpenAiUrl(url: string) {
set(() => ({ openaiUrl: url }));
set(() => ({ openaiUrl: url?.trim() }));
},
isAuthorized() {
get().fetch();
@@ -75,8 +79,10 @@ export const useAccessStore = create<AccessControlStore>()(
console.log("[Config] got config from server", res);
set(() => ({ ...res }));
if ((res as any).botHello) {
BOT_HELLO.content = (res as any).botHello;
if (res.disableGPT4) {
DEFAULT_MODELS.forEach(
(m: any) => (m.available = !m.name.startsWith("gpt-4")),
);
}
})
.catch(() => {

View File

@@ -289,7 +289,6 @@ export const useChatStore = create<ChatStore>()(
const botMessage: ChatMessage = createMessage({
role: "assistant",
streaming: true,
id: userMessage.id! + 1,
model: modelConfig.model,
});
@@ -333,7 +332,7 @@ export const useChatStore = create<ChatStore>()(
},
onError(error) {
const isAborted = error.message.includes("aborted");
botMessage.content =
botMessage.content +=
"\n\n" +
prettyObject({
error: true,
@@ -387,8 +386,7 @@ export const useChatStore = create<ChatStore>()(
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 shouldInjectSystemPrompts = modelConfig.enableInjectSystemPrompts;
const systemPrompts = shouldInjectSystemPrompts
? [
createMessage({
@@ -481,6 +479,7 @@ export const useChatStore = create<ChatStore>()(
},
summarizeSession() {
const config = useAppConfig.getState();
const session = get().currentSession();
// remove error messages if any
@@ -489,6 +488,7 @@ export const useChatStore = create<ChatStore>()(
// should summarize topic after chating more than 50 words
const SUMMARIZE_MIN_LEN = 50;
if (
config.enableAutoGenerateTitle &&
session.topic === DEFAULT_TOPIC &&
countMessages(messages) >= SUMMARIZE_MIN_LEN
) {
@@ -555,7 +555,7 @@ export const useChatStore = create<ChatStore>()(
date: "",
}),
),
config: { ...modelConfig, stream: true },
config: { ...modelConfig, stream: true, model: "gpt-3.5-turbo" },
onUpdate(message) {
session.memoryPrompt = message;
},
@@ -591,7 +591,7 @@ export const useChatStore = create<ChatStore>()(
}),
{
name: StoreKey.Chat,
version: 3,
version: 3.1,
migrate(persistedState, version) {
const state = persistedState as any;
const newState = JSON.parse(JSON.stringify(state)) as ChatStore;
@@ -619,6 +619,23 @@ export const useChatStore = create<ChatStore>()(
});
}
// Enable `enableInjectSystemPrompts` attribute for old sessions.
// Resolve issue of old sessions not automatically enabling.
if (version < 3.1) {
newState.sessions.forEach((s) => {
if (
// Exclude those already set by user
!s.mask.modelConfig.hasOwnProperty("enableInjectSystemPrompts")
) {
// Because users may have changed this configuration,
// the user's current configuration is used instead of the default
const config = useAppConfig.getState();
s.mask.modelConfig.enableInjectSystemPrompts =
config.modelConfig.enableInjectSystemPrompts;
}
});
}
return newState;
},
},

View File

@@ -27,6 +27,7 @@ export const DEFAULT_CONFIG = {
theme: Theme.Auto as Theme,
tightBorder: !!getClientConfig()?.isApp,
sendPreviewBubble: true,
enableAutoGenerateTitle: true,
sidebarWidth: 300,
disablePromptHint: false,
@@ -47,6 +48,7 @@ export const DEFAULT_CONFIG = {
sendMemory: true,
historyMessageCount: 4,
compressMessageLengthThreshold: 1000,
enableInjectSystemPrompts: true,
template: DEFAULT_INPUT_TEMPLATE,
},
};
@@ -80,7 +82,7 @@ export const ModalConfigValidator = {
return x as ModelType;
},
max_tokens(x: number) {
return limitNumber(x, 0, 32000, 2000);
return limitNumber(x, 0, 100000, 2000);
},
presence_penalty(x: number) {
return limitNumber(x, -2, 2, 0);
@@ -146,7 +148,7 @@ export const useAppConfig = create<ChatConfigStore>()(
}),
{
name: StoreKey.Config,
version: 3.5,
version: 3.7,
migrate(persistedState, version) {
const state = persistedState as ChatConfig;
@@ -165,6 +167,14 @@ export const useAppConfig = create<ChatConfigStore>()(
state.customModels = "claude,claude-100k";
}
if (version < 3.6) {
state.modelConfig.enableInjectSystemPrompts = true;
}
if (version < 3.7) {
state.enableAutoGenerateTitle = true;
}
return state as any;
},
},

View File

@@ -109,7 +109,7 @@ export const useMaskStore = create<MaskStore>()(
}),
{
name: StoreKey.Mask,
version: 3,
version: 3.1,
migrate(state, version) {
const newState = JSON.parse(JSON.stringify(state)) as MaskState;
@@ -119,6 +119,14 @@ export const useMaskStore = create<MaskStore>()(
Object.values(newState.masks).forEach((m) => (m.id = nanoid()));
}
if (version < 3.1) {
const updatedMasks: Record<string, Mask> = {};
Object.values(newState.masks).forEach((m) => {
updatedMasks[m.id] = m;
});
newState.masks = updatedMasks;
}
return newState as any;
},
},

View File

@@ -89,7 +89,7 @@
html {
height: var(--full-height);
font-family: "Noto Sans SC", "SF Pro SC", "SF Pro Text", "SF Pro Icons",
font-family: "Noto Sans", "SF Pro SC", "SF Pro Text", "SF Pro Icons",
"PingFang SC", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
@@ -105,6 +105,7 @@ body {
align-items: center;
user-select: none;
touch-action: pan-x pan-y;
overflow: hidden;
@media only screen and (max-width: 600px) {
background-color: var(--second);

View File

@@ -0,0 +1,38 @@
# Cloudflare Pages 導入ガイド
## 新規プロジェクトの作成方法
GitHub でこのプロジェクトをフォークし、dash.cloudflare.com にログインして Pages にアクセスします。
1. "Create a project" をクリックする。
2. "Connect to Git" を選択する。
3. Cloudflare Pages を GitHub アカウントに接続します。
4. フォークしたプロジェクトを選択します。
5. "Begin setup" をクリックする。
6. "Project name" と "Production branch" はデフォルト値を使用するか、必要に応じて変更してください。
7. "Build Settings" で、"Framework presets" オプションを選択し、"Next.js" を選択します。
8. node:buffer のバグのため、デフォルトの "Build command" は使用しないでください。代わりに、以下のコマンドを使用してください:
```
npx https://prerelease-registry.devprod.cloudflare.dev/next-on-pages/runs/4930842298/npm-package-next-on-pages-230 --experimental-minify
```
9. "Build output directory" はデフォルト値を使用し、変更しない。
10. "Root Directory" を変更しない。
11. "Environment variables" は、">" をクリックし、"Add variable" をクリックします。そして以下の情報を入力します:
- `NODE_VERSION=20.1`
- `NEXT_TELEMETRY_DISABLE=1`
- `OPENAI_API_KEY=your_own_API_key`
- `YARN_VERSION=1.22.19`
- `PHP_VERSION=7.4`
必要に応じて、以下の項目を入力してください:
- `CODE= Optional, access passwords, multiple passwords can be separated by commas`
- `OPENAI_ORG_ID= Optional, specify the organization ID in OpenAI`
- `HIDE_USER_API_KEY=1 Optional, do not allow users to enter their own API key`
- `DISABLE_GPT4=1 Optional, do not allow users to use GPT-4`
12. "Save and Deploy" をクリックする。
13. 互換性フラグを記入する必要があるため、"Cancel deployment" をクリックする。
14. "Build settings" の "Functions" から "Compatibility flags" を見つける。
15. "Configure Production compatibility flag" と "Configure Preview compatibility flag" の両方に "nodejs_compat "を記入する。
16. "Deployments" に移動し、"Retry deployment" をクリックします。
17. お楽しみください。

View File

@@ -39,7 +39,7 @@ Docker 版本相当于稳定版latest Docker 总是与 latest release version
> 相关讨论:[#386](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/386)
如果你使用 ngnix 反向代理,需要在配置文件中增加下列代码:
如果你使用 nginx 反向代理,需要在配置文件中增加下列代码:
```
# 不缓存,支持流式输出
@@ -212,7 +212,8 @@ OpenAI 网站计费说明https://openai.com/pricing#language-models
OpenAI 根据 token 数收费1000 个 token 通常可代表 750 个英文单词,或 500 个汉字。输入Prompt和输出Completion分别统计费用。
|模型|用户输入Prompt计费|模型输出Completion计费|每次交互最大 token 数|
|----|----|----|----|
|gpt-3.5|$0.002 / 1 千 tokens|$0.002 / 1 千 tokens|4096|
|gpt-3.5-turbo|$0.0015 / 1 千 tokens|$0.002 / 1 千 tokens|4096|
|gpt-3.5-turbo-16K|$0.003 / 1 千 tokens|$0.004 / 1 千 tokens|16384|
|gpt-4|$0.03 / 1 千 tokens|$0.06 / 1 千 tokens|8192|
|gpt-4-32K|$0.06 / 1 千 tokens|$0.12 / 1 千 tokens|32768|

View File

@@ -39,7 +39,7 @@ Esta es su contraseña de acceso personalizada, puede elegir:
> Debates relacionados:[#386](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/386)
Si utiliza el proxy inverso ngnix, debe agregar el siguiente código al archivo de configuración:
Si utiliza el proxy inverso nginx, debe agregar el siguiente código al archivo de configuración:
# 不缓存,支持流式输出
proxy_cache off; # 关闭缓存

191
docs/faq-ja.md Normal file
View File

@@ -0,0 +1,191 @@
# よくある質問
## 早く助けを求めるには?
1. ChatGPT / Bing / Baidu / Google などに尋ねてください。
2. オンラインの友達に聞く。背景情報と問題の詳細な説明を提供してください。質の高い質問ほど、有益な回答を得られる可能性が高くなります。
# デプロイメントに関する質問
## なぜ Docker のデプロイバージョンは常に更新を要求するのか
Docker のバージョンは安定版と同等であり、最新の Docker は常に最新のリリースバージョンと一致しています。現在、私たちのリリース頻度は12日に1回なので、Dockerのバージョンは常に最新のコミットから12日遅れており、これは予想されることです。
## Vercel での展開方法
1. GitHub アカウントを登録し、このプロジェクトをフォークする。
2. Vercel を登録し携帯電話認証が必要、中国の番号でも可、GitHub アカウントを接続する。
3. Vercel で新規プロジェクトを作成し、GitHub でフォークしたプロジェクトを選択し、必要な環境変数を入力し、デプロイを開始する。デプロイ後、Vercel が提供するドメインからプロジェクトにアクセスできます。(中国本土ではプロキシが必要)
- 中国で直接アクセスする必要がある場合: DNS プロバイダーで、cname.vercel-dns.com を指すドメイン名の CNAME レコードを追加します。その後、Vercel でドメインアクセスを設定してください。
## Vercel 環境変数の変更方法
- Vercel のコンソールページに入ります;
- chatgpt-next-web プロジェクトを選択してください;
- ページ上部の設定オプションをクリックしてください;
- サイドバーで環境変数オプションを見つけます;
- 必要に応じて対応する値を変更してください。
## 環境変数 CODE とは何ですか?設定する必要がありますか?
カスタムアクセスパスワードです:
1. 設定しないで、環境変数を削除する。この時、誰でもあなたのプロジェクトにアクセスすることができます。
2. プロジェクトをデプロイするときに、環境変数 CODE を設定する(カンマ区切りで複数のパスワードをサポート)。アクセスパスワードを設定した後、ユーザーはそれを使用するために設定ページでアクセスパスワードを入力する必要があります。[関連手順](https://github.com/Yidadaa/ChatGPT-Next-Web#access-password)
## なぜ私がデプロイしたバージョンにはストリーミングレスポンスがないのでしょうか?
> 関連する議論: [#386](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/386)
nginx のリバースプロキシを使っている場合、設定ファイルに以下のコードを追加する必要があります:
```
# キャッシュなし、ストリーミング出力をサポート
proxy_cache off; # キャッシュをオフにする
proxy_buffering off; # プロキシバッファリングをオフにする
chunked_transfer_encoding on; # チャンク転送エンコーディングをオンにする
tcp_nopush on; # TCP NOPUSH オプションをオンにし、Nagleアルゴリズムを無効にする
tcp_nodelay on; # TCP NODELAY オプションをオンにし、遅延ACKアルゴリズムを無効にする
keepalive_timeout 300; # keep-alive のタイムアウトを 65 秒に設定する
```
netlify でデプロイしている場合、この問題はまだ解決待ちです。
## デプロイしましたが、アクセスできません。
以下の問題を確認し、トラブルシューティングを行ってください:
- サービスは開始されていますか?
- ポートは正しくマッピングされていますか?
- ファイアウォールのポートは開いていますか?
- サーバーへのルートは問題ありませんか?
- ドメイン名は正しく解決されていますか?
## "Error: Loading CSS chunk xxx failed..." と表示されることがあります。
Next.js では、最初のホワイトスクリーンの時間を短縮するために、デフォルトでチャンキングを有効にしています。技術的な詳細はこちらをご覧ください:
- 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
ただし、Next.js は古いブラウザとの互換性に制限があるため、このエラーが発生することがあります。
ビルド時にチャンキングを無効にすることができます。
Vercel プラットフォームの場合は、環境変数に `DISABLE_CHUNK=1` を追加して再デプロイします。
セルフデプロイのプロジェクトでは、ビルド時に `DISABLE_CHUNK=1 yarn build` を使用することができます。
Docker ユーザーの場合、ビルドはパッケージング時にすでに完了しているため、この機能を無効にすることは現在サポートされていません。
この機能を無効にすると、ユーザーの最初の訪問時にすべてのリソースがロードされることに注意してください。その結果、ユーザーのネットワーク接続が悪い場合、ホワイト・スクリーンの時間が長くなり、ユーザーエクスペリエンスに影響を与える可能性があります。この点を考慮の上、ご判断ください。
# 使用法に関する質問
## なぜいつも "An error occurred, please try again later" と表示されるのですか?
様々な原因が考えられますので、以下の項目を順番にチェックしてみてください:
- まず、コードのバージョンが最新版かどうかを確認し、最新版にアップデートしてから再試行してください;
- api キーが正しく設定されているか確認してください。環境変数名は大文字とアンダースコアでなければなりません;
- api キーが使用可能かどうか確認する;
- 上記のステップを踏んでも問題が解決しない場合は、issue エリアに新しい issue を投稿し、vercel のランタイムログまたは docker のランタイムログを添付してください。
## ChatGPT の返信が文字化けするのはなぜですか?
設定画面-機種設定の中に `temperature` という項目があります。この値が 1 より大きい場合、返信が文字化けすることがあります。1 以内に調整してください。
## 設定ページでアクセスパスワードを入力してください」と表示される。
プロジェクトでは環境変数 CODE でアクセスパスワードを設定しています。初めて使うときは、設定ページでアクセスコードを入力する必要があります。
## 使用すると、"You exceeded your current quota, ..." と表示される。
API KEY に問題があります。残高不足です。
## プロキシとは何ですか?
OpenAI の IP 制限により、中国をはじめとする一部の国や地域では、OpenAI API に直接接続することができず、プロキシを経由する必要があります。プロキシサーバ(フォワードプロキシ)を利用するか、事前に設定された OpenAI API リバースプロキシを利用します。
- フォワードプロキシの例: VPN ラダー。docker デプロイの場合は、環境変数 HTTP_PROXY にプロキシアドレス (http://address:port) を設定します。
- リバースプロキシの例: 他人のプロキシアドレスを使うか、Cloudflare を通じて無料で設定できる。プロジェクトの環境変数 BASE_URL にプロキシアドレスを設定してください。
## 中国のサーバーにデプロイできますか?
可能ですが、対処すべき問題があります:
- GitHub や OpenAI などのウェブサイトに接続するにはプロキシが必要です;
- GitHub や OpenAI のようなウェブサイトに接続するにはプロキシが必要です;
- 中国の政策により、海外のウェブサイト/ChatGPT 関連アプリケーションへのプロキシアクセスが制限されており、ブロックされる可能性があります。
# ネットワークサービス関連の質問
## クラウドフレアとは何ですか?
CloudflareCFは、CDN、ドメイン管理、静的ページホスティング、エッジコンピューティング機能展開などを提供するネットワークサービスプロバイダーです。一般的な使用例: メインの購入やホスティング(解決、ダイナミックドメインなど)、サーバーへの CDN の適用(ブロックされないように IP を隠すことができる、ウェブサイトCF Pagesの展開。CF はほとんどのサービスを無料で提供しています。
## Vercel とは?
Vercel はグローバルなクラウドプラットフォームで、開発者がモダンなウェブアプリケーションをより迅速に構築、デプロイできるように設計されています。このプロジェクトや多くのウェブアプリケーションは、ワンクリックで Vercel 上に無料でデプロイできます。コードを理解する必要も、Linux を理解する必要も、サーバーを持つ必要も、お金を払う必要も、OpenAI API プロキシを設定する必要もありません。欠点は、中国の制限なしにアクセスするためにドメイン名をバインドする必要があることだ。
## ドメイン名の取得方法
1. Namesiloアリペイ対応や Cloudflare海外プロバイダー、Wanwang中国国内プロバイダーなどのドメインプロバイダーに登録する。
2. 無料ドメインプロバイダー: eu.orgセカンドレベルドメインなど。
3. 無料セカンドレベルドメインを友人に頼む。
## サーバーの取得方法
- 海外サーバープロバイダーの例 Amazon Web Services、Google Cloud、Vultr、Bandwagon、Hostdare など。
海外サーバーの注意点 サーバー回線は中国でのアクセス速度に影響するため、CN2 GIA、CN2 回線を推奨。もしサーバーが中国でアクセスしにくい場合深刻なパケットロスなど、CDNCloudflare のようなプロバイダーのもの)を使ってみるとよいでしょう。
- 国内のサーバープロバイダー アリババクラウド、テンセントなど
国内サーバーの注意点 ドメイン名の解決にはファイリングが必要。国内サーバーの帯域幅は比較的高い。海外のウェブサイトGitHub、OpenAI など)へのアクセスにはプロキシが必要。
# OpenAI 関連の質問
## OpenAI のアカウントを登録するには?
chat.openai.com にアクセスして登録してください。以下のものが必要です:
- 優れた VPN (OpenAI はサポートされている地域のネイティブ IP アドレスしか許可しません)
- サポートされているメール (例: Gmail や会社/学校のメール。Outlook や QQ のメールは不可)
- SMS 認証を受ける方法SMS-activate ウェブサイトなど)
## OpenAI API を有効にするにはAPI 残高の確認方法は?
公式ウェブサイトVPN が必要): https://platform.openai.com/account/usage
VPN なしで残高を確認するためにプロキシを設定しているユーザーもいます。API キーの漏洩を避けるため、信頼できる情報源であることを確認してください。
## OpenAI の新規アカウントに API 残高がないのはなぜですか?
(4月6日更新) 新規登録アカウントは通常 24 時間以内に API 残高が表示されます。現在、新規アカウントには 5 ドルの残高が与えられています。
## OpenAI API へのチャージ方法を教えてください。
OpenAI では、指定された地域のクレジットカードのみご利用いただけます(中国のクレジットカードはご利用いただけません)。お住まいの地域のクレジットカードに対応していない場合は、以下の方法があります:
1. Depay バーチャルクレジットカード
2. 海外のクレジットカードを申し込む
3. オンラインでトップアップしてくれる人を探す
## GPT-4 API にアクセスするには?
(4月6日更新) GPT-4 API へのアクセスには別途申請が必要です。以下のアドレスにアクセスし、ウェイティングリストに参加するための情報を入力してくださいOpenAI の組織 ID をご用意ください): https://openai.com/waitlist/gpt-4-api
その後、メールの更新をお待ちください。
## Azure OpenAI インターフェースの使い方
次を参照: [#371](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/371)
## トークンの消費が速いのはなぜですか?
> 関連する議論: [#518](https://github.com/Yidadaa/ChatGPT-Next-Web/issues/518)
- GPT-4 にアクセスし、GPT-4 の API を定期的に使用している場合、GPT-4 の価格は GPT-3.5 の約 15 倍であるため、請求額が急激に増加します;
- GPT-3.5 を使用しており、頻繁に使用していないにもかかわらず、請求額が急速に増加している場合は、以下の手順で直ちにトラブルシューティングを行ってください:
- OpenAI のウェブサイトで API キーの消費記録を確認してください。トークンが 1 時間ごとに消費され、毎回数万トークンが消費される場合は、キーが流出している可能性があります。すぐに削除して再生成してください。**適当なサイトで残高を確認しないでください。**
- パスワードが 5 文字以下など短い場合、ブルートフォースによるコストは非常に低くなります。誰かが大量のパスワードの組み合わせを試したかどうかを確認するために、docker のログを検索することを推奨する。キーワード:アクセスコードの取得
- これら 2 つの方法を実行することで、トークンが急速に消費された原因を突き止めることができます:
- OpenAI の消費記録に異常があるが、Docker ログに問題がない場合、API キーが流出したことを意味します;
- Docker ログにアクセスコード取得のブルートフォース試行回数が多い場合は、パスワードがクラックされています。

48
docs/vercel-ja.md Normal file
View File

@@ -0,0 +1,48 @@
# Vercel 使用説明書
## 新規プロジェクトの作成方法
このプロジェクトを GitHub からフォークし、Vercel で新しい Vercel プロジェクトを作成して再デプロイする必要がある場合は、以下の手順に従ってください。
![vercel-create-1](./images/vercel/vercel-create-1.jpg)
1. Vercel コンソールのホームページにアクセスします;
2. 新規追加をクリックする;
3. プロジェクトを選択します。
![vercel-create-2](./images/vercel/vercel-create-2.jpg)
1. Git リポジトリのインポートで、chatgpt-next-web を検索します;
2 .新しいフォークプロジェクトを選択し、インポートをクリックします。
![vercel-create-3](./images/vercel/vercel-create-3.jpg)
1. Project Settings ページで、Environment Variables をクリックして環境変数を設定する;
2. OPENAI_API_KEY と CODE という名前の環境変数を追加します;
3. 環境変数に対応する値を入力します;
4. Add をクリックして、環境変数の追加を確認する;
5. OPENAI_API_KEY を必ず追加してください;
6. Deploy をクリックして作成し、デプロイが完了するまで約 5 分間辛抱強く待つ。
## カスタムドメイン名の追加方法
\[TODO]
## 環境変数の変更方法
![vercel-env-edit](./images/vercel/vercel-env-edit.jpg)
1. 内部 Vercel プロジェクトコンソールに移動し、上部の設定ボタンをクリックします;
2. 左側の Environment Variables をクリックします;
3. 既存のエントリーの右側のボタンをクリックします;
4. 編集を選択して編集し、保存する。
⚠️️ 注意: [プロジェクトの再デプロイ](#再実装の方法)環境変数を変更するたびに、変更を有効にするために必要です!
## 再実装の方法
![vercel-redeploy](./images/vercel/vercel-redeploy.jpg)
1. Vercelプロジェクトの内部コンソールに移動し、一番上のDeploymentsボタンをクリックします;
2. リストの一番上の項目の右のボタンを選択します;
3. 再デプロイをクリックして再デプロイします。

View File

@@ -30,6 +30,9 @@ const nextConfig = {
images: {
unoptimized: mode === "export",
},
experimental: {
forceSwcTransforms: true,
},
};
if (mode !== "export") {

View File

@@ -25,12 +25,12 @@
"html-to-image": "^1.11.11",
"mermaid": "^10.2.3",
"nanoid": "^4.0.2",
"next": "^13.4.6",
"next": "^13.4.9",
"node-fetch": "^3.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.10.0",
"react-router-dom": "^6.14.1",
"rehype-highlight": "^6.0.0",
"rehype-katex": "^6.0.3",
"remark-breaks": "^3.0.2",
@@ -42,14 +42,14 @@
"zustand": "^4.3.8"
},
"devDependencies": {
"@tauri-apps/cli": "^1.3.1",
"@tauri-apps/cli": "^1.4.0",
"@types/node": "^20.3.3",
"@types/react": "^18.2.12",
"@types/react-dom": "^18.0.11",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.7",
"@types/react-katex": "^3.0.0",
"@types/spark-md5": "^3.0.2",
"cross-env": "^7.0.3",
"eslint": "^8.36.0",
"eslint": "^8.44.0",
"eslint-config-next": "13.2.3",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",

View File

@@ -9,7 +9,7 @@
},
"package": {
"productName": "ChatGPT Next Web",
"version": "2.8.9"
"version": "2.9.4"
},
"tauri": {
"allowlist": {

397
yarn.lock
View File

@@ -2,6 +2,11 @@
# yarn lockfile v1
"@aashutoshrathi/word-wrap@^1.2.3":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
"@ampproject/remapping@^2.2.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
@@ -1012,14 +1017,14 @@
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724"
integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==
"@eslint/eslintrc@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02"
integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==
"@eslint/eslintrc@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.0.tgz#82256f164cc9e0b59669efc19d57f8092706841d"
integrity sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^9.5.1"
espree "^9.6.0"
globals "^13.19.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
@@ -1027,10 +1032,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@8.37.0":
version "8.37.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.37.0.tgz#cf1b5fa24217fe007f6487a26d765274925efa7d"
integrity sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==
"@eslint/js@8.44.0":
version "8.44.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.44.0.tgz#961a5903c74139390478bdc808bcde3fc45ab7af"
integrity sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==
"@fortaine/fetch-event-source@^3.0.6":
version "3.0.6"
@@ -1050,10 +1055,10 @@
redux "^4.2.1"
use-memo-one "^1.1.3"
"@humanwhocodes/config-array@^0.11.8":
version "0.11.8"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==
"@humanwhocodes/config-array@^0.11.10":
version "0.11.10"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==
dependencies:
"@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
@@ -1126,10 +1131,10 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"
"@next/env@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.6.tgz#3f2041c7758660d7255707ae4cb9166519113dea"
integrity sha512-nqUxEtvDqFhmV1/awSg0K2XHNwkftNaiUqCYO9e6+MYmqNObpKVl7OgMkGaQ2SZnFx5YqF0t60ZJTlyJIDAijg==
"@next/env@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.9.tgz#b77759514dd56bfa9791770755a2482f4d6ca93e"
integrity sha512-vuDRK05BOKfmoBYLNi2cujG2jrYbEod/ubSSyqgmEx9n/W3eZaJQdRNhTfumO+qmq/QTzLurW487n/PM/fHOkw==
"@next/eslint-plugin-next@13.2.3":
version "13.2.3"
@@ -1138,50 +1143,50 @@
dependencies:
glob "7.1.7"
"@next/swc-darwin-arm64@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.6.tgz#47485f3deaee6681b4a4036c74bb9c4b728d5ddd"
integrity sha512-ahi6VP98o4HV19rkOXPSUu+ovfHfUxbJQ7VVJ7gL2FnZRr7onEFC1oGQ6NQHpm8CxpIzSSBW79kumlFMOmZVjg==
"@next/swc-darwin-arm64@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.9.tgz#0ed408d444bbc6b0a20f3506a9b4222684585677"
integrity sha512-TVzGHpZoVBk3iDsTOQA/R6MGmFp0+17SWXMEWd6zG30AfuELmSSMe2SdPqxwXU0gbpWkJL1KgfLzy5ReN0crqQ==
"@next/swc-darwin-x64@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.6.tgz#a6a5b232ec0f2079224fb8ed6bf11dc479af1acf"
integrity sha512-13cXxKFsPJIJKzUqrU5XB1mc0xbUgYsRcdH6/rB8c4NMEbWGdtD4QoK9ShN31TZdePpD4k416Ur7p+deMIxnnA==
"@next/swc-darwin-x64@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.9.tgz#a08fccdee68201522fe6618ec81f832084b222f8"
integrity sha512-aSfF1fhv28N2e7vrDZ6zOQ+IIthocfaxuMWGReB5GDriF0caTqtHttAvzOMgJgXQtQx6XhyaJMozLTSEXeNN+A==
"@next/swc-linux-arm64-gnu@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.6.tgz#2a67144e863d9c45fdbd13c7827370e7f2a28405"
integrity sha512-Ti+NMHEjTNktCVxNjeWbYgmZvA2AqMMI2AMlzkXsU7W4pXCMhrryAmAIoo+7YdJbsx01JQWYVxGe62G6DoCLaA==
"@next/swc-linux-arm64-gnu@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.9.tgz#1798c2341bb841e96521433eed00892fb24abbd1"
integrity sha512-JhKoX5ECzYoTVyIy/7KykeO4Z2lVKq7HGQqvAH+Ip9UFn1MOJkOnkPRB7v4nmzqAoY+Je05Aj5wNABR1N18DMg==
"@next/swc-linux-arm64-musl@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.6.tgz#5a191ac3575a70598e9e9c6e7264fc0b8a90b2db"
integrity sha512-OHoC6gO7XfjstgwR+z6UHKlvhqJfyMtNaJidjx3sEcfaDwS7R2lqR5AABi8PuilGgi0BO0O0sCXqLlpp3a0emQ==
"@next/swc-linux-arm64-musl@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.9.tgz#cee04c51610eddd3638ce2499205083656531ea0"
integrity sha512-OOn6zZBIVkm/4j5gkPdGn4yqQt+gmXaLaSjRSO434WplV8vo2YaBNbSHaTM9wJpZTHVDYyjzuIYVEzy9/5RVZw==
"@next/swc-linux-x64-gnu@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.6.tgz#d38adf842a8b8f9de492454328fd32a2c53350f3"
integrity sha512-zHZxPGkUlpfNJCboUrFqwlwEX5vI9LSN70b8XEb0DYzzlrZyCyOi7hwDp/+3Urm9AB7YCAJkgR5Sp1XBVjHdfQ==
"@next/swc-linux-x64-gnu@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.9.tgz#1932d0367916adbc6844b244cda1d4182bd11f7a"
integrity sha512-iA+fJXFPpW0SwGmx/pivVU+2t4zQHNOOAr5T378PfxPHY6JtjV6/0s1vlAJUdIHeVpX98CLp9k5VuKgxiRHUpg==
"@next/swc-linux-x64-musl@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.6.tgz#74c745774358b78be7f958e7a8b7d93936cd6ebc"
integrity sha512-K/Y8lYGTwTpv5ME8PSJxwxLolaDRdVy+lOd9yMRMiQE0BLUhtxtCWC9ypV42uh9WpLjoaD0joOsB9Q6mbrSGJg==
"@next/swc-linux-x64-musl@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.9.tgz#a66aa8c1383b16299b72482f6360facd5cde3c7a"
integrity sha512-rlNf2WUtMM+GAQrZ9gMNdSapkVi3koSW3a+dmBVp42lfugWVvnyzca/xJlN48/7AGx8qu62WyO0ya1ikgOxh6A==
"@next/swc-win32-arm64-msvc@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.6.tgz#1e1e02c175573e64808fc1a7e8650e3e217f1edc"
integrity sha512-U6LtxEUrjBL2tpW+Kr1nHCSJWNeIed7U7l5o7FiKGGwGgIlFi4UHDiLI6TQ2lxi20fAU33CsruV3U0GuzMlXIw==
"@next/swc-win32-arm64-msvc@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.9.tgz#39482ee856c867177a612a30b6861c75e0736a4a"
integrity sha512-5T9ybSugXP77nw03vlgKZxD99AFTHaX8eT1ayKYYnGO9nmYhJjRPxcjU5FyYI+TdkQgEpIcH7p/guPLPR0EbKA==
"@next/swc-win32-ia32-msvc@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.6.tgz#2b528ae3ec7f6e727f4f0d81a1015f63da55c7a6"
integrity sha512-eEBeAqpCfhdPSlCZCayjCiyIllVqy4tcqvm1xmg3BgJG0G5ITiMM4Cw2WVeRSgWDJqQGRyyb+q8Y2ltzhXOWsQ==
"@next/swc-win32-ia32-msvc@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.9.tgz#29db85e34b597ade1a918235d16a760a9213c190"
integrity sha512-ojZTCt1lP2ucgpoiFgrFj07uq4CZsq4crVXpLGgQfoFq00jPKRPgesuGPaz8lg1yLfvafkU3Jd1i8snKwYR3LA==
"@next/swc-win32-x64-msvc@13.4.6":
version "13.4.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.6.tgz#38620bd68267ff13e50ecd432f1822eac51382a8"
integrity sha512-OrZs94AuO3ZS5tnqlyPRNgfWvboXaDQCi5aXGve3o3C+Sj0ctMUV9+Do+0zMvvLRumR8E0PTWKvtz9n5vzIsWw==
"@next/swc-win32-x64-msvc@13.4.9":
version "13.4.9"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.9.tgz#0c2758164cccd61bc5a1c6cd8284fe66173e4a2b"
integrity sha512-QbT03FXRNdpuL+e9pLnu+XajZdm/TtIXVYY4lA9t+9l0fLZbHXDYEKitAqxrOj37o3Vx5ufxiRAniaIebYDCgw==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@@ -1216,10 +1221,10 @@
tiny-glob "^0.2.9"
tslib "^2.4.0"
"@remix-run/router@1.5.0":
version "1.5.0"
resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.5.0.tgz#57618e57942a5f0131374a9fdb0167e25a117fdc"
integrity sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==
"@remix-run/router@1.7.1":
version "1.7.1"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.1.tgz#fea7ac35ae4014637c130011f59428f618730498"
integrity sha512-bgVQM4ZJ2u2CM8k1ey70o1ePFXsEzYVZoWghh6WjM8p59jQ7HxzbHW4SbnWFG7V9ig9chLawQxDTZ3xzOF8MkQ==
"@rushstack/eslint-patch@^1.1.3":
version "1.2.0"
@@ -1339,65 +1344,71 @@
dependencies:
tslib "^2.4.0"
"@tauri-apps/cli-darwin-arm64@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.3.1.tgz#ef0fe290e0a6e3e53fa2cc4f1a72a0c87921427c"
integrity sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==
"@tauri-apps/cli-darwin-arm64@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz#e76bb8515ae31f03f2cbd440c1a09b237a79b3ac"
integrity sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==
"@tauri-apps/cli-darwin-x64@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.3.1.tgz#4c84ea0f08a5b636b067943d637a38e091a4aad3"
integrity sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg==
"@tauri-apps/cli-darwin-x64@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz#dd1472460550d0aa0ec6e699b073be2d77e5b962"
integrity sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==
"@tauri-apps/cli-linux-arm-gnueabihf@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.3.1.tgz#a4f1b237189e4f8f89cc890e1dc2eec76d4345be"
integrity sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA==
"@tauri-apps/cli-linux-arm-gnueabihf@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz#325e90e47d260ba71a499850ce769b5a6bdfd48d"
integrity sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==
"@tauri-apps/cli-linux-arm64-gnu@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.3.1.tgz#e2391326b64dfe13c7442bdcc13c4988ce5e6df9"
integrity sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw==
"@tauri-apps/cli-linux-arm64-gnu@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz#b5d8f5cba3f8f7c7d44d071681f0ab0a37f2c46e"
integrity sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==
"@tauri-apps/cli-linux-arm64-musl@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.3.1.tgz#49354349f80f879ffc6950c0c03c0aea1395efa5"
integrity sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ==
"@tauri-apps/cli-linux-arm64-musl@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz#f805ab2ee415875900f4b456f17dc4900d2a7911"
integrity sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==
"@tauri-apps/cli-linux-x64-gnu@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.3.1.tgz#9a33ffe9e0d9b1b3825db57cbcfcddeb773682c6"
integrity sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ==
"@tauri-apps/cli-linux-x64-gnu@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz#d3f5e69c22420c7ac9e4021b7a94bce2e48cb45d"
integrity sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==
"@tauri-apps/cli-linux-x64-musl@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.3.1.tgz#5283731e894c17bc070c499e73145cfe2633ef21"
integrity sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA==
"@tauri-apps/cli-linux-x64-musl@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz#2e7f718272ffdd9ace80f57a35023ba0c74767ad"
integrity sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==
"@tauri-apps/cli-win32-ia32-msvc@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.3.1.tgz#f31538abfd94f27ade1f17d01f30da6be1660c6f"
integrity sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ==
"@tauri-apps/cli-win32-arm64-msvc@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz#85cdb52a06feb92da785def4d02512099464525e"
integrity sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==
"@tauri-apps/cli-win32-x64-msvc@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.3.1.tgz#1eb09d55b99916a3cd84cb91c75ef906db67d35d"
integrity sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA==
"@tauri-apps/cli-win32-ia32-msvc@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz#0b7c921204058215aec9a5a00f735e73909bd330"
integrity sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==
"@tauri-apps/cli@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.3.1.tgz#4c5259bf1f9c97084dd016e6b34dca53de380e24"
integrity sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ==
"@tauri-apps/cli-win32-x64-msvc@1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz#23abe3f08c0df89111c29602f91c21a23577b908"
integrity sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==
"@tauri-apps/cli@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@tauri-apps/cli/-/cli-1.4.0.tgz#72732ae61e6b7d097e44a8a2ef5f211b2d01d98b"
integrity sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==
optionalDependencies:
"@tauri-apps/cli-darwin-arm64" "1.3.1"
"@tauri-apps/cli-darwin-x64" "1.3.1"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.3.1"
"@tauri-apps/cli-linux-arm64-gnu" "1.3.1"
"@tauri-apps/cli-linux-arm64-musl" "1.3.1"
"@tauri-apps/cli-linux-x64-gnu" "1.3.1"
"@tauri-apps/cli-linux-x64-musl" "1.3.1"
"@tauri-apps/cli-win32-ia32-msvc" "1.3.1"
"@tauri-apps/cli-win32-x64-msvc" "1.3.1"
"@tauri-apps/cli-darwin-arm64" "1.4.0"
"@tauri-apps/cli-darwin-x64" "1.4.0"
"@tauri-apps/cli-linux-arm-gnueabihf" "1.4.0"
"@tauri-apps/cli-linux-arm64-gnu" "1.4.0"
"@tauri-apps/cli-linux-arm64-musl" "1.4.0"
"@tauri-apps/cli-linux-x64-gnu" "1.4.0"
"@tauri-apps/cli-linux-x64-musl" "1.4.0"
"@tauri-apps/cli-win32-arm64-msvc" "1.4.0"
"@tauri-apps/cli-win32-ia32-msvc" "1.4.0"
"@tauri-apps/cli-win32-x64-msvc" "1.4.0"
"@trysound/sax@0.2.0":
version "0.2.0"
@@ -1494,10 +1505,10 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
"@types/react-dom@^18.0.11":
version "18.0.11"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33"
integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==
"@types/react-dom@^18.2.7":
version "18.2.7"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63"
integrity sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==
dependencies:
"@types/react" "*"
@@ -1508,10 +1519,10 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.2.12":
version "18.2.12"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.12.tgz#95d584338610b78bb9ba0415e3180fb03debdf97"
integrity sha512-ndmBMLCgn38v3SntMeoJaIrO6tGHYKMEBohCUmw8HoLLQdRMOIGXfeYaBTLe2lsFaSB3MOK1VXscYFnmLtTSmw==
"@types/react@*", "@types/react@^18.2.14":
version "18.2.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127"
integrity sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
@@ -1732,10 +1743,10 @@ acorn@^8.7.1, acorn@^8.8.2:
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59"
integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==
acorn@^8.8.0:
version "8.8.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
acorn@^8.9.0:
version "8.10.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
aggregate-error@^3.0.0:
version "3.1.0"
@@ -2007,12 +2018,7 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449:
version "1.0.30001473"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz#3859898b3cab65fc8905bb923df36ad35058153c"
integrity sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==
caniuse-lite@^1.0.30001503:
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001449, 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==
@@ -2999,29 +3005,29 @@ eslint-scope@5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
eslint-scope@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
eslint-scope@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b"
integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc"
integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==
eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
eslint@^8.36.0:
version "8.37.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.37.0.tgz#1f660ef2ce49a0bfdec0b0d698e0b8b627287412"
integrity sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==
eslint@^8.44.0:
version "8.44.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.44.0.tgz#51246e3889b259bbcd1d7d736a0c10add4f0e500"
integrity sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.4.0"
"@eslint/eslintrc" "^2.0.2"
"@eslint/js" "8.37.0"
"@humanwhocodes/config-array" "^0.11.8"
"@eslint/eslintrc" "^2.1.0"
"@eslint/js" "8.44.0"
"@humanwhocodes/config-array" "^0.11.10"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
ajv "^6.10.0"
@@ -3030,9 +3036,9 @@ eslint@^8.36.0:
debug "^4.3.2"
doctrine "^3.0.0"
escape-string-regexp "^4.0.0"
eslint-scope "^7.1.1"
eslint-visitor-keys "^3.4.0"
espree "^9.5.1"
eslint-scope "^7.2.0"
eslint-visitor-keys "^3.4.1"
espree "^9.6.0"
esquery "^1.4.2"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
@@ -3040,32 +3046,31 @@ eslint@^8.36.0:
find-up "^5.0.0"
glob-parent "^6.0.2"
globals "^13.19.0"
grapheme-splitter "^1.0.4"
graphemer "^1.4.0"
ignore "^5.2.0"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
is-path-inside "^3.0.3"
js-sdsl "^4.1.4"
js-yaml "^4.1.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash.merge "^4.6.2"
minimatch "^3.1.2"
natural-compare "^1.4.0"
optionator "^0.9.1"
optionator "^0.9.3"
strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
text-table "^0.2.0"
espree@^9.5.1:
version "9.5.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4"
integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==
espree@^9.6.0:
version "9.6.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f"
integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==
dependencies:
acorn "^8.8.0"
acorn "^8.9.0"
acorn-jsx "^5.3.2"
eslint-visitor-keys "^3.4.0"
eslint-visitor-keys "^3.4.1"
esquery@^1.4.2:
version "1.5.0"
@@ -3402,10 +3407,10 @@ graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
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==
grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2"
@@ -3858,11 +3863,6 @@ jest-worker@^27.4.5:
merge-stream "^2.0.0"
supports-color "^8.0.0"
js-sdsl@^4.1.4:
version "4.4.0"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -4654,12 +4654,12 @@ neo-async@^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:
version "13.4.6"
resolved "https://registry.yarnpkg.com/next/-/next-13.4.6.tgz#ebe52f5c74d60176d45b45e73f25a51103713ea4"
integrity sha512-sjVqjxU+U2aXZnYt4Ud6CTLNNwWjdSfMgemGpIQJcN3Z7Jni9xRWbR0ie5fQzCg87aLqQVhKA2ud2gPoqJ9lGw==
next@^13.4.9:
version "13.4.9"
resolved "https://registry.yarnpkg.com/next/-/next-13.4.9.tgz#473de5997cb4c5d7a4fb195f566952a1cbffbeba"
integrity sha512-vtefFm/BWIi/eWOqf1GsmKG3cjKw1k3LjuefKRcL3iiLl3zWzFdPG3as6xtxrGO6gwTzzaO1ktL4oiHt/uvTjA==
dependencies:
"@next/env" "13.4.6"
"@next/env" "13.4.9"
"@swc/helpers" "0.5.1"
busboy "1.6.0"
caniuse-lite "^1.0.30001406"
@@ -4668,15 +4668,15 @@ next@^13.4.6:
watchpack "2.4.0"
zod "3.21.4"
optionalDependencies:
"@next/swc-darwin-arm64" "13.4.6"
"@next/swc-darwin-x64" "13.4.6"
"@next/swc-linux-arm64-gnu" "13.4.6"
"@next/swc-linux-arm64-musl" "13.4.6"
"@next/swc-linux-x64-gnu" "13.4.6"
"@next/swc-linux-x64-musl" "13.4.6"
"@next/swc-win32-arm64-msvc" "13.4.6"
"@next/swc-win32-ia32-msvc" "13.4.6"
"@next/swc-win32-x64-msvc" "13.4.6"
"@next/swc-darwin-arm64" "13.4.9"
"@next/swc-darwin-x64" "13.4.9"
"@next/swc-linux-arm64-gnu" "13.4.9"
"@next/swc-linux-arm64-musl" "13.4.9"
"@next/swc-linux-x64-gnu" "13.4.9"
"@next/swc-linux-x64-musl" "13.4.9"
"@next/swc-win32-arm64-msvc" "13.4.9"
"@next/swc-win32-ia32-msvc" "13.4.9"
"@next/swc-win32-x64-msvc" "13.4.9"
node-domexception@^1.0.0:
version "1.0.0"
@@ -4824,17 +4824,17 @@ open@^8.4.0:
is-docker "^2.1.1"
is-wsl "^2.2.0"
optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
optionator@^0.9.3:
version "0.9.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
dependencies:
"@aashutoshrathi/word-wrap" "^1.2.3"
deep-is "^0.1.3"
fast-levenshtein "^2.0.6"
levn "^0.4.1"
prelude-ls "^1.2.1"
type-check "^0.4.0"
word-wrap "^1.2.3"
p-limit@^3.0.2:
version "3.1.0"
@@ -5039,20 +5039,20 @@ react-redux@^8.1.1:
react-is "^18.0.0"
use-sync-external-store "^1.0.0"
react-router-dom@^6.10.0:
version "6.10.0"
resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.10.0.tgz#090ddc5c84dc41b583ce08468c4007c84245f61f"
integrity sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==
react-router-dom@^6.14.1:
version "6.14.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.14.1.tgz#0ad7ba7abdf75baa61169d49f096f0494907a36f"
integrity sha512-ssF6M5UkQjHK70fgukCJyjlda0Dgono2QGwqGvuk7D+EDGHdacEN3Yke2LTMjkrpHuFwBfDFsEjGVXBDmL+bWw==
dependencies:
"@remix-run/router" "1.5.0"
react-router "6.10.0"
"@remix-run/router" "1.7.1"
react-router "6.14.1"
react-router@6.10.0:
version "6.10.0"
resolved "https://registry.npmmirror.com/react-router/-/react-router-6.10.0.tgz#230f824fde9dd0270781b5cb497912de32c0a971"
integrity sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==
react-router@6.14.1:
version "6.14.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.14.1.tgz#5e82bcdabf21add859dc04b1859f91066b3a5810"
integrity sha512-U4PfgvG55LdvbQjg5Y9QRWyVxIdO1LlpYT7x+tMAxd9/vmiPuJhIwdxZuIQLN/9e3O4KFDHYfR9gzGeYMasW8g==
dependencies:
"@remix-run/router" "1.5.0"
"@remix-run/router" "1.7.1"
react@^18.2.0:
version "18.2.0"
@@ -5322,14 +5322,14 @@ schema-utils@^3.1.1, schema-utils@^3.2.0:
ajv-keywords "^3.5.2"
semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
version "6.3.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.3.7:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
dependencies:
lru-cache "^6.0.0"
@@ -6027,11 +6027,6 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"