Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/png" href="/logo.png" />
|
<link rel="icon" type="image/png" href="/logo.png" />
|
||||||
|
<meta name="description" content="An AI frontend for both light and core users.">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>RisuAI</title>
|
<title>RisuAI</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
4363
package-lock.json
generated
4363
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/css-tools": "4.3.0-beta.2",
|
"@adobe/css-tools": "4.3.0-beta.2",
|
||||||
"@dqbd/tiktoken": "^1.0.4",
|
"@dqbd/tiktoken": "^1.0.4",
|
||||||
"@msgpack/msgpack": "3.0.0-beta2",
|
|
||||||
"@tauri-apps/api": "1.3.0",
|
"@tauri-apps/api": "1.3.0",
|
||||||
"@xenova/transformers": "^2.1.1",
|
"@xenova/transformers": "^2.1.1",
|
||||||
"blueimp-md5": "^2.19.0",
|
"blueimp-md5": "^2.19.0",
|
||||||
@@ -27,6 +26,7 @@
|
|||||||
"dompurify": "^3.0.1",
|
"dompurify": "^3.0.1",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"fflate": "^0.8.0",
|
||||||
"gpt-3-encoder": "^1.1.4",
|
"gpt-3-encoder": "^1.1.4",
|
||||||
"gpt3-tokenizer": "^1.1.5",
|
"gpt3-tokenizer": "^1.1.5",
|
||||||
"isomorphic-dompurify": "^1.2.0",
|
"isomorphic-dompurify": "^1.2.0",
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-svelte": "^0.130.0",
|
"lucide-svelte": "^0.130.0",
|
||||||
"mobile-drag-drop": "3.0.0-rc.0",
|
"mobile-drag-drop": "3.0.0-rc.0",
|
||||||
|
"msgpackr": "^1.9.5",
|
||||||
"node-html-parser": "^6.1.5",
|
"node-html-parser": "^6.1.5",
|
||||||
"pako": "^2.1.0",
|
|
||||||
"png-chunk-text": "^1.0.0",
|
"png-chunk-text": "^1.0.0",
|
||||||
"png-chunks-encode": "^1.0.0",
|
"png-chunks-encode": "^1.0.0",
|
||||||
"png-chunks-extract": "^1.0.0",
|
"png-chunks-extract": "^1.0.0",
|
||||||
@@ -58,7 +58,6 @@
|
|||||||
"@types/lodash.clonedeep": "^4.5.7",
|
"@types/lodash.clonedeep": "^4.5.7",
|
||||||
"@types/lodash.isequal": "^4.5.6",
|
"@types/lodash.isequal": "^4.5.6",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/pako": "^2.0.0",
|
|
||||||
"@types/pngjs": "^6.0.1",
|
"@types/pngjs": "^6.0.1",
|
||||||
"@types/showdown": "^2.0.0",
|
"@types/showdown": "^2.0.0",
|
||||||
"@types/uuid": "^9.0.1",
|
"@types/uuid": "^9.0.1",
|
||||||
|
|||||||
104
pnpm-lock.yaml
generated
104
pnpm-lock.yaml
generated
@@ -7,9 +7,6 @@ dependencies:
|
|||||||
'@dqbd/tiktoken':
|
'@dqbd/tiktoken':
|
||||||
specifier: ^1.0.4
|
specifier: ^1.0.4
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
'@msgpack/msgpack':
|
|
||||||
specifier: 3.0.0-beta2
|
|
||||||
version: 3.0.0-beta2
|
|
||||||
'@tauri-apps/api':
|
'@tauri-apps/api':
|
||||||
specifier: 1.3.0
|
specifier: 1.3.0
|
||||||
version: 1.3.0
|
version: 1.3.0
|
||||||
@@ -40,6 +37,9 @@ dependencies:
|
|||||||
express:
|
express:
|
||||||
specifier: ^4.18.2
|
specifier: ^4.18.2
|
||||||
version: 4.18.2
|
version: 4.18.2
|
||||||
|
fflate:
|
||||||
|
specifier: ^0.8.0
|
||||||
|
version: 0.8.0
|
||||||
gpt-3-encoder:
|
gpt-3-encoder:
|
||||||
specifier: ^1.1.4
|
specifier: ^1.1.4
|
||||||
version: 1.1.4
|
version: 1.1.4
|
||||||
@@ -61,12 +61,12 @@ dependencies:
|
|||||||
mobile-drag-drop:
|
mobile-drag-drop:
|
||||||
specifier: 3.0.0-rc.0
|
specifier: 3.0.0-rc.0
|
||||||
version: 3.0.0-rc.0
|
version: 3.0.0-rc.0
|
||||||
|
msgpackr:
|
||||||
|
specifier: ^1.9.5
|
||||||
|
version: 1.9.5
|
||||||
node-html-parser:
|
node-html-parser:
|
||||||
specifier: ^6.1.5
|
specifier: ^6.1.5
|
||||||
version: 6.1.5
|
version: 6.1.5
|
||||||
pako:
|
|
||||||
specifier: ^2.1.0
|
|
||||||
version: 2.1.0
|
|
||||||
png-chunk-text:
|
png-chunk-text:
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
@@ -129,9 +129,6 @@ devDependencies:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^18.7.10
|
specifier: ^18.7.10
|
||||||
version: 18.15.11
|
version: 18.15.11
|
||||||
'@types/pako':
|
|
||||||
specifier: ^2.0.0
|
|
||||||
version: 2.0.0
|
|
||||||
'@types/pngjs':
|
'@types/pngjs':
|
||||||
specifier: ^6.0.1
|
specifier: ^6.0.1
|
||||||
version: 6.0.1
|
version: 6.0.1
|
||||||
@@ -405,10 +402,53 @@ packages:
|
|||||||
'@jridgewell/sourcemap-codec': 1.4.14
|
'@jridgewell/sourcemap-codec': 1.4.14
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@msgpack/msgpack@3.0.0-beta2:
|
/@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.2:
|
||||||
resolution: {integrity: sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw==}
|
resolution: {integrity: sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==}
|
||||||
engines: {node: '>= 14'}
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.2:
|
||||||
|
resolution: {integrity: sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.2:
|
||||||
|
resolution: {integrity: sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@msgpackr-extract/msgpackr-extract-linux-arm@3.0.2:
|
||||||
|
resolution: {integrity: sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@msgpackr-extract/msgpackr-extract-linux-x64@3.0.2:
|
||||||
|
resolution: {integrity: sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2:
|
||||||
|
resolution: {integrity: sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
requiresBuild: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
/@nodelib/fs.scandir@2.1.5:
|
/@nodelib/fs.scandir@2.1.5:
|
||||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||||
@@ -784,10 +824,6 @@ packages:
|
|||||||
/@types/node@18.15.11:
|
/@types/node@18.15.11:
|
||||||
resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==}
|
resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==}
|
||||||
|
|
||||||
/@types/pako@2.0.0:
|
|
||||||
resolution: {integrity: sha512-10+iaz93qR5WYxTo+PMifD5TSxiOtdRaxBf7INGGXMQgTCu8Z/7GYWYFUOS3q/G0nE5boj1r4FEB+WSy7s5gbA==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/pngjs@6.0.1:
|
/@types/pngjs@6.0.1:
|
||||||
resolution: {integrity: sha512-J39njbdW1U/6YyVXvC9+1iflZghP8jgRf2ndYghdJb5xL49LYDB+1EuAxfbuJ2IBbWIL3AjHPQhgaTxT3YaYeg==}
|
resolution: {integrity: sha512-J39njbdW1U/6YyVXvC9+1iflZghP8jgRf2ndYghdJb5xL49LYDB+1EuAxfbuJ2IBbWIL3AjHPQhgaTxT3YaYeg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1505,6 +1541,10 @@ packages:
|
|||||||
reusify: 1.0.4
|
reusify: 1.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/fflate@0.8.0:
|
||||||
|
resolution: {integrity: sha512-FAdS4qMuFjsJj6XHbBaZeXOgaypXp8iw/Tpyuq/w3XA41jjLHT8NPA+n7czH/DDhdncq0nAyDZmPeWXh2qmdIg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fill-range@7.0.1:
|
/fill-range@7.0.1:
|
||||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -2079,6 +2119,28 @@ packages:
|
|||||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/msgpackr-extract@3.0.2:
|
||||||
|
resolution: {integrity: sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
dependencies:
|
||||||
|
node-gyp-build-optional-packages: 5.0.7
|
||||||
|
optionalDependencies:
|
||||||
|
'@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.2
|
||||||
|
'@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.2
|
||||||
|
'@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.2
|
||||||
|
'@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.2
|
||||||
|
'@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.2
|
||||||
|
'@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.2
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
/msgpackr@1.9.5:
|
||||||
|
resolution: {integrity: sha512-/IJ3cFSN6Ci3eG2wLhbFEL6GT63yEaoN/R5My2QkV6zro+OJaVRLPlwvxY7EtHYSmDlQpk8stvOQTL2qJFkDRg==}
|
||||||
|
optionalDependencies:
|
||||||
|
msgpackr-extract: 3.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/mz@2.7.0:
|
/mz@2.7.0:
|
||||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2113,6 +2175,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==}
|
resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-gyp-build-optional-packages@5.0.7:
|
||||||
|
resolution: {integrity: sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
optional: true
|
||||||
|
|
||||||
/node-html-parser@6.1.5:
|
/node-html-parser@6.1.5:
|
||||||
resolution: {integrity: sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg==}
|
resolution: {integrity: sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2244,10 +2312,6 @@ packages:
|
|||||||
p-finally: 1.0.0
|
p-finally: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/pako@2.1.0:
|
|
||||||
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/parent-module@1.0.1:
|
/parent-module@1.0.1:
|
||||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|||||||
4
src-tauri/Cargo.lock
generated
4
src-tauri/Cargo.lock
generated
@@ -3182,9 +3182,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.28.1"
|
version = "1.28.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
|
checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "RisuAI",
|
"productName": "RisuAI",
|
||||||
"version": "1.27.1"
|
"version": "1.27.4"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||
@@ -304,6 +304,8 @@ export const languageChinese = {
|
|||||||
tags: "标签",
|
tags: "标签",
|
||||||
copied: "已复制",
|
copied: "已复制",
|
||||||
useChatCopy: "使用聊天复制",
|
useChatCopy: "使用聊天复制",
|
||||||
|
useChatSticker: "使用聊天贴纸",
|
||||||
|
useAdditionalAssetsPreview: "使用附加资源预览",
|
||||||
autoTranslateInput: "使用自动翻译输入",
|
autoTranslateInput: "使用自动翻译输入",
|
||||||
enterMessageForTranslateToEnglish: "输入要翻译为英语的消息",
|
enterMessageForTranslateToEnglish: "输入要翻译为英语的消息",
|
||||||
recent: '最新',
|
recent: '最新',
|
||||||
|
|||||||
@@ -308,6 +308,8 @@ export const languageEnglish = {
|
|||||||
backgroundHTML: "Background Embedding",
|
backgroundHTML: "Background Embedding",
|
||||||
copied: "Copied",
|
copied: "Copied",
|
||||||
useChatCopy: "Use Chat Message Copy",
|
useChatCopy: "Use Chat Message Copy",
|
||||||
|
useChatSticker: "Use Chat Sticker",
|
||||||
|
useAdditionalAssetsPreview: "Use Additional Assets Preview",
|
||||||
autoTranslateInput: "Auto Translate Input",
|
autoTranslateInput: "Auto Translate Input",
|
||||||
enterMessageForTranslateToEnglish: "Enter Message for Translate to English",
|
enterMessageForTranslateToEnglish: "Enter Message for Translate to English",
|
||||||
recent: 'Recent',
|
recent: 'Recent',
|
||||||
|
|||||||
@@ -280,6 +280,8 @@ export const languageKorean = {
|
|||||||
backgroundHTML: "백그라운드 임베딩",
|
backgroundHTML: "백그라운드 임베딩",
|
||||||
copied: "복사됨",
|
copied: "복사됨",
|
||||||
useChatCopy: "채팅 메시지 복사 사용",
|
useChatCopy: "채팅 메시지 복사 사용",
|
||||||
|
useChatSticker: "채팅 스티커 사용",
|
||||||
|
useAdditionalAssetsPreview: "추가 에셋 미리보기 사용",
|
||||||
autoTranslateInput: "입력 자동 번역",
|
autoTranslateInput: "입력 자동 번역",
|
||||||
enterMessageForTranslateToEnglish: "영어로 번역할 메시지를 입력해주세요",
|
enterMessageForTranslateToEnglish: "영어로 번역할 메시지를 입력해주세요",
|
||||||
imageCompression: "이미지 압축",
|
imageCompression: "이미지 압축",
|
||||||
|
|||||||
75
src/lib/ChatScreens/AssetInput.svelte
Normal file
75
src/lib/ChatScreens/AssetInput.svelte
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { FileAudioIcon, PlusIcon } from "lucide-svelte";
|
||||||
|
import { DataBase, setDatabase, type character, type groupChat } from "src/ts/storage/database";
|
||||||
|
import { getFileSrc, saveAsset } from "src/ts/storage/globalApi";
|
||||||
|
import { selectMultipleFile } from "src/ts/util";
|
||||||
|
export let currentCharacter:character|groupChat;
|
||||||
|
export let onSelect:(additionalAsset:[string,string,string])=>void;
|
||||||
|
let assetFileExtensions:string[] = []
|
||||||
|
let assetFilePath:string[] = []
|
||||||
|
|
||||||
|
$:{
|
||||||
|
if(currentCharacter.type ==='character'){
|
||||||
|
if(currentCharacter.additionalAssets){
|
||||||
|
for(let i = 0; i < currentCharacter.additionalAssets.length; i++){
|
||||||
|
// console.log('check content type ...', currentCharacter.additionalAssets[i][0], currentCharacter.additionalAssets[i][1]);
|
||||||
|
if(currentCharacter.additionalAssets[i].length > 2 && currentCharacter.additionalAssets[i][2]) {
|
||||||
|
assetFileExtensions[i] = currentCharacter.additionalAssets[i][2]
|
||||||
|
} else {
|
||||||
|
assetFileExtensions[i] = currentCharacter.additionalAssets[i][1].split('.').pop()
|
||||||
|
}
|
||||||
|
getFileSrc(currentCharacter.additionalAssets[i][1]).then((filePath) => {
|
||||||
|
assetFilePath[i] = filePath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{#if currentCharacter.type ==='character'}
|
||||||
|
<button class="hover:text-green-500 bg-gray-500 flex justify-center items-center w-16 h-16 m-1 rounded-md" on:click={async () => {
|
||||||
|
if(currentCharacter.type === 'character'){
|
||||||
|
const da = await selectMultipleFile(['png', 'webp', 'mp4', 'mp3', 'gif'])
|
||||||
|
currentCharacter.additionalAssets = currentCharacter.additionalAssets ?? []
|
||||||
|
if(!da){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for(const f of da){
|
||||||
|
console.log(f)
|
||||||
|
const img = f.data
|
||||||
|
const name = f.name
|
||||||
|
const extension = name.split('.').pop().toLowerCase()
|
||||||
|
const imgp = await saveAsset(img,'',extension)
|
||||||
|
currentCharacter.additionalAssets.push([name, imgp, extension])
|
||||||
|
currentCharacter = currentCharacter
|
||||||
|
}
|
||||||
|
const db = get(DataBase);
|
||||||
|
setDatabase(db)
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<PlusIcon />
|
||||||
|
</button>
|
||||||
|
{#if currentCharacter.additionalAssets}
|
||||||
|
{#each currentCharacter.additionalAssets as additionalAsset, i}
|
||||||
|
<button on:click={()=>{
|
||||||
|
onSelect(additionalAsset)
|
||||||
|
}}>
|
||||||
|
{#if assetFilePath[i]}
|
||||||
|
{#if assetFileExtensions[i] === 'mp4'}
|
||||||
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
|
<video class="w-16 h-16 m-1 rounded-md"><source src={assetFilePath[i]} type="video/mp4"></video>
|
||||||
|
{:else if assetFileExtensions[i] === 'mp3'}
|
||||||
|
<div class='w-16 h-16 m-1 rounded-md bg-slate-500 flex flex-col justify-center items-center'>
|
||||||
|
<FileAudioIcon/>
|
||||||
|
<div class='w-16 px-1 text-ellipsis whitespace-nowrap overflow-hidden'>{additionalAsset[0]}</div>
|
||||||
|
</div>
|
||||||
|
<!-- <audio controls class="w-16 h-16 m-1 rounded-md"><source src={assetPath} type="audio/mpeg"></audio> -->
|
||||||
|
{:else}
|
||||||
|
<img src={assetFilePath[i]} class="w-16 h-16 m-1 rounded-md" alt={additionalAsset[0]}/>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
import { selectedCharID } from "../../ts/stores";
|
import { selectedCharID } from "../../ts/stores";
|
||||||
import { translate } from "../../ts/translator/translator";
|
import { translate } from "../../ts/translator/translator";
|
||||||
import { replacePlaceholders } from "../../ts/util";
|
import { replacePlaceholders } from "../../ts/util";
|
||||||
|
|
||||||
export let message = ''
|
export let message = ''
|
||||||
export let name = ''
|
export let name = ''
|
||||||
export let isLastMemory:boolean
|
export let isLastMemory:boolean
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
export let onReroll = () => {}
|
export let onReroll = () => {}
|
||||||
export let unReroll = () => {}
|
export let unReroll = () => {}
|
||||||
export let character:character|groupChat|null = null
|
export let character:character|groupChat|null = null
|
||||||
|
let md:string
|
||||||
let translating = false
|
let translating = false
|
||||||
let editMode = false
|
let editMode = false
|
||||||
let statusMessage:string = ''
|
let statusMessage:string = ''
|
||||||
@@ -24,7 +26,8 @@
|
|||||||
|
|
||||||
let msgDisplay = ''
|
let msgDisplay = ''
|
||||||
let msgTranslated = ''
|
let msgTranslated = ''
|
||||||
let translated = false;
|
let translated = false
|
||||||
|
|
||||||
async function rm(){
|
async function rm(){
|
||||||
const rm = $DataBase.askRemoval ? await alertConfirm(language.removeChat) : true
|
const rm = $DataBase.askRemoval ? await alertConfirm(language.removeChat) : true
|
||||||
if(rm){
|
if(rm){
|
||||||
@@ -53,7 +56,7 @@
|
|||||||
$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message = msg
|
$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message = msg
|
||||||
}
|
}
|
||||||
|
|
||||||
async function displaya(message:string){
|
async function displaya(message:string, isStreaming:boolean = false){
|
||||||
if($DataBase.autoTranslate && $DataBase.translator !== ''){
|
if($DataBase.autoTranslate && $DataBase.translator !== ''){
|
||||||
if(msgTranslated==='')
|
if(msgTranslated==='')
|
||||||
msgDisplay = replacePlaceholders(message, name)
|
msgDisplay = replacePlaceholders(message, name)
|
||||||
@@ -64,6 +67,12 @@
|
|||||||
else{
|
else{
|
||||||
msgDisplay = replacePlaceholders(message, name)
|
msgDisplay = replacePlaceholders(message, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!md || !isStreaming || isStreaming && idx === $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message.length - 1) {
|
||||||
|
ParseMarkdown(msgDisplay, character, 'normal').then(mdNew=>{
|
||||||
|
md = mdNew
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setStatusMessage = (message:string, timeout:number = 0)=>{
|
const setStatusMessage = (message:string, timeout:number = 0)=>{
|
||||||
@@ -74,7 +83,7 @@
|
|||||||
}, timeout)
|
}, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: displaya(message)
|
$: displaya(message, $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].isStreaming)
|
||||||
</script>
|
</script>
|
||||||
<div class="flex max-w-full justify-center" class:bgc={isLastMemory}>
|
<div class="flex max-w-full justify-center" class:bgc={isLastMemory}>
|
||||||
<div class="text-neutral-200 mt-1 ml-4 mr-4 mb-1 p-2 bg-transparent flex-grow border-t-gray-900 border-opacity-30 border-transparent flexium items-start max-w-full" >
|
<div class="text-neutral-200 mt-1 ml-4 mr-4 mb-1 p-2 bg-transparent flex-grow border-t-gray-900 border-opacity-30 border-transparent flexium items-start max-w-full" >
|
||||||
@@ -161,8 +170,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
<AutoresizeArea bind:value={message} />
|
<AutoresizeArea bind:value={message} />
|
||||||
{:else}
|
{:else if md}
|
||||||
{#await ParseMarkdown(msgDisplay, character) then md}
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<span class="text chat chattext prose prose-invert minw-0" on:click={() => {
|
<span class="text chat chattext prose prose-invert minw-0" on:click={() => {
|
||||||
if($DataBase.clickToEdit && idx > -1){
|
if($DataBase.clickToEdit && idx > -1){
|
||||||
@@ -173,7 +181,6 @@
|
|||||||
style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
|
style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
|
||||||
style:line-height="{1.25 * ($DataBase.zoomsize / 100)}rem"
|
style:line-height="{1.25 * ($DataBase.zoomsize / 100)}rem"
|
||||||
>{@html md}</span>
|
>{@html md}</span>
|
||||||
{/await}
|
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Suggestion from './Suggestion.svelte';
|
import Suggestion from './Suggestion.svelte';
|
||||||
import { DatabaseIcon, DicesIcon, LanguagesIcon, MenuIcon, MicOffIcon, PowerIcon, RefreshCcwIcon, ReplyIcon, Send } from "lucide-svelte";
|
import { DatabaseIcon, DicesIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, RefreshCcwIcon, ReplyIcon, Send } from "lucide-svelte";
|
||||||
import { selectedCharID } from "../../ts/stores";
|
import { selectedCharID } from "../../ts/stores";
|
||||||
import Chat from "./Chat.svelte";
|
import Chat from "./Chat.svelte";
|
||||||
import { DataBase, type Message } from "../../ts/storage/database";
|
import { DataBase, type Message, type character, type groupChat } from "../../ts/storage/database";
|
||||||
import { getCharImage } from "../../ts/characters";
|
import { getCharImage } from "../../ts/characters";
|
||||||
import { doingChat, sendChat } from "../../ts/process/index";
|
import { doingChat, sendChat } from "../../ts/process/index";
|
||||||
import { findCharacterbyId, messageForm, sleep } from "../../ts/util";
|
import { findCharacterbyId, messageForm, sleep } from "../../ts/util";
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
import { stopTTS } from "src/ts/process/tts";
|
import { stopTTS } from "src/ts/process/tts";
|
||||||
import MainMenu from '../UI/MainMenu.svelte';
|
import MainMenu from '../UI/MainMenu.svelte';
|
||||||
import Help from '../Others/Help.svelte';
|
import Help from '../Others/Help.svelte';
|
||||||
|
import AssetInput from './AssetInput.svelte';
|
||||||
|
|
||||||
let messageInput:string = ''
|
let messageInput:string = ''
|
||||||
let messageInputTranslate:string = ''
|
let messageInputTranslate:string = ''
|
||||||
@@ -28,6 +29,8 @@
|
|||||||
let rerollid = -1
|
let rerollid = -1
|
||||||
let lastCharId = -1
|
let lastCharId = -1
|
||||||
let doingChatInputTranslate = false
|
let doingChatInputTranslate = false
|
||||||
|
let currentCharacter:character|groupChat = $DataBase.characters[$selectedCharID]
|
||||||
|
let toggleStickers:boolean = false
|
||||||
|
|
||||||
async function send() {
|
async function send() {
|
||||||
let selectedChar = $selectedCharID
|
let selectedChar = $selectedCharID
|
||||||
@@ -218,6 +221,10 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
currentCharacter = $DataBase.characters[$selectedCharID]
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<div class="w-full h-full" style={customStyle} on:click={() => {
|
<div class="w-full h-full" style={customStyle} on:click={() => {
|
||||||
@@ -234,6 +241,12 @@
|
|||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<div class="flex items-end mt-2 mb-2 w-full">
|
<div class="flex items-end mt-2 mb-2 w-full">
|
||||||
|
{#if $DataBase.useChatSticker && currentCharacter.type !== 'group'}
|
||||||
|
<div on:click={()=>{toggleStickers = !toggleStickers}}
|
||||||
|
class={"ml-4 bg-gray-500 flex justify-center items-center w-12 h-12 rounded-md hover:bg-green-500 transition-colors "+(toggleStickers ? 'text-green-500':'text-white')}>
|
||||||
|
<Laugh/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
<textarea class="text-neutral-200 p-2 min-w-0 bg-transparent input-text text-xl flex-grow ml-4 mr-2 border-gray-700 resize-none focus:bg-selected overflow-y-hidden overflow-x-hidden max-w-full"
|
<textarea class="text-neutral-200 p-2 min-w-0 bg-transparent input-text text-xl flex-grow ml-4 mr-2 border-gray-700 resize-none focus:bg-selected overflow-y-hidden overflow-x-hidden max-w-full"
|
||||||
bind:value={messageInput}
|
bind:value={messageInput}
|
||||||
bind:this={inputEle}
|
bind:this={inputEle}
|
||||||
@@ -299,9 +312,27 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if toggleStickers}
|
||||||
|
<div class="ml-4 flex flex-wrap">
|
||||||
|
<AssetInput bind:currentCharacter={currentCharacter} onSelect={(additionalAsset)=>{
|
||||||
|
let fileType = 'img'
|
||||||
|
if(additionalAsset.length > 2 && additionalAsset[2]) {
|
||||||
|
const fileExtension = additionalAsset[2]
|
||||||
|
if(fileExtension === 'mp4' || fileExtension === 'webm')
|
||||||
|
fileType = 'video'
|
||||||
|
else if(fileExtension === 'mp3' || fileExtension === 'wav')
|
||||||
|
fileType = 'audio'
|
||||||
|
}
|
||||||
|
messageInput += `<span class='notranslate' translate='no'>{{${fileType}::${additionalAsset[0]}}}</span> *${additionalAsset[0]} added*`
|
||||||
|
updateInputSizeAll()
|
||||||
|
}}/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if $DataBase.useAutoSuggestions}
|
{#if $DataBase.useAutoSuggestions}
|
||||||
<Suggestion messageInput={(msg)=>messageInput=msg} {send}/>
|
<Suggestion messageInput={(msg)=>messageInput=msg} {send}/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#each messageForm($DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
{#each messageForm($DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
||||||
{#if chat.role === 'char'}
|
{#if chat.role === 'char'}
|
||||||
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
||||||
|
|||||||
@@ -26,24 +26,11 @@
|
|||||||
<span class="text-neutral-200">{language.requestretrys}</span>
|
<span class="text-neutral-200">{language.requestretrys}</span>
|
||||||
<input class="text-neutral-200 mb-4 p-2 bg-transparent input-text focus:bg-selected text-sm" type="number" min={0} max="20" bind:value={$DataBase.requestRetrys}>
|
<input class="text-neutral-200 mb-4 p-2 bg-transparent input-text focus:bg-selected text-sm" type="number" min={0} max="20" bind:value={$DataBase.requestRetrys}>
|
||||||
|
|
||||||
<span class="text-neutral-200">Request Type</span>
|
|
||||||
<select class="bg-transparent input-text text-gray-200 appearance-none text-sm mb-4" bind:value={$DataBase.requestmet}>
|
|
||||||
<option value="normal" class="bg-darkbg appearance-none">Normal</option>
|
|
||||||
<option value="proxy" class="bg-darkbg appearance-none">Proxy</option>
|
|
||||||
<option value="plain" class="bg-darkbg appearance-none">Plain Fetch</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{#if $DataBase.requestmet === 'proxy'}
|
|
||||||
<span class="text-neutral-200">Request Proxy URL</span>
|
|
||||||
<input class="text-neutral-200 mb-4 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={$DataBase.requestproxy}>
|
|
||||||
{/if}
|
|
||||||
{#if isTauri && $DataBase.requestmet === 'normal'}
|
|
||||||
<span class="text-neutral-200">Request Lib</span>
|
<span class="text-neutral-200">Request Lib</span>
|
||||||
<select class="bg-transparent input-text text-gray-200 appearance-none text-sm" bind:value={$DataBase.requester}>
|
<select class="bg-transparent input-text text-gray-200 appearance-none text-sm" bind:value={$DataBase.requester}>
|
||||||
<option value="new" class="bg-darkbg appearance-none">Reqwest</option>
|
<option value="new" class="bg-darkbg appearance-none">Reqwest</option>
|
||||||
<option value="old" class="bg-darkbg appearance-none">Tauri</option>
|
<option value="old" class="bg-darkbg appearance-none">Tauri</option>
|
||||||
</select>
|
</select>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
<div class="flex items-center mt-4">
|
||||||
<Check bind:check={$DataBase.useSayNothing} name={language.sayNothing}/>
|
<Check bind:check={$DataBase.useSayNothing} name={language.sayNothing}/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import Help from "src/lib/Others/Help.svelte";
|
import Help from "src/lib/Others/Help.svelte";
|
||||||
import { DataBase } from "src/ts/storage/database";
|
import { DataBase } from "src/ts/storage/database";
|
||||||
import { customProviderStore, getCurrentPluginMax } from "src/ts/process/plugins";
|
import { customProviderStore, getCurrentPluginMax } from "src/ts/plugins/plugins";
|
||||||
import { isTauri } from "src/ts/storage/globalApi";
|
import { isTauri } from "src/ts/storage/globalApi";
|
||||||
import { tokenize } from "src/ts/tokenizer";
|
import { tokenize } from "src/ts/tokenizer";
|
||||||
import ModelList from "src/lib/UI/ModelList.svelte";
|
import ModelList from "src/lib/UI/ModelList.svelte";
|
||||||
|
|||||||
@@ -142,3 +142,14 @@
|
|||||||
<div class="flex items-center mt-2">
|
<div class="flex items-center mt-2">
|
||||||
<Check bind:check={$DataBase.useChatCopy} name={language.useChatCopy}/>
|
<Check bind:check={$DataBase.useChatCopy} name={language.useChatCopy}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center mt-2">
|
||||||
|
<Check bind:check={$DataBase.useAdditionalAssetsPreview} name={language.useAdditionalAssetsPreview}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if $DataBase.useExperimental}
|
||||||
|
<div class="flex items-center mt-2">
|
||||||
|
<Check bind:check={$DataBase.useChatSticker} name={language.useChatSticker}/>
|
||||||
|
<Help key="experimental" name={language.useChatSticker}/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import { alertConfirm } from "src/ts/alert";
|
import { alertConfirm } from "src/ts/alert";
|
||||||
import { DataBase } from "src/ts/storage/database";
|
import { DataBase } from "src/ts/storage/database";
|
||||||
import { importPlugin } from "src/ts/process/plugins";
|
import { importPlugin } from "src/ts/plugins/plugins";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<h2 class="mb-2 text-2xl font-bold mt-2">{language.plugin}</h2>
|
<h2 class="mb-2 text-2xl font-bold mt-2">{language.plugin}</h2>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import { alertConfirm, alertError } from "../../ts/alert";
|
import { alertConfirm, alertError } from "../../ts/alert";
|
||||||
import { language } from "../../lang";
|
import { language } from "../../lang";
|
||||||
import { DataBase, changeToPreset, copyPreset, presetTemplate } from "../../ts/storage/database";
|
import { DataBase, changeToPreset, copyPreset, downloadPreset, importPreset, presetTemplate } from "../../ts/storage/database";
|
||||||
import { CopyIcon, EditIcon, PlusIcon, TrashIcon, XIcon } from "lucide-svelte";
|
import { CopyIcon, DownloadIcon, EditIcon, FolderUpIcon, PlusIcon, TrashIcon, XIcon } from "lucide-svelte";
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
let editMode = false
|
let editMode = false
|
||||||
export let close = () => {}
|
export let close = () => {}
|
||||||
@@ -41,6 +42,13 @@
|
|||||||
}}>
|
}}>
|
||||||
<CopyIcon size={18}/>
|
<CopyIcon size={18}/>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="text-gray-500 hover:text-green-500 cursor-pointer mr-2" on:click={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
downloadPreset(i)
|
||||||
|
}}>
|
||||||
|
|
||||||
|
<DownloadIcon size={18} />
|
||||||
|
</button>
|
||||||
<button class="text-gray-500 hover:text-green-500 cursor-pointer" on:click={async (e) => {
|
<button class="text-gray-500 hover:text-green-500 cursor-pointer" on:click={async (e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if($DataBase.botPresets.length === 1){
|
if($DataBase.botPresets.length === 1){
|
||||||
@@ -63,7 +71,7 @@
|
|||||||
<div class="flex mt-2 items-center">
|
<div class="flex mt-2 items-center">
|
||||||
<button class="text-gray-500 hover:text-green-500 cursor-pointer mr-1" on:click={() => {
|
<button class="text-gray-500 hover:text-green-500 cursor-pointer mr-1" on:click={() => {
|
||||||
let botPresets = $DataBase.botPresets
|
let botPresets = $DataBase.botPresets
|
||||||
let newPreset = JSON.parse(JSON.stringify(presetTemplate))
|
let newPreset = cloneDeep(presetTemplate)
|
||||||
newPreset.name = `New Preset`
|
newPreset.name = `New Preset`
|
||||||
botPresets.push(newPreset)
|
botPresets.push(newPreset)
|
||||||
|
|
||||||
@@ -71,6 +79,11 @@
|
|||||||
}}>
|
}}>
|
||||||
<PlusIcon/>
|
<PlusIcon/>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="text-gray-500 hover:text-green-500 mr-2 cursor-pointer" on:click={() => {
|
||||||
|
importPreset()
|
||||||
|
}}>
|
||||||
|
<FolderUpIcon size={18}/>
|
||||||
|
</button>
|
||||||
<button class="text-gray-500 hover:text-green-500 cursor-pointer" on:click={() => {
|
<button class="text-gray-500 hover:text-green-500 cursor-pointer" on:click={() => {
|
||||||
editMode = !editMode
|
editMode = !editMode
|
||||||
}}>
|
}}>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
import RegexData from "./RegexData.svelte";
|
import RegexData from "./RegexData.svelte";
|
||||||
import { exportChar, shareRisuHub } from "src/ts/characterCards";
|
import { exportChar, shareRisuHub } from "src/ts/characterCards";
|
||||||
import { getElevenTTSVoices, getWebSpeechTTSVoices, getVOICEVOXVoices } from "src/ts/process/tts";
|
import { getElevenTTSVoices, getWebSpeechTTSVoices, getVOICEVOXVoices } from "src/ts/process/tts";
|
||||||
import { checkCharOrder } from "src/ts/storage/globalApi";
|
import { checkCharOrder, getFileSrc } from "src/ts/storage/globalApi";
|
||||||
import { addGroupChar, rmCharFromGroup } from "src/ts/process/group";
|
import { addGroupChar, rmCharFromGroup } from "src/ts/process/group";
|
||||||
import HubUpload from "../UI/HubUpload.svelte";
|
import HubUpload from "../UI/HubUpload.svelte";
|
||||||
|
|
||||||
@@ -95,6 +95,8 @@
|
|||||||
currentChar = currentChar
|
currentChar = currentChar
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let assetFileExtensions:string[] = []
|
||||||
|
let assetFilePath:string[] = []
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if(database.characters[$selectedCharID].chaId === currentChar.data.chaId){
|
if(database.characters[$selectedCharID].chaId === currentChar.data.chaId){
|
||||||
@@ -106,6 +108,20 @@
|
|||||||
emos = currentChar.data.emotionImages
|
emos = currentChar.data.emotionImages
|
||||||
DataBase.set(database)
|
DataBase.set(database)
|
||||||
loadTokenize(currentChar.data)
|
loadTokenize(currentChar.data)
|
||||||
|
|
||||||
|
if(currentChar.type ==='character' && database.useAdditionalAssetsPreview){
|
||||||
|
if(currentChar.data.additionalAssets){
|
||||||
|
for(let i = 0; i < currentChar.data.additionalAssets.length; i++){
|
||||||
|
if(currentChar.data.additionalAssets[i].length > 2 && currentChar.data.additionalAssets[i][2]) {
|
||||||
|
assetFileExtensions[i] = currentChar.data.additionalAssets[i][2]
|
||||||
|
} else
|
||||||
|
assetFileExtensions[i] = currentChar.data.additionalAssets[i][1].split('.').pop()
|
||||||
|
getFileSrc(currentChar.data.additionalAssets[i][1]).then((filePath) => {
|
||||||
|
assetFilePath[i] = filePath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy(unsub);
|
onDestroy(unsub);
|
||||||
@@ -615,9 +631,10 @@
|
|||||||
for(const f of da){
|
for(const f of da){
|
||||||
console.log(f)
|
console.log(f)
|
||||||
const img = f.data
|
const img = f.data
|
||||||
const imgp = await saveAsset(img)
|
|
||||||
const name = f.name
|
const name = f.name
|
||||||
currentChar.data.additionalAssets.push([name, imgp])
|
const extension = name.split('.').pop().toLowerCase()
|
||||||
|
const imgp = await saveAsset(img,'', extension)
|
||||||
|
currentChar.data.additionalAssets.push([name, imgp, extension])
|
||||||
currentChar.data.additionalAssets = currentChar.data.additionalAssets
|
currentChar.data.additionalAssets = currentChar.data.additionalAssets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -634,8 +651,19 @@
|
|||||||
{#each currentChar.data.additionalAssets as assets, i}
|
{#each currentChar.data.additionalAssets as assets, i}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="font-medium truncate">
|
<td class="font-medium truncate">
|
||||||
|
{#if assetFilePath[i] && database.useAdditionalAssetsPreview}
|
||||||
|
{#if assetFileExtensions[i] === 'mp4'}
|
||||||
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
|
<video controls class="mt-2 px-2 w-full m-1 rounded-md"><source src={assetFilePath[i]} type="video/mp4"></video>
|
||||||
|
{:else if assetFileExtensions[i] === 'mp3'}
|
||||||
|
<audio controls class="mt-2 px-2 w-full h-16 m-1 rounded-md" loop><source src={assetFilePath[i]} type="audio/mpeg"></audio>
|
||||||
|
{:else}
|
||||||
|
<img src={assetFilePath[i]} class="w-16 h-16 m-1 rounded-md" alt={assets[0]}/>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
<input class="text-neutral-200 mt-2 mb-4 p-2 bg-transparent input-text focus:bg-selected w-full resize-none" bind:value={currentChar.data.additionalAssets[i][0]} placeholder="..." />
|
<input class="text-neutral-200 mt-2 mb-4 p-2 bg-transparent input-text focus:bg-selected w-full resize-none" bind:value={currentChar.data.additionalAssets[i][0]} placeholder="..." />
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<th class="font-medium cursor-pointer w-10">
|
<th class="font-medium cursor-pointer w-10">
|
||||||
<button class="hover:text-green-500" on:click={() => {
|
<button class="hover:text-green-500" on:click={() => {
|
||||||
if(currentChar.type === 'character'){
|
if(currentChar.type === 'character'){
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { appVer } from "src/ts/storage/database";
|
import { appVer, webAppSubVer } from "src/ts/storage/database";
|
||||||
import GithubStars from "../Others/GithubStars.svelte";
|
import GithubStars from "../Others/GithubStars.svelte";
|
||||||
import Hub from "./Hub.svelte";
|
import Hub from "./Hub.svelte";
|
||||||
import { sideBarStore } from "src/ts/stores";
|
import { sideBarStore } from "src/ts/stores";
|
||||||
import { ArrowLeft } from "lucide-svelte";
|
import { ArrowLeft } from "lucide-svelte";
|
||||||
import { openURL } from "src/ts/storage/globalApi";
|
import { isNodeServer, isTauri, openURL } from "src/ts/storage/globalApi";
|
||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import { getRisuHub } from "src/ts/characterCards";
|
import { getRisuHub } from "src/ts/characterCards";
|
||||||
import RisuHubIcon from "./RisuHubIcon.svelte";
|
import RisuHubIcon from "./RisuHubIcon.svelte";
|
||||||
@@ -13,7 +13,11 @@
|
|||||||
<div class="h-full w-full flex flex-col overflow-y-auto items-center">
|
<div class="h-full w-full flex flex-col overflow-y-auto items-center">
|
||||||
{#if !openHub}
|
{#if !openHub}
|
||||||
<h2 class="text-4xl text-white mb-0 mt-6 font-black">RisuAI</h2>
|
<h2 class="text-4xl text-white mb-0 mt-6 font-black">RisuAI</h2>
|
||||||
|
{#if (!isTauri) && (!isNodeServer)}
|
||||||
|
<h3 class="text-gray-500 mt-1">Version {appVer}{webAppSubVer}</h3>
|
||||||
|
{:else}
|
||||||
<h3 class="text-gray-500 mt-1">Version {appVer}</h3>
|
<h3 class="text-gray-500 mt-1">Version {appVer}</h3>
|
||||||
|
{/if}
|
||||||
<GithubStars />
|
<GithubStars />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="w-full flex p-4 flex-col text-white max-w-4xl">
|
<div class="w-full flex p-4 flex-col text-white max-w-4xl">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { alertConfirm, alertError, alertMd, alertNormal, alertSelect, alertStore
|
|||||||
import { DataBase, defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook } from "./storage/database"
|
import { DataBase, defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook } from "./storage/database"
|
||||||
import { checkNullish, selectMultipleFile, selectSingleFile, sleep } from "./util"
|
import { checkNullish, selectMultipleFile, selectSingleFile, sleep } from "./util"
|
||||||
import { language } from "src/lang"
|
import { language } from "src/lang"
|
||||||
import { encode as encodeMsgpack, decode as decodeMsgpack } from "@msgpack/msgpack";
|
import { encode as encodeMsgpack, decode as decodeMsgpack } from "msgpackr";
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import exifr from 'exifr'
|
import exifr from 'exifr'
|
||||||
import { PngMetadata } from "./exif"
|
import { PngMetadata } from "./exif"
|
||||||
@@ -132,7 +132,7 @@ export async function characterHubImport() {
|
|||||||
const url = new URL(location.href);
|
const url = new URL(location.href);
|
||||||
url.searchParams.delete('charahub');
|
url.searchParams.delete('charahub');
|
||||||
window.history.pushState(null, '', url.toString());
|
window.history.pushState(null, '', url.toString());
|
||||||
const chara = await fetch("https://api.characterhub.org/api/characters/download", {
|
const chara = await fetch("https://api.chub.ai/api/characters/download", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
"format": "tavern",
|
"format": "tavern",
|
||||||
@@ -329,7 +329,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
|
|||||||
let customScripts:customscript[] = []
|
let customScripts:customscript[] = []
|
||||||
let utilityBot = false
|
let utilityBot = false
|
||||||
let sdData = defaultSdDataFunc()
|
let sdData = defaultSdDataFunc()
|
||||||
let extAssets:[string,string][] = []
|
let extAssets:[string,string,string][] = []
|
||||||
|
|
||||||
if(risuext){
|
if(risuext){
|
||||||
if(risuext.emotions){
|
if(risuext.emotions){
|
||||||
@@ -350,8 +350,11 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
|
|||||||
msg: `Loading... (Getting Assets ${i} / ${risuext.additionalAssets.length})`
|
msg: `Loading... (Getting Assets ${i} / ${risuext.additionalAssets.length})`
|
||||||
})
|
})
|
||||||
await sleep(10)
|
await sleep(10)
|
||||||
const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'))
|
let fileName = ''
|
||||||
extAssets.push([risuext.additionalAssets[i][0],imgp])
|
if(risuext.additionalAssets[i].length >= 3)
|
||||||
|
fileName = risuext.additionalAssets[i][2]
|
||||||
|
const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'), '', fileName)
|
||||||
|
extAssets.push([risuext.additionalAssets[i][0],imgp,fileName])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bias = risuext.bias ?? bias
|
bias = risuext.bias ?? bias
|
||||||
@@ -756,7 +759,7 @@ type CharacterCardV2 = {
|
|||||||
customScripts?:customscript[]
|
customScripts?:customscript[]
|
||||||
utilityBot?: boolean,
|
utilityBot?: boolean,
|
||||||
sdData?:[string,string][],
|
sdData?:[string,string][],
|
||||||
additionalAssets?:[string,string][],
|
additionalAssets?:[string,string,string][],
|
||||||
backgroundHTML?:string
|
backgroundHTML?:string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import exifr from 'exifr'
|
|||||||
import { alertConfirm, alertError, alertNormal, alertSelect, alertStore } from "./alert";
|
import { alertConfirm, alertError, alertNormal, alertSelect, alertStore } from "./alert";
|
||||||
import { language } from "../lang";
|
import { language } from "../lang";
|
||||||
import { PngMetadata } from "./exif";
|
import { PngMetadata } from "./exif";
|
||||||
import { encode as encodeMsgpack, decode as decodeMsgpack } from "@msgpack/msgpack";
|
import { encode as encodeMsgpack, decode as decodeMsgpack } from "msgpackr";
|
||||||
import { checkNullish, findCharacterbyId, selectMultipleFile, selectSingleFile, sleep } from "./util";
|
import { checkNullish, findCharacterbyId, selectMultipleFile, selectSingleFile, sleep } from "./util";
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { selectedCharID } from "./stores";
|
import { selectedCharID } from "./stores";
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ async function backupDrive(ACCESS_TOKEN:string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbData = encodeRisuSave(get(DataBase))
|
const dbData = encodeRisuSave(get(DataBase), 'compression')
|
||||||
|
|
||||||
alertStore.set({
|
alertStore.set({
|
||||||
type: "wait",
|
type: "wait",
|
||||||
@@ -402,7 +402,7 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise<voi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.didFirstSetup = true
|
db.didFirstSetup = true
|
||||||
const dbData = encodeRisuSave(db)
|
const dbData = encodeRisuSave(db, 'compression')
|
||||||
|
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
||||||
|
|||||||
@@ -20,6 +20,23 @@ export const PngMetadata = {
|
|||||||
const encoded = encode(chunks);
|
const encoded = encode(chunks);
|
||||||
return encoded
|
return encoded
|
||||||
},
|
},
|
||||||
|
writeStream:(pngBuffer: Uint8Array, metadata: Record<string, string>): Buffer => {
|
||||||
|
let chunks:{
|
||||||
|
name:string
|
||||||
|
data:Uint8Array
|
||||||
|
}[] = extract(Buffer.from(pngBuffer));
|
||||||
|
|
||||||
|
chunks = chunks.filter((v) => {
|
||||||
|
return v.name.toLocaleLowerCase() !== 'text'
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const key in metadata) {
|
||||||
|
const value = metadata[key];
|
||||||
|
chunks.splice(-1, 0, textKey.encode(key, value))
|
||||||
|
}
|
||||||
|
const encoded = encode(chunks);
|
||||||
|
return encoded
|
||||||
|
},
|
||||||
filter: (pngBuffer: Uint8Array) => {
|
filter: (pngBuffer: Uint8Array) => {
|
||||||
let chunks:{
|
let chunks:{
|
||||||
name:string
|
name:string
|
||||||
|
|||||||
@@ -63,9 +63,9 @@ async function parseAdditionalAssets(data:string, char:character, mode:'normal'|
|
|||||||
for(const asset of char.additionalAssets){
|
for(const asset of char.additionalAssets){
|
||||||
const assetPath = await getFileSrc(asset[1])
|
const assetPath = await getFileSrc(asset[1])
|
||||||
data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
|
data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
|
||||||
replaceAll(`{{img::${asset[0]}}}`,`<img src="${assetPath}" />`)
|
replaceAll(`{{img::${asset[0]}}}`,`<img src="${assetPath}" alt="${asset[0]}"/>`)
|
||||||
.replaceAll(`{{video::${asset[0]}}}`,`<video autoplay loop><source src="${assetPath}" type="video/mp4"></video>`)
|
.replaceAll(`{{video::${asset[0]}}}`,`<video controls autoplay loop><source src="${assetPath}" type="video/mp4"></video>`)
|
||||||
.replaceAll(`{{audio::${asset[0]}}}`,`<audio autoplay loop><source src="${assetPath}" type="audio/mpeg"></audio>`)
|
.replaceAll(`{{audio::${asset[0]}}}`,`<audio controls autoplay loop><source src="${assetPath}" type="audio/mpeg"></audio>`)
|
||||||
if(mode === 'back'){
|
if(mode === 'back'){
|
||||||
data = data.replaceAll(`{{bg::${asset[0]}}}`, `<div style="width:100%;height:100%;background: linear-gradient(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.8)),url(${assetPath}); background-size: cover;"></div>`)
|
data = data.replaceAll(`{{bg::${asset[0]}}}`, `<div style="width:100%;height:100%;background: linear-gradient(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.8)),url(${assetPath}); background-size: cover;"></div>`)
|
||||||
}
|
}
|
||||||
|
|||||||
56
src/ts/plugins/automark.ts
Normal file
56
src/ts/plugins/automark.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
const reg:[RegExp,string][] = []
|
||||||
|
|
||||||
|
|
||||||
|
export function autoMarkPlugin(data:string){
|
||||||
|
if(reg.length === 0){
|
||||||
|
const pluginRegex = [
|
||||||
|
{
|
||||||
|
"in": "“|”",
|
||||||
|
"out": "\"",
|
||||||
|
"flag": "g"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "‘|’",
|
||||||
|
"out": "'",
|
||||||
|
"flag": "g"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "^(?!\\d\\.)([\\wㄱ-ㅎ가-힣'])(?!.*[{<>}])|(?<=^\\[.*\\] *|^\\(.*\\) *)([\\wㄱ-ㅎ가-힣'])(?!.*[{<>}])",
|
||||||
|
"out": "<em>$1$2",
|
||||||
|
"flag": "gm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "(?<!^ +.*)(\".*|<em>.*)(?<!\")$",
|
||||||
|
"out": "$1</em>",
|
||||||
|
"flag": "gm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "(?<=<em>.*|^\".*)( +\"[\\S])|(?<=<em>.*|\" +.*)( *\\[)",
|
||||||
|
"out": "</em>$1$2",
|
||||||
|
"flag": "gm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "(?<=^\".*|<\\/em>.*)([\\S]\" +|[\\S]\"(?=[,.…ㄱ-ㅎ가-힣]))|(?<=<\\/em>.*)( *\\] *)",
|
||||||
|
"out": "$1$2<em>",
|
||||||
|
"flag": "gm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "(?<=<em>.*? +|\\[|\\[.* +|\\(|\\(.* +|\"|\".*? +)(?<!style=.*)(')|(?<=<em>)('[\\wㄱ-ㅎ가-힣])",
|
||||||
|
"out": "<strong><em>$1$2",
|
||||||
|
"flag": "gm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "(?<=<strong><em>')(.*?')(?= +.+?|[ㄱ-ㅎ가-힣?!:;,.…—-])|(?<=<strong><em>'.*)(')(?=<\\/em>|\")|(?<=\\(<strong><em>')(?=\\))",
|
||||||
|
"out": "$1$2</em></strong>",
|
||||||
|
"flag": "gm"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
for(const r of pluginRegex){
|
||||||
|
reg.push([new RegExp(r.in, r.flag),r.out])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(let i=0;i<reg.length;i++){
|
||||||
|
data = data.replace(reg[i][0], reg[i][1])
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { language } from "../../lang";
|
|||||||
import { alertError } from "../alert";
|
import { alertError } from "../alert";
|
||||||
import { DataBase } from "../storage/database";
|
import { DataBase } from "../storage/database";
|
||||||
import { checkNullish, selectSingleFile, sleep } from "../util";
|
import { checkNullish, selectSingleFile, sleep } from "../util";
|
||||||
import type { OpenAIChat } from ".";
|
import type { OpenAIChat } from "../process";
|
||||||
import { globalFetch } from "../storage/globalApi";
|
import { globalFetch } from "../storage/globalApi";
|
||||||
import { selectedCharID } from "../stores";
|
import { selectedCharID } from "../stores";
|
||||||
|
|
||||||
@@ -409,6 +409,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
|||||||
else if(req.type === 'streaming'){
|
else if(req.type === 'streaming'){
|
||||||
const reader = req.result.getReader()
|
const reader = req.result.getReader()
|
||||||
const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
|
const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
|
||||||
|
db.characters[selectedChar].chats[selectedChat].isStreaming = true
|
||||||
db.characters[selectedChar].chats[selectedChat].message.push({
|
db.characters[selectedChar].chats[selectedChat].message.push({
|
||||||
role: 'char',
|
role: 'char',
|
||||||
data: "",
|
data: "",
|
||||||
@@ -424,6 +425,8 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
|
|||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
}
|
}
|
||||||
if(readed.done){
|
if(readed.done){
|
||||||
|
db.characters[selectedChar].chats[selectedChat].isStreaming = false
|
||||||
|
setDatabase(db)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,19 +200,26 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
|
|||||||
comment:string
|
comment:string
|
||||||
content:string
|
content:string
|
||||||
order:number
|
order:number
|
||||||
constant:boolean
|
constant:boolean,
|
||||||
|
name:string,
|
||||||
|
keywords:string[],
|
||||||
|
priority:number
|
||||||
|
entry:string
|
||||||
|
secondary_keys:string[]
|
||||||
|
selective:boolean
|
||||||
}} = importedlore.entries
|
}} = importedlore.entries
|
||||||
for(const key in entries){
|
for(const key in entries){
|
||||||
const currentLore = entries[key]
|
const currentLore = entries[key]
|
||||||
lore.push({
|
lore.push({
|
||||||
key: currentLore.key.join(', '),
|
key: currentLore.key ? currentLore.key.join(', ') :
|
||||||
insertorder: currentLore.order,
|
currentLore.keywords ? currentLore.keywords.join(', ') : '',
|
||||||
comment: currentLore.comment.length < 1 ? 'Unnamed Imported Lore' : currentLore.comment,
|
insertorder: currentLore.order ?? currentLore.priority ?? 0,
|
||||||
content: currentLore.content,
|
comment: currentLore.comment || currentLore.name || '',
|
||||||
|
content: currentLore.content || currentLore.entry || '',
|
||||||
mode: "normal",
|
mode: "normal",
|
||||||
alwaysActive: currentLore.constant,
|
alwaysActive: currentLore.constant ?? false,
|
||||||
secondkey: "",
|
secondkey: currentLore.secondary_keys ? currentLore.secondary_keys.join(', ') : "",
|
||||||
selective: false
|
selective: currentLore.selective ?? false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import type { OpenAIChat, OpenAIChatFull } from ".";
|
import type { OpenAIChat, OpenAIChatFull } from ".";
|
||||||
import { DataBase, setDatabase, type character } from "../storage/database";
|
import { DataBase, setDatabase, type character } from "../storage/database";
|
||||||
import { pluginProcess } from "./plugins";
|
import { pluginProcess } from "../plugins/plugins";
|
||||||
import { language } from "../../lang";
|
import { language } from "../../lang";
|
||||||
import { stringlizeChat, unstringlizeChat } from "./stringlize";
|
import { stringlizeChat, unstringlizeChat } from "./stringlize";
|
||||||
import { globalFetch, isTauri } from "../storage/globalApi";
|
import { globalFetch, isNodeServer, isTauri } from "../storage/globalApi";
|
||||||
import { sleep } from "../util";
|
import { sleep } from "../util";
|
||||||
import { createDeep } from "./deepai";
|
import { createDeep } from "./deepai";
|
||||||
|
|
||||||
@@ -167,7 +167,20 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model'
|
|||||||
|
|
||||||
if(db.useStreaming && arg.useStreaming){
|
if(db.useStreaming && arg.useStreaming){
|
||||||
body.stream = true
|
body.stream = true
|
||||||
const da = await fetch(replacerURL, {
|
const da = ((!isTauri) && (!isNodeServer))
|
||||||
|
? await fetch(`/proxy?url=${encodeURIComponent(replacerURL)}`, {
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
headers: {
|
||||||
|
"risu-header": encodeURIComponent(JSON.stringify({
|
||||||
|
"Authorization": "Bearer " + db.openAIKey,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
})),
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
signal: abortSignal
|
||||||
|
})
|
||||||
|
: await fetch(replacerURL, {
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
import { get, writable } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import { checkNullish } from '../util';
|
import { checkNullish, selectSingleFile } from '../util';
|
||||||
import { changeLanguage } from '../../lang';
|
import { changeLanguage, language } from '../../lang';
|
||||||
import type { RisuPlugin } from '../process/plugins';
|
import type { RisuPlugin } from '../plugins/plugins';
|
||||||
import { saveAsset as saveImageGlobal } from './globalApi';
|
import { downloadFile, saveAsset as saveImageGlobal } from './globalApi';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import { defaultAutoSuggestPrompt, defaultJailbreak, defaultMainPrompt } from './defaultPrompts';
|
import { defaultAutoSuggestPrompt, defaultJailbreak, defaultMainPrompt } from './defaultPrompts';
|
||||||
|
import { alertNormal } from '../alert';
|
||||||
|
|
||||||
export const DataBase = writable({} as any as Database)
|
export const DataBase = writable({} as any as Database)
|
||||||
export const loadedStore = writable(false)
|
export const loadedStore = writable(false)
|
||||||
export let appVer = '1.27.1'
|
export let appVer = '1.27.4'
|
||||||
|
export let webAppSubVer = ''
|
||||||
|
|
||||||
export function setDatabase(data:Database){
|
export function setDatabase(data:Database){
|
||||||
|
console.log(data)
|
||||||
if(checkNullish(data.characters)){
|
if(checkNullish(data.characters)){
|
||||||
data.characters = []
|
data.characters = []
|
||||||
}
|
}
|
||||||
@@ -339,7 +342,7 @@ export interface character{
|
|||||||
VOLUME_SCALE?: number
|
VOLUME_SCALE?: number
|
||||||
}
|
}
|
||||||
supaMemory?:boolean
|
supaMemory?:boolean
|
||||||
additionalAssets?:[string, string][]
|
additionalAssets?:[string, string, string][]
|
||||||
ttsReadOnlyQuoted?:boolean
|
ttsReadOnlyQuoted?:boolean
|
||||||
replaceGlobalNote:string
|
replaceGlobalNote:string
|
||||||
backgroundHTML?:string
|
backgroundHTML?:string
|
||||||
@@ -522,7 +525,9 @@ export interface Database{
|
|||||||
expires_in?: number
|
expires_in?: number
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
classicMaxWidth: boolean
|
classicMaxWidth: boolean,
|
||||||
|
useChatSticker:boolean,
|
||||||
|
useAdditionalAssetsPreview:boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface hordeConfig{
|
interface hordeConfig{
|
||||||
@@ -561,6 +566,7 @@ export interface Chat{
|
|||||||
supaMemoryData?:string
|
supaMemoryData?:string
|
||||||
lastMemory?:string
|
lastMemory?:string
|
||||||
suggestMessages?:string[]
|
suggestMessages?:string[]
|
||||||
|
isStreaming?:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Message{
|
export interface Message{
|
||||||
@@ -710,3 +716,26 @@ export function changeToPreset(id =0){
|
|||||||
db.koboldURL = newPres.koboldURL ?? db.koboldURL
|
db.koboldURL = newPres.koboldURL ?? db.koboldURL
|
||||||
DataBase.set(db)
|
DataBase.set(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function downloadPreset(id:number){
|
||||||
|
saveCurrentPreset()
|
||||||
|
let db = get(DataBase)
|
||||||
|
let pres = cloneDeep(db.botPresets[id])
|
||||||
|
pres.openAIKey = ''
|
||||||
|
pres.forceReplaceUrl = ''
|
||||||
|
pres.forceReplaceUrl2 = ''
|
||||||
|
downloadFile(pres.name + "_preset.json", Buffer.from(JSON.stringify(pres, null, 2)))
|
||||||
|
alertNormal(language.successExport)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function importPreset(){
|
||||||
|
const f = await selectSingleFile(["json"])
|
||||||
|
if(!f){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let db = get(DataBase)
|
||||||
|
const pre = (JSON.parse(Buffer.from(f.data).toString('utf-8')))
|
||||||
|
pre.name ??= "Imported"
|
||||||
|
db.botPresets.push(pre)
|
||||||
|
DataBase.set(db)
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import { appWindow } from "@tauri-apps/api/window";
|
|||||||
import { checkOldDomain, checkUpdate } from "../update";
|
import { checkOldDomain, checkUpdate } from "../update";
|
||||||
import { selectedCharID } from "../stores";
|
import { selectedCharID } from "../stores";
|
||||||
import { Body, ResponseType, fetch as TauriFetch } from "@tauri-apps/api/http";
|
import { Body, ResponseType, fetch as TauriFetch } from "@tauri-apps/api/http";
|
||||||
import { loadPlugins } from "../process/plugins";
|
import { loadPlugins } from "../plugins/plugins";
|
||||||
import { alertError, alertStore } from "../alert";
|
import { alertError, alertStore } from "../alert";
|
||||||
import { checkDriverInit, syncDrive } from "../drive/drive";
|
import { checkDriverInit, syncDrive } from "../drive/drive";
|
||||||
import { hasher } from "../parser";
|
import { hasher } from "../parser";
|
||||||
@@ -170,7 +170,7 @@ export async function readImage(data:string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveAsset(data:Uint8Array, customId:string = ''){
|
export async function saveAsset(data:Uint8Array, customId:string = '', fileName:string = ''){
|
||||||
let id = ''
|
let id = ''
|
||||||
if(customId !== ''){
|
if(customId !== ''){
|
||||||
id = customId
|
id = customId
|
||||||
@@ -182,13 +182,17 @@ export async function saveAsset(data:Uint8Array, customId:string = ''){
|
|||||||
id = uuidv4()
|
id = uuidv4()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let fileExtension:string = 'png'
|
||||||
|
if(fileName && fileName.split('.').length > 0){
|
||||||
|
fileExtension = fileName.split('.').pop()
|
||||||
|
}
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
await writeBinaryFile(`assets/${id}.png`, data ,{dir: BaseDirectory.AppData})
|
await writeBinaryFile(`assets/${id}.${fileExtension}`, data ,{dir: BaseDirectory.AppData})
|
||||||
return `assets/${id}.png`
|
return `assets/${id}.${fileExtension}`
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
await forageStorage.setItem(`assets/${id}.png`, data)
|
await forageStorage.setItem(`assets/${id}.${fileExtension}`, data)
|
||||||
return `assets/${id}.png`
|
return `assets/${id}.${fileExtension}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,6 +207,7 @@ export async function saveDb(){
|
|||||||
})
|
})
|
||||||
while(true){
|
while(true){
|
||||||
if(changed){
|
if(changed){
|
||||||
|
changed = false
|
||||||
const dbData = encodeRisuSave(get(DataBase))
|
const dbData = encodeRisuSave(get(DataBase))
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
||||||
@@ -373,7 +378,7 @@ export async function loadData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const knownHostes = ["localhost","127.0.0.1","api.openai.com"]
|
const knownHostes = ["localhost","127.0.0.1"]
|
||||||
|
|
||||||
export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:string]:string}, rawResponse?:boolean, method?:"POST"|"GET", abortSignal?:AbortSignal} = {}): Promise<{
|
export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:string]:string}, rawResponse?:boolean, method?:"POST"|"GET", abortSignal?:AbortSignal} = {}): Promise<{
|
||||||
ok: boolean;
|
ok: boolean;
|
||||||
@@ -383,6 +388,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
|
|||||||
try {
|
try {
|
||||||
const db = get(DataBase)
|
const db = get(DataBase)
|
||||||
const method = arg.method ?? "POST"
|
const method = arg.method ?? "POST"
|
||||||
|
db.requestmet = "normal"
|
||||||
|
|
||||||
function addFetchLog(response:any, success:boolean){
|
function addFetchLog(response:any, success:boolean){
|
||||||
try{
|
try{
|
||||||
@@ -410,7 +416,7 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
|
|||||||
const urlHost = (new URL(url)).hostname
|
const urlHost = (new URL(url)).hostname
|
||||||
let forcePlainFetch = knownHostes.includes(urlHost) && (!isTauri)
|
let forcePlainFetch = knownHostes.includes(urlHost) && (!isTauri)
|
||||||
|
|
||||||
if(db.requestmet === 'plain' || forcePlainFetch){
|
if(forcePlainFetch){
|
||||||
try {
|
try {
|
||||||
let headers = arg.headers ?? {}
|
let headers = arg.headers ?? {}
|
||||||
if(!headers["Content-Type"]){
|
if(!headers["Content-Type"]){
|
||||||
@@ -451,48 +457,6 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(db.requestmet === 'proxy'){
|
|
||||||
try {
|
|
||||||
let headers = arg.headers ?? {}
|
|
||||||
if(!headers["Content-Type"]){
|
|
||||||
headers["Content-Type"] = `application/json`
|
|
||||||
}
|
|
||||||
const furl = new URL(db.requestproxy)
|
|
||||||
furl.pathname = url
|
|
||||||
|
|
||||||
const da = await fetch(furl, {
|
|
||||||
body: JSON.stringify(arg.body),
|
|
||||||
headers: arg.headers,
|
|
||||||
method: method,
|
|
||||||
signal: arg.abortSignal
|
|
||||||
})
|
|
||||||
|
|
||||||
if(arg.rawResponse){
|
|
||||||
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
|
|
||||||
return {
|
|
||||||
ok: da.ok && da.status >= 200 && da.status < 300,
|
|
||||||
data: new Uint8Array(await da.arrayBuffer()),
|
|
||||||
headers: Object.fromEntries(da.headers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
const dat = await da.json()
|
|
||||||
addFetchLog(dat, da.ok && da.status >= 200 && da.status < 300)
|
|
||||||
return {
|
|
||||||
ok: da.ok && da.status >= 200 && da.status < 300,
|
|
||||||
data: dat,
|
|
||||||
headers: Object.fromEntries(da.headers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
ok: false,
|
|
||||||
data: `${error}`,
|
|
||||||
headers: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(isTauri){
|
if(isTauri){
|
||||||
if(db.requester === 'new'){
|
if(db.requester === 'new'){
|
||||||
try {
|
try {
|
||||||
@@ -609,8 +573,8 @@ export async function globalFetch(url:string, arg:{body?:any,headers?:{[key:stri
|
|||||||
"risu-header": encodeURIComponent(JSON.stringify(arg.headers)),
|
"risu-header": encodeURIComponent(JSON.stringify(arg.headers)),
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
},
|
},
|
||||||
method: method
|
method: method,
|
||||||
,signal: arg.abortSignal
|
signal: arg.abortSignal
|
||||||
})
|
})
|
||||||
|
|
||||||
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
|
addFetchLog("Uint8Array Response", da.ok && da.status >= 200 && da.status < 300)
|
||||||
|
|||||||
@@ -1,31 +1,90 @@
|
|||||||
import { decode, encode } from "@msgpack/msgpack";
|
import { Packr, Unpackr, decode } from "msgpackr";
|
||||||
import { isEqual } from "lodash";
|
import * as fflate from "fflate";
|
||||||
import pako from "pako";
|
import { isTauri } from "./globalApi";
|
||||||
|
|
||||||
|
const packr = new Packr({
|
||||||
|
useRecords:false
|
||||||
|
});
|
||||||
|
|
||||||
export function encodeRisuSave(data:any){
|
const unpackr = new Unpackr({
|
||||||
const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
|
int64AsType: 'number',
|
||||||
const encoded = encode(data)
|
useRecords:false
|
||||||
const mergedArray = new Uint8Array(risuSaveHeader.length + encoded.length);
|
})
|
||||||
mergedArray.set(risuSaveHeader);
|
|
||||||
mergedArray.set(encoded, risuSaveHeader.length);
|
const magicHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 7]);
|
||||||
return mergedArray
|
const magicCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 8]);
|
||||||
|
|
||||||
|
export function encodeRisuSave(data:any, compression:'noCompression'|'compression' = 'noCompression'){
|
||||||
|
let encoded:Uint8Array = packr.encode(data)
|
||||||
|
if(isTauri || compression === 'compression'){
|
||||||
|
encoded = fflate.compressSync(encoded)
|
||||||
|
const result = new Uint8Array(encoded.length + magicCompressedHeader.length);
|
||||||
|
result.set(magicCompressedHeader, 0)
|
||||||
|
result.set(encoded, magicCompressedHeader.length)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
const result = new Uint8Array(encoded.length + magicHeader.length);
|
||||||
|
result.set(magicHeader, 0)
|
||||||
|
result.set(encoded, magicHeader.length)
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeRisuSave(data:Uint8Array){
|
export function decodeRisuSave(data:Uint8Array){
|
||||||
const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
|
|
||||||
const sub = data.subarray(0, risuSaveHeader.length)
|
|
||||||
if(isEqual(sub, risuSaveHeader)){
|
|
||||||
try {
|
try {
|
||||||
|
switch(checkHeader(data)){
|
||||||
|
case "compressed":
|
||||||
|
data = data.slice(magicCompressedHeader.length)
|
||||||
|
return decode(fflate.decompressSync(data))
|
||||||
|
case "raw":
|
||||||
|
data = data.slice(magicHeader.length)
|
||||||
|
return unpackr.decode(data)
|
||||||
|
}
|
||||||
|
return unpackr.decode(data)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
try {
|
||||||
|
console.log('risudecode')
|
||||||
|
const risuSaveHeader = new Uint8Array(Buffer.from("\u0000\u0000RISU",'utf-8'))
|
||||||
const realData = data.subarray(risuSaveHeader.length)
|
const realData = data.subarray(risuSaveHeader.length)
|
||||||
const dec = decode(realData)
|
const dec = unpackr.decode(realData)
|
||||||
return dec
|
return dec
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
const buf = Buffer.from(fflate.decompressSync(Buffer.from(data)))
|
||||||
throw error
|
try {
|
||||||
|
return JSON.parse(buf.toString('utf-8'))
|
||||||
|
} catch (error) {
|
||||||
|
return unpackr.decode(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
return JSON.parse(Buffer.from(pako.inflate(Buffer.from(data))).toString('utf-8'))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkHeader(data: Uint8Array) {
|
||||||
|
|
||||||
|
let header:'none'|'compressed'|'raw' = 'raw'
|
||||||
|
|
||||||
|
if (data.length < magicHeader.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < magicHeader.length; i++) {
|
||||||
|
if (data[i] !== magicHeader[i]) {
|
||||||
|
header = 'none'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header === 'none'){
|
||||||
|
header = 'compressed'
|
||||||
|
for (let i = 0; i < magicCompressedHeader.length; i++) {
|
||||||
|
if (data[i] !== magicCompressedHeader[i]) {
|
||||||
|
header = 'none'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All bytes matched
|
||||||
|
return header;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { translatorPlugin } from "../process/plugins"
|
import { translatorPlugin } from "../plugins/plugins"
|
||||||
import { DataBase } from "../storage/database"
|
import { DataBase } from "../storage/database"
|
||||||
|
|
||||||
let cache={
|
let cache={
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":"1.27.1"}
|
{"version":"1.27.4"}
|
||||||
Reference in New Issue
Block a user