Compare commits

5 Commits

Author SHA1 Message Date
Redon
0fdf75eba0 chore: version 2.9.2 (#261)
* feat: 添加  OPENAI_API_BASE_URL 可选参数[#249]

* fix: 生成的代码块不能复制的问题[#251][#260]

* perf: 限制高分屏上的宽度[#257]

* perf: 文字按单词换行[#215][#225]

* perf: highlight.js 新语法警告

* fix: 移动端输入框不会被键盘弹起[#256]

* chore: 更新文档

* chore: version 2.9.2
2023-03-04 09:34:28 +08:00
Yule Hou
2293969070 feat: add latex rendering (#247)
* feat: add latex rendering

* perf: 提升 css 引入路径

---------

Co-authored-by: ChenZhaoYu <790348264@qq.com>
2023-03-04 08:22:50 +08:00
api man
f7f87e266f feat: 支持webAPP(苹果添加到主页书签访问) (#227)
* feat: 应用自定义头像

* feat: 头像添加缺省判断

* feat: 头像缺省和响应式

* feat: 支持webAPP(苹果添加到主页书签访问)

---------

Co-authored-by: wangqy <wangqy@inketang.com>
Co-authored-by: ChenZhaoYu <790348264@qq.com>
2023-03-04 08:10:01 +08:00
ChenZhaoYu
f95af40ab8 chore: 更新文档 2023-03-03 11:59:16 +08:00
InterestingDarkness
20d6135658 Add support for SOCKS proxy in ChatGPTAPI fetch (#214) 2023-03-03 10:43:27 +08:00
21 changed files with 345 additions and 126 deletions

View File

@@ -31,6 +31,7 @@
"GPTAPI", "GPTAPI",
"hljs", "hljs",
"iconify", "iconify",
"katex",
"logprobs", "logprobs",
"nodata", "nodata",
"OPENAI", "OPENAI",

View File

@@ -1,3 +1,24 @@
## v2.9.2
`2023-03-04`
手动部署的同学,务必删除根目录和`service`中的`node_modules`重新安装依赖,降低出现问题的概率,自动部署的不需要做改动。
### Feature
- 感谢 [hyln9](https://github.com/Chanzhaoyu/chatgpt-web/pull/247) 添加对渲染 `LaTex` 数学公式的支持
- 感谢 [ottocsb](https://github.com/Chanzhaoyu/chatgpt-web/pull/227) 添加支持 `webAPP` (苹果添加到主页书签访问)支持
- 添加 `OPENAI_API_BASE_URL` 可选环境变量[#249]
## Enhancement
- 优化在高分屏上主题内容的最大宽度[#257]
- 现在文字按单词截断[#215][#225]
### BugFix
- 修复动态生成时代码块不能被复制的问题[#251][#260]
- 修复 `iOS` 移动端输入框不会被键盘顶起的问题[#256]
- 修复控制台渲染警告
## Other
- 更新依赖至最新
- 修改 `README` 内容
## v2.9.1 ## v2.9.1
`2023-03-02` `2023-03-02`

View File

@@ -2,8 +2,8 @@
> 声明:此项目只发布于 Github基于 MIT 协议,免费且作为开源学习使用。并且不会有任何形式的卖号、付费服务、讨论群、讨论组等行为。谨防受骗。 > 声明:此项目只发布于 Github基于 MIT 协议,免费且作为开源学习使用。并且不会有任何形式的卖号、付费服务、讨论群、讨论组等行为。谨防受骗。
![cover](./docs/c1-2.8.0.png) ![cover](./docs/c1.png)
![cover2](./docs/c2-2.8.0.png) ![cover2](./docs/c2.png)
- [ChatGPT Web](#chatgpt-web) - [ChatGPT Web](#chatgpt-web)
- [介绍](#介绍) - [介绍](#介绍)
@@ -36,13 +36,13 @@
支持双模型,提供了两种非官方 `ChatGPT API` 方法 支持双模型,提供了两种非官方 `ChatGPT API` 方法
| 方式 | 免费? | 可靠性 | 质量 | | 方式 | 免费? | 可靠性 | 质量 |
| ---- | ---- | ---- | ---- | | --------------------------------------------- | ------ | ---------- | ---- |
| `ChatGPTAPI(GPT-3)` | 否 | 可靠 | 较笨 | | `ChatGPTAPI(gpt-3.5-turbo-0301)` | 否 | 可靠 | 相对较笨 |
| `ChatGPTUnofficialProxyAPI(网页 accessToken)` | | 相对不可靠 | 聪明 | | `ChatGPTUnofficialProxyAPI(网页 accessToken)` | 是 | 相对不可靠 | 聪明 |
对比: 对比:
1. `ChatGPTAPI` 使用 `text-davinci-003` 通过官方`OpenAI`补全`API`模拟`ChatGPT`(最稳健的方法,但它不是免费的,并且没有使用针对聊天进行微调的模型) 1. `ChatGPTAPI` 使用 `gpt-3.5-turbo-0301` 通过官方`OpenAI`补全`API`模拟`ChatGPT`(最稳健的方法,但它不是免费的,并且没有使用针对聊天进行微调的模型)
2. `ChatGPTUnofficialProxyAPI` 使用非官方代理服务器访问 `ChatGPT` 的后端`API`,绕过`Cloudflare`(使用真实的的`ChatGPT`,非常轻量级,但依赖于第三方服务器,并且有速率限制) 2. `ChatGPTUnofficialProxyAPI` 使用非官方代理服务器访问 `ChatGPT` 的后端`API`,绕过`Cloudflare`(使用真实的的`ChatGPT`,非常轻量级,但依赖于第三方服务器,并且有速率限制)
[查看详情](https://github.com/Chanzhaoyu/chatgpt-web/issues/138) [查看详情](https://github.com/Chanzhaoyu/chatgpt-web/issues/138)
@@ -55,13 +55,21 @@
反向代理: 反向代理:
`ChatGPTUnofficialProxyAPI`时可用 [详情](https://github.com/transitive-bullshit/chatgpt-api#reverse-proxy) `ChatGPTUnofficialProxyAPI`时可用
```shell ```shell
# service/.env # service/.env
API_REVERSE_PROXY= API_REVERSE_PROXY=
``` ```
环境变量:
全部参数变量请查看或[这里](#docker-参数示例)
```
/service/.env
```
## 待实现路线 ## 待实现路线
[✓] 双模型 [✓] 双模型
@@ -145,8 +153,11 @@ pnpm dev
- `OPENAI_API_KEY` 二选一 - `OPENAI_API_KEY` 二选一
- `OPENAI_ACCESS_TOKEN` 二选一,同时存在时,`OPENAI_API_KEY` 优先 - `OPENAI_ACCESS_TOKEN` 二选一,同时存在时,`OPENAI_API_KEY` 优先
- `OPENAI_API_BASE_URL` 可选,设置 `OPENAI_API_KEY` 时可用
- `API_REVERSE_PROXY` 可选,设置 `OPENAI_ACCESS_TOKEN` 时可用 [参考](#介绍) - `API_REVERSE_PROXY` 可选,设置 `OPENAI_ACCESS_TOKEN` 时可用 [参考](#介绍)
- `TIMEOUT_MS` 超时,单位毫秒,可选 - `TIMEOUT_MS` 超时,单位毫秒,可选
- `SOCKS_PROXY_HOST` 可选,和 SOCKS_PROXY_PORT 一起时生效
- `SOCKS_PROXY_PORT` 可选,和 SOCKS_PROXY_HOST 一起时生效
![docker](./docs/docker.png) ![docker](./docs/docker.png)
@@ -182,25 +193,34 @@ services:
OPENAI_API_KEY: xxxxxx OPENAI_API_KEY: xxxxxx
# 二选一 # 二选一
OPENAI_ACCESS_TOKEN: xxxxxx OPENAI_ACCESS_TOKEN: xxxxxx
# API接口地址可选设置 OPENAI_API_KEY 时可用
OPENAI_API_BASE_URL: xxxx
# 反向代理,可选 # 反向代理,可选
API_REVERSE_PROXY: xxx API_REVERSE_PROXY: xxx
# 超时,单位毫秒,可选 # 超时,单位毫秒,可选
TIMEOUT_MS: 60000 TIMEOUT_MS: 60000
# Socks代理可选和 SOCKS_PROXY_PORT 一起时生效
SOCKS_PROXY_HOST: xxxx
# Socks代理端口可选和 SOCKS_PROXY_HOST 一起时生效
SOCKS_PROXY_PORT: xxxx
``` ```
- `OPENAI_API_BASE_URL` 可选,设置 `OPENAI_API_KEY` 时可用
### 使用 Railway 部署 ### 使用 Railway 部署
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/yytmgc) [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/yytmgc)
#### Railway 环境变量 #### Railway 环境变量
| 环境变量名称 | 必填 | 备注 | | 环境变量名称 | 必填 | 备注 |
| --------------------------- | ---- | ----------------------- | | --------------------- | ---------------------- | -------------------------------------------------------------------------------------------------- |
| `PORT` | 必填 | 默认 `3002` | | `PORT` | 必填 | 默认 `3002` |
| `TIMEOUT_MS` | 可选 | 超时时间,单位毫秒, | | `TIMEOUT_MS` | 可选 | 超时时间,单位毫秒, |
| `OPENAI_API_KEY` | `OpenAI API` 二选一 | 使用 `OpenAI API` 所需的 `apiKey` [(获取 apiKey)](https://platform.openai.com/overview) | | `OPENAI_API_KEY` | `OpenAI API` 二选一 | 使用 `OpenAI API` 所需的 `apiKey` [(获取 apiKey)](https://platform.openai.com/overview) |
| `OPENAI_ACCESS_TOKEN` | `Web API` 二选一 | 使用 `Web API` 所需的 `accessToken` [(获取 accessToken)](https://chat.openai.com/api/auth/session) | | `OPENAI_ACCESS_TOKEN` | `Web API` 二选一 | 使用 `Web API` 所需的 `accessToken` [(获取 accessToken)](https://chat.openai.com/api/auth/session) |
| `API_REVERSE_PROXY` | 可选,`Web API` 时可用 | `Web API` 反向代理地址 [详情](https://github.com/transitive-bullshit/chatgpt-api#reverse-proxy) | | `OPENAI_API_BASE_URL` | 可选,`OpenAI API` 时可用 | `API`接口地址 |
| `API_REVERSE_PROXY` | 可选,`Web API` 时可用 | `Web API` 反向代理地址 [详情](https://github.com/transitive-bullshit/chatgpt-api#reverse-proxy) |
| `SOCKS_PROXY_HOST` | 可选,和 `SOCKS_PROXY_PORT` 一起时生效 | Socks代理 |
| `SOCKS_PROXY_PORT` | 可选,和 `SOCKS_PROXY_HOST` 一起时生效 | Socks代理端口 |
> 注意: `Railway` 修改环境变量会重新 `Deploy` > 注意: `Railway` 修改环境变量会重新 `Deploy`

View File

@@ -10,10 +10,16 @@ services:
OPENAI_API_KEY: xxxx OPENAI_API_KEY: xxxx
# 二选一 # 二选一
OPENAI_ACCESS_TOKEN: xxxxxx OPENAI_ACCESS_TOKEN: xxxxxx
# API接口地址可选设置 OPENAI_API_KEY 时可用
OPENAI_API_BASE_URL: xxxx
# 反向代理,可选 # 反向代理,可选
API_REVERSE_PROXY: xxx API_REVERSE_PROXY: xxx
# 超时,单位毫秒,可选 # 超时,单位毫秒,可选
TIMEOUT_MS: 60000 TIMEOUT_MS: 60000
# Socks代理可选和 SOCKS_PROXY_PORT 一起时生效
SOCKS_PROXY_HOST: xxxx
# Socks代理端口可选和 SOCKS_PROXY_HOST 一起时生效
SOCKS_PROXY_PORT: xxxx
nginx: nginx:
build: nginx build: nginx
image: chatgpt/nginx image: chatgpt/nginx

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 KiB

View File

@@ -3,6 +3,8 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" type="image/svg+xml" href="/favicon.svg"> <link rel="icon" type="image/svg+xml" href="/favicon.svg">
<meta content="yes" name="apple-mobile-web-app-capable"/>
<link rel="apple-touch-icon" href="/favicon.ico">
<meta name="viewport" <meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" /> content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<title>ChatGPT Web</title> <title>ChatGPT Web</title>

View File

@@ -1,6 +1,6 @@
{ {
"name": "chatgpt-web", "name": "chatgpt-web",
"version": "2.9.1", "version": "2.9.2",
"private": false, "private": false,
"description": "ChatGPT Web", "description": "ChatGPT Web",
"author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>", "author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>",
@@ -25,6 +25,7 @@
"dependencies": { "dependencies": {
"@vueuse/core": "^9.13.0", "@vueuse/core": "^9.13.0",
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"katex": "^0.16.4",
"marked": "^4.2.12", "marked": "^4.2.12",
"naive-ui": "^2.34.3", "naive-ui": "^2.34.3",
"pinia": "^2.0.32", "pinia": "^2.0.32",
@@ -38,8 +39,9 @@
"@commitlint/config-conventional": "^17.4.4", "@commitlint/config-conventional": "^17.4.4",
"@iconify/vue": "^4.1.0", "@iconify/vue": "^4.1.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/katex": "^0.16.0",
"@types/marked": "^4.0.8", "@types/marked": "^4.0.8",
"@types/node": "^18.14.4", "@types/node": "^18.14.6",
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^4.0.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"axios": "^1.3.4", "axios": "^1.3.4",
@@ -50,7 +52,7 @@
"lint-staged": "^13.1.2", "lint-staged": "^13.1.2",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"postcss": "^8.4.21", "postcss": "^8.4.21",
"rimraf": "^4.1.3", "rimraf": "^4.2.0",
"tailwindcss": "^3.2.7", "tailwindcss": "^3.2.7",
"typescript": "~4.9.5", "typescript": "~4.9.5",
"vite": "^4.1.4", "vite": "^4.1.4",

97
pnpm-lock.yaml generated
View File

@@ -6,8 +6,9 @@ specifiers:
'@commitlint/config-conventional': ^17.4.4 '@commitlint/config-conventional': ^17.4.4
'@iconify/vue': ^4.1.0 '@iconify/vue': ^4.1.0
'@types/crypto-js': ^4.1.1 '@types/crypto-js': ^4.1.1
'@types/katex': ^0.16.0
'@types/marked': ^4.0.8 '@types/marked': ^4.0.8
'@types/node': ^18.14.4 '@types/node': ^18.14.6
'@vitejs/plugin-vue': ^4.0.0 '@vitejs/plugin-vue': ^4.0.0
'@vueuse/core': ^9.13.0 '@vueuse/core': ^9.13.0
autoprefixer: ^10.4.13 autoprefixer: ^10.4.13
@@ -16,6 +17,7 @@ specifiers:
eslint: ^8.35.0 eslint: ^8.35.0
highlight.js: ^11.7.0 highlight.js: ^11.7.0
husky: ^8.0.3 husky: ^8.0.3
katex: ^0.16.4
less: ^4.1.3 less: ^4.1.3
lint-staged: ^13.1.2 lint-staged: ^13.1.2
marked: ^4.2.12 marked: ^4.2.12
@@ -23,7 +25,7 @@ specifiers:
npm-run-all: ^4.1.5 npm-run-all: ^4.1.5
pinia: ^2.0.32 pinia: ^2.0.32
postcss: ^8.4.21 postcss: ^8.4.21
rimraf: ^4.1.3 rimraf: ^4.2.0
tailwindcss: ^3.2.7 tailwindcss: ^3.2.7
typescript: ~4.9.5 typescript: ~4.9.5
vite: ^4.1.4 vite: ^4.1.4
@@ -35,6 +37,7 @@ specifiers:
dependencies: dependencies:
'@vueuse/core': 9.13.0_vue@3.2.47 '@vueuse/core': 9.13.0_vue@3.2.47
highlight.js: 11.7.0 highlight.js: 11.7.0
katex: 0.16.4
marked: 4.2.12 marked: 4.2.12
naive-ui: 2.34.3_vue@3.2.47 naive-ui: 2.34.3_vue@3.2.47
pinia: 2.0.32_hmuptsblhheur2tugfgucj7gc4 pinia: 2.0.32_hmuptsblhheur2tugfgucj7gc4
@@ -48,8 +51,9 @@ devDependencies:
'@commitlint/config-conventional': 17.4.4 '@commitlint/config-conventional': 17.4.4
'@iconify/vue': 4.1.0_vue@3.2.47 '@iconify/vue': 4.1.0_vue@3.2.47
'@types/crypto-js': 4.1.1 '@types/crypto-js': 4.1.1
'@types/katex': 0.16.0
'@types/marked': 4.0.8 '@types/marked': 4.0.8
'@types/node': 18.14.4 '@types/node': 18.14.6
'@vitejs/plugin-vue': 4.0.0_vite@4.1.4+vue@3.2.47 '@vitejs/plugin-vue': 4.0.0_vite@4.1.4+vue@3.2.47
autoprefixer: 10.4.13_postcss@8.4.21 autoprefixer: 10.4.13_postcss@8.4.21
axios: 1.3.4 axios: 1.3.4
@@ -60,10 +64,10 @@ devDependencies:
lint-staged: 13.1.2 lint-staged: 13.1.2
npm-run-all: 4.1.5 npm-run-all: 4.1.5
postcss: 8.4.21 postcss: 8.4.21
rimraf: 4.1.3 rimraf: 4.2.0
tailwindcss: 3.2.7_postcss@8.4.21 tailwindcss: 3.2.7_postcss@8.4.21
typescript: 4.9.5 typescript: 4.9.5
vite: 4.1.4_752grm4nw4hff7lyew72esoj4m vite: 4.1.4_4l5pdn5ozbjpiwj3fcgseihr44
vue-tsc: 1.2.0_typescript@4.9.5 vue-tsc: 1.2.0_typescript@4.9.5
packages: packages:
@@ -289,15 +293,15 @@ packages:
'@commitlint/execute-rule': 17.4.0 '@commitlint/execute-rule': 17.4.0
'@commitlint/resolve-extends': 17.4.4 '@commitlint/resolve-extends': 17.4.4
'@commitlint/types': 17.4.4 '@commitlint/types': 17.4.4
'@types/node': 18.14.4 '@types/node': 18.14.6
chalk: 4.1.2 chalk: 4.1.2
cosmiconfig: 8.1.0 cosmiconfig: 8.1.0
cosmiconfig-typescript-loader: 4.3.0_nd25hbh3ectnnkbvturxnqqqfm cosmiconfig-typescript-loader: 4.3.0_y2okb5cfqgxv537umje5rj3w6m
lodash.isplainobject: 4.0.6 lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2 lodash.merge: 4.6.2
lodash.uniq: 4.5.0 lodash.uniq: 4.5.0
resolve-from: 5.0.0 resolve-from: 5.0.0
ts-node: 10.9.1_oboltcrkaqheaa54woelu7cdsa ts-node: 10.9.1_alpjt73dvgv6kni625hu7f2l4m
typescript: 4.9.5 typescript: 4.9.5
transitivePeerDependencies: transitivePeerDependencies:
- '@swc/core' - '@swc/core'
@@ -772,6 +776,10 @@ packages:
resolution: {integrity: sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==} resolution: {integrity: sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==}
dev: false dev: false
/@types/katex/0.16.0:
resolution: {integrity: sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==}
dev: true
/@types/lodash-es/4.17.6: /@types/lodash-es/4.17.6:
resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==}
dependencies: dependencies:
@@ -796,8 +804,8 @@ packages:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true dev: true
/@types/node/18.14.4: /@types/node/18.14.6:
resolution: {integrity: sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==} resolution: {integrity: sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==}
dev: true dev: true
/@types/normalize-package-data/2.4.1: /@types/normalize-package-data/2.4.1:
@@ -953,7 +961,7 @@ packages:
vite: ^4.0.0 vite: ^4.0.0
vue: ^3.2.25 vue: ^3.2.25
dependencies: dependencies:
vite: 4.1.4_752grm4nw4hff7lyew72esoj4m vite: 4.1.4_4l5pdn5ozbjpiwj3fcgseihr44
vue: 3.2.47 vue: 3.2.47
dev: true dev: true
@@ -1530,6 +1538,11 @@ packages:
delayed-stream: 1.0.0 delayed-stream: 1.0.0
dev: true dev: true
/commander/8.3.0:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
dev: false
/commander/9.5.0: /commander/9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14} engines: {node: ^12.20.0 || >=14}
@@ -1582,7 +1595,7 @@ packages:
is-what: 3.14.1 is-what: 3.14.1
dev: true dev: true
/cosmiconfig-typescript-loader/4.3.0_nd25hbh3ectnnkbvturxnqqqfm: /cosmiconfig-typescript-loader/4.3.0_y2okb5cfqgxv537umje5rj3w6m:
resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==} resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==}
engines: {node: '>=12', npm: '>=6'} engines: {node: '>=12', npm: '>=6'}
peerDependencies: peerDependencies:
@@ -1591,9 +1604,9 @@ packages:
ts-node: '>=10' ts-node: '>=10'
typescript: '>=3' typescript: '>=3'
dependencies: dependencies:
'@types/node': 18.14.4 '@types/node': 18.14.6
cosmiconfig: 8.1.0 cosmiconfig: 8.1.0
ts-node: 10.9.1_oboltcrkaqheaa54woelu7cdsa ts-node: 10.9.1_alpjt73dvgv6kni625hu7f2l4m
typescript: 4.9.5 typescript: 4.9.5
dev: true dev: true
@@ -2594,6 +2607,16 @@ packages:
path-is-absolute: 1.0.1 path-is-absolute: 1.0.1
dev: true dev: true
/glob/9.2.1:
resolution: {integrity: sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==}
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
fs.realpath: 1.0.0
minimatch: 7.4.2
minipass: 4.2.4
path-scurry: 1.6.1
dev: true
/global-dirs/0.1.1: /global-dirs/0.1.1:
resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -3076,6 +3099,13 @@ packages:
engines: {'0': node >= 0.2.0} engines: {'0': node >= 0.2.0}
dev: true dev: true
/katex/0.16.4:
resolution: {integrity: sha512-WudRKUj8yyBeVDI4aYMNxhx5Vhh2PjpzQw1GRu/LVGqL4m1AxwD1GcUp0IMbdJaf5zsjtj8ghP0DOQRYhroNkw==}
hasBin: true
dependencies:
commander: 8.3.0
dev: false
/kind-of/6.0.3: /kind-of/6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -3253,6 +3283,11 @@ packages:
yallist: 4.0.0 yallist: 4.0.0
dev: true dev: true
/lru-cache/7.18.1:
resolution: {integrity: sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg==}
engines: {node: '>=12'}
dev: true
/magic-string/0.25.9: /magic-string/0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
dependencies: dependencies:
@@ -3400,6 +3435,13 @@ packages:
brace-expansion: 2.0.1 brace-expansion: 2.0.1
dev: true dev: true
/minimatch/7.4.2:
resolution: {integrity: sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==}
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: true
/minimist-options/4.1.0: /minimist-options/4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@@ -3413,6 +3455,11 @@ packages:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true dev: true
/minipass/4.2.4:
resolution: {integrity: sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==}
engines: {node: '>=8'}
dev: true
/ms/2.1.2: /ms/2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true dev: true
@@ -3726,6 +3773,14 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true dev: true
/path-scurry/1.6.1:
resolution: {integrity: sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==}
engines: {node: '>=14'}
dependencies:
lru-cache: 7.18.1
minipass: 4.2.4
dev: true
/path-type/3.0.0: /path-type/3.0.0:
resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -4048,10 +4103,12 @@ packages:
glob: 7.2.3 glob: 7.2.3
dev: true dev: true
/rimraf/4.1.3: /rimraf/4.2.0:
resolution: {integrity: sha512-iyzalDLo3l5FZxxaIGUY7xI4Bf90Xt7pCipc1Mr7RsdU7H3538z+M0tlsUDrz0aHeGS9uNqiKHUJyTewwRP91Q==} resolution: {integrity: sha512-tPt+gLORNVqRCk0NwuJ5SlMEcOGvt4CCU8sUPqgCFtCbnoNCTd9Q6vq7JlBbxQlACiH14OR28y7piA2Bak9Sxw==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dependencies:
glob: 9.2.1
dev: true dev: true
/rollup/3.18.0: /rollup/3.18.0:
@@ -4422,7 +4479,7 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/ts-node/10.9.1_oboltcrkaqheaa54woelu7cdsa: /ts-node/10.9.1_alpjt73dvgv6kni625hu7f2l4m:
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@@ -4441,7 +4498,7 @@ packages:
'@tsconfig/node12': 1.0.11 '@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3 '@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.3 '@tsconfig/node16': 1.0.3
'@types/node': 18.14.4 '@types/node': 18.14.6
acorn: 8.8.2 acorn: 8.8.2
acorn-walk: 8.2.0 acorn-walk: 8.2.0
arg: 4.1.3 arg: 4.1.3
@@ -4586,7 +4643,7 @@ packages:
vue: 3.2.47 vue: 3.2.47
dev: false dev: false
/vite/4.1.4_752grm4nw4hff7lyew72esoj4m: /vite/4.1.4_4l5pdn5ozbjpiwj3fcgseihr44:
resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==} resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true hasBin: true
@@ -4611,7 +4668,7 @@ packages:
terser: terser:
optional: true optional: true
dependencies: dependencies:
'@types/node': 18.14.4 '@types/node': 18.14.6
esbuild: 0.16.17 esbuild: 0.16.17
less: 4.1.3 less: 4.1.3
postcss: 8.4.21 postcss: 8.4.21

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -4,8 +4,17 @@ OPENAI_API_KEY=
# change this to an `accessToken` extracted from the ChatGPT site's `https://chat.openai.com/api/auth/session` response # change this to an `accessToken` extracted from the ChatGPT site's `https://chat.openai.com/api/auth/session` response
OPENAI_ACCESS_TOKEN= OPENAI_ACCESS_TOKEN=
# OpenAI API Base URL - https://api.openai.com
OPENAI_API_BASE_URL=
# Reverse Proxy # Reverse Proxy
API_REVERSE_PROXY= API_REVERSE_PROXY=
# timeout # timeout
TIMEOUT_MS=100000 TIMEOUT_MS=100000
# Socks Proxy Host
SOCKS_PROXY_HOST=
# Socks Proxy Port
SOCKS_PROXY_PORT=

View File

@@ -24,7 +24,7 @@
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml" "common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml"
}, },
"dependencies": { "dependencies": {
"chatgpt": "^5.0.4", "chatgpt": "^5.0.6",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"esno": "^0.16.3", "esno": "^0.16.3",
"express": "^4.18.2", "express": "^4.18.2",
@@ -35,9 +35,9 @@
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^0.35.3", "@antfu/eslint-config": "^0.35.3",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/node": "^18.14.4", "@types/node": "^18.14.6",
"eslint": "^8.35.0", "eslint": "^8.35.0",
"rimraf": "^4.1.3", "rimraf": "^4.2.0",
"tsup": "^6.6.3", "tsup": "^6.6.3",
"typescript": "^4.9.5" "typescript": "^4.9.5"
} }

75
service/pnpm-lock.yaml generated
View File

@@ -3,21 +3,21 @@ lockfileVersion: 5.4
specifiers: specifiers:
'@antfu/eslint-config': ^0.35.3 '@antfu/eslint-config': ^0.35.3
'@types/express': ^4.17.17 '@types/express': ^4.17.17
'@types/node': ^18.14.4 '@types/node': ^18.14.6
chatgpt: ^5.0.4 chatgpt: ^5.0.6
dotenv: ^16.0.3 dotenv: ^16.0.3
eslint: ^8.35.0 eslint: ^8.35.0
esno: ^0.16.3 esno: ^0.16.3
express: ^4.18.2 express: ^4.18.2
isomorphic-fetch: ^3.0.0 isomorphic-fetch: ^3.0.0
node-fetch: ^3.3.0 node-fetch: ^3.3.0
rimraf: ^4.1.3 rimraf: ^4.2.0
socks-proxy-agent: ^7.0.0 socks-proxy-agent: ^7.0.0
tsup: ^6.6.3 tsup: ^6.6.3
typescript: ^4.9.5 typescript: ^4.9.5
dependencies: dependencies:
chatgpt: 5.0.4 chatgpt: 5.0.6
dotenv: 16.0.3 dotenv: 16.0.3
esno: 0.16.3 esno: 0.16.3
express: 4.18.2 express: 4.18.2
@@ -28,9 +28,9 @@ dependencies:
devDependencies: devDependencies:
'@antfu/eslint-config': 0.35.3_ycpbpc6yetojsgtrx3mwntkhsu '@antfu/eslint-config': 0.35.3_ycpbpc6yetojsgtrx3mwntkhsu
'@types/express': 4.17.17 '@types/express': 4.17.17
'@types/node': 18.14.4 '@types/node': 18.14.6
eslint: 8.35.0 eslint: 8.35.0
rimraf: 4.1.3 rimraf: 4.2.0
tsup: 6.6.3_typescript@4.9.5 tsup: 6.6.3_typescript@4.9.5
typescript: 4.9.5 typescript: 4.9.5
@@ -428,19 +428,19 @@ packages:
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
dependencies: dependencies:
'@types/connect': 3.4.35 '@types/connect': 3.4.35
'@types/node': 18.14.4 '@types/node': 18.14.6
dev: true dev: true
/@types/connect/3.4.35: /@types/connect/3.4.35:
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
dependencies: dependencies:
'@types/node': 18.14.4 '@types/node': 18.14.6
dev: true dev: true
/@types/express-serve-static-core/4.17.33: /@types/express-serve-static-core/4.17.33:
resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==}
dependencies: dependencies:
'@types/node': 18.14.4 '@types/node': 18.14.6
'@types/qs': 6.9.7 '@types/qs': 6.9.7
'@types/range-parser': 1.2.4 '@types/range-parser': 1.2.4
dev: true dev: true
@@ -472,8 +472,8 @@ packages:
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
dev: true dev: true
/@types/node/18.14.4: /@types/node/18.14.6:
resolution: {integrity: sha512-VhCw7I7qO2X49+jaKcAUwi3rR+hbxT5VcYF493+Z5kMLI0DL568b7JI4IDJaxWFH0D/xwmGJNoXisyX+w7GH/g==} resolution: {integrity: sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==}
dev: true dev: true
/@types/normalize-package-data/2.4.1: /@types/normalize-package-data/2.4.1:
@@ -495,7 +495,7 @@ packages:
resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==} resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==}
dependencies: dependencies:
'@types/mime': 3.0.1 '@types/mime': 3.0.1
'@types/node': 18.14.4 '@types/node': 18.14.6
dev: true dev: true
/@types/unist/2.0.6: /@types/unist/2.0.6:
@@ -816,6 +816,12 @@ packages:
concat-map: 0.0.1 concat-map: 0.0.1
dev: true dev: true
/brace-expansion/2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: true
/braces/3.0.2: /braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -896,8 +902,8 @@ packages:
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
dev: true dev: true
/chatgpt/5.0.4: /chatgpt/5.0.6:
resolution: {integrity: sha512-qkppO2IDYDJC1eaXfqupXdZcOPNqtBkToRcvr9CAGM1rdsKfBDpWLTx4Y6OMNH02sgWu48aJB//0lO1M17K58w==} resolution: {integrity: sha512-BQ0eN2GpAlw9ojsxkHmW+bTuekbllZbOkKqjDSIVSMtbMoYDx59vcg6xXnCPkB0OBFGuG89eqGhLAfMIW34Hcw==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dependencies: dependencies:
@@ -1955,6 +1961,16 @@ packages:
path-is-absolute: 1.0.1 path-is-absolute: 1.0.1
dev: true dev: true
/glob/9.2.1:
resolution: {integrity: sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==}
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
fs.realpath: 1.0.0
minimatch: 7.4.2
minipass: 4.2.4
path-scurry: 1.6.1
dev: true
/globals/13.20.0: /globals/13.20.0:
resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -2439,6 +2455,11 @@ packages:
dependencies: dependencies:
yallist: 4.0.0 yallist: 4.0.0
/lru-cache/7.18.1:
resolution: {integrity: sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg==}
engines: {node: '>=12'}
dev: true
/mdast-util-from-markdown/0.8.5: /mdast-util-from-markdown/0.8.5:
resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
dependencies: dependencies:
@@ -2534,10 +2555,22 @@ packages:
brace-expansion: 1.1.11 brace-expansion: 1.1.11
dev: true dev: true
/minimatch/7.4.2:
resolution: {integrity: sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==}
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: true
/minimist/1.2.8: /minimist/1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true dev: true
/minipass/4.2.4:
resolution: {integrity: sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==}
engines: {node: '>=8'}
dev: true
/ms/2.0.0: /ms/2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
dev: false dev: false
@@ -2804,6 +2837,14 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true dev: true
/path-scurry/1.6.1:
resolution: {integrity: sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==}
engines: {node: '>=14'}
dependencies:
lru-cache: 7.18.1
minipass: 4.2.4
dev: true
/path-to-regexp/0.1.7: /path-to-regexp/0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
dev: false dev: false
@@ -3007,10 +3048,12 @@ packages:
glob: 7.2.3 glob: 7.2.3
dev: true dev: true
/rimraf/4.1.3: /rimraf/4.2.0:
resolution: {integrity: sha512-iyzalDLo3l5FZxxaIGUY7xI4Bf90Xt7pCipc1Mr7RsdU7H3538z+M0tlsUDrz0aHeGS9uNqiKHUJyTewwRP91Q==} resolution: {integrity: sha512-tPt+gLORNVqRCk0NwuJ5SlMEcOGvt4CCU8sUPqgCFtCbnoNCTd9Q6vq7JlBbxQlACiH14OR28y7piA2Bak9Sxw==}
engines: {node: '>=14'} engines: {node: '>=14'}
hasBin: true hasBin: true
dependencies:
glob: 9.2.1
dev: true dev: true
/rollup/3.15.0: /rollup/3.15.0:

View File

@@ -1,11 +1,11 @@
import * as dotenv from 'dotenv' import * as dotenv from 'dotenv'
import 'isomorphic-fetch' import 'isomorphic-fetch'
import type { ChatMessage, SendMessageOptions } from 'chatgpt' import type { ChatGPTAPIOptions, ChatMessage, SendMessageOptions } from 'chatgpt'
import { ChatGPTAPI, ChatGPTUnofficialProxyAPI } from 'chatgpt' import { ChatGPTAPI, ChatGPTUnofficialProxyAPI } from 'chatgpt'
import { SocksProxyAgent } from 'socks-proxy-agent' import { SocksProxyAgent } from 'socks-proxy-agent'
import fetch from 'node-fetch' import fetch from 'node-fetch'
import { sendResponse } from '../utils' import { sendResponse } from '../utils'
import type { ApiModel, ChatContext, ChatGPTAPIOptions, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types' import type { ApiModel, ChatContext, ChatGPTUnofficialProxyAPIOptions, ModelConfig } from '../types'
dotenv.config() dotenv.config()
@@ -18,7 +18,6 @@ if (!process.env.OPENAI_API_KEY && !process.env.OPENAI_ACCESS_TOKEN)
let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI
// To use ESM in CommonJS, you can use a dynamic import
(async () => { (async () => {
// More Info: https://github.com/transitive-bullshit/chatgpt-api // More Info: https://github.com/transitive-bullshit/chatgpt-api
@@ -28,6 +27,19 @@ let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI
debug: false, debug: false,
} }
if (process.env.OPENAI_API_BASE_URL && process.env.OPENAI_API_BASE_URL.trim().length > 0)
options.apiBaseUrl = process.env.OPENAI_API_BASE_URL
if (process.env.SOCKS_PROXY_HOST && process.env.SOCKS_PROXY_PORT) {
const agent = new SocksProxyAgent({
hostname: process.env.SOCKS_PROXY_HOST,
port: process.env.SOCKS_PROXY_PORT,
})
options.fetch = (url, options) => {
return fetch(url, { agent, ...options })
}
}
api = new ChatGPTAPI({ ...options }) api = new ChatGPTAPI({ ...options })
apiModel = 'ChatGPTAPI' apiModel = 'ChatGPTAPI'
} }
@@ -50,10 +62,7 @@ let api: ChatGPTAPI | ChatGPTUnofficialProxyAPI
if (process.env.API_REVERSE_PROXY) if (process.env.API_REVERSE_PROXY)
options.apiReverseProxyUrl = process.env.API_REVERSE_PROXY options.apiReverseProxyUrl = process.env.API_REVERSE_PROXY
api = new ChatGPTUnofficialProxyAPI({ api = new ChatGPTUnofficialProxyAPI({ ...options })
accessToken: process.env.OPENAI_ACCESS_TOKEN,
...options,
})
apiModel = 'ChatGPTUnofficialProxyAPI' apiModel = 'ChatGPTUnofficialProxyAPI'
} }
})() })()

View File

@@ -1,16 +1,10 @@
import type { FetchFn, openai } from 'chatgpt' import type { FetchFn } from 'chatgpt'
export interface ChatContext { export interface ChatContext {
conversationId?: string conversationId?: string
parentMessageId?: string parentMessageId?: string
} }
export interface ChatGPTAPIOptions {
apiKey: string
debug?: boolean
completionParams?: Partial<openai.CompletionParams>
}
export interface ChatGPTUnofficialProxyAPIOptions { export interface ChatGPTUnofficialProxyAPIOptions {
accessToken: string accessToken: string
apiReverseProxyUrl?: string apiReverseProxyUrl?: string

View File

@@ -1,3 +1,4 @@
import 'katex/dist/katex.min.css'
import '@/styles/lib/tailwind.css' import '@/styles/lib/tailwind.css'
import '@/styles/lib/highlight.less' import '@/styles/lib/highlight.less'
import '@/styles/lib/github-markdown.less' import '@/styles/lib/github-markdown.less'

View File

@@ -1,5 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import katex from 'katex'
import { marked } from 'marked' import { marked } from 'marked'
import hljs from 'highlight.js' import hljs from 'highlight.js'
import { useBasicLayout } from '@/hooks/useBasicLayout' import { useBasicLayout } from '@/hooks/useBasicLayout'
@@ -29,7 +30,7 @@ renderer.code = (code, language) => {
const validLang = !!(language && hljs.getLanguage(language)) const validLang = !!(language && hljs.getLanguage(language))
if (validLang) { if (validLang) {
const lang = language ?? '' const lang = language ?? ''
return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t('chat.copyCode')}</span></div><code class="hljs code-block-body ${language}">${hljs.highlight(lang, code).value}</code></pre>` return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t('chat.copyCode')}</span></div><code class="hljs code-block-body ${language}">${hljs.highlight(code, { language: lang }).value}</code></pre>`
} }
return `<pre style="background: none">${hljs.highlightAuto(code).value}</pre>` return `<pre style="background: none">${hljs.highlightAuto(code).value}</pre>`
} }
@@ -41,6 +42,54 @@ marked.setOptions({
}, },
}) })
const katexOptions = {
throwOnError: false,
}
const katexInline = {
name: 'katexInline',
level: 'inline',
start(src: string) {
return src.indexOf('$')
},
tokenizer(src: string) {
const match = src.match(/^\$+([^$\n]+?)\$+/)
if (match) {
return {
type: 'katexInline',
raw: match[0],
text: match[1].trim(),
}
}
},
renderer(token: marked.Tokens.Generic) {
return katex.renderToString(token.text, katexOptions)
},
}
const katexBlock = {
name: 'katexBlock',
level: 'block',
start(src: string) {
return src.indexOf('\n$$')
},
tokenizer(src: string) {
const match = src.match(/^\$\$+\n([^$]+?)\n\$\$+\n/)
if (match) {
return {
type: 'katexBlock',
raw: match[0],
text: match[1].trim(),
}
}
},
renderer(token: marked.Tokens.Generic) {
return `<p>${katex.renderToString(token.text, katexOptions)}</p>`
},
}
marked.use({ extensions: [katexInline, katexBlock] })
const wrapClass = computed(() => { const wrapClass = computed(() => {
return [ return [
'text-wrap', 'text-wrap',
@@ -69,7 +118,7 @@ defineExpose({ textRef })
<span class="dark:text-white w-[4px] h-[20px] block animate-blink" /> <span class="dark:text-white w-[4px] h-[20px] block animate-blink" />
</template> </template>
<template v-else> <template v-else>
<div ref="textRef" class="leading-relaxed break-all"> <div ref="textRef" class="leading-relaxed break-words">
<div v-if="!inversion" class="markdown-body" v-html="text" /> <div v-if="!inversion" class="markdown-body" v-html="text" />
<div v-else class="whitespace-pre-wrap" v-text="text" /> <div v-else class="whitespace-pre-wrap" v-text="text" />
</div> </div>

View File

@@ -1,4 +1,4 @@
import { onMounted } from 'vue' import { onMounted, onUpdated } from 'vue'
export function useCopyCode() { export function useCopyCode() {
function copyCodeBlock() { function copyCodeBlock() {
@@ -15,4 +15,6 @@ export function useCopyCode() {
} }
onMounted(() => copyCodeBlock()) onMounted(() => copyCodeBlock())
onUpdated(() => copyCodeBlock())
} }

View File

@@ -326,15 +326,14 @@ const buttonDisabled = computed(() => {
const wrapClass = computed(() => { const wrapClass = computed(() => {
if (isMobile.value) if (isMobile.value)
return ['pt-14', 'pb-16'] return ['pt-14']
return [] return []
}) })
const footerClass = computed(() => { const footerClass = computed(() => {
let classes = ['p-4'] let classes = ['p-4']
if (isMobile.value) if (isMobile.value)
classes = ['p-2', 'pr-4', 'fixed', 'bottom-4', 'left-0', 'right-0', 'z-30', 'h-14', 'overflow-hidden'] classes = ['sticky', 'left-0', 'bottom-0', 'right-0', 'p-2', 'pr-4', 'h-14', 'overflow-hidden']
return classes return classes
}) })
@@ -349,7 +348,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<div class="flex flex-col h-full" :class="wrapClass"> <div class="flex flex-col w-full h-full" :class="wrapClass">
<main class="flex-1 overflow-hidden"> <main class="flex-1 overflow-hidden">
<div <div
id="scrollRef" id="scrollRef"
@@ -357,58 +356,62 @@ onUnmounted(() => {
class="h-full overflow-hidden overflow-y-auto" class="h-full overflow-hidden overflow-y-auto"
:class="[isMobile ? 'p-2' : 'p-4']" :class="[isMobile ? 'p-2' : 'p-4']"
> >
<template v-if="!dataSources.length"> <div class="w-full max-w-screen-xl m-auto">
<div class="flex items-center justify-center mt-4 text-center text-neutral-300"> <template v-if="!dataSources.length">
<SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" /> <div class="flex items-center justify-center mt-4 text-center text-neutral-300">
<span>Aha~</span> <SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
</div> <span>Aha~</span>
</template>
<template v-else>
<div>
<Message
v-for="(item, index) of dataSources"
:key="index"
:date-time="item.dateTime"
:text="item.text"
:inversion="item.inversion"
:error="item.error"
:loading="item.loading"
@regenerate="onRegenerate(index)"
@delete="handleDelete(index)"
/>
<div class="sticky bottom-0 left-0 flex justify-center">
<NButton v-if="loading" type="warning" @click="handleStop">
<template #icon>
<SvgIcon icon="ri:stop-circle-line" />
</template>
Stop Responding
</NButton>
</div> </div>
</div> </template>
</template> <template v-else>
<div>
<Message
v-for="(item, index) of dataSources"
:key="index"
:date-time="item.dateTime"
:text="item.text"
:inversion="item.inversion"
:error="item.error"
:loading="item.loading"
@regenerate="onRegenerate(index)"
@delete="handleDelete(index)"
/>
<div class="sticky bottom-0 left-0 flex justify-center">
<NButton v-if="loading" type="warning" @click="handleStop">
<template #icon>
<SvgIcon icon="ri:stop-circle-line" />
</template>
Stop Responding
</NButton>
</div>
</div>
</template>
</div>
</div> </div>
</main> </main>
<footer :class="footerClass"> <footer :class="footerClass">
<div class="flex items-center justify-between space-x-2"> <div class="w-full max-w-screen-xl m-auto">
<HoverButton @click="handleClear"> <div class="flex items-center justify-between space-x-2">
<span class="text-xl text-[#4f555e] dark:text-white"> <HoverButton @click="handleClear">
<SvgIcon icon="ri:delete-bin-line" /> <span class="text-xl text-[#4f555e] dark:text-white">
</span> <SvgIcon icon="ri:delete-bin-line" />
</HoverButton>
<NInput
v-model:value="prompt"
type="textarea"
:autosize="{ minRows: 1, maxRows: 2 }"
:placeholder="placeholder"
@keypress="handleEnter"
/>
<NButton type="primary" :disabled="buttonDisabled" @click="handleSubmit">
<template #icon>
<span class="dark:text-black">
<SvgIcon icon="ri:send-plane-fill" />
</span> </span>
</template> </HoverButton>
</NButton> <NInput
v-model:value="prompt"
type="textarea"
:autosize="{ minRows: 1, maxRows: 2 }"
:placeholder="placeholder"
@keypress="handleEnter"
/>
<NButton type="primary" :disabled="buttonDisabled" @click="handleSubmit">
<template #icon>
<span class="dark:text-black">
<SvgIcon icon="ri:send-plane-fill" />
</span>
</template>
</NButton>
</div>
</div> </div>
</footer> </footer>
</div> </div>