chore: v2.5.0 整体优化 (#70)
* feat: locale language * refactor: 页面暂存 * feat: 逻辑判断 * feat: 分组消息 * feat: 实验场 * feat: 重新请求结果 * feat: 基础问答逻辑和重新询问 * feat: 上下文消息删除确认 * feat: 处理类型报错 * chore: 更新 deps 和移除 i18n * feat: 路由页面切换终止请求 * feat: let me think * feat: 信息更新代码高亮匹配 * feat: 加载时添加光标 * feat: 错误提示 * feat: 历史记录删除确认 * fix: 侧边栏高度不正确的问题 * chore: version 2.5.0 * chore: update deps
This commit is contained in:
parent
6216d84ecd
commit
fda6c6bb6a
|
@ -29,9 +29,11 @@
|
|||
"esno",
|
||||
"GPTAPI",
|
||||
"iconify",
|
||||
"logprobs",
|
||||
"nodata",
|
||||
"OPENAI",
|
||||
"pinia",
|
||||
"Popconfirm",
|
||||
"rushstack",
|
||||
"Sider",
|
||||
"tailwindcss",
|
||||
|
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,3 +1,21 @@
|
|||
## v2.5.0
|
||||
|
||||
`2023-02-20`
|
||||
|
||||
### Feature
|
||||
- 会话 `loading` 现在显示为光标动画
|
||||
- 会话现在可以再次生成回复
|
||||
- 会话异常可以再次进行请求
|
||||
- 所有删除选项添加确认操作
|
||||
|
||||
### Enhancement
|
||||
- 调整 `chat` 为路由页面而不是组件形式
|
||||
- 更新依赖至最新
|
||||
- 调整移动端体验
|
||||
|
||||
### BugFix
|
||||
- 修复移动端左侧菜单显示不完整的问题
|
||||
|
||||
## v2.4.1
|
||||
|
||||
`2023-02-18`
|
||||
|
|
16
package.json
16
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "chatgpt-web",
|
||||
"version": "2.4.1",
|
||||
"version": "2.5.0",
|
||||
"private": false,
|
||||
"description": "ChatGPT Web",
|
||||
"author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"common:prepare": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^9.12.0",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"highlight.js": "^11.7.0",
|
||||
"naive-ui": "^2.34.3",
|
||||
"pinia": "^2.0.30",
|
||||
|
@ -32,11 +32,11 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.35.2",
|
||||
"@commitlint/cli": "^17.4.3",
|
||||
"@commitlint/config-conventional": "^17.4.3",
|
||||
"@commitlint/cli": "^17.4.4",
|
||||
"@commitlint/config-conventional": "^17.4.4",
|
||||
"@iconify/vue": "^4.1.0",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/node": "^18.13.0",
|
||||
"@types/node": "^18.14.0",
|
||||
"@types/web-bluetooth": "^0.0.16",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
|
@ -49,10 +49,10 @@
|
|||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.21",
|
||||
"rimraf": "^4.1.2",
|
||||
"tailwindcss": "^3.2.6",
|
||||
"tailwindcss": "^3.2.7",
|
||||
"typescript": "~4.9.5",
|
||||
"vite": "^4.1.1",
|
||||
"vue-tsc": "^1.1.0"
|
||||
"vite": "^4.1.2",
|
||||
"vue-tsc": "^1.1.4"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx,vue}": [
|
||||
|
|
216
pnpm-lock.yaml
216
pnpm-lock.yaml
|
@ -2,14 +2,14 @@ lockfileVersion: 5.4
|
|||
|
||||
specifiers:
|
||||
'@antfu/eslint-config': ^0.35.2
|
||||
'@commitlint/cli': ^17.4.3
|
||||
'@commitlint/config-conventional': ^17.4.3
|
||||
'@commitlint/cli': ^17.4.4
|
||||
'@commitlint/config-conventional': ^17.4.4
|
||||
'@iconify/vue': ^4.1.0
|
||||
'@types/crypto-js': ^4.1.1
|
||||
'@types/node': ^18.13.0
|
||||
'@types/node': ^18.14.0
|
||||
'@types/web-bluetooth': ^0.0.16
|
||||
'@vitejs/plugin-vue': ^4.0.0
|
||||
'@vueuse/core': ^9.12.0
|
||||
'@vueuse/core': ^9.13.0
|
||||
autoprefixer: ^10.4.13
|
||||
axios: ^1.3.3
|
||||
crypto-js: ^4.1.1
|
||||
|
@ -23,15 +23,15 @@ specifiers:
|
|||
pinia: ^2.0.30
|
||||
postcss: ^8.4.21
|
||||
rimraf: ^4.1.2
|
||||
tailwindcss: ^3.2.6
|
||||
tailwindcss: ^3.2.7
|
||||
typescript: ~4.9.5
|
||||
vite: ^4.1.1
|
||||
vite: ^4.1.2
|
||||
vue: ^3.2.47
|
||||
vue-router: ^4.1.6
|
||||
vue-tsc: ^1.1.0
|
||||
vue-tsc: ^1.1.4
|
||||
|
||||
dependencies:
|
||||
'@vueuse/core': 9.12.0_vue@3.2.47
|
||||
'@vueuse/core': 9.13.0_vue@3.2.47
|
||||
highlight.js: 11.7.0
|
||||
naive-ui: 2.34.3_vue@3.2.47
|
||||
pinia: 2.0.30_hmuptsblhheur2tugfgucj7gc4
|
||||
|
@ -40,13 +40,13 @@ dependencies:
|
|||
|
||||
devDependencies:
|
||||
'@antfu/eslint-config': 0.35.2_7kw3g6rralp5ps6mg3uyzz6azm
|
||||
'@commitlint/cli': 17.4.3
|
||||
'@commitlint/config-conventional': 17.4.3
|
||||
'@commitlint/cli': 17.4.4
|
||||
'@commitlint/config-conventional': 17.4.4
|
||||
'@iconify/vue': 4.1.0_vue@3.2.47
|
||||
'@types/crypto-js': 4.1.1
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
'@types/web-bluetooth': 0.0.16
|
||||
'@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.47
|
||||
'@vitejs/plugin-vue': 4.0.0_vite@4.1.2+vue@3.2.47
|
||||
autoprefixer: 10.4.13_postcss@8.4.21
|
||||
axios: 1.3.3
|
||||
crypto-js: 4.1.1
|
||||
|
@ -57,10 +57,10 @@ devDependencies:
|
|||
npm-run-all: 4.1.5
|
||||
postcss: 8.4.21
|
||||
rimraf: 4.1.2
|
||||
tailwindcss: 3.2.6_postcss@8.4.21
|
||||
tailwindcss: 3.2.7_postcss@8.4.21
|
||||
typescript: 4.9.5
|
||||
vite: 4.1.1_edl3ajnhen4c5iqs57t4gqrzly
|
||||
vue-tsc: 1.1.0_typescript@4.9.5
|
||||
vite: 4.1.2_lxiyzdpogvsuukhx3wcpsdczbq
|
||||
vue-tsc: 1.1.4_typescript@4.9.5
|
||||
|
||||
packages:
|
||||
|
||||
|
@ -199,16 +199,16 @@ packages:
|
|||
'@babel/helper-validator-identifier': 7.19.1
|
||||
to-fast-properties: 2.0.0
|
||||
|
||||
/@commitlint/cli/17.4.3:
|
||||
resolution: {integrity: sha512-IPTS7AZuBHgD0gl24El8HwuDM9zJN9JLa5KmZUQoFD1BQeGGdzAYJOnAr85CeJWpTDok0BGHDL0+4odnH0iTyA==}
|
||||
/@commitlint/cli/17.4.4:
|
||||
resolution: {integrity: sha512-HwKlD7CPVMVGTAeFZylVNy14Vm5POVY0WxPkZr7EXLC/os0LH/obs6z4HRvJtH/nHCMYBvUBQhGwnufKfTjd5g==}
|
||||
engines: {node: '>=v14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@commitlint/format': 17.4.0
|
||||
'@commitlint/lint': 17.4.3
|
||||
'@commitlint/load': 17.4.2
|
||||
'@commitlint/read': 17.4.2
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/format': 17.4.4
|
||||
'@commitlint/lint': 17.4.4
|
||||
'@commitlint/load': 17.4.4
|
||||
'@commitlint/read': 17.4.4
|
||||
'@commitlint/types': 17.4.4
|
||||
execa: 5.1.1
|
||||
lodash.isfunction: 3.0.9
|
||||
resolve-from: 5.0.0
|
||||
|
@ -219,26 +219,26 @@ packages:
|
|||
- '@swc/wasm'
|
||||
dev: true
|
||||
|
||||
/@commitlint/config-conventional/17.4.3:
|
||||
resolution: {integrity: sha512-8EsY2iDw74hCk3hIQSg7/E0R8/KtPjnFPZVwmmHxcjhZjkSykmxysefICPDnbI3xgxfov0zwL1WKDHM8zglJdw==}
|
||||
/@commitlint/config-conventional/17.4.4:
|
||||
resolution: {integrity: sha512-u6ztvxqzi6NuhrcEDR7a+z0yrh11elY66nRrQIpqsqW6sZmpxYkDLtpRH8jRML+mmxYQ8s4qqF06Q/IQx5aJeQ==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
conventional-changelog-conventionalcommits: 5.0.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/config-validator/17.4.0:
|
||||
resolution: {integrity: sha512-Sa/+8KNpDXz4zT4bVbz2fpFjvgkPO6u2V2fP4TKgt6FjmOw2z3eEX859vtfeaTav/ukBw0/0jr+5ZTZp9zCBhA==}
|
||||
/@commitlint/config-validator/17.4.4:
|
||||
resolution: {integrity: sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
ajv: 8.12.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/ensure/17.4.0:
|
||||
resolution: {integrity: sha512-7oAxt25je0jeQ/E0O/M8L3ADb1Cvweu/5lc/kYF8g/kXatI0wxGE5La52onnAUAWeWlsuvBNar15WcrmDmr5Mw==}
|
||||
/@commitlint/ensure/17.4.4:
|
||||
resolution: {integrity: sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
lodash.camelcase: 4.3.0
|
||||
lodash.kebabcase: 4.1.1
|
||||
lodash.snakecase: 4.1.1
|
||||
|
@ -251,49 +251,49 @@ packages:
|
|||
engines: {node: '>=v14'}
|
||||
dev: true
|
||||
|
||||
/@commitlint/format/17.4.0:
|
||||
resolution: {integrity: sha512-Z2bWAU5+f1YZh9W76c84J8iLIWIvvm+mzqogTz0Nsc1x6EHW0Z2gI38g5HAjB0r0I3ZjR15IDEJKhsxyblcyhA==}
|
||||
/@commitlint/format/17.4.4:
|
||||
resolution: {integrity: sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
chalk: 4.1.2
|
||||
dev: true
|
||||
|
||||
/@commitlint/is-ignored/17.4.2:
|
||||
resolution: {integrity: sha512-1b2Y2qJ6n7bHG9K6h8S4lBGUl6kc7mMhJN9gy1SQfUZqe92ToDjUTtgNWb6LbzR1X8Cq4SEus4VU8Z/riEa94Q==}
|
||||
/@commitlint/is-ignored/17.4.4:
|
||||
resolution: {integrity: sha512-Y3eo1SFJ2JQDik4rWkBC4tlRIxlXEFrRWxcyrzb1PUT2k3kZ/XGNuCDfk/u0bU2/yS0tOA/mTjFsV+C4qyACHw==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
semver: 7.3.8
|
||||
dev: true
|
||||
|
||||
/@commitlint/lint/17.4.3:
|
||||
resolution: {integrity: sha512-GnPsqEYmXIB/MaBhRMzkiDJWyjuLrKad4xoxKO4N6Kc19iqjR4DPc/bl2dxeW9kUmtrAtefOzIEzJAevpA5y2w==}
|
||||
/@commitlint/lint/17.4.4:
|
||||
resolution: {integrity: sha512-qgkCRRFjyhbMDWsti/5jRYVJkgYZj4r+ZmweZObnbYqPUl5UKLWMf9a/ZZisOI4JfiPmRktYRZ2JmqlSvg+ccw==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/is-ignored': 17.4.2
|
||||
'@commitlint/parse': 17.4.2
|
||||
'@commitlint/rules': 17.4.3
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/is-ignored': 17.4.4
|
||||
'@commitlint/parse': 17.4.4
|
||||
'@commitlint/rules': 17.4.4
|
||||
'@commitlint/types': 17.4.4
|
||||
dev: true
|
||||
|
||||
/@commitlint/load/17.4.2:
|
||||
resolution: {integrity: sha512-Si++F85rJ9t4hw6JcOw1i2h0fdpdFQt0YKwjuK4bk9KhFjyFkRxvR3SB2dPaMs+EwWlDrDBGL+ygip1QD6gmPw==}
|
||||
/@commitlint/load/17.4.4:
|
||||
resolution: {integrity: sha512-z6uFIQ7wfKX5FGBe1AkOF4l/ShOQsaa1ml/nLMkbW7R/xF8galGS7Zh0yHvzVp/srtfS0brC+0bUfQfmpMPFVQ==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/config-validator': 17.4.0
|
||||
'@commitlint/config-validator': 17.4.4
|
||||
'@commitlint/execute-rule': 17.4.0
|
||||
'@commitlint/resolve-extends': 17.4.0
|
||||
'@commitlint/types': 17.4.0
|
||||
'@types/node': 18.13.0
|
||||
'@commitlint/resolve-extends': 17.4.4
|
||||
'@commitlint/types': 17.4.4
|
||||
'@types/node': 18.14.0
|
||||
chalk: 4.1.2
|
||||
cosmiconfig: 8.0.0
|
||||
cosmiconfig-typescript-loader: 4.3.0_p7cp6dsfhdrlk7mvuxd3wodbsu
|
||||
cosmiconfig-typescript-loader: 4.3.0_ipkhww4xc5z2tt2x53vp2mt2be
|
||||
lodash.isplainobject: 4.0.6
|
||||
lodash.merge: 4.6.2
|
||||
lodash.uniq: 4.5.0
|
||||
resolve-from: 5.0.0
|
||||
ts-node: 10.9.1_4bewfcp2iebiwuold25d6rgcsy
|
||||
ts-node: 10.9.1_tncu2ai53lzgmizdedur7lbibe
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
|
@ -305,46 +305,46 @@ packages:
|
|||
engines: {node: '>=v14'}
|
||||
dev: true
|
||||
|
||||
/@commitlint/parse/17.4.2:
|
||||
resolution: {integrity: sha512-DK4EwqhxfXpyCA+UH8TBRIAXAfmmX4q9QRBz/2h9F9sI91yt6mltTrL6TKURMcjUVmgaB80wgS9QybNIyVBIJA==}
|
||||
/@commitlint/parse/17.4.4:
|
||||
resolution: {integrity: sha512-EKzz4f49d3/OU0Fplog7nwz/lAfXMaDxtriidyGF9PtR+SRbgv4FhsfF310tKxs6EPj8Y+aWWuX3beN5s+yqGg==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
conventional-changelog-angular: 5.0.13
|
||||
conventional-commits-parser: 3.2.4
|
||||
dev: true
|
||||
|
||||
/@commitlint/read/17.4.2:
|
||||
resolution: {integrity: sha512-hasYOdbhEg+W4hi0InmXHxtD/1favB4WdwyFxs1eOy/DvMw6+2IZBmATgGOlqhahsypk4kChhxjAFJAZ2F+JBg==}
|
||||
/@commitlint/read/17.4.4:
|
||||
resolution: {integrity: sha512-B2TvUMJKK+Svzs6eji23WXsRJ8PAD+orI44lVuVNsm5zmI7O8RSGJMvdEZEikiA4Vohfb+HevaPoWZ7PiFZ3zA==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/top-level': 17.4.0
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
fs-extra: 11.1.0
|
||||
git-raw-commits: 2.0.11
|
||||
minimist: 1.2.8
|
||||
dev: true
|
||||
|
||||
/@commitlint/resolve-extends/17.4.0:
|
||||
resolution: {integrity: sha512-3JsmwkrCzoK8sO22AzLBvNEvC1Pmdn/65RKXzEtQMy6oYMl0Snrq97a5bQQEFETF0VsvbtUuKttLqqgn99OXRQ==}
|
||||
/@commitlint/resolve-extends/17.4.4:
|
||||
resolution: {integrity: sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/config-validator': 17.4.0
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/config-validator': 17.4.4
|
||||
'@commitlint/types': 17.4.4
|
||||
import-fresh: 3.3.0
|
||||
lodash.mergewith: 4.6.2
|
||||
resolve-from: 5.0.0
|
||||
resolve-global: 1.0.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/rules/17.4.3:
|
||||
resolution: {integrity: sha512-xHReDfE3Z+O9p1sXeEhPRSk4FifBsC4EbXzvQ4aa0ykQe+n/iZDd4CrFC/Oiv2K9BU4ZnFHak30IbMLa4ks1Rw==}
|
||||
/@commitlint/rules/17.4.4:
|
||||
resolution: {integrity: sha512-0tgvXnHi/mVcyR8Y8mjTFZIa/FEQXA4uEutXS/imH2v1UNkYDSEMsK/68wiXRpfW1euSgEdwRkvE1z23+yhNrQ==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/ensure': 17.4.0
|
||||
'@commitlint/ensure': 17.4.4
|
||||
'@commitlint/message': 17.4.2
|
||||
'@commitlint/to-lines': 17.4.0
|
||||
'@commitlint/types': 17.4.0
|
||||
'@commitlint/types': 17.4.4
|
||||
execa: 5.1.1
|
||||
dev: true
|
||||
|
||||
|
@ -360,8 +360,8 @@ packages:
|
|||
find-up: 5.0.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/types/17.4.0:
|
||||
resolution: {integrity: sha512-2NjAnq5IcxY9kXtUeO2Ac0aPpvkuOmwbH/BxIm36XXK5LtWFObWJWjXOA+kcaABMrthjWu6la+FUpyYFMHRvbA==}
|
||||
/@commitlint/types/17.4.4:
|
||||
resolution: {integrity: sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
|
@ -745,8 +745,8 @@ packages:
|
|||
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.13.0:
|
||||
resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==}
|
||||
/@types/node/18.14.0:
|
||||
resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==}
|
||||
dev: true
|
||||
|
||||
/@types/normalize-package-data/2.4.1:
|
||||
|
@ -894,40 +894,40 @@ packages:
|
|||
eslint-visitor-keys: 3.3.0
|
||||
dev: true
|
||||
|
||||
/@vitejs/plugin-vue/4.0.0_vite@4.1.1+vue@3.2.47:
|
||||
/@vitejs/plugin-vue/4.0.0_vite@4.1.2+vue@3.2.47:
|
||||
resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
vite: ^4.0.0
|
||||
vue: ^3.2.25
|
||||
dependencies:
|
||||
vite: 4.1.1_edl3ajnhen4c5iqs57t4gqrzly
|
||||
vite: 4.1.2_lxiyzdpogvsuukhx3wcpsdczbq
|
||||
vue: 3.2.47
|
||||
dev: true
|
||||
|
||||
/@volar/language-core/1.2.0-alpha.11:
|
||||
resolution: {integrity: sha512-OfbPmmFa4LUA8kJCg77V9ud4NASjJ3VKJ79QCQSfHa5SwXeZ5w7lvQe2yILFBjZ3JDB5EfFnHZUSct6ziK3x5Q==}
|
||||
/@volar/language-core/1.2.0-alpha.16:
|
||||
resolution: {integrity: sha512-aIktWe9Zg0M+u/RIXHCuL+IoLRHTrpsbTib8olrg4etlurHDXahoVhoEnH9wmlliray0iigIo2z5vwueYInp3g==}
|
||||
dependencies:
|
||||
'@volar/source-map': 1.2.0-alpha.11
|
||||
'@volar/source-map': 1.2.0-alpha.16
|
||||
dev: true
|
||||
|
||||
/@volar/source-map/1.2.0-alpha.11:
|
||||
resolution: {integrity: sha512-GCRqcq2bn8Gf9N/qbdl8GgfGbmYuuSIB8arhl+gRZfCIWvT5NhIRVlG5GX0lkgpp02lA8ZYWZ0GLGOkwz7+DMQ==}
|
||||
/@volar/source-map/1.2.0-alpha.16:
|
||||
resolution: {integrity: sha512-/AK3VqnFqONd221COI2ZnEvfgBulfoQkjA/ZjPOXpsOkWri99TLcfZY/NTQRytp7Hx6EP/1p1DDeyGuMCUYjgA==}
|
||||
dependencies:
|
||||
muggle-string: 0.2.2
|
||||
dev: true
|
||||
|
||||
/@volar/typescript/1.2.0-alpha.11:
|
||||
resolution: {integrity: sha512-tJ20326E/Xi1lvvuWX57boVJtzhStNF3HjBu4orjl9PqCXUbhqWwP+jRYzyb+nLbHqGPmEBvHKYjAO3GsJ/YXg==}
|
||||
/@volar/typescript/1.2.0-alpha.16:
|
||||
resolution: {integrity: sha512-ltlTLHIkLxgmTVBZmOnhmnlNzEj2lpvlBmmaV2GWYTrBUMt0z1OgeCq0Utlj9HjjrGPhwWxZNkv86ZABgrMA3Q==}
|
||||
dependencies:
|
||||
'@volar/language-core': 1.2.0-alpha.11
|
||||
'@volar/language-core': 1.2.0-alpha.16
|
||||
dev: true
|
||||
|
||||
/@volar/vue-language-core/1.1.0:
|
||||
resolution: {integrity: sha512-1zTAyeGiyNKYE9s+i3dUpmuvY/Cz1U7LjIh9d5FX3p0NWpaBrzYvSh0gQY+nRaz67or7Y9qYSUCaHLKOmeolzg==}
|
||||
/@volar/vue-language-core/1.1.4:
|
||||
resolution: {integrity: sha512-2C2CwHvaT5AzNzDbYZQ85lNr4jACZARoZMZBLuU5+JyIwhWeAfxvyAeoE3VbgfgycN5t6X4uBqx/Wzh1QLgD8Q==}
|
||||
dependencies:
|
||||
'@volar/language-core': 1.2.0-alpha.11
|
||||
'@volar/source-map': 1.2.0-alpha.11
|
||||
'@volar/language-core': 1.2.0-alpha.16
|
||||
'@volar/source-map': 1.2.0-alpha.16
|
||||
'@vue/compiler-dom': 3.2.47
|
||||
'@vue/compiler-sfc': 3.2.47
|
||||
'@vue/reactivity': 3.2.47
|
||||
|
@ -937,11 +937,11 @@ packages:
|
|||
vue-template-compiler: 2.7.14
|
||||
dev: true
|
||||
|
||||
/@volar/vue-typescript/1.1.0:
|
||||
resolution: {integrity: sha512-smtfaePuNpVzXEypJayORtl8muvBdtV1FDWjces1WLYbbtcnmfWtdACW9xY0dkVk0LoE/LZTEmLBCQrRJ6hS1w==}
|
||||
/@volar/vue-typescript/1.1.4:
|
||||
resolution: {integrity: sha512-x5i5TUUXb1PM0rM80Y8XUeMBUcoS3/TjR3WTxvvEUIol9uEOPp6uxxQQ67uSv7ocN6vB0LugJqS6FA7Z93oL0Q==}
|
||||
dependencies:
|
||||
'@volar/typescript': 1.2.0-alpha.11
|
||||
'@volar/vue-language-core': 1.1.0
|
||||
'@volar/typescript': 1.2.0-alpha.16
|
||||
'@volar/vue-language-core': 1.1.4
|
||||
dev: true
|
||||
|
||||
/@vue/compiler-core/3.2.47:
|
||||
|
@ -1021,24 +1021,24 @@ packages:
|
|||
/@vue/shared/3.2.47:
|
||||
resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==}
|
||||
|
||||
/@vueuse/core/9.12.0_vue@3.2.47:
|
||||
resolution: {integrity: sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==}
|
||||
/@vueuse/core/9.13.0_vue@3.2.47:
|
||||
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
|
||||
dependencies:
|
||||
'@types/web-bluetooth': 0.0.16
|
||||
'@vueuse/metadata': 9.12.0
|
||||
'@vueuse/shared': 9.12.0_vue@3.2.47
|
||||
'@vueuse/metadata': 9.13.0
|
||||
'@vueuse/shared': 9.13.0_vue@3.2.47
|
||||
vue-demi: 0.13.11_vue@3.2.47
|
||||
transitivePeerDependencies:
|
||||
- '@vue/composition-api'
|
||||
- vue
|
||||
dev: false
|
||||
|
||||
/@vueuse/metadata/9.12.0:
|
||||
resolution: {integrity: sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ==}
|
||||
/@vueuse/metadata/9.13.0:
|
||||
resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
|
||||
dev: false
|
||||
|
||||
/@vueuse/shared/9.12.0_vue@3.2.47:
|
||||
resolution: {integrity: sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ==}
|
||||
/@vueuse/shared/9.13.0_vue@3.2.47:
|
||||
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
|
||||
dependencies:
|
||||
vue-demi: 0.13.11_vue@3.2.47
|
||||
transitivePeerDependencies:
|
||||
|
@ -1530,7 +1530,7 @@ packages:
|
|||
is-what: 3.14.1
|
||||
dev: true
|
||||
|
||||
/cosmiconfig-typescript-loader/4.3.0_p7cp6dsfhdrlk7mvuxd3wodbsu:
|
||||
/cosmiconfig-typescript-loader/4.3.0_ipkhww4xc5z2tt2x53vp2mt2be:
|
||||
resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
peerDependencies:
|
||||
|
@ -1539,9 +1539,9 @@ packages:
|
|||
ts-node: '>=10'
|
||||
typescript: '>=3'
|
||||
dependencies:
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
cosmiconfig: 8.0.0
|
||||
ts-node: 10.9.1_4bewfcp2iebiwuold25d6rgcsy
|
||||
ts-node: 10.9.1_tncu2ai53lzgmizdedur7lbibe
|
||||
typescript: 4.9.5
|
||||
dev: true
|
||||
|
||||
|
@ -4290,8 +4290,8 @@ packages:
|
|||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/tailwindcss/3.2.6_postcss@8.4.21:
|
||||
resolution: {integrity: sha512-BfgQWZrtqowOQMC2bwaSNe7xcIjdDEgixWGYOd6AL0CbKHJlvhfdbINeAW76l1sO+1ov/MJ93ODJ9yluRituIw==}
|
||||
/tailwindcss/3.2.7_postcss@8.4.21:
|
||||
resolution: {integrity: sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==}
|
||||
engines: {node: '>=12.13.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
@ -4363,7 +4363,7 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/ts-node/10.9.1_4bewfcp2iebiwuold25d6rgcsy:
|
||||
/ts-node/10.9.1_tncu2ai53lzgmizdedur7lbibe:
|
||||
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
@ -4382,7 +4382,7 @@ packages:
|
|||
'@tsconfig/node12': 1.0.11
|
||||
'@tsconfig/node14': 1.0.3
|
||||
'@tsconfig/node16': 1.0.3
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
acorn: 8.8.2
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.3
|
||||
|
@ -4527,8 +4527,8 @@ packages:
|
|||
vue: 3.2.47
|
||||
dev: false
|
||||
|
||||
/vite/4.1.1_edl3ajnhen4c5iqs57t4gqrzly:
|
||||
resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==}
|
||||
/vite/4.1.2_lxiyzdpogvsuukhx3wcpsdczbq:
|
||||
resolution: {integrity: sha512-MWDb9Rfy3DI8omDQySbMK93nQqStwbsQWejXRY2EBzEWKmLAXWb1mkI9Yw2IJrc+oCvPCI1Os5xSSIBYY6DEAw==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
@ -4552,7 +4552,7 @@ packages:
|
|||
terser:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
esbuild: 0.16.17
|
||||
less: 4.1.3
|
||||
postcss: 8.4.21
|
||||
|
@ -4620,14 +4620,14 @@ packages:
|
|||
he: 1.2.0
|
||||
dev: true
|
||||
|
||||
/vue-tsc/1.1.0_typescript@4.9.5:
|
||||
resolution: {integrity: sha512-+JqTcuScA6OfyaVH3ezeCh2i2wRgzUScZ6EdTZ3AW69Nb+rmRyOAxmAjL6MPam8YCdwmmdfAUhmN/BNGVp5vQg==}
|
||||
/vue-tsc/1.1.4_typescript@4.9.5:
|
||||
resolution: {integrity: sha512-CMG8KZsBBPyulYie05XxJCfq/yAPiB/uMMeHmog09aLm2Kml82C6tUSRgQz8ujM4JoCrpDqVCd9G0NuM9aLt1g==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
typescript: '*'
|
||||
dependencies:
|
||||
'@volar/vue-language-core': 1.1.0
|
||||
'@volar/vue-typescript': 1.1.0
|
||||
'@volar/vue-language-core': 1.1.4
|
||||
'@volar/vue-typescript': 1.1.4
|
||||
typescript: 4.9.5
|
||||
dev: true
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
"common:cleanup": "rimraf node_modules && rimraf pnpm-lock.yaml"
|
||||
},
|
||||
"dependencies": {
|
||||
"chatgpt": "^4.3.2",
|
||||
"chatgpt": "^4.7.1",
|
||||
"dotenv": "^16.0.3",
|
||||
"esno": "^0.16.3",
|
||||
"express": "^4.18.2",
|
||||
|
@ -32,10 +32,10 @@
|
|||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.35.2",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/node": "^18.13.0",
|
||||
"@types/node": "^18.14.0",
|
||||
"eslint": "^8.34.0",
|
||||
"rimraf": "^4.1.2",
|
||||
"tsup": "^6.6.2",
|
||||
"tsup": "^6.6.3",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,19 @@ lockfileVersion: 5.4
|
|||
specifiers:
|
||||
'@antfu/eslint-config': ^0.35.2
|
||||
'@types/express': ^4.17.17
|
||||
'@types/node': ^18.13.0
|
||||
chatgpt: ^4.3.2
|
||||
'@types/node': ^18.14.0
|
||||
chatgpt: ^4.7.1
|
||||
dotenv: ^16.0.3
|
||||
eslint: ^8.34.0
|
||||
esno: ^0.16.3
|
||||
express: ^4.18.2
|
||||
isomorphic-fetch: ^3.0.0
|
||||
rimraf: ^4.1.2
|
||||
tsup: ^6.6.2
|
||||
tsup: ^6.6.3
|
||||
typescript: ^4.9.5
|
||||
|
||||
dependencies:
|
||||
chatgpt: 4.4.0
|
||||
chatgpt: 4.7.1
|
||||
dotenv: 16.0.3
|
||||
esno: 0.16.3
|
||||
express: 4.18.2
|
||||
|
@ -24,7 +24,7 @@ dependencies:
|
|||
devDependencies:
|
||||
'@antfu/eslint-config': 0.35.2_7kw3g6rralp5ps6mg3uyzz6azm
|
||||
'@types/express': 4.17.17
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
eslint: 8.34.0
|
||||
rimraf: 4.1.2
|
||||
tsup: 6.6.3_typescript@4.9.5
|
||||
|
@ -133,12 +133,10 @@ packages:
|
|||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/highlight': 7.18.6
|
||||
dev: true
|
||||
|
||||
/@babel/helper-validator-identifier/7.19.1:
|
||||
resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/highlight/7.18.6:
|
||||
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
|
||||
|
@ -147,7 +145,6 @@ packages:
|
|||
'@babel/helper-validator-identifier': 7.19.1
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@esbuild-kit/cjs-loader/2.4.2:
|
||||
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
||||
|
@ -418,19 +415,19 @@ packages:
|
|||
resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==}
|
||||
dependencies:
|
||||
'@types/connect': 3.4.35
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
dev: true
|
||||
|
||||
/@types/connect/3.4.35:
|
||||
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
|
||||
dependencies:
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
dev: true
|
||||
|
||||
/@types/express-serve-static-core/4.17.33:
|
||||
resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==}
|
||||
dependencies:
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
'@types/qs': 6.9.7
|
||||
'@types/range-parser': 1.2.4
|
||||
dev: true
|
||||
|
@ -462,13 +459,12 @@ packages:
|
|||
resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==}
|
||||
dev: true
|
||||
|
||||
/@types/node/18.13.0:
|
||||
resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==}
|
||||
/@types/node/18.14.0:
|
||||
resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==}
|
||||
dev: true
|
||||
|
||||
/@types/normalize-package-data/2.4.1:
|
||||
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
|
||||
dev: true
|
||||
|
||||
/@types/qs/6.9.7:
|
||||
resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==}
|
||||
|
@ -486,7 +482,7 @@ packages:
|
|||
resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==}
|
||||
dependencies:
|
||||
'@types/mime': 3.0.1
|
||||
'@types/node': 18.13.0
|
||||
'@types/node': 18.14.0
|
||||
dev: true
|
||||
|
||||
/@types/unist/2.0.6:
|
||||
|
@ -645,6 +641,15 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ajv-formats/2.1.1:
|
||||
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
|
||||
peerDependenciesMeta:
|
||||
ajv:
|
||||
optional: true
|
||||
dependencies:
|
||||
ajv: 8.12.0
|
||||
dev: false
|
||||
|
||||
/ajv/6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
dependencies:
|
||||
|
@ -654,6 +659,15 @@ packages:
|
|||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/ajv/8.12.0:
|
||||
resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
dev: false
|
||||
|
||||
/ansi-regex/5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -664,7 +678,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
color-convert: 1.9.3
|
||||
dev: true
|
||||
|
||||
/ansi-styles/4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
|
@ -704,6 +717,10 @@ packages:
|
|||
is-string: 1.0.7
|
||||
dev: true
|
||||
|
||||
/array-keyed-map/2.1.3:
|
||||
resolution: {integrity: sha512-JIUwuFakO+jHjxyp4YgSiKXSZeC0U+R1jR94bXWBcVlFRBycqXlb+kH9JHxBGcxnVuSqx5bnn0Qz9xtSeKOjiA==}
|
||||
dev: false
|
||||
|
||||
/array-union/2.1.0:
|
||||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -729,6 +746,13 @@ packages:
|
|||
es-shim-unscopables: 1.0.0
|
||||
dev: true
|
||||
|
||||
/atomically/2.0.1:
|
||||
resolution: {integrity: sha512-sxBhVZUFBFhqSAsYMM3X2oaUi2NVDJ8U026FsIusM8gYXls9AYs/eXzgGrufs1Qjpkxi9zunds+75QUFz+m7UQ==}
|
||||
dependencies:
|
||||
stubborn-fs: 1.2.4
|
||||
when-exit: 2.1.0
|
||||
dev: false
|
||||
|
||||
/available-typed-arrays/1.0.5:
|
||||
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -814,7 +838,6 @@ packages:
|
|||
/cac/6.7.14:
|
||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/call-bind/1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
|
@ -834,7 +857,6 @@ packages:
|
|||
ansi-styles: 3.2.1
|
||||
escape-string-regexp: 1.0.5
|
||||
supports-color: 5.5.0
|
||||
dev: true
|
||||
|
||||
/chalk/4.1.2:
|
||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||
|
@ -856,15 +878,19 @@ packages:
|
|||
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
|
||||
dev: true
|
||||
|
||||
/chatgpt/4.4.0:
|
||||
resolution: {integrity: sha512-rS1F423hR5marIB7hvZ4KyczK9oFloWY+AR4WKIt+HLyiRgOOWv6V4olu1HvaoOayc5+A/N2WwX0SzuU1rI9Rg==}
|
||||
engines: {node: '>=18'}
|
||||
/chatgpt/4.7.1:
|
||||
resolution: {integrity: sha512-FRXfpjn//Y4gUMcUo60W5byJ0CbFhC1Xp3PCm2qcBthBYFbC+LyRrwxvSVTdNwgQywHV4Pc5SFkaZ72f5rCNdQ==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
conf: 11.0.1
|
||||
eventsource-parser: 0.0.5
|
||||
gpt-3-encoder: 1.1.4
|
||||
gpt3-tokenizer: 1.1.5
|
||||
keyv: 4.5.2
|
||||
p-timeout: 6.1.1
|
||||
quick-lru: 6.1.1
|
||||
read-pkg-up: 9.1.0
|
||||
uuid: 9.0.0
|
||||
dev: false
|
||||
|
||||
|
@ -899,7 +925,6 @@ packages:
|
|||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
|
||||
dependencies:
|
||||
color-name: 1.1.3
|
||||
dev: true
|
||||
|
||||
/color-convert/2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
|
@ -910,7 +935,6 @@ packages:
|
|||
|
||||
/color-name/1.1.3:
|
||||
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
|
||||
dev: true
|
||||
|
||||
/color-name/1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
@ -925,6 +949,20 @@ packages:
|
|||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
dev: true
|
||||
|
||||
/conf/11.0.1:
|
||||
resolution: {integrity: sha512-WlLiQboEjKx0bYx2IIRGedBgNjLAxtwPaCSnsjWPST5xR0DB4q8lcsO/bEH9ZRYNcj63Y9vj/JG/5Fg6uWzI0Q==}
|
||||
engines: {node: '>=14.16'}
|
||||
dependencies:
|
||||
ajv: 8.12.0
|
||||
ajv-formats: 2.1.1
|
||||
atomically: 2.0.1
|
||||
debounce-fn: 5.1.2
|
||||
dot-prop: 7.2.0
|
||||
env-paths: 3.0.0
|
||||
json-schema-typed: 8.0.1
|
||||
semver: 7.3.8
|
||||
dev: false
|
||||
|
||||
/content-disposition/0.5.4:
|
||||
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
@ -961,6 +999,13 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/debounce-fn/5.1.2:
|
||||
resolution: {integrity: sha512-Sr4SdOZ4vw6eQDvPYNxHogvrxmCIld/VenC5JbNrFwMiwd7lY/Z18ZFfo+EWNG4DD9nFlAujWAo/wGuOPHmy5A==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
mimic-fn: 4.0.0
|
||||
dev: false
|
||||
|
||||
/debug/2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
peerDependencies:
|
||||
|
@ -1065,6 +1110,13 @@ packages:
|
|||
domhandler: 5.0.3
|
||||
dev: true
|
||||
|
||||
/dot-prop/7.2.0:
|
||||
resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
type-fest: 2.19.0
|
||||
dev: false
|
||||
|
||||
/dotenv/16.0.3:
|
||||
resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -1084,11 +1136,15 @@ packages:
|
|||
engines: {node: '>=0.12'}
|
||||
dev: true
|
||||
|
||||
/env-paths/3.0.0:
|
||||
resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: false
|
||||
|
||||
/error-ex/1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
dev: true
|
||||
|
||||
/es-abstract/1.21.1:
|
||||
resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==}
|
||||
|
@ -1189,7 +1245,6 @@ packages:
|
|||
/escape-string-regexp/1.0.5:
|
||||
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: true
|
||||
|
||||
/escape-string-regexp/4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
|
@ -1667,7 +1722,6 @@ packages:
|
|||
|
||||
/fast-deep-equal/3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
|
||||
/fast-glob/3.2.12:
|
||||
resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
|
||||
|
@ -1739,6 +1793,14 @@ packages:
|
|||
path-exists: 4.0.0
|
||||
dev: true
|
||||
|
||||
/find-up/6.3.0:
|
||||
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
locate-path: 7.2.0
|
||||
path-exists: 5.0.0
|
||||
dev: false
|
||||
|
||||
/flat-cache/3.0.4:
|
||||
resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
|
||||
engines: {node: ^10.12.0 || >=12.0.0}
|
||||
|
@ -1887,8 +1949,11 @@ packages:
|
|||
get-intrinsic: 1.2.0
|
||||
dev: true
|
||||
|
||||
/gpt-3-encoder/1.1.4:
|
||||
resolution: {integrity: sha512-fSQRePV+HUAhCn7+7HL7lNIXNm6eaFWFbNLOOGtmSJ0qJycyQvj60OvRlH7mee8xAMjBDNRdMXlMwjAbMTDjkg==}
|
||||
/gpt3-tokenizer/1.1.5:
|
||||
resolution: {integrity: sha512-O9iCL8MqGR0Oe9wTh0YftzIbysypNQmS5a5JG3cB3M4LMYjlAVvNnf8LUzVY9MrI7tj+YLY356uHtO2lLX2HpA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
array-keyed-map: 2.1.3
|
||||
dev: false
|
||||
|
||||
/grapheme-splitter/1.0.4:
|
||||
|
@ -1902,7 +1967,6 @@ packages:
|
|||
/has-flag/3.0.0:
|
||||
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/has-flag/4.0.0:
|
||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||
|
@ -1941,6 +2005,13 @@ packages:
|
|||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
dev: true
|
||||
|
||||
/hosted-git-info/4.1.0:
|
||||
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: false
|
||||
|
||||
/htmlparser2/8.0.1:
|
||||
resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==}
|
||||
dependencies:
|
||||
|
@ -2041,7 +2112,6 @@ packages:
|
|||
|
||||
/is-arrayish/0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
dev: true
|
||||
|
||||
/is-bigint/1.0.4:
|
||||
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
|
||||
|
@ -2080,7 +2150,6 @@ packages:
|
|||
resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
|
||||
dependencies:
|
||||
has: 1.0.3
|
||||
dev: true
|
||||
|
||||
/is-date-object/1.0.5:
|
||||
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
|
||||
|
@ -2205,7 +2274,6 @@ packages:
|
|||
|
||||
/js-tokens/4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: true
|
||||
|
||||
/js-yaml/4.1.0:
|
||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
||||
|
@ -2231,12 +2299,19 @@ packages:
|
|||
|
||||
/json-parse-even-better-errors/2.3.1:
|
||||
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
|
||||
dev: true
|
||||
|
||||
/json-schema-traverse/0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
dev: true
|
||||
|
||||
/json-schema-traverse/1.0.0:
|
||||
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
|
||||
dev: false
|
||||
|
||||
/json-schema-typed/8.0.1:
|
||||
resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==}
|
||||
dev: false
|
||||
|
||||
/json-stable-stringify-without-jsonify/1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
dev: true
|
||||
|
@ -2279,7 +2354,6 @@ packages:
|
|||
|
||||
/lines-and-columns/1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: true
|
||||
|
||||
/load-tsconfig/0.2.3:
|
||||
resolution: {integrity: sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==}
|
||||
|
@ -2305,6 +2379,13 @@ packages:
|
|||
p-locate: 5.0.0
|
||||
dev: true
|
||||
|
||||
/locate-path/7.2.0:
|
||||
resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
p-locate: 6.0.0
|
||||
dev: false
|
||||
|
||||
/lodash.merge/4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
dev: true
|
||||
|
@ -2322,7 +2403,6 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/mdast-util-from-markdown/0.8.5:
|
||||
resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
|
||||
|
@ -2403,6 +2483,11 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/mimic-fn/4.0.0:
|
||||
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/min-indent/1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -2471,6 +2556,16 @@ packages:
|
|||
validate-npm-package-license: 3.0.4
|
||||
dev: true
|
||||
|
||||
/normalize-package-data/3.0.3:
|
||||
resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
hosted-git-info: 4.1.0
|
||||
is-core-module: 2.11.0
|
||||
semver: 7.3.8
|
||||
validate-npm-package-license: 3.0.4
|
||||
dev: false
|
||||
|
||||
/normalize-path/3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -2567,6 +2662,13 @@ packages:
|
|||
yocto-queue: 0.1.0
|
||||
dev: true
|
||||
|
||||
/p-limit/4.0.0:
|
||||
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
yocto-queue: 1.0.0
|
||||
dev: false
|
||||
|
||||
/p-locate/4.1.0:
|
||||
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -2581,6 +2683,13 @@ packages:
|
|||
p-limit: 3.1.0
|
||||
dev: true
|
||||
|
||||
/p-locate/6.0.0:
|
||||
resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
p-limit: 4.0.0
|
||||
dev: false
|
||||
|
||||
/p-timeout/6.1.1:
|
||||
resolution: {integrity: sha512-yqz2Wi4fiFRpMmK0L2pGAU49naSUaP23fFIQL2Y6YT+qDGPoFwpvgQM/wzc6F8JoenUkIlAFa4Ql7NguXBxI7w==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
@ -2617,7 +2726,6 @@ packages:
|
|||
error-ex: 1.3.2
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 1.2.4
|
||||
dev: true
|
||||
|
||||
/parseurl/1.3.3:
|
||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
|
@ -2629,6 +2737,11 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/path-exists/5.0.0:
|
||||
resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: false
|
||||
|
||||
/path-is-absolute/1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -2707,7 +2820,6 @@ packages:
|
|||
/punycode/2.3.0:
|
||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/qs/6.11.0:
|
||||
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
|
||||
|
@ -2749,6 +2861,15 @@ packages:
|
|||
type-fest: 0.8.1
|
||||
dev: true
|
||||
|
||||
/read-pkg-up/9.1.0:
|
||||
resolution: {integrity: sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
find-up: 6.3.0
|
||||
read-pkg: 7.1.0
|
||||
type-fest: 2.19.0
|
||||
dev: false
|
||||
|
||||
/read-pkg/5.2.0:
|
||||
resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -2759,6 +2880,16 @@ packages:
|
|||
type-fest: 0.6.0
|
||||
dev: true
|
||||
|
||||
/read-pkg/7.1.0:
|
||||
resolution: {integrity: sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==}
|
||||
engines: {node: '>=12.20'}
|
||||
dependencies:
|
||||
'@types/normalize-package-data': 2.4.1
|
||||
normalize-package-data: 3.0.3
|
||||
parse-json: 5.2.0
|
||||
type-fest: 2.19.0
|
||||
dev: false
|
||||
|
||||
/readdirp/3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
@ -2792,6 +2923,11 @@ packages:
|
|||
jsesc: 0.5.0
|
||||
dev: true
|
||||
|
||||
/require-from-string/2.0.2:
|
||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/resolve-from/4.0.0:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -2881,7 +3017,6 @@ packages:
|
|||
hasBin: true
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: true
|
||||
|
||||
/send/0.18.0:
|
||||
resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
|
||||
|
@ -2972,22 +3107,18 @@ packages:
|
|||
dependencies:
|
||||
spdx-expression-parse: 3.0.1
|
||||
spdx-license-ids: 3.0.12
|
||||
dev: true
|
||||
|
||||
/spdx-exceptions/2.3.0:
|
||||
resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
|
||||
dev: true
|
||||
|
||||
/spdx-expression-parse/3.0.1:
|
||||
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
|
||||
dependencies:
|
||||
spdx-exceptions: 2.3.0
|
||||
spdx-license-ids: 3.0.12
|
||||
dev: true
|
||||
|
||||
/spdx-license-ids/3.0.12:
|
||||
resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==}
|
||||
dev: true
|
||||
|
||||
/statuses/2.0.1:
|
||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||
|
@ -3039,6 +3170,10 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/stubborn-fs/1.2.4:
|
||||
resolution: {integrity: sha512-KRa4nIRJ8q6uApQbPwYZVhOof8979fw4xbajBWa5kPJFa4nyY3aFaMWVyIVCDnkNCCG/3HLipUZ4QaNlYsmX1w==}
|
||||
dev: false
|
||||
|
||||
/sucrase/3.29.0:
|
||||
resolution: {integrity: sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -3057,7 +3192,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
has-flag: 3.0.0
|
||||
dev: true
|
||||
|
||||
/supports-color/7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
|
@ -3211,6 +3345,11 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/type-fest/2.19.0:
|
||||
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||
engines: {node: '>=12.20'}
|
||||
dev: false
|
||||
|
||||
/type-is/1.6.18:
|
||||
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
@ -3257,7 +3396,6 @@ packages:
|
|||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
dependencies:
|
||||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/util-deprecate/1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
@ -3278,7 +3416,6 @@ packages:
|
|||
dependencies:
|
||||
spdx-correct: 3.1.1
|
||||
spdx-expression-parse: 3.0.1
|
||||
dev: true
|
||||
|
||||
/vary/1.1.2:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
|
@ -3330,6 +3467,10 @@ packages:
|
|||
webidl-conversions: 4.0.2
|
||||
dev: true
|
||||
|
||||
/when-exit/2.1.0:
|
||||
resolution: {integrity: sha512-H85ulNwUBU1e6PGxkWUDgxnbohSXD++ah6Xw1VHAN7CtypcbZaC4aYjQ+C2PMVaDkURDuOinNAT+Lnz3utWXxQ==}
|
||||
dev: false
|
||||
|
||||
/which-boxed-primitive/1.0.2:
|
||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||
dependencies:
|
||||
|
@ -3376,7 +3517,6 @@ packages:
|
|||
|
||||
/yallist/4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
||||
/yaml-eslint-parser/1.1.0:
|
||||
resolution: {integrity: sha512-b464Q1fYiX1oYx2kE8k4mEp6S9Prk+tfDsY/IPxQ0FCjEuj3AKko5Skf3/yQJeYTTDyjDE+aWIJemnv29HvEWQ==}
|
||||
|
@ -3401,3 +3541,8 @@ packages:
|
|||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/yocto-queue/1.0.0:
|
||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||
engines: {node: '>=12.20'}
|
||||
dev: false
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
reversal?: boolean
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-2 mt-2 rounded-md" :class="[reversal ? 'bg-[#d2f9d1]' : 'bg-[#f4f6f8]']">
|
||||
<span v-highlight class="leading-relaxed whitespace-pre-wrap">
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hljs {
|
||||
background-color: #fff0 !important;
|
||||
}
|
||||
</style>
|
|
@ -1,32 +0,0 @@
|
|||
<script setup lang='ts'>
|
||||
import Avatar from './Avatar.vue'
|
||||
import Text from './Text.vue'
|
||||
|
||||
interface Props {
|
||||
message?: string
|
||||
dateTime?: string
|
||||
reversal?: boolean
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex w-full mb-6" :class="[{ 'flex-row-reverse': reversal }]">
|
||||
<div
|
||||
class="flex items-center justify-center rounded-full overflow-hidden w-[32px] h-[32px]"
|
||||
:class="[reversal ? 'ml-3' : 'mr-3']"
|
||||
>
|
||||
<Avatar :image="reversal" />
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 text-sm" :class="[reversal ? 'items-end' : 'items-start']">
|
||||
<span class="text-xs text-[#b4bbc4]">
|
||||
{{ dateTime }}
|
||||
</span>
|
||||
<Text :reversal="reversal" :error="error">
|
||||
{{ message }}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,26 +0,0 @@
|
|||
import { useHistoryStore } from '@/store'
|
||||
|
||||
export function useChat() {
|
||||
const historyStore = useHistoryStore()
|
||||
|
||||
function addChat(
|
||||
message: string,
|
||||
args?: { reversal?: boolean; error?: boolean; options?: Chat.ChatOptions },
|
||||
) {
|
||||
historyStore.addChat(
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
message,
|
||||
reversal: args?.reversal ?? false,
|
||||
error: args?.error ?? false,
|
||||
options: args?.options ?? undefined,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
function clearChat() {
|
||||
historyStore.clearChat()
|
||||
}
|
||||
|
||||
return { addChat, clearChat }
|
||||
}
|
|
@ -1,208 +0,0 @@
|
|||
<script setup lang='ts'>
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import type { MessageReactive } from 'naive-ui'
|
||||
import { NButton, NInput, useMessage } from 'naive-ui'
|
||||
import { Message } from './components'
|
||||
import { Layout } from './layout'
|
||||
import { useChat } from './hooks/useChat'
|
||||
import { fetchChatAPI } from '@/api'
|
||||
import { HoverButton, SvgIcon } from '@/components/common'
|
||||
import { useHistoryStore } from '@/store'
|
||||
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
||||
|
||||
let controller = new AbortController()
|
||||
|
||||
const ms = useMessage()
|
||||
|
||||
const historyStore = useHistoryStore()
|
||||
|
||||
const { isMobile } = useBasicLayout()
|
||||
|
||||
let messageReactive: MessageReactive | null = null
|
||||
|
||||
const scrollRef = ref<HTMLDivElement>()
|
||||
|
||||
const { addChat, clearChat } = useChat()
|
||||
|
||||
const prompt = ref('')
|
||||
const loading = ref(false)
|
||||
|
||||
const currentActive = computed(() => historyStore.active)
|
||||
const heartbeat = computed(() => historyStore.heartbeat)
|
||||
|
||||
const list = computed<Chat.Chat[]>(() => historyStore.getCurrentChat)
|
||||
const chatList = computed<Chat.Chat[]>(() => list.value.filter(item => (!item.reversal && !item.error)))
|
||||
|
||||
const footerMobileStyle = computed(() => {
|
||||
if (isMobile.value)
|
||||
return ['pl-2', 'pt-2', 'pb-6', 'fixed', 'bottom-0', 'left-0', 'right-0', 'z-30']
|
||||
return []
|
||||
})
|
||||
|
||||
async function handleSubmit() {
|
||||
if (loading.value)
|
||||
return
|
||||
|
||||
controller = new AbortController()
|
||||
|
||||
const message = prompt.value.trim()
|
||||
|
||||
if (!message || !message.length) {
|
||||
ms.warning('Please enter a message')
|
||||
return
|
||||
}
|
||||
|
||||
addMessage(message, { reversal: true })
|
||||
prompt.value = ''
|
||||
|
||||
let options: Chat.ChatOptions = {}
|
||||
const lastContext = chatList.value[chatList.value.length - 1]?.options
|
||||
|
||||
if (lastContext)
|
||||
options = { ...lastContext }
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
createMessage()
|
||||
const { data } = await fetchChatAPI(message, options, controller.signal)
|
||||
addMessage(data?.text ?? '', { options: { conversationId: data.conversationId, parentMessageId: data.id } })
|
||||
}
|
||||
catch (error: any) {
|
||||
if (error.message !== 'canceled')
|
||||
addMessage(`${error.message ?? 'Request failed, please try again later.'}`, { error: true })
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
removeMessage()
|
||||
}
|
||||
}
|
||||
|
||||
function handleEnter(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault()
|
||||
handleSubmit()
|
||||
}
|
||||
}
|
||||
|
||||
function addMessage(
|
||||
message: string,
|
||||
args?: { reversal?: boolean; error?: boolean; options?: Chat.ChatOptions },
|
||||
) {
|
||||
addChat(message, args)
|
||||
scrollToBottom()
|
||||
}
|
||||
|
||||
function scrollToBottom() {
|
||||
nextTick(() => scrollRef.value && (scrollRef.value.scrollTop = scrollRef.value.scrollHeight))
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
handleCancel()
|
||||
clearChat()
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
controller.abort()
|
||||
controller = new AbortController()
|
||||
loading.value = false
|
||||
removeMessage()
|
||||
}
|
||||
|
||||
function createMessage() {
|
||||
if (!messageReactive) {
|
||||
messageReactive = ms.loading('Thinking...', {
|
||||
duration: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function removeMessage() {
|
||||
if (messageReactive) {
|
||||
messageReactive.destroy()
|
||||
messageReactive = null
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
scrollToBottom()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
handleCancel()
|
||||
})
|
||||
|
||||
watch(
|
||||
heartbeat,
|
||||
() => {
|
||||
handleCancel()
|
||||
scrollToBottom()
|
||||
},
|
||||
)
|
||||
|
||||
watch(
|
||||
currentActive,
|
||||
(_, oldActive) => {
|
||||
if (oldActive !== null) {
|
||||
handleCancel()
|
||||
scrollToBottom()
|
||||
}
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<div class="flex flex-col h-full">
|
||||
<main class="flex-1 overflow-hidden">
|
||||
<div
|
||||
ref="scrollRef"
|
||||
class="h-full p-4 overflow-hidden overflow-y-auto"
|
||||
:class="[{ 'p-2': isMobile }]"
|
||||
>
|
||||
<template v-if="!list.length">
|
||||
<div class="flex items-center justify-center mt-4 text-center text-neutral-300">
|
||||
<SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
|
||||
<span>Aha~</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div>
|
||||
<Message
|
||||
v-for="(item, index) of list"
|
||||
:key="index"
|
||||
:date-time="item.dateTime"
|
||||
:message="item.message"
|
||||
:reversal="item.reversal"
|
||||
:error="item.error"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</main>
|
||||
<footer
|
||||
class="p-4"
|
||||
:class="footerMobileStyle"
|
||||
>
|
||||
<div class="flex items-center justify-between space-x-2">
|
||||
<HoverButton tooltip="Clear conversations">
|
||||
<span class="text-xl text-[#4f555e]" @click="handleClear">
|
||||
<SvgIcon icon="ri:delete-bin-line" />
|
||||
</span>
|
||||
</HoverButton>
|
||||
<NInput
|
||||
v-model:value="prompt"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 1, maxRows: 2 }"
|
||||
placeholder="Ask me anything..."
|
||||
@keypress="handleEnter"
|
||||
/>
|
||||
<NButton type="primary" :disabled="loading" @click="handleSubmit">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:send-plane-fill" />
|
||||
</template>
|
||||
</NButton>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
|
@ -1,3 +0,0 @@
|
|||
import Layout from './Layout.vue'
|
||||
|
||||
export { Layout }
|
|
@ -1,79 +0,0 @@
|
|||
<script setup lang='ts'>
|
||||
import { ref } from 'vue'
|
||||
import { NInput, NScrollbar } from 'naive-ui'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
import { useHistoryStore } from '@/store'
|
||||
|
||||
const historyStore = useHistoryStore()
|
||||
|
||||
const dataSources = ref(historyStore.historyChat)
|
||||
|
||||
function handleSelect(index: number) {
|
||||
historyStore.chooseHistory(index)
|
||||
}
|
||||
|
||||
function handleEdit(index: number, isEdit: boolean, event?: MouseEvent) {
|
||||
historyStore.editHistory(index, isEdit)
|
||||
event?.stopPropagation()
|
||||
}
|
||||
|
||||
function handleRemove(index: number, event?: MouseEvent) {
|
||||
historyStore.removeHistory(index)
|
||||
event?.stopPropagation()
|
||||
}
|
||||
|
||||
function handleEnter(index: number, isEdit: boolean, event: KeyboardEvent) {
|
||||
if (event.key === 'Enter') {
|
||||
handleEdit(index, isEdit)
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NScrollbar class="px-4">
|
||||
<div class="flex flex-col gap-2 text-sm">
|
||||
<template v-if="!dataSources.length">
|
||||
<div class="flex flex-col items-center mt-4 text-center text-neutral-300">
|
||||
<SvgIcon icon="ri:inbox-line" class="mb-2 text-3xl" />
|
||||
<span>No history</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-for="(item, index) of dataSources" :key="index">
|
||||
<a
|
||||
class="relative flex items-center gap-3 px-3 py-3 break-all border rounded-md cursor-pointer hover:bg-neutral-100 group"
|
||||
:class="historyStore.active === index && ['border-[#4b9e5f]', 'bg-neutral-100', 'text-[#4b9e5f]', 'pr-14']"
|
||||
@click="handleSelect(index)"
|
||||
>
|
||||
<span>
|
||||
<SvgIcon icon="ri:message-3-line" />
|
||||
</span>
|
||||
<div class="relative flex-1 overflow-hidden break-all text-ellipsis whitespace-nowrap">
|
||||
<NInput
|
||||
v-if="item.isEdit" v-model:value="item.title" size="tiny"
|
||||
@keypress="handleEnter(index, false, $event)"
|
||||
/>
|
||||
<span v-else>{{ item.title }}</span>
|
||||
</div>
|
||||
<div v-if="historyStore.active === index" class="absolute z-10 flex visible right-1">
|
||||
<template v-if="item.isEdit">
|
||||
<button class="p-1" @click="handleEdit(index, false, $event)">
|
||||
<SvgIcon icon="ri:save-line" />
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="p-1">
|
||||
<SvgIcon icon="ri:edit-line" @click="handleEdit(index, true, $event)" />
|
||||
</button>
|
||||
<button class="p-1" @click="handleRemove(index, $event)">
|
||||
<SvgIcon icon="ri:delete-bin-line" />
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</NScrollbar>
|
||||
</template>
|
|
@ -1,3 +1 @@
|
|||
import Chat from './Chat/index.vue'
|
||||
|
||||
export { Chat }
|
||||
export { }
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import type { App, Directive } from 'vue'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
const regexp = /^(?:\s{4}|\t).+/gm
|
||||
function highlightCode(el: HTMLElement) {
|
||||
const regexp = /^(?:\s{4}|\t).+/gm
|
||||
if (el.textContent?.indexOf(' = ') !== -1 || el.textContent.match(regexp))
|
||||
hljs.highlightBlock(el)
|
||||
}
|
||||
|
||||
export default function setupHighlightDirective(app: App) {
|
||||
const highLightDirective: Directive<HTMLElement> = {
|
||||
mounted(el: HTMLElement) {
|
||||
if (el.textContent?.indexOf(' = ') !== -1 || el.textContent.match(regexp))
|
||||
hljs.highlightBlock(el)
|
||||
highlightCode(el)
|
||||
},
|
||||
updated(el: HTMLElement) {
|
||||
highlightCode(el)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
import type { App } from 'vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { ChatLayout } from '@/views/chat/layout'
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: () => import('@/views/home/index.vue'),
|
||||
name: 'Root',
|
||||
component: ChatLayout,
|
||||
redirect: '/chat',
|
||||
children: [
|
||||
{
|
||||
path: '/chat/:uuid?',
|
||||
name: 'Chat',
|
||||
component: () => import('@/views/chat/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import { ss } from '@/utils/storage'
|
||||
|
||||
const LOCAL_NAME = 'chatStorage'
|
||||
|
||||
export function defaultState(): Chat.ChatState {
|
||||
const uuid = Date.now()
|
||||
return { active: uuid, history: [{ uuid, title: 'New Chat', isEdit: false }], chat: [{ uuid, data: [] }] }
|
||||
}
|
||||
|
||||
export function getLocalState(): Chat.ChatState {
|
||||
const localState = ss.get(LOCAL_NAME)
|
||||
return localState ?? defaultState()
|
||||
}
|
||||
|
||||
export function setLocalState(state: Chat.ChatState) {
|
||||
ss.set(LOCAL_NAME, state)
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { getLocalState, setLocalState } from './helper'
|
||||
import { router } from '@/router'
|
||||
|
||||
export const useChatStore = defineStore('chat-store', {
|
||||
state: (): Chat.ChatState => getLocalState(),
|
||||
|
||||
getters: {
|
||||
getChatByUuid(state: Chat.ChatState) {
|
||||
return (uuid?: number) => {
|
||||
if (uuid)
|
||||
return state.chat.find(item => item.uuid === uuid)?.data ?? []
|
||||
return state.chat.find(item => item.uuid === state.active)?.data ?? []
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
addHistory(history: Chat.History, chatData: Chat.Chat[] = []) {
|
||||
this.history.push(history)
|
||||
this.chat.push({ uuid: history.uuid, data: chatData })
|
||||
this.active = history.uuid
|
||||
this.reloadRoute(history.uuid)
|
||||
},
|
||||
|
||||
updateHistory(uuid: number, edit: Partial<Chat.History>) {
|
||||
const index = this.history.findIndex(item => item.uuid === uuid)
|
||||
if (index !== -1) {
|
||||
this.history[index] = { ...this.history[index], ...edit }
|
||||
this.recordState()
|
||||
}
|
||||
},
|
||||
|
||||
async deleteHistory(index: number) {
|
||||
this.history.splice(index, 1)
|
||||
this.chat.splice(index, 1)
|
||||
|
||||
if (this.history.length === 0) {
|
||||
this.active = null
|
||||
this.reloadRoute()
|
||||
return
|
||||
}
|
||||
|
||||
if (index > 0 && index <= this.history.length) {
|
||||
const uuid = this.history[index - 1].uuid
|
||||
this.active = uuid
|
||||
this.reloadRoute(uuid)
|
||||
return
|
||||
}
|
||||
|
||||
if (index === 0) {
|
||||
if (this.history.length > 0) {
|
||||
const uuid = this.history[0].uuid
|
||||
this.active = uuid
|
||||
this.reloadRoute(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
if (index > this.history.length) {
|
||||
const uuid = this.history[this.history.length - 1].uuid
|
||||
this.active = uuid
|
||||
this.reloadRoute(uuid)
|
||||
}
|
||||
},
|
||||
|
||||
setActive(uuid: number) {
|
||||
this.active = uuid
|
||||
this.reloadRoute(uuid)
|
||||
},
|
||||
|
||||
addChatByUuid(uuid: number, chat: Chat.Chat) {
|
||||
if (!uuid || uuid === 0) {
|
||||
if (this.history.length === 0) {
|
||||
const uuid = Date.now()
|
||||
this.history.push({ uuid, title: chat.text, isEdit: false })
|
||||
this.chat.push({ uuid, data: [chat] })
|
||||
this.active = uuid
|
||||
this.recordState()
|
||||
}
|
||||
else {
|
||||
this.chat[0].data.push(chat)
|
||||
if (this.history[0].title === 'New Chat')
|
||||
this.history[0].title = chat.text
|
||||
this.recordState()
|
||||
}
|
||||
}
|
||||
|
||||
const index = this.chat.findIndex(item => item.uuid === uuid)
|
||||
if (index !== -1) {
|
||||
this.chat[index].data.push(chat)
|
||||
if (this.history[index].title === 'New Chat')
|
||||
this.history[index].title = chat.text
|
||||
this.recordState()
|
||||
}
|
||||
},
|
||||
|
||||
updateChatByUuid(uuid: number, index: number, chat: Chat.Chat) {
|
||||
if (!uuid || uuid === 0) {
|
||||
if (this.chat.length) {
|
||||
this.chat[0].data[index] = chat
|
||||
this.recordState()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const chatIndex = this.chat.findIndex(item => item.uuid === uuid)
|
||||
if (chatIndex !== -1) {
|
||||
this.chat[chatIndex].data[index] = chat
|
||||
this.recordState()
|
||||
}
|
||||
},
|
||||
|
||||
clearChatByUuid(uuid: number) {
|
||||
if (!uuid || uuid === 0) {
|
||||
if (this.chat.length) {
|
||||
this.chat[0].data = []
|
||||
this.recordState()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const index = this.chat.findIndex(item => item.uuid === uuid)
|
||||
if (index !== -1) {
|
||||
this.chat[index].data = []
|
||||
this.recordState()
|
||||
}
|
||||
},
|
||||
|
||||
async reloadRoute(uuid?: number) {
|
||||
this.recordState()
|
||||
await router.push({ name: 'Chat', params: { uuid } })
|
||||
},
|
||||
|
||||
recordState() {
|
||||
setLocalState(this.$state)
|
||||
},
|
||||
},
|
||||
})
|
|
@ -1,22 +0,0 @@
|
|||
import { ss } from '@/utils/storage'
|
||||
|
||||
const LOCAL_NAME = 'historyChat'
|
||||
|
||||
export interface HistoryState {
|
||||
historyChat: Chat.HistoryChat[]
|
||||
active: number | null
|
||||
heartbeat: boolean
|
||||
}
|
||||
|
||||
export function defaultSetting() {
|
||||
return { historyChat: [], active: null, heartbeat: false }
|
||||
}
|
||||
|
||||
export function getLocalHistory() {
|
||||
const localSetting: HistoryState | undefined = ss.get(LOCAL_NAME)
|
||||
return localSetting ?? defaultSetting()
|
||||
}
|
||||
|
||||
export function setLocalHistory(data: HistoryState) {
|
||||
ss.set(LOCAL_NAME, data)
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import type { HistoryState } from './helper'
|
||||
import { getLocalHistory, setLocalHistory } from './helper'
|
||||
|
||||
export const useHistoryStore = defineStore('history-store', {
|
||||
state: (): HistoryState => getLocalHistory(),
|
||||
getters: {
|
||||
getCurrentHistory(state): Chat.HistoryChat {
|
||||
if (state.historyChat.length) {
|
||||
if (state.active === null || state.active >= state.historyChat.length || state.active < 0)
|
||||
state.active = 0
|
||||
return state.historyChat[state.active] ?? { title: '', isEdit: false, data: [] }
|
||||
}
|
||||
state.active = null
|
||||
return { title: '', isEdit: false, data: [] }
|
||||
},
|
||||
getCurrentChat(): Chat.Chat[] {
|
||||
return this.getCurrentHistory.data ?? []
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
addChat(data: Chat.Chat) {
|
||||
if (this.active === null) {
|
||||
this.historyChat.push({ title: data.message, isEdit: false, data: [data] })
|
||||
this.active = this.historyChat.length - 1
|
||||
}
|
||||
else {
|
||||
if (this.historyChat[this.active].title === 'New Chat')
|
||||
this.historyChat[this.active].title = data.message
|
||||
|
||||
this.historyChat[this.active].data.push(data)
|
||||
}
|
||||
setLocalHistory(this.$state)
|
||||
},
|
||||
|
||||
clearChat() {
|
||||
if (this.active !== null) {
|
||||
this.historyChat[this.active].data = []
|
||||
setLocalHistory(this.$state)
|
||||
}
|
||||
},
|
||||
|
||||
addHistory(data: Chat.HistoryChat) {
|
||||
this.historyChat.push(data)
|
||||
this.active = this.historyChat.length - 1
|
||||
setLocalHistory(this.$state)
|
||||
},
|
||||
|
||||
editHistory(index: number, isEdit: boolean) {
|
||||
this.historyChat[index].isEdit = isEdit
|
||||
setLocalHistory(this.$state)
|
||||
},
|
||||
|
||||
removeHistory(index: number) {
|
||||
this.historyChat.splice(index, 1)
|
||||
|
||||
if (this.active === index) {
|
||||
if (this.historyChat.length === 0)
|
||||
this.active = null
|
||||
else if (this.active === this.historyChat.length)
|
||||
this.active = this.historyChat.length - 1
|
||||
}
|
||||
|
||||
if (this.historyChat.length === 0)
|
||||
this.active = null
|
||||
|
||||
this.toggleHeartbeat()
|
||||
|
||||
setLocalHistory(this.$state)
|
||||
},
|
||||
|
||||
chooseHistory(index: number) {
|
||||
if (this.active === index)
|
||||
return
|
||||
this.active = index
|
||||
setLocalHistory(this.$state)
|
||||
},
|
||||
|
||||
toggleHeartbeat() {
|
||||
this.heartbeat = !this.heartbeat
|
||||
},
|
||||
},
|
||||
})
|
|
@ -1,2 +1,2 @@
|
|||
export * from './app'
|
||||
export * from './history'
|
||||
export * from './chat'
|
||||
|
|
|
@ -1,20 +1,45 @@
|
|||
declare namespace Chat{
|
||||
interface ChatOptions {
|
||||
declare namespace Chat {
|
||||
|
||||
interface Chat {
|
||||
dateTime: string
|
||||
text: string
|
||||
inversion?: boolean
|
||||
error?: boolean
|
||||
loading?: boolean
|
||||
conversationOptions?: ConversationRequest | null
|
||||
requestOptions: { prompt: string; options?: ConversationRequest | null }
|
||||
}
|
||||
|
||||
interface History {
|
||||
title: string
|
||||
isEdit: boolean
|
||||
uuid: number
|
||||
}
|
||||
|
||||
interface ChatState {
|
||||
active: number | null
|
||||
history: History[]
|
||||
chat: { uuid: number; data: Chat[] }[]
|
||||
}
|
||||
|
||||
interface ConversationRequest {
|
||||
conversationId?: string
|
||||
parentMessageId?: string
|
||||
}
|
||||
|
||||
interface Chat {
|
||||
dateTime: string
|
||||
message: string
|
||||
reversal?: boolean
|
||||
error?: boolean
|
||||
options?: ChatOptions
|
||||
interface ConversationResponse {
|
||||
conversationId: string
|
||||
detail: {
|
||||
choices: { finish_reason: string; index: number; logprobs: any; text: string }[]
|
||||
created: number
|
||||
id: string
|
||||
model: string
|
||||
object: string
|
||||
usage: { completion_tokens: number; prompt_tokens: number; total_tokens: number }
|
||||
}
|
||||
|
||||
interface HistoryChat {
|
||||
title: string
|
||||
isEdit: boolean
|
||||
data: Chat[]
|
||||
id: string
|
||||
parentMessageId: string
|
||||
role: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
inversion?: boolean
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="min-w-[20px] p-2 rounded-md"
|
||||
:class="[inversion ? 'bg-[#d2f9d1]' : 'bg-[#f4f6f8]', { 'text-red-500': error }]"
|
||||
>
|
||||
<span
|
||||
v-highlight
|
||||
class="leading-relaxed whitespace-pre-wrap"
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.hljs {
|
||||
background-color: #fff0 !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,54 @@
|
|||
<script setup lang='ts'>
|
||||
import Avatar from './Avatar.vue'
|
||||
import Text from './Text.vue'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
|
||||
interface Props {
|
||||
dateTime?: string
|
||||
text?: string
|
||||
inversion?: boolean
|
||||
error?: boolean
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
interface Emit {
|
||||
(ev: 'regenerate'): void
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
function handleRegenerate() {
|
||||
emit('regenerate')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex w-full mb-6" :class="[{ 'flex-row-reverse': inversion }]">
|
||||
<div
|
||||
class="flex items-center justify-center rounded-full overflow-hidden w-[32px] h-[32px]"
|
||||
:class="[inversion ? 'ml-3' : 'mr-3']"
|
||||
>
|
||||
<Avatar :image="inversion" />
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 text-sm" :class="[inversion ? 'items-end' : 'items-start']">
|
||||
<span class="text-xs text-[#b4bbc4]">
|
||||
{{ dateTime }}
|
||||
</span>
|
||||
<div class="flex items-end mt-2">
|
||||
<Text :inversion="inversion" :error="error">
|
||||
<span v-if="loading" class="w-[3px] h-[20px] block animate-blink" />
|
||||
<span v-else>{{ text }}</span>
|
||||
</Text>
|
||||
<button
|
||||
v-if="!inversion && !loading"
|
||||
class="mb-2 ml-2 transition text-neutral-400 hover:text-neutral-800"
|
||||
@click="handleRegenerate"
|
||||
>
|
||||
<SvgIcon icon="ri:restart-line" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,18 @@
|
|||
import { useChatStore } from '@/store'
|
||||
|
||||
export function useChat() {
|
||||
const chatStore = useChatStore()
|
||||
|
||||
const addChat = (uuid: number, chat: Chat.Chat) => {
|
||||
chatStore.addChatByUuid(uuid, chat)
|
||||
}
|
||||
|
||||
const updateChat = (uuid: number, index: number, chat: Chat.Chat) => {
|
||||
chatStore.updateChatByUuid(uuid, index, chat)
|
||||
}
|
||||
|
||||
return {
|
||||
addChat,
|
||||
updateChat,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import type { Ref } from 'vue'
|
||||
import { nextTick, ref } from 'vue'
|
||||
|
||||
type ScrollElement = HTMLDivElement | null
|
||||
|
||||
interface ScrollReturn {
|
||||
scrollRef: Ref<ScrollElement>
|
||||
scrollToBottom: () => Promise<void>
|
||||
scrollToTop: () => Promise<void>
|
||||
}
|
||||
|
||||
export function useScroll(): ScrollReturn {
|
||||
const scrollRef = ref<ScrollElement>(null)
|
||||
|
||||
const scrollToBottom = async () => {
|
||||
await nextTick()
|
||||
if (scrollRef.value)
|
||||
scrollRef.value.scrollTop = scrollRef.value.scrollHeight
|
||||
}
|
||||
|
||||
const scrollToTop = async () => {
|
||||
await nextTick()
|
||||
if (scrollRef.value)
|
||||
scrollRef.value.scrollTop = 0
|
||||
}
|
||||
|
||||
return {
|
||||
scrollRef,
|
||||
scrollToBottom,
|
||||
scrollToTop,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,292 @@
|
|||
<script setup lang='ts'>
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { NButton, NInput, useDialog } from 'naive-ui'
|
||||
import { Message } from './components'
|
||||
import { useScroll } from './hooks/useScroll'
|
||||
import { useChat } from './hooks/useChat'
|
||||
import { HoverButton, SvgIcon } from '@/components/common'
|
||||
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
||||
import { useChatStore } from '@/store'
|
||||
import { fetchChatAPI } from '@/api'
|
||||
|
||||
let controller = new AbortController()
|
||||
|
||||
const route = useRoute()
|
||||
const dialog = useDialog()
|
||||
|
||||
const chatStore = useChatStore()
|
||||
|
||||
const { isMobile } = useBasicLayout()
|
||||
const { addChat, updateChat } = useChat()
|
||||
const { scrollRef, scrollToBottom } = useScroll()
|
||||
|
||||
const { uuid } = route.params as { uuid: string }
|
||||
|
||||
const dataSources = computed(() => chatStore.getChatByUuid(+uuid))
|
||||
const conversationList = computed(() => dataSources.value.filter(item => (!item.inversion && !item.error)))
|
||||
|
||||
const prompt = ref<string>('')
|
||||
const loading = ref<boolean>(false)
|
||||
|
||||
function handleSubmit() {
|
||||
onConversation()
|
||||
}
|
||||
|
||||
async function onConversation() {
|
||||
const message = prompt.value
|
||||
|
||||
if (loading.value)
|
||||
return
|
||||
|
||||
if (!message || message.trim() === '')
|
||||
return
|
||||
|
||||
controller = new AbortController()
|
||||
|
||||
addChat(
|
||||
+uuid,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: message,
|
||||
inversion: true,
|
||||
error: false,
|
||||
conversationOptions: null,
|
||||
requestOptions: { prompt: message, options: null },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
|
||||
loading.value = true
|
||||
prompt.value = ''
|
||||
|
||||
let options: Chat.ConversationRequest = {}
|
||||
const lastContext = conversationList.value[conversationList.value.length - 1]?.conversationOptions
|
||||
|
||||
if (lastContext)
|
||||
options = { ...lastContext }
|
||||
|
||||
addChat(
|
||||
+uuid,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: 'Aha, Thinking...',
|
||||
loading: true,
|
||||
inversion: false,
|
||||
error: false,
|
||||
conversationOptions: null,
|
||||
requestOptions: { prompt: message, options: { ...options } },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
|
||||
try {
|
||||
const { data } = await fetchChatAPI<Chat.ConversationResponse>(message, options, controller.signal)
|
||||
updateChat(
|
||||
+uuid,
|
||||
dataSources.value.length - 1,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: data.text ?? '',
|
||||
inversion: false,
|
||||
error: false,
|
||||
loading: false,
|
||||
conversationOptions: { conversationId: data.conversationId, parentMessageId: data.id },
|
||||
requestOptions: { prompt: message, options: { ...options } },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
}
|
||||
catch (error: any) {
|
||||
let errorMessage = error?.message ?? 'Something went wrong, please try again later.'
|
||||
|
||||
if (error.message === 'canceled')
|
||||
errorMessage = 'Request canceled. Please try again.'
|
||||
|
||||
updateChat(
|
||||
+uuid,
|
||||
dataSources.value.length - 1,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: errorMessage,
|
||||
inversion: false,
|
||||
error: true,
|
||||
loading: false,
|
||||
conversationOptions: null,
|
||||
requestOptions: { prompt: message, options: { ...options } },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function onRegenerate(index: number) {
|
||||
if (loading.value)
|
||||
return
|
||||
|
||||
controller = new AbortController()
|
||||
|
||||
const { requestOptions } = dataSources.value[index]
|
||||
|
||||
const message = requestOptions?.prompt ?? ''
|
||||
|
||||
let options: Chat.ConversationRequest = {}
|
||||
|
||||
if (requestOptions.options)
|
||||
options = { ...requestOptions.options }
|
||||
|
||||
loading.value = true
|
||||
|
||||
updateChat(
|
||||
+uuid,
|
||||
index,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: 'Aha, Let me think again...',
|
||||
inversion: false,
|
||||
error: false,
|
||||
loading: true,
|
||||
conversationOptions: null,
|
||||
requestOptions: { prompt: message, ...options },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
|
||||
try {
|
||||
const { data } = await fetchChatAPI<Chat.ConversationResponse>(message, options, controller.signal)
|
||||
updateChat(
|
||||
+uuid,
|
||||
index,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: data.text ?? '',
|
||||
inversion: false,
|
||||
error: false,
|
||||
loading: false,
|
||||
conversationOptions: { conversationId: data.conversationId, parentMessageId: data.id },
|
||||
requestOptions: { prompt: message, ...options },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
}
|
||||
catch (error: any) {
|
||||
let errorMessage = 'Something went wrong, please try again later.'
|
||||
|
||||
if (error.message === 'canceled')
|
||||
errorMessage = 'Request canceled. Please try again.'
|
||||
|
||||
updateChat(
|
||||
+uuid,
|
||||
index,
|
||||
{
|
||||
dateTime: new Date().toLocaleString(),
|
||||
text: errorMessage,
|
||||
inversion: false,
|
||||
error: true,
|
||||
loading: false,
|
||||
conversationOptions: null,
|
||||
requestOptions: { prompt: message, ...options },
|
||||
},
|
||||
)
|
||||
scrollToBottom()
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
if (loading.value)
|
||||
return
|
||||
|
||||
dialog.warning({
|
||||
title: 'Clear Chat',
|
||||
content: 'Are you sure to clear this chat?',
|
||||
positiveText: 'Yes',
|
||||
negativeText: 'No',
|
||||
onPositiveClick: () => {
|
||||
chatStore.clearChatByUuid(+uuid)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handleEnter(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault()
|
||||
handleSubmit()
|
||||
}
|
||||
}
|
||||
|
||||
const buttonDisabled = computed(() => {
|
||||
return loading.value || !prompt.value || prompt.value.trim() === ''
|
||||
})
|
||||
|
||||
const footerClass = computed(() => {
|
||||
let classes = ['p-4']
|
||||
if (isMobile.value)
|
||||
classes = [...classes, 'pl-2', 'pt-2', 'pb-2', 'fixed', 'bottom-0', 'left-0', 'right-0', 'z-30']
|
||||
return classes
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
scrollToBottom()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (loading.value)
|
||||
controller.abort()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col h-full">
|
||||
<main class="flex-1 overflow-hidden">
|
||||
<div ref="scrollRef" class="h-full p-4 overflow-hidden overflow-y-auto" :class="[{ 'p-2': isMobile }]">
|
||||
<template v-if="!dataSources.length">
|
||||
<div class="flex items-center justify-center mt-4 text-center text-neutral-300">
|
||||
<SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
|
||||
<span>Aha~</span>
|
||||
</div>
|
||||
</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)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</main>
|
||||
<footer :class="footerClass">
|
||||
<div class="flex items-center justify-between space-x-2">
|
||||
<HoverButton @click="handleClear">
|
||||
<span class="text-xl text-[#4f555e]">
|
||||
<SvgIcon icon="ri:delete-bin-line" />
|
||||
</span>
|
||||
</HoverButton>
|
||||
<NInput
|
||||
v-model:value="prompt"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 1, maxRows: 2 }"
|
||||
placeholder="Ask me anything..."
|
||||
@keypress="handleEnter"
|
||||
/>
|
||||
<NButton type="primary" :disabled="buttonDisabled" @click="handleSubmit">
|
||||
<template #icon>
|
||||
<SvgIcon icon="ri:send-plane-fill" />
|
||||
</template>
|
||||
</NButton>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
|
@ -22,7 +22,6 @@ const getContainerClass = computed(() => {
|
|||
return [
|
||||
'h-full',
|
||||
{ 'pt-14': isMobile.value },
|
||||
{ 'pb-[70px]': isMobile.value },
|
||||
{ 'pl-[260px]': !isMobile.value && !collapsed.value },
|
||||
]
|
||||
})
|
||||
|
@ -35,7 +34,9 @@ const getContainerClass = computed(() => {
|
|||
<Sider />
|
||||
<Header v-if="isMobile" />
|
||||
<NLayoutContent class="h-full">
|
||||
<slot />
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</RouterView>
|
||||
</NLayoutContent>
|
||||
</NLayout>
|
||||
</div>
|
|
@ -1,19 +1,15 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
import { useAppStore, useHistoryStore } from '@/store'
|
||||
import { useAppStore, useChatStore } from '@/store'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const historyStore = useHistoryStore()
|
||||
const chatStore = useChatStore()
|
||||
|
||||
const collapsed = computed(() => appStore.siderCollapsed)
|
||||
|
||||
function handleAdd() {
|
||||
historyStore.addHistory({
|
||||
title: 'New Chat',
|
||||
isEdit: false,
|
||||
data: [],
|
||||
})
|
||||
chatStore.addHistory({ title: 'New Chat', uuid: Date.now(), isEdit: false })
|
||||
}
|
||||
|
||||
function handleUpdateCollapsed() {
|
|
@ -0,0 +1,3 @@
|
|||
import ChatLayout from './Layout.vue'
|
||||
|
||||
export { ChatLayout }
|
|
@ -0,0 +1,92 @@
|
|||
<script setup lang='ts'>
|
||||
import { computed } from 'vue'
|
||||
import { NInput, NPopconfirm, NScrollbar } from 'naive-ui'
|
||||
import { SvgIcon } from '@/components/common'
|
||||
import { useChatStore } from '@/store'
|
||||
|
||||
const chatStore = useChatStore()
|
||||
|
||||
const dataSources = computed(() => chatStore.history)
|
||||
|
||||
async function handleSelect({ uuid }: Chat.History) {
|
||||
if (isActive(uuid))
|
||||
return
|
||||
|
||||
chatStore.setActive(uuid)
|
||||
}
|
||||
|
||||
function handleEdit({ uuid }: Chat.History, isEdit: boolean, event?: MouseEvent) {
|
||||
event?.stopPropagation()
|
||||
chatStore.updateHistory(uuid, { isEdit })
|
||||
}
|
||||
|
||||
function handleDelete(index: number, event?: MouseEvent | TouchEvent) {
|
||||
event?.stopPropagation()
|
||||
chatStore.deleteHistory(index)
|
||||
}
|
||||
|
||||
function handleEnter({ uuid }: Chat.History, isEdit: boolean, event: KeyboardEvent) {
|
||||
event?.stopPropagation()
|
||||
if (event.key === 'Enter')
|
||||
chatStore.updateHistory(uuid, { isEdit })
|
||||
}
|
||||
|
||||
function isActive(uuid: number) {
|
||||
return chatStore.active === uuid
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NScrollbar class="px-4">
|
||||
<div class="flex flex-col gap-2 text-sm">
|
||||
<template v-if="!dataSources.length">
|
||||
<div class="flex flex-col items-center mt-4 text-center text-neutral-300">
|
||||
<SvgIcon icon="ri:inbox-line" class="mb-2 text-3xl" />
|
||||
<span>No history</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div v-for="(item, index) of dataSources" :key="index">
|
||||
<a
|
||||
class="relative flex items-center gap-3 px-3 py-3 break-all border rounded-md cursor-pointer hover:bg-neutral-100 group"
|
||||
:class="isActive(item.uuid) && ['border-[#4b9e5f]', 'bg-neutral-100', 'text-[#4b9e5f]', 'pr-14']"
|
||||
@click="handleSelect(item)"
|
||||
>
|
||||
<span>
|
||||
<SvgIcon icon="ri:message-3-line" />
|
||||
</span>
|
||||
<div class="relative flex-1 overflow-hidden break-all text-ellipsis whitespace-nowrap">
|
||||
<NInput
|
||||
v-if="item.isEdit"
|
||||
v-model:value="item.title"
|
||||
size="tiny"
|
||||
@keypress="handleEnter(item, false, $event)"
|
||||
/>
|
||||
<span v-else>{{ item.title }}</span>
|
||||
</div>
|
||||
<div v-if="isActive(item.uuid)" class="absolute z-10 flex visible right-1">
|
||||
<template v-if="item.isEdit">
|
||||
<button class="p-1" @click="handleEdit(item, false, $event)">
|
||||
<SvgIcon icon="ri:save-line" />
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="p-1">
|
||||
<SvgIcon icon="ri:edit-line" @click="handleEdit(item, true, $event)" />
|
||||
</button>
|
||||
<NPopconfirm placement="bottom" @positive-click="handleDelete(index, $event)">
|
||||
<template #trigger>
|
||||
<button class="p-1">
|
||||
<SvgIcon icon="ri:delete-bin-line" />
|
||||
</button>
|
||||
</template>
|
||||
Are you sure to clear this history?
|
||||
</NPopconfirm>
|
||||
</template>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</NScrollbar>
|
||||
</template>
|
|
@ -1,29 +1,37 @@
|
|||
<script setup lang='ts'>
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { computed, watch } from 'vue'
|
||||
import { NButton, NLayoutSider } from 'naive-ui'
|
||||
import List from './List.vue'
|
||||
import { HoverButton, SvgIcon, UserAvatar } from '@/components/common'
|
||||
import { useAppStore, useHistoryStore } from '@/store'
|
||||
import { useAppStore, useChatStore } from '@/store'
|
||||
import { useBasicLayout } from '@/hooks/useBasicLayout'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const historyStore = useHistoryStore()
|
||||
const chatStore = useChatStore()
|
||||
|
||||
const { isMobile } = useBasicLayout()
|
||||
|
||||
const collapsed = computed(() => appStore.siderCollapsed)
|
||||
|
||||
function handleAdd() {
|
||||
historyStore.addHistory({
|
||||
title: 'New Chat',
|
||||
isEdit: false,
|
||||
data: [],
|
||||
})
|
||||
chatStore.addHistory({ title: 'New Chat', uuid: Date.now(), isEdit: false })
|
||||
}
|
||||
|
||||
function handleUpdateCollapsed() {
|
||||
appStore.setSiderCollapsed(!collapsed.value)
|
||||
}
|
||||
|
||||
const getMobileClass = computed<CSSProperties>(() => {
|
||||
if (isMobile.value) {
|
||||
return {
|
||||
position: 'fixed',
|
||||
zIndex: 50,
|
||||
}
|
||||
}
|
||||
return {}
|
||||
})
|
||||
|
||||
watch(
|
||||
isMobile,
|
||||
(val) => {
|
||||
|
@ -45,7 +53,7 @@ watch(
|
|||
collapse-mode="transform"
|
||||
position="absolute"
|
||||
bordered
|
||||
style="z-index: 50;"
|
||||
:style="getMobileClass"
|
||||
@update-collapsed="handleUpdateCollapsed"
|
||||
>
|
||||
<div class="flex flex-col h-full" :class="[{ 'pt-14': isMobile }]">
|
||||
|
@ -57,7 +65,7 @@ watch(
|
|||
</div>
|
||||
<List />
|
||||
</main>
|
||||
<footer class="flex items-center justify-between min-w-0 p-4 overflow-hidden border-t h-[70px]">
|
||||
<footer class="flex items-center justify-between min-w-0 p-4 overflow-hidden border-t">
|
||||
<UserAvatar />
|
||||
<HoverButton tooltip="Setting">
|
||||
<span class="text-xl text-[#4f555e]">
|
||||
|
@ -68,6 +76,6 @@ watch(
|
|||
</div>
|
||||
</NLayoutSider>
|
||||
<template v-if="isMobile">
|
||||
<div v-show="!collapsed" class="absolute inset-0 z-40 bg-black/40" @click="handleUpdateCollapsed" />
|
||||
<div v-show="!collapsed" class="fixed inset-0 z-40 bg-black/40" @click="handleUpdateCollapsed" />
|
||||
</template>
|
||||
</template>
|
|
@ -1,7 +0,0 @@
|
|||
<script setup lang='ts'>
|
||||
import { Chat } from '@/components/business'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Chat />
|
||||
</template>
|
|
@ -5,7 +5,17 @@ module.exports = {
|
|||
'./src/**/*.{vue,js,ts,jsx,tsx}',
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
animation: {
|
||||
blink: 'blink 1.2s infinite steps(1, start)',
|
||||
},
|
||||
keyframes: {
|
||||
blink: {
|
||||
'0%, 100%': { 'background-color': '#000' },
|
||||
'50%': { 'background-color': 'transparent' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue