mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'dev' of https://github.com/SillyLossy/TavernAI into dev
This commit is contained in:
32
.github/workflows/npm-publish.yml
vendored
Normal file
32
.github/workflows/npm-publish.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
||||||
|
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
||||||
|
|
||||||
|
name: Node.js Package
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
- run: npm ci
|
||||||
|
|
||||||
|
publish-npm:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm publish
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ config.conf
|
|||||||
public/settings.json
|
public/settings.json
|
||||||
/thumbnails
|
/thumbnails
|
||||||
whitelist.txt
|
whitelist.txt
|
||||||
|
.vscode
|
||||||
|
4
.npmignore
Normal file
4
.npmignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
node_modules/
|
||||||
|
/uploads/
|
||||||
|
.DS_Store
|
||||||
|
/thumbnails
|
174
package-lock.json
generated
174
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "TavernAI",
|
"name": "sillytavern",
|
||||||
"version": "1.3.0",
|
"version": "1.4.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "TavernAI",
|
"name": "sillytavern",
|
||||||
"version": "1.3.0",
|
"version": "1.4.8",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
@ -31,10 +31,11 @@
|
|||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
"ws": "^8.13.0"
|
"ws": "^8.13.0",
|
||||||
|
"yargs": "^17.7.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"TavernAI": "server.js"
|
"sillytavern": "server.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@dqbd/tiktoken": {
|
"node_modules/@dqbd/tiktoken": {
|
||||||
@ -476,6 +477,28 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/any-base": {
|
"node_modules/any-base": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
|
||||||
@ -652,6 +675,35 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cliui": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"strip-ansi": "^6.0.1",
|
||||||
|
"wrap-ansi": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
|
},
|
||||||
"node_modules/combined-stream": {
|
"node_modules/combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
@ -880,6 +932,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||||
},
|
},
|
||||||
|
"node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||||
|
},
|
||||||
"node_modules/encodeurl": {
|
"node_modules/encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
@ -888,6 +945,14 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/escalade": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-html": {
|
"node_modules/escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
@ -1073,6 +1138,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/get-caller-file": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
|
"engines": {
|
||||||
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
|
||||||
@ -1245,6 +1318,14 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-function": {
|
"node_modules/is-function": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
||||||
@ -1779,6 +1860,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/require-directory": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rimraf": {
|
"node_modules/rimraf": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
@ -1937,6 +2026,30 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
},
|
},
|
||||||
|
"node_modules/string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strtok3": {
|
"node_modules/strtok3": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
|
||||||
@ -2083,6 +2196,22 @@
|
|||||||
"webidl-conversions": "^3.0.0"
|
"webidl-conversions": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wrap-ansi": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
@ -2151,6 +2280,39 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4"
|
"node": ">=0.4"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/y18n": {
|
||||||
|
"version": "5.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs": {
|
||||||
|
"version": "17.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
|
||||||
|
"integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
|
||||||
|
"dependencies": {
|
||||||
|
"cliui": "^8.0.1",
|
||||||
|
"escalade": "^3.1.1",
|
||||||
|
"get-caller-file": "^2.0.5",
|
||||||
|
"require-directory": "^2.1.1",
|
||||||
|
"string-width": "^4.2.3",
|
||||||
|
"y18n": "^5.0.5",
|
||||||
|
"yargs-parser": "^21.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs-parser": {
|
||||||
|
"version": "21.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||||
|
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
package.json
12
package.json
@ -23,17 +23,21 @@
|
|||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
"ws": "^8.13.0"
|
"ws": "^8.13.0",
|
||||||
|
"yargs": "^17.7.1"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"parse-bmfont-xml": {
|
"parse-bmfont-xml": {
|
||||||
"xml2js": "^0.5.0"
|
"xml2js": "^0.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"name": "TavernAI",
|
"name": "sillytavern",
|
||||||
"version": "1.3.0",
|
"version": "1.4.8",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"TavernAI": "server.js"
|
"sillytavern": "./server.js"
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-path-concat": "off",
|
"no-path-concat": "off",
|
||||||
|
@ -1416,13 +1416,27 @@
|
|||||||
<div title="Token counts may be inaccurate and provided just for reference." id="result_info"></div>
|
<div title="Token counts may be inaccurate and provided just for reference." id="result_info"></div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div id="description_div" class="margin-bot-10px">
|
<div id="fav_chara_wrap">
|
||||||
Description
|
<div id="fav_chara_label" class="margin-bot-10px">
|
||||||
<a href="/notes/1" class="notes-link" target="_blank">
|
<label for="fav_checkbox" class="checkbox_label">
|
||||||
<span class="note-link-span">?</span>
|
<input type="checkbox" id="fav_checkbox" name="fav"/>
|
||||||
</a>
|
Favorite
|
||||||
|
<a href="/notes/15" class="notes-link" target="_blank">
|
||||||
|
<span class="note-link-span">?</span>
|
||||||
|
</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
<div id="description_div" class="margin-bot-10px">
|
||||||
|
Description
|
||||||
|
<a href="/notes/1" class="notes-link" target="_blank">
|
||||||
|
<span class="note-link-span">?</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
<textarea id="description_textarea" placeholder="Describe your character's physical and mental traits here." class="margin-bot-10px" name="description" placeholder=""></textarea>
|
<textarea id="description_textarea" placeholder="Describe your character's physical and mental traits here." class="margin-bot-10px" name="description" placeholder=""></textarea>
|
||||||
|
|
||||||
<div id="first_message_div" class="margin-bot-10px">
|
<div id="first_message_div" class="margin-bot-10px">
|
||||||
@ -1459,6 +1473,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="rm_group_buttons">
|
<div id="rm_group_buttons">
|
||||||
<div class="rm_group_settings">
|
<div class="rm_group_settings">
|
||||||
|
<label class="checkbox_label">
|
||||||
|
<input id="rm_group_fav" type="checkbox" />
|
||||||
|
Favorite
|
||||||
|
</label>
|
||||||
<label class="checkbox_label">
|
<label class="checkbox_label">
|
||||||
<input id="rm_group_allow_self_responses" type="checkbox" />
|
<input id="rm_group_allow_self_responses" type="checkbox" />
|
||||||
Allow bot responses to self
|
Allow bot responses to self
|
||||||
@ -1518,6 +1536,8 @@
|
|||||||
<div class="fa-solid fa-user-group"></div>
|
<div class="fa-solid fa-user-group"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ch_name"></div>
|
<div class="ch_name"></div>
|
||||||
|
<i class='group_fav_icon fa-solid fa-star fa-2xs'></i>
|
||||||
|
<input class="ch_fav" value="" hidden />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1533,6 +1553,7 @@
|
|||||||
<div id="rm_button_create" title="Create New Character" class="menu_button fa-solid fa-user-plus "></div>
|
<div id="rm_button_create" title="Create New Character" class="menu_button fa-solid fa-user-plus "></div>
|
||||||
<div id="character_import_button" title="Import Character from File" class="menu_button fa-solid fa-file-arrow-up "></div>
|
<div id="character_import_button" title="Import Character from File" class="menu_button fa-solid fa-file-arrow-up "></div>
|
||||||
<div id="rm_button_group_chats" title="Create New Chat Group" class="menu_button fa-solid fa-users-gear "></div>
|
<div id="rm_button_group_chats" title="Create New Chat Group" class="menu_button fa-solid fa-users-gear "></div>
|
||||||
|
<div id="filter_by_fav" title="Filter By Favorite" class="menu_button fa-solid fa-star"></div>
|
||||||
</div>
|
</div>
|
||||||
<form id="form_character_search_form" action="javascript:void(null);">
|
<form id="form_character_search_form" action="javascript:void(null);">
|
||||||
<input id="character_search_bar" class="text_pole" type="search" placeholder="Character search..." maxlength="50" />
|
<input id="character_search_bar" class="text_pole" type="search" placeholder="Character search..." maxlength="50" />
|
||||||
|
@ -1,47 +1,47 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Character Descriptions</title>
|
<title>Character Descriptions</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>Character description</h2>
|
<h2>Character description</h2>
|
||||||
<p>
|
<p>
|
||||||
Used to add the character description and the rest that the AI should know.<br><br>
|
Used to add the character description and the rest that the AI should know.<br><br>
|
||||||
For example, you can add information about the world in which the action takes place and describe
|
For example, you can add information about the world in which the action takes place and describe
|
||||||
the characteristics for the character you are playing for.<br><br>
|
the characteristics for the character you are playing for.<br><br>
|
||||||
Usually it all takes 200-350 tokens.
|
Usually it all takes 200-350 tokens.
|
||||||
</p>
|
</p>
|
||||||
<h3>Methods and format</h3>
|
<h3>Methods and format</h3>
|
||||||
<p>
|
<p>
|
||||||
For most Kobold's models the easiest way is to use a free form for description, and in each sentence it is desirable to specify the name of the character.<br><br>
|
For most Kobold's models the easiest way is to use a free form for description, and in each sentence it
|
||||||
The entire description should be in one line without hyphenation.<br><br>
|
is desirable to specify the name of the character.<br><br>
|
||||||
For example:<br><br>
|
The entire description should be in one line without hyphenation.<br><br>
|
||||||
<code>
|
For example:<br><br>
|
||||||
Chloe is a female elf. Chloe wears black-white maid dress with green collar and red glasses. Chloe has medium length black hair. Chloe's personality is...
|
<code>
|
||||||
</code>
|
Chloe is a female elf. Chloe wears black-white maid dress with green collar and red glasses. Chloe has medium length black hair. Chloe's personality is...
|
||||||
</p>
|
</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
But that the AI would be less confused the best way is to use the W++ format.<Br><br>
|
But that the AI would be less confused the best way is to use the W++ format.<Br><br>
|
||||||
Details here: <a target="_blank" href="https://github.com/KoboldAI/KoboldAI-Client/wiki/Pro-Tips">Pro-Tips</a>
|
Details here: <a target="_blank"
|
||||||
</p>
|
href="https://github.com/KoboldAI/KoboldAI-Client/wiki/Pro-Tips">Pro-Tips</a>
|
||||||
<hr>
|
</p>
|
||||||
<p>
|
<hr>
|
||||||
<u>A list of tags that are replaced when sending to generate:</u><br><br>
|
<p>
|
||||||
{{user}} and <USER> are replaced by the User's Name<br>
|
<u>A list of tags that are replaced when sending to generate:</u><br><br>
|
||||||
{{char}} and <BOT> are replaced by the Character's Name
|
{{user}} and <USER> are replaced by the User's Name<br>
|
||||||
</p>
|
{{char}} and <BOT> are replaced by the Character's Name
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Import Chat</title>
|
<title>Import Chat</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Example Dialogues</title>
|
<title>Example Dialogues</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Scenario</title>
|
<title>Scenario</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -15,15 +13,20 @@
|
|||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>World Info</h2>
|
<h2>World Info</h2>
|
||||||
<h4>World Info enhances AI's understanding of the details in your world.</h4>
|
<h4>World Info enhances AI's understanding of the details in your world.</h4>
|
||||||
<p>It functions like a dynamic dictionary that only inserts relevant information from World Info entries when keywords associated with the entries are present in the message text.</p>
|
<p>It functions like a dynamic dictionary that only inserts relevant information from World Info entries
|
||||||
<p>The SillyTavern engine activates and seamlessly integrates the appropriate lore into the prompt, providing background information to the AI.</p>
|
when keywords associated with the entries are present in the message text.</p>
|
||||||
<p><i>It is important to note that while World Info helps guide the AI towards your desired lore, it does not guarantee its appearance in the generated output messages.</i></p>
|
<p>The SillyTavern engine activates and seamlessly integrates the appropriate lore into the prompt,
|
||||||
|
providing background information to the AI.</p>
|
||||||
|
<p><i>It is important to note that while World Info helps guide the AI towards your desired lore, it does
|
||||||
|
not guarantee its appearance in the generated output messages.</i></p>
|
||||||
|
|
||||||
<h3>Pro Tips</h3>
|
<h3>Pro Tips</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>The AI does not insert keywords into context, so each World Info entry should be a comprehensive, standalone description.</li>
|
<li>The AI does not insert keywords into context, so each World Info entry should be a comprehensive,
|
||||||
|
standalone description.</li>
|
||||||
<li>To create a rich and detailed world lore, entries can be interlinked and reference one another.</li>
|
<li>To create a rich and detailed world lore, entries can be interlinked and reference one another.</li>
|
||||||
<li>To conserve tokens, it is advisable to keep entry contents concise, with a general recommended limit of 50 tokens per entry.</li>
|
<li>To conserve tokens, it is advisable to keep entry contents concise, with a general recommended limit
|
||||||
|
of 50 tokens per entry.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
</head>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
22
public/notes/15.html
Normal file
22
public/notes/15.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Favorite Character</title>
|
||||||
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="main">
|
||||||
|
<div id="content">
|
||||||
|
<h2>Favorite Character</h2>
|
||||||
|
<p>
|
||||||
|
Mark character as favorite to quickly filter on the side menu bar by pressing the star button.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Personality Summary</title>
|
<title>Personality Summary</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -15,7 +13,8 @@
|
|||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>Personality summary</h2>
|
<h2>Personality summary</h2>
|
||||||
<p>
|
<p>
|
||||||
A brief description of the personality. It is added to the chat at a depth of 8-15 messages, so it has a significant impact on the character.
|
A brief description of the personality. It is added to the chat at a depth of 8-15 messages, so it has a
|
||||||
|
significant impact on the character.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - First Message</title>
|
<title>First Message</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>First message</h2>
|
<h2>First message</h2>
|
||||||
<p>
|
<p>
|
||||||
The First Message is an important thing that sets exactly how and in what style the character will communicate.<Br><br>
|
The First Message is an important thing that sets exactly how and in what style the character will
|
||||||
It is desirable that the character's first message be long, so that later it would be less likely that the character would respond in with very short messages. <br><br>
|
communicate.<Br><br>
|
||||||
You can also use asterisks ** to describe the character's actions.
|
It is desirable that the character's first message be long, so that later it would be less likely that
|
||||||
</P>
|
the character would respond in with very short messages. <br><br>
|
||||||
|
You can also use asterisks ** to describe the character's actions.
|
||||||
|
</P>
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
<br><br>
|
<br><br>
|
||||||
<code>
|
<code>
|
||||||
*I noticed you came inside, I walked up and stood right in front of you* Welcome. I'm glad to see you here.
|
*I noticed you came inside, I walked up and stood right in front of you* Welcome. I'm glad to see you here.
|
||||||
*I said with toothy smug sunny smile looking you straight in the eye* What brings you...
|
*I said with toothy smug sunny smile looking you straight in the eye* What brings you...
|
||||||
</code>
|
</code>
|
||||||
<Br>
|
<Br>
|
||||||
<hr>
|
<hr>
|
||||||
<p>
|
<p>
|
||||||
<u>A list of tags that are replaced when sending to generate:</u><br><br>
|
<u>A list of tags that are replaced when sending to generate:</u><br><br>
|
||||||
{{user}} and <USER> are replaced by the User's Name<br>
|
{{user}} and <USER> are replaced by the User's Name<br>
|
||||||
{{char}} and <BOT> are replaced by the Character's Name
|
{{char}} and <BOT> are replaced by the Character's Name
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - KobolAI Settings</title>
|
<title>KoboldAI Settings</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,36 +1,37 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Novel AI API Key</title>
|
<title>NovelAI API Key</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>Finding your NAI API key</h2>
|
<h2>Finding your NAI API key</h2>
|
||||||
<h4>To get a NovelAI API key, follow these instructions:</h4>
|
<h4>To get a NovelAI API key, follow these instructions:</h4>
|
||||||
<p>
|
<p>
|
||||||
1. Go to the NovelAI website and Login.<br><br>
|
1. Go to the NovelAI website and Login.<br><br>
|
||||||
|
|
||||||
2. Create a new story, or open an existing story.<br><br>
|
2. Create a new story, or open an existing story.<br><br>
|
||||||
|
|
||||||
3. Open the Network Tools on your web browser. (For Chrome or Firefox, you do this by pressing Ctrl+Shift+I, then switching to the Network tab.)<br><br>
|
3. Open the Network Tools on your web browser. (For Chrome or Firefox, you do this by pressing
|
||||||
|
Ctrl+Shift+I, then switching to the Network tab.)<br><br>
|
||||||
|
|
||||||
4. Generate something. You should see two requests to api.novelai.net/ai/generate-stream, which might look something like this:<br><br>
|
4. Generate something. You should see two requests to api.novelai.net/ai/generate-stream, which might
|
||||||
<img src="1.png"><br><br>
|
look something like this:<br><br>
|
||||||
5. Select the second request, then in the Headers tab of the inspection panel, scroll down to the very bottom. Look for a header called Authorization:<br><br>
|
<img src="1.png"><br><br>
|
||||||
<img src="2.png"><br><br>
|
5. Select the second request, then in the Headers tab of the inspection panel, scroll down to the very
|
||||||
The long string (after "Bearer", not including it) is your API key.<br><br>
|
bottom. Look for a header called Authorization:<br><br>
|
||||||
* Proxies and Cloudflare-type services may interfere with connection.
|
<img src="2.png"><br><br>
|
||||||
</p>
|
The long string (after "Bearer", not including it) is your API key.<br><br>
|
||||||
</div>
|
* Proxies and Cloudflare-type services may interfere with connection.
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,43 +1,43 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - NovelAI Settings</title>
|
<title>NovelAI Settings</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>NovelAI settings</h2>
|
<h2>NovelAI settings</h2>
|
||||||
<p>
|
<p>
|
||||||
The files with the settings are here (SillyTavern\public\NovelAI Settings).<br>
|
The files with the settings are here (SillyTavern\public\NovelAI Settings).<br>
|
||||||
You can also manually add your own settings files.
|
You can also manually add your own settings files.
|
||||||
</p>
|
</p>
|
||||||
<h3>Temperature</h3>
|
<h3>Temperature</h3>
|
||||||
<p>
|
<p>
|
||||||
Value from 0.1 to 2.0. <br>
|
Value from 0.1 to 2.0. <br>
|
||||||
Lower value - the answers are more logical, but less creative. <br>
|
Lower value - the answers are more logical, but less creative. <br>
|
||||||
Higher value - the answers are more creative, but less logical.
|
Higher value - the answers are more creative, but less logical.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Repetition penalty</h3>
|
<h3>Repetition penalty</h3>
|
||||||
<p>
|
<p>
|
||||||
Repetition penalty is responsible for the penalty of repeated words. <br>
|
Repetition penalty is responsible for the penalty of repeated words. <br>
|
||||||
If the character is fixated on something or repeats the same phrase, then increasing this parameter will fix it. <br>
|
If the character is fixated on something or repeats the same phrase, then increasing this parameter will
|
||||||
It is not recommended to increase this parameter too much for the chat format, as it may break this format. <br>
|
fix it. <br>
|
||||||
<b>The standard value for chat is approximately 1.0 - 1.05</b>
|
It is not recommended to increase this parameter too much for the chat format, as it may break this
|
||||||
</p>
|
format. <br>
|
||||||
<h3>Repetition penalty range</h3>
|
<b>The standard value for chat is approximately 1.0 - 1.05</b>
|
||||||
<p>
|
</p>
|
||||||
The range of influence of Repetition penalty in tokens.
|
<h3>Repetition penalty range</h3>
|
||||||
</p>
|
<p>
|
||||||
</div>
|
The range of influence of Repetition penalty in tokens.
|
||||||
</div>
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,13 +1,11 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - NovelAI Models</title>
|
<title>NovelAI Models</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,49 +1,53 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>SillyTavern - Note - Anchors</title>
|
<title>Anchors</title>
|
||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h2>Anchors</h2>
|
<h2>Anchors</h2>
|
||||||
<p>
|
<p>
|
||||||
Anchors are used to increase the length of messages.<br>
|
Anchors are used to increase the length of messages.<br>
|
||||||
There are two types of anchors: <u>Character Anchor</u> and <u>Style Anchor</u>
|
There are two types of anchors: <u>Character Anchor</u> and <u>Style Anchor</u>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<u>Character Anchor</u> - affects the character played by the AI by motivating it to write longer messages.<br><br>
|
<u>Character Anchor</u> - affects the character played by the AI by motivating it to write longer
|
||||||
Looks like:
|
messages.<br><br>
|
||||||
<code>[Elaborate speaker]</code>
|
Looks like:
|
||||||
</p>
|
<code>[Elaborate speaker]</code>
|
||||||
<p>
|
</p>
|
||||||
<u>Style Anchor</u> - affects the entire AI model, motivating the AI to write longer messages even when it is not acting as the character.<Br><br>
|
<p>
|
||||||
Looks like:
|
<u>Style Anchor</u> - affects the entire AI model, motivating the AI to write longer messages even when
|
||||||
<code>[Writing style: very long messages]</code>
|
it is not acting as the character.<Br><br>
|
||||||
</p>
|
Looks like:
|
||||||
<hr>
|
<code>[Writing style: very long messages]</code>
|
||||||
<p>
|
</p>
|
||||||
Anchors Order sets the location of anchors in the promt, the first anchor in the order is much further back in the context and thus has less influence than second.
|
<hr>
|
||||||
</p>
|
<p>
|
||||||
<p>
|
Anchors Order sets the location of anchors in the promt, the first anchor in the order is much further
|
||||||
The second anchor is only turned on after 8-12 messages, because when the chat still only has a few messages, the first anchor creates enough effect on its own.
|
back in the context and thus has less influence than second.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Sometimes an AI model may not perceive anchors correctly or the AI model already generates sufficiently long messages.
|
The second anchor is only turned on after 8-12 messages, because when the chat still only has a few
|
||||||
For these cases, you can disable the anchors by unchecking their respective boxes.
|
messages, the first anchor creates enough effect on its own.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<u>When using Pygmalion models these anchors are automatically disabled, since Pygmalion already generates long enough messages.</u>
|
Sometimes an AI model may not perceive anchors correctly or the AI model already generates sufficiently
|
||||||
</p>
|
long messages.
|
||||||
</div>
|
For these cases, you can disable the anchors by unchecking their respective boxes.
|
||||||
</div>
|
</p>
|
||||||
|
<p>
|
||||||
|
<u>When using Pygmalion models these anchors are automatically disabled, since Pygmalion already
|
||||||
|
generates long enough messages.</u>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -5,11 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
|
||||||
rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
|
||||||
rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
|
||||||
rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,11 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
|
||||||
rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
<link rel="stylesheet" href="/css/notes.css">
|
<link rel="stylesheet" href="/css/notes.css">
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link href="/webfonts/NotoSans/stylesheet.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -159,7 +159,7 @@ export {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// API OBJECT FOR EXTERNAL WIRING
|
// API OBJECT FOR EXTERNAL WIRING
|
||||||
window["TavernAI"] = {};
|
window["SillyTavern"] = {};
|
||||||
|
|
||||||
let converter = new showdown.Converter({ emoji: "true" });
|
let converter = new showdown.Converter({ emoji: "true" });
|
||||||
const gpt3 = new GPT3BrowserTokenizer({ type: 'gpt3' });
|
const gpt3 = new GPT3BrowserTokenizer({ type: 'gpt3' });
|
||||||
@ -204,6 +204,8 @@ let dialogueResolve = null;
|
|||||||
let chat_metadata = {};
|
let chat_metadata = {};
|
||||||
let streamingProcessor = null;
|
let streamingProcessor = null;
|
||||||
|
|
||||||
|
let fav_ch_checked = false;
|
||||||
|
window.filterByFav = false;
|
||||||
|
|
||||||
const durationSaveEdit = 200;
|
const durationSaveEdit = 200;
|
||||||
const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit);
|
const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit);
|
||||||
@ -330,6 +332,7 @@ var menu_type = ""; //what is selected in the menu
|
|||||||
var selected_button = ""; //which button pressed
|
var selected_button = ""; //which button pressed
|
||||||
//create pole save
|
//create pole save
|
||||||
var create_save_name = "";
|
var create_save_name = "";
|
||||||
|
var create_fav_chara = "";
|
||||||
var create_save_description = "";
|
var create_save_description = "";
|
||||||
var create_save_personality = "";
|
var create_save_personality = "";
|
||||||
var create_save_first_message = "";
|
var create_save_first_message = "";
|
||||||
@ -635,8 +638,6 @@ function updateSoftPromptsList(soft_prompts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function printCharacters() {
|
function printCharacters() {
|
||||||
//console.log('printCharacters() entered');
|
|
||||||
|
|
||||||
$("#rm_print_characters_block").empty();
|
$("#rm_print_characters_block").empty();
|
||||||
//console.log('printCharacters() -- sees '+characters.length+' characters.');
|
//console.log('printCharacters() -- sees '+characters.length+' characters.');
|
||||||
characters.forEach(function (item, i, arr) {
|
characters.forEach(function (item, i, arr) {
|
||||||
@ -648,7 +649,8 @@ function printCharacters() {
|
|||||||
|
|
||||||
`<div class=character_select chid=${i} id="CharID${i}">
|
`<div class=character_select chid=${i} id="CharID${i}">
|
||||||
<div class=avatar><img src="${this_avatar}"></div>
|
<div class=avatar><img src="${this_avatar}"></div>
|
||||||
<div class=ch_name>${item.name}</div>
|
<div class=ch_name>${item.name} ${item.fav == "true" ? '<i class="fa-solid fa-star fa-2xs"></i>' : ''}</div>
|
||||||
|
<input class="ch_fav" value=${item.fav} hidden />
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
//console.log('printcharacters() -- printing -- ChID '+i+' ('+item.name+')');
|
//console.log('printcharacters() -- printing -- ChID '+i+' ('+item.name+')');
|
||||||
@ -1314,7 +1316,7 @@ class StreamingProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function Generate(type, automatic_trigger, force_name2) {
|
async function Generate(type, automatic_trigger, force_name2) {
|
||||||
console.log('Generate entered');
|
//console.log('Generate entered');
|
||||||
setGenerationProgress(0);
|
setGenerationProgress(0);
|
||||||
tokens_already_generated = 0;
|
tokens_already_generated = 0;
|
||||||
const isImpersonate = type == "impersonate";
|
const isImpersonate = type == "impersonate";
|
||||||
@ -3166,6 +3168,9 @@ function select_selected_character(chid) {
|
|||||||
if (characters[chid].avatar != "none") {
|
if (characters[chid].avatar != "none") {
|
||||||
this_avatar = getThumbnailUrl('avatar', characters[chid].avatar);
|
this_avatar = getThumbnailUrl('avatar', characters[chid].avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#fav_checkbox").prop("checked", characters[chid].fav == "true");
|
||||||
|
|
||||||
$("#avatar_load_preview").attr("src", this_avatar);
|
$("#avatar_load_preview").attr("src", this_avatar);
|
||||||
$("#name_div").css("display", "none");
|
$("#name_div").css("display", "none");
|
||||||
|
|
||||||
@ -3456,7 +3461,7 @@ function isHordeGenerationNotAllowed() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window["TavernAI"].getContext = function () {
|
window["SillyTavern"].getContext = function () {
|
||||||
return {
|
return {
|
||||||
chat: chat,
|
chat: chat,
|
||||||
characters: characters,
|
characters: characters,
|
||||||
@ -3791,6 +3796,25 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#filter_by_fav").click(function() {
|
||||||
|
filterByFav = !filterByFav;
|
||||||
|
|
||||||
|
const selector = ['#rm_print_characters_block .character_select', '#rm_print_characters_block .group_select'].join(',');
|
||||||
|
if(filterByFav){
|
||||||
|
$(selector).each(function () {
|
||||||
|
if($(this).children(".ch_fav").length !== 0){
|
||||||
|
$(this).children(".ch_fav").val().toLowerCase().includes(true)
|
||||||
|
? $(this).show()
|
||||||
|
: $(this).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#filter_by_fav").addClass("fav_on");
|
||||||
|
}else{
|
||||||
|
$(selector).show();
|
||||||
|
$("#filter_by_fav").removeClass("fav_on");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#send_but").click(function () {
|
$("#send_but").click(function () {
|
||||||
if (is_send_press == false) {
|
if (is_send_press == false) {
|
||||||
is_send_press = true;
|
is_send_press = true;
|
||||||
@ -3833,6 +3857,7 @@ $(document).ready(function () {
|
|||||||
selected_button = "character_edit";
|
selected_button = "character_edit";
|
||||||
select_selected_character(this_chid);
|
select_selected_character(this_chid);
|
||||||
}
|
}
|
||||||
|
$("#character_search_bar").val("").trigger("input");
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", ".character_select", function () {
|
$(document).on("click", ".character_select", function () {
|
||||||
@ -3860,7 +3885,6 @@ $(document).ready(function () {
|
|||||||
selected_button = "character_edit";
|
selected_button = "character_edit";
|
||||||
select_selected_character(this_chid);
|
select_selected_character(this_chid);
|
||||||
}
|
}
|
||||||
$("#character_search_bar").val("").trigger("input");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -4128,6 +4152,7 @@ $(document).ready(function () {
|
|||||||
$("#rm_info_avatar").html("");
|
$("#rm_info_avatar").html("");
|
||||||
let save_name = create_save_name;
|
let save_name = create_save_name;
|
||||||
var formData = new FormData($("#form_create").get(0));
|
var formData = new FormData($("#form_create").get(0));
|
||||||
|
formData.set('fav', fav_ch_checked);
|
||||||
if ($("#form_create").attr("actiontype") == "createcharacter") {
|
if ($("#form_create").attr("actiontype") == "createcharacter") {
|
||||||
if ($("#character_name_pole").val().length > 0) {
|
if ($("#character_name_pole").val().length > 0) {
|
||||||
//if the character name text area isn't empty (only posible when creating a new character)
|
//if the character name text area isn't empty (only posible when creating a new character)
|
||||||
@ -4294,11 +4319,18 @@ $(document).ready(function () {
|
|||||||
create_save_scenario = $("#scenario_pole").val();
|
create_save_scenario = $("#scenario_pole").val();
|
||||||
create_save_mes_example = $("#mes_example_textarea").val();
|
create_save_mes_example = $("#mes_example_textarea").val();
|
||||||
create_save_first_message = $("#firstmessage_textarea").val();
|
create_save_first_message = $("#firstmessage_textarea").val();
|
||||||
|
create_fav_chara = $("#fav_checkbox").val();
|
||||||
} else {
|
} else {
|
||||||
saveCharacterDebounced();
|
saveCharacterDebounced();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#fav_checkbox").change(function(){
|
||||||
|
fav_ch_checked = $(this).prop("checked");
|
||||||
|
if (menu_type != "create") {
|
||||||
|
saveCharacterDebounced();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#talkativeness_slider").on("input", function () {
|
$("#talkativeness_slider").on("input", function () {
|
||||||
if (menu_type == "create") {
|
if (menu_type == "create") {
|
||||||
|
@ -30,7 +30,7 @@ const extension_settings = {
|
|||||||
let modules = [];
|
let modules = [];
|
||||||
let activeExtensions = new Set();
|
let activeExtensions = new Set();
|
||||||
|
|
||||||
const getContext = () => window['TavernAI'].getContext();
|
const getContext = () => window['SillyTavern'].getContext();
|
||||||
const getApiUrl = () => extension_settings.apiUrl;
|
const getApiUrl = () => extension_settings.apiUrl;
|
||||||
const defaultRequestArgs = { method: 'GET', headers: { 'Bypass-Tunnel-Reminder': 'bypass' } };
|
const defaultRequestArgs = { method: 'GET', headers: { 'Bypass-Tunnel-Reminder': 'bypass' } };
|
||||||
let connectedToApi = false;
|
let connectedToApi = false;
|
||||||
|
102
public/scripts/extensions/elevenlabstts/elevenlabs.js
Normal file
102
public/scripts/extensions/elevenlabstts/elevenlabs.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
export { ElevenLabsTtsProvider }
|
||||||
|
|
||||||
|
class ElevenLabsTtsProvider {
|
||||||
|
API_KEY
|
||||||
|
set API_KEY(apiKey) {
|
||||||
|
this.API_KEY = apiKey
|
||||||
|
}
|
||||||
|
get API_KEY() {
|
||||||
|
return this.API_KEY
|
||||||
|
}
|
||||||
|
async fetchTtsVoiceIds() {
|
||||||
|
const headers = {
|
||||||
|
'xi-api-key': this.API_KEY
|
||||||
|
}
|
||||||
|
const response = await fetch(`https://api.elevenlabs.io/v1/voices`, {
|
||||||
|
headers: headers
|
||||||
|
})
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${await response.json()}`)
|
||||||
|
}
|
||||||
|
const responseJson = await response.json()
|
||||||
|
return responseJson.voices
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTtsVoiceSettings() {
|
||||||
|
const headers = {
|
||||||
|
'xi-api-key': this.API_KEY
|
||||||
|
}
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.elevenlabs.io/v1/voices/settings/default`,
|
||||||
|
{
|
||||||
|
headers: headers
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${await response.json()}`)
|
||||||
|
}
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTtsGeneration(text, voiceId) {
|
||||||
|
console.info(`Generating new TTS for voice_id ${voiceId}`)
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'xi-api-key': this.API_KEY,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ text: text })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${await response.json()}`)
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTtsFromHistory(history_item_id) {
|
||||||
|
console.info(`Fetched existing TTS with history_item_id ${history_item_id}`)
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.elevenlabs.io/v1/history/${history_item_id}/audio`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'xi-api-key': this.API_KEY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${await response.json()}`)
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTtsHistory() {
|
||||||
|
const headers = {
|
||||||
|
'xi-api-key': this.API_KEY
|
||||||
|
}
|
||||||
|
const response = await fetch(`https://api.elevenlabs.io/v1/history`, {
|
||||||
|
headers: headers
|
||||||
|
})
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status}: ${await response.json()}`)
|
||||||
|
}
|
||||||
|
const responseJson = await response.json()
|
||||||
|
return responseJson.history
|
||||||
|
}
|
||||||
|
|
||||||
|
async findTtsGenerationInHistory(message, voiceId) {
|
||||||
|
const ttsHistory = await this.fetchTtsHistory()
|
||||||
|
for (const history of ttsHistory) {
|
||||||
|
const text = history.text
|
||||||
|
const itemId = history.history_item_id
|
||||||
|
if (message === text && history.voice_id == voiceId) {
|
||||||
|
console.info(`Existing TTS history item ${itemId} found: ${text} `)
|
||||||
|
return itemId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
@ -1,160 +1,80 @@
|
|||||||
import { callPopup, saveSettingsDebounced } from "../../../script.js";
|
import { callPopup, saveSettingsDebounced } from '../../../script.js'
|
||||||
import { extension_settings, getContext } from "../../extensions.js";
|
import { extension_settings, getContext } from '../../extensions.js'
|
||||||
import { getStringHash } from "../../utils.js";
|
import { getStringHash } from '../../utils.js'
|
||||||
|
import { ElevenLabsTtsProvider } from './elevenlabs.js'
|
||||||
|
|
||||||
const UPDATE_INTERVAL = 1000;
|
const UPDATE_INTERVAL = 1000
|
||||||
let API_KEY
|
|
||||||
|
|
||||||
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
||||||
let elevenlabsTtsVoices = []
|
let elevenlabsTtsVoices = []
|
||||||
let audioControl
|
let audioControl
|
||||||
|
|
||||||
|
let lastCharacterId = null
|
||||||
|
let lastGroupId = null
|
||||||
|
let lastChatId = null
|
||||||
|
let lastMessageHash = null
|
||||||
|
|
||||||
let lastCharacterId = null;
|
let ttsProvider = new ElevenLabsTtsProvider()
|
||||||
let lastGroupId = null;
|
|
||||||
let lastChatId = null;
|
|
||||||
let lastMessageHash = null;
|
|
||||||
|
|
||||||
|
|
||||||
async function moduleWorker() {
|
async function moduleWorker() {
|
||||||
// Primarily determinign when to add new chat to the TTS queue
|
// Primarily determinign when to add new chat to the TTS queue
|
||||||
const enabled = $("#elevenlabs_enabled").is(':checked');
|
const enabled = $('#elevenlabs_enabled').is(':checked')
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = getContext()
|
const context = getContext()
|
||||||
const chat = context.chat;
|
const chat = context.chat
|
||||||
|
|
||||||
processTtsQueue();
|
processTtsQueue()
|
||||||
processAudioJobQueue();
|
processAudioJobQueue()
|
||||||
updateUiAudioPlayState();
|
updateUiAudioPlayState()
|
||||||
|
|
||||||
// no characters or group selected
|
// no characters or group selected
|
||||||
if (!context.groupId && !context.characterId) {
|
if (!context.groupId && !context.characterId) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chat/character/group changed
|
// Chat/character/group changed
|
||||||
if ((context.groupId && lastGroupId !== context.groupId) || (context.characterId !== lastCharacterId) || (context.chatId !== lastChatId)) {
|
if (
|
||||||
|
(context.groupId && lastGroupId !== context.groupId) ||
|
||||||
|
context.characterId !== lastCharacterId ||
|
||||||
|
context.chatId !== lastChatId
|
||||||
|
) {
|
||||||
currentMessageNumber = context.chat.length ? context.chat.length : 0
|
currentMessageNumber = context.chat.length ? context.chat.length : 0
|
||||||
saveLastValues();
|
saveLastValues()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// take the count of messages
|
// take the count of messages
|
||||||
let lastMessageNumber = context.chat.length ? context.chat.length : 0;
|
let lastMessageNumber = context.chat.length ? context.chat.length : 0
|
||||||
|
|
||||||
// There's no new messages
|
// There's no new messages
|
||||||
let diff = lastMessageNumber - currentMessageNumber;
|
let diff = lastMessageNumber - currentMessageNumber
|
||||||
let hashNew = getStringHash((chat.length && chat[chat.length - 1].mes) ?? '');
|
let hashNew = getStringHash((chat.length && chat[chat.length - 1].mes) ?? '')
|
||||||
|
|
||||||
if (diff == 0 && hashNew === lastMessageHash) {
|
if (diff == 0 && hashNew === lastMessageHash) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = chat[chat.length - 1];
|
const message = chat[chat.length - 1]
|
||||||
|
|
||||||
// We're currently swiping or streaming. Don't generate voice
|
// We're currently swiping or streaming. Don't generate voice
|
||||||
if (message.mes === '...' || (context.streamingProcessor && !context.streamingProcessor.isFinished)) {
|
if (
|
||||||
return;
|
message.mes === '...' ||
|
||||||
|
(context.streamingProcessor && !context.streamingProcessor.isFinished)
|
||||||
|
) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// New messages, add new chat to history
|
// New messages, add new chat to history
|
||||||
lastMessageHash = hashNew;
|
lastMessageHash = hashNew
|
||||||
currentMessageNumber = lastMessageNumber;
|
currentMessageNumber = lastMessageNumber
|
||||||
|
|
||||||
console.debug(`Adding message from ${message.name} for TTS processing: "${message.mes}"`);
|
console.debug(
|
||||||
ttsJobQueue.push(message);
|
`Adding message from ${message.name} for TTS processing: "${message.mes}"`
|
||||||
}
|
)
|
||||||
|
ttsJobQueue.push(message)
|
||||||
|
|
||||||
//#################//
|
|
||||||
// TTS API Calls //
|
|
||||||
//#################//
|
|
||||||
|
|
||||||
async function fetchTtsVoiceIds() {
|
|
||||||
const headers = {
|
|
||||||
'xi-api-key': API_KEY
|
|
||||||
};
|
|
||||||
const response = await fetch(`https://api.elevenlabs.io/v1/voices`, {
|
|
||||||
headers: headers
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${await response.json()}`);
|
|
||||||
}
|
|
||||||
const responseJson = await response.json();
|
|
||||||
return responseJson.voices;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchTtsVoiceSettings() {
|
|
||||||
const headers = {
|
|
||||||
'xi-api-key': API_KEY
|
|
||||||
};
|
|
||||||
const response = await fetch(`https://api.elevenlabs.io/v1/voices/settings/default`, {
|
|
||||||
headers: headers
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${await response.json()}`);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchTtsGeneration(text, voiceId) {
|
|
||||||
console.info(`Generating new TTS for voice_id ${voiceId}`);
|
|
||||||
const response = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'xi-api-key': API_KEY,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ text: text })
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${await response.json()}`);
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchTtsFromHistory(history_item_id) {
|
|
||||||
console.info(`Fetched existing TTS with history_item_id ${history_item_id}`);
|
|
||||||
const response = await fetch(`https://api.elevenlabs.io/v1/history/${history_item_id}/audio`, {
|
|
||||||
headers: {
|
|
||||||
'xi-api-key': API_KEY
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${await response.json()}`);
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchTtsHistory() {
|
|
||||||
const headers = {
|
|
||||||
'xi-api-key': API_KEY
|
|
||||||
};
|
|
||||||
const response = await fetch(`https://api.elevenlabs.io/v1/history`, {
|
|
||||||
headers: headers
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP ${response.status}: ${await response.json()}`);
|
|
||||||
}
|
|
||||||
const responseJson = await response.json();
|
|
||||||
return responseJson.history;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function findTtsGenerationInHistory(message, voiceId) {
|
|
||||||
const ttsHistory = await fetchTtsHistory();
|
|
||||||
for (const history of ttsHistory) {
|
|
||||||
const text = history.text;
|
|
||||||
const itemId = history.history_item_id;
|
|
||||||
if (message === text && history.voice_id == voiceId) {
|
|
||||||
console.info(`Existing TTS history item ${itemId} found: ${text} `)
|
|
||||||
return itemId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//##################//
|
//##################//
|
||||||
@ -170,14 +90,13 @@ let queueProcessorReady = true
|
|||||||
|
|
||||||
let lastAudioPosition = 0
|
let lastAudioPosition = 0
|
||||||
|
|
||||||
|
|
||||||
async function playAudioData(audioBlob) {
|
async function playAudioData(audioBlob) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader()
|
||||||
reader.onload = function (e) {
|
reader.onload = function (e) {
|
||||||
const srcUrl = e.target.result;
|
const srcUrl = e.target.result
|
||||||
audioElement.src = srcUrl;
|
audioElement.src = srcUrl
|
||||||
};
|
}
|
||||||
reader.readAsDataURL(audioBlob);
|
reader.readAsDataURL(audioBlob)
|
||||||
audioElement.addEventListener('ended', completeCurrentAudioJob)
|
audioElement.addEventListener('ended', completeCurrentAudioJob)
|
||||||
audioElement.addEventListener('canplay', () => {
|
audioElement.addEventListener('canplay', () => {
|
||||||
console.debug(`Starting TTS playback`)
|
console.debug(`Starting TTS playback`)
|
||||||
@ -185,28 +104,26 @@ async function playAudioData(audioBlob) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
window['elevenlabsPreview'] = function(id) {
|
window['elevenlabsPreview'] = function (id) {
|
||||||
const audio = document.getElementById(id);
|
const audio = document.getElementById(id)
|
||||||
audio.play();
|
audio.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onElevenlabsVoicesClick() {
|
async function onElevenlabsVoicesClick() {
|
||||||
let popupText = '';
|
let popupText = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const voiceIds = await fetchTtsVoiceIds();
|
const voiceIds = await ttsProvider.fetchTtsVoiceIds()
|
||||||
|
|
||||||
for (const voice of voiceIds) {
|
for (const voice of voiceIds) {
|
||||||
popupText += `<div class="voice_preview"><b>${voice.name}</b> <i onclick="elevenlabsPreview('${voice.voice_id}')" class="fa-solid fa-play"></i></div>`;
|
popupText += `<div class="voice_preview"><b>${voice.name}</b> <i onclick="elevenlabsPreview('${voice.voice_id}')" class="fa-solid fa-play"></i></div>`
|
||||||
popupText += `<audio id="${voice.voice_id}" src="${voice.preview_url}"></audio>`;
|
popupText += `<audio id="${voice.voice_id}" src="${voice.preview_url}"></audio>`
|
||||||
}
|
}
|
||||||
}
|
} catch {
|
||||||
catch {
|
|
||||||
popupText = 'Could not load voices list. Check your API key.'
|
popupText = 'Could not load voices list. Check your API key.'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callPopup(popupText, 'text')
|
||||||
callPopup(popupText, 'text');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function completeCurrentAudioJob() {
|
function completeCurrentAudioJob() {
|
||||||
@ -217,21 +134,21 @@ function completeCurrentAudioJob() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts an HTTP response containing audio/mpeg data, and puts the data as a Blob() on the queue for playback
|
* Accepts an HTTP response containing audio/mpeg data, and puts the data as a Blob() on the queue for playback
|
||||||
* @param {*} response
|
* @param {*} response
|
||||||
*/
|
*/
|
||||||
async function addAudioJob(response) {
|
async function addAudioJob(response) {
|
||||||
const audioData = await response.blob()
|
const audioData = await response.blob()
|
||||||
if (audioData.type != "audio/mpeg") {
|
if (audioData.type != 'audio/mpeg') {
|
||||||
throw `TTS received HTTP response with invalid data format. Expecting audio/mpeg, got ${audioData.type}`
|
throw `TTS received HTTP response with invalid data format. Expecting audio/mpeg, got ${audioData.type}`
|
||||||
}
|
}
|
||||||
audioJobQueue.push(audioData)
|
audioJobQueue.push(audioData)
|
||||||
console.debug("Pushed audio job to queue.")
|
console.debug('Pushed audio job to queue.')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processAudioJobQueue() {
|
async function processAudioJobQueue() {
|
||||||
// Nothing to do, audio not completed, or audio paused - stop processing.
|
// Nothing to do, audio not completed, or audio paused - stop processing.
|
||||||
if (audioJobQueue.length == 0 || !queueProcessorReady || audioPaused) {
|
if (audioJobQueue.length == 0 || !queueProcessorReady || audioPaused) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
queueProcessorReady = false
|
queueProcessorReady = false
|
||||||
@ -243,7 +160,6 @@ async function processAudioJobQueue() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//################//
|
//################//
|
||||||
// TTS Control //
|
// TTS Control //
|
||||||
//################//
|
//################//
|
||||||
@ -259,22 +175,24 @@ function completeTtsJob() {
|
|||||||
|
|
||||||
function saveLastValues() {
|
function saveLastValues() {
|
||||||
const context = getContext()
|
const context = getContext()
|
||||||
lastGroupId = context.groupId;
|
lastGroupId = context.groupId
|
||||||
lastCharacterId = context.characterId;
|
lastCharacterId = context.characterId
|
||||||
lastChatId = context.chatId;
|
lastChatId = context.chatId
|
||||||
lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1].mes) ?? '');
|
lastMessageHash = getStringHash(
|
||||||
|
(context.chat.length && context.chat[context.chat.length - 1].mes) ?? ''
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tts(text, voiceId) {
|
async function tts(text, voiceId) {
|
||||||
const historyId = await findTtsGenerationInHistory(text, voiceId);
|
const historyId = await ttsProvider.findTtsGenerationInHistory(text, voiceId)
|
||||||
|
|
||||||
let response;
|
let response
|
||||||
if (historyId) {
|
if (historyId) {
|
||||||
console.debug(`Found existing TTS generation with id ${historyId}`)
|
console.debug(`Found existing TTS generation with id ${historyId}`)
|
||||||
response = await fetchTtsFromHistory(historyId);
|
response = await ttsProvider.fetchTtsFromHistory(historyId)
|
||||||
} else {
|
} else {
|
||||||
console.debug(`No existing TTS generation found, requesting new generation`)
|
console.debug(`No existing TTS generation found, requesting new generation`)
|
||||||
response = await fetchTtsGeneration(text, voiceId);
|
response = await ttsProvider.fetchTtsGeneration(text, voiceId)
|
||||||
}
|
}
|
||||||
addAudioJob(response)
|
addAudioJob(response)
|
||||||
completeTtsJob()
|
completeTtsJob()
|
||||||
@ -283,12 +201,12 @@ async function tts(text, voiceId) {
|
|||||||
async function processTtsQueue() {
|
async function processTtsQueue() {
|
||||||
// Called each moduleWorker iteration to pull chat messages from queue
|
// Called each moduleWorker iteration to pull chat messages from queue
|
||||||
if (currentTtsJob || ttsJobQueue.length <= 0 || audioPaused) {
|
if (currentTtsJob || ttsJobQueue.length <= 0 || audioPaused) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.debug("New message found, running TTS")
|
console.debug('New message found, running TTS')
|
||||||
currentTtsJob = ttsJobQueue.shift()
|
currentTtsJob = ttsJobQueue.shift()
|
||||||
const text = currentTtsJob.mes.replaceAll('*', '...');
|
const text = currentTtsJob.mes.replaceAll('*', '...')
|
||||||
const char = currentTtsJob.name
|
const char = currentTtsJob.name
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -298,20 +216,19 @@ async function processTtsQueue() {
|
|||||||
const voice = await getTtsVoice(voiceMap[char])
|
const voice = await getTtsVoice(voiceMap[char])
|
||||||
const voiceId = voice.voice_id
|
const voiceId = voice.voice_id
|
||||||
if (voiceId == null) {
|
if (voiceId == null) {
|
||||||
throw (`Unable to attain voiceId for ${char}`)
|
throw `Unable to attain voiceId for ${char}`
|
||||||
}
|
}
|
||||||
tts(text, voiceId)
|
tts(text, voiceId)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
currentTtsJob = null
|
currentTtsJob = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Secret function for now
|
// Secret function for now
|
||||||
async function playFullConversation() {
|
async function playFullConversation() {
|
||||||
const context = getContext()
|
const context = getContext()
|
||||||
const chat = context.chat;
|
const chat = context.chat
|
||||||
ttsJobQueue = chat
|
ttsJobQueue = chat
|
||||||
}
|
}
|
||||||
window.playFullConversation = playFullConversation
|
window.playFullConversation = playFullConversation
|
||||||
@ -323,52 +240,60 @@ window.playFullConversation = playFullConversation
|
|||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
const context = getContext()
|
const context = getContext()
|
||||||
if (Object.keys(extension_settings.elevenlabstts).length === 0) {
|
if (Object.keys(extension_settings.elevenlabstts).length === 0) {
|
||||||
Object.assign(extension_settings.elevenlabstts, defaultSettings);
|
Object.assign(extension_settings.elevenlabstts, defaultSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#elevenlabs_api_key').val(extension_settings.elevenlabstts.elevenlabsApiKey);
|
$('#elevenlabs_api_key').val(
|
||||||
$('#elevenlabs_voice_map').val(extension_settings.elevenlabstts.elevenlabsVoiceMap);
|
extension_settings.elevenlabstts.elevenlabsApiKey
|
||||||
$('#elevenlabs_enabled').prop('checked', extension_settings.elevenlabstts.enabled);
|
)
|
||||||
|
$('#elevenlabs_voice_map').val(
|
||||||
|
extension_settings.elevenlabstts.elevenlabsVoiceMap
|
||||||
|
)
|
||||||
|
$('#elevenlabs_enabled').prop(
|
||||||
|
'checked',
|
||||||
|
extension_settings.elevenlabstts.enabled
|
||||||
|
)
|
||||||
onElevenlabsApplyClick()
|
onElevenlabsApplyClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
elevenlabsApiKey: "",
|
elevenlabsApiKey: '',
|
||||||
elevenlabsVoiceMap: "",
|
elevenlabsVoiceMap: '',
|
||||||
elevenlabsEnabed: false
|
elevenlabsEnabed: false
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
function setElevenLabsStatus(status, success) {
|
function setElevenLabsStatus(status, success) {
|
||||||
$('#elevenlabs_status').text(status)
|
$('#elevenlabs_status').text(status)
|
||||||
if (success) {
|
if (success) {
|
||||||
$("#elevenlabs_status").removeAttr("style");
|
$('#elevenlabs_status').removeAttr('style')
|
||||||
} else {
|
} else {
|
||||||
$('#elevenlabs_status').css('color', 'red');
|
$('#elevenlabs_status').css('color', 'red')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateApiKey() {
|
async function updateApiKey() {
|
||||||
const context = getContext();
|
const context = getContext()
|
||||||
const value = $('#elevenlabs_api_key').val();
|
const value = $('#elevenlabs_api_key').val()
|
||||||
|
|
||||||
// Using this call to validate API key
|
// Using this call to validate API key
|
||||||
API_KEY = String(value)
|
ttsProvider.API_KEY = String(value)
|
||||||
await fetchTtsVoiceIds().catch((error => {
|
await ttsProvider.fetchTtsVoiceIds().catch(error => {
|
||||||
API_KEY = null
|
ttsProvider.API_KEY = null
|
||||||
throw `ElevenLabs TTS API key invalid`
|
throw `ElevenLabs TTS API key invalid`
|
||||||
}))
|
})
|
||||||
|
|
||||||
extension_settings.elevenlabstts.elevenlabsApiKey = String(value);
|
extension_settings.elevenlabstts.elevenlabsApiKey = String(value)
|
||||||
console.debug(`Saved new API_KEY: ${value}`);
|
console.debug(`Saved new API_KEY: ${value}`)
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced()
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseVoiceMap(voiceMapString) {
|
function parseVoiceMap(voiceMapString) {
|
||||||
let parsedVoiceMap = {}
|
let parsedVoiceMap = {}
|
||||||
for (const [charName, voiceId] of voiceMapString.split(",").map(s => s.split(":"))) {
|
for (const [charName, voiceId] of voiceMapString
|
||||||
|
.split(',')
|
||||||
|
.map(s => s.split(':'))) {
|
||||||
if (charName && voiceId) {
|
if (charName && voiceId) {
|
||||||
parsedVoiceMap[charName.trim()] = voiceId.trim();
|
parsedVoiceMap[charName.trim()] = voiceId.trim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parsedVoiceMap
|
return parsedVoiceMap
|
||||||
@ -377,24 +302,26 @@ function parseVoiceMap(voiceMapString) {
|
|||||||
async function getTtsVoice(name) {
|
async function getTtsVoice(name) {
|
||||||
// We're caching the list of voice_ids. This might cause trouble if the user creates a new voice without restarting
|
// We're caching the list of voice_ids. This might cause trouble if the user creates a new voice without restarting
|
||||||
if (elevenlabsTtsVoices.length == 0) {
|
if (elevenlabsTtsVoices.length == 0) {
|
||||||
elevenlabsTtsVoices = await fetchTtsVoiceIds();
|
elevenlabsTtsVoices = await ttsProvider.fetchTtsVoiceIds()
|
||||||
}
|
}
|
||||||
const match = elevenlabsTtsVoices.filter((elevenVoice) => elevenVoice.name == name)[0];
|
const match = elevenlabsTtsVoices.filter(
|
||||||
|
elevenVoice => elevenVoice.name == name
|
||||||
|
)[0]
|
||||||
if (!match) {
|
if (!match) {
|
||||||
throw `TTS Voice name ${name} not found in ElevenLabs account`;
|
throw `TTS Voice name ${name} not found in ElevenLabs account`
|
||||||
}
|
}
|
||||||
return match;
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
async function voicemapIsValid(parsedVoiceMap) {
|
async function voicemapIsValid(parsedVoiceMap) {
|
||||||
let valid = true
|
let valid = true
|
||||||
for (const characterName in parsedVoiceMap) {
|
for (const characterName in parsedVoiceMap) {
|
||||||
const parsedVoiceName = parsedVoiceMap[characterName];
|
const parsedVoiceName = parsedVoiceMap[characterName]
|
||||||
try {
|
try {
|
||||||
await getTtsVoice(parsedVoiceName);
|
await getTtsVoice(parsedVoiceName)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
valid = false;
|
valid = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid
|
return valid
|
||||||
@ -402,19 +329,19 @@ async function voicemapIsValid(parsedVoiceMap) {
|
|||||||
|
|
||||||
async function updateVoiceMap() {
|
async function updateVoiceMap() {
|
||||||
let isValidResult = false
|
let isValidResult = false
|
||||||
const context = getContext();
|
const context = getContext()
|
||||||
// console.debug("onElevenlabsVoiceMapSubmit");
|
// console.debug("onElevenlabsVoiceMapSubmit");
|
||||||
const value = $('#elevenlabs_voice_map').val();
|
const value = $('#elevenlabs_voice_map').val()
|
||||||
const parsedVoiceMap = parseVoiceMap(value);
|
const parsedVoiceMap = parseVoiceMap(value)
|
||||||
isValidResult = await voicemapIsValid(parsedVoiceMap);
|
isValidResult = await voicemapIsValid(parsedVoiceMap)
|
||||||
if (isValidResult) {
|
if (isValidResult) {
|
||||||
extension_settings.elevenlabstts.elevenlabsVoiceMap = String(value);
|
extension_settings.elevenlabstts.elevenlabsVoiceMap = String(value)
|
||||||
context.elevenlabsVoiceMap = String(value)
|
context.elevenlabsVoiceMap = String(value)
|
||||||
voiceMap = parsedVoiceMap
|
voiceMap = parsedVoiceMap
|
||||||
console.debug(`Saved new voiceMap: ${value}`)
|
console.debug(`Saved new voiceMap: ${value}`)
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced()
|
||||||
} else {
|
} else {
|
||||||
throw "Voice map is invalid, check console for errors"
|
throw 'Voice map is invalid, check console for errors'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,23 +349,27 @@ function onElevenlabsApplyClick() {
|
|||||||
Promise.all([updateApiKey(), updateVoiceMap()])
|
Promise.all([updateApiKey(), updateVoiceMap()])
|
||||||
.then(([result1, result2]) => {
|
.then(([result1, result2]) => {
|
||||||
updateUiAudioPlayState()
|
updateUiAudioPlayState()
|
||||||
setElevenLabsStatus("Successfully applied settings", true)
|
setElevenLabsStatus('Successfully applied settings', true)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(error => {
|
||||||
setElevenLabsStatus(error, false)
|
setElevenLabsStatus(error, false)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onElevenlabsEnableClick() {
|
function onElevenlabsEnableClick() {
|
||||||
extension_settings.elevenlabstts.enabled = $("#elevenlabs_enabled").is(':checked');
|
extension_settings.elevenlabstts.enabled = $('#elevenlabs_enabled').is(
|
||||||
|
':checked'
|
||||||
|
)
|
||||||
updateUiAudioPlayState()
|
updateUiAudioPlayState()
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced()
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUiAudioPlayState() {
|
function updateUiAudioPlayState() {
|
||||||
if (extension_settings.elevenlabstts.enabled == true) {
|
if (extension_settings.elevenlabstts.enabled == true) {
|
||||||
audioControl.style.display = 'flex'
|
audioControl.style.display = 'flex'
|
||||||
const img = !audioElement.paused ? "fa-solid fa-circle-pause" : "fa-solid fa-circle-play"
|
const img = !audioElement.paused
|
||||||
|
? 'fa-solid fa-circle-pause'
|
||||||
|
: 'fa-solid fa-circle-play'
|
||||||
audioControl.className = img
|
audioControl.className = img
|
||||||
} else {
|
} else {
|
||||||
audioControl.style.display = 'none'
|
audioControl.style.display = 'none'
|
||||||
@ -452,9 +383,9 @@ function onAudioControlClicked() {
|
|||||||
|
|
||||||
function addAudioControl() {
|
function addAudioControl() {
|
||||||
$('#send_but_sheld').prepend('<div id="tts_media_control"/>')
|
$('#send_but_sheld').prepend('<div id="tts_media_control"/>')
|
||||||
$('#tts_media_control').on('click', onAudioControlClicked)
|
$('#send_but_sheld').on('click', onAudioControlClicked)
|
||||||
audioControl = document.getElementById('tts_media_control');
|
audioControl = document.getElementById('tts_media_control')
|
||||||
updateUiAudioPlayState();
|
updateUiAudioPlayState()
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
@ -487,14 +418,14 @@ $(document).ready(function () {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`
|
||||||
$('#extensions_settings').append(settingsHtml);
|
$('#extensions_settings').append(settingsHtml)
|
||||||
$('#elevenlabs_apply').on('click', onElevenlabsApplyClick);
|
$('#elevenlabs_apply').on('click', onElevenlabsApplyClick)
|
||||||
$('#elevenlabs_enabled').on('click', onElevenlabsEnableClick);
|
$('#elevenlabs_enabled').on('click', onElevenlabsEnableClick)
|
||||||
$('#elevenlabs_voices').on('click', onElevenlabsVoicesClick);
|
$('#elevenlabs_voices').on('click', onElevenlabsVoicesClick)
|
||||||
}
|
}
|
||||||
addAudioControl();
|
addAudioControl()
|
||||||
addExtensionControls();
|
addExtensionControls()
|
||||||
loadSettings();
|
loadSettings()
|
||||||
setInterval(moduleWorker, UPDATE_INTERVAL);
|
setInterval(moduleWorker, UPDATE_INTERVAL)
|
||||||
});
|
})
|
||||||
|
@ -266,7 +266,6 @@ async function getSpritesList(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getExpressionsList() {
|
async function getExpressionsList() {
|
||||||
console.log('getting expressions list');
|
|
||||||
// get something for offline mode (default images)
|
// get something for offline mode (default images)
|
||||||
if (!modules.includes('classify')) {
|
if (!modules.includes('classify')) {
|
||||||
return DEFAULT_EXPRESSIONS;
|
return DEFAULT_EXPRESSIONS;
|
||||||
|
@ -214,7 +214,9 @@ function printGroups() {
|
|||||||
const template = $("#group_list_template .group_select").clone();
|
const template = $("#group_list_template .group_select").clone();
|
||||||
template.data("id", group.id);
|
template.data("id", group.id);
|
||||||
template.attr("grid", group.id);
|
template.attr("grid", group.id);
|
||||||
template.find(".ch_name").text(group.name);
|
template.find(".ch_name").html(group.name);
|
||||||
|
group.fav ? template.find(".group_fav_icon").show() : template.find(".group_fav_icon").hide();
|
||||||
|
template.find(".ch_fav").val(group.fav);
|
||||||
$("#rm_print_characters_block").prepend(template);
|
$("#rm_print_characters_block").prepend(template);
|
||||||
updateGroupAvatar(group);
|
updateGroupAvatar(group);
|
||||||
}
|
}
|
||||||
@ -695,7 +697,6 @@ async function reorderGroupMember(chat_id, groupMember, direction) {
|
|||||||
function select_group_chats(chat_id, skipAnimation) {
|
function select_group_chats(chat_id, skipAnimation) {
|
||||||
const group = chat_id && groups.find((x) => x.id == chat_id);
|
const group = chat_id && groups.find((x) => x.id == chat_id);
|
||||||
const groupName = group?.name ?? "";
|
const groupName = group?.name ?? "";
|
||||||
|
|
||||||
$("#rm_group_chat_name").val(groupName);
|
$("#rm_group_chat_name").val(groupName);
|
||||||
$("#rm_group_chat_name").off();
|
$("#rm_group_chat_name").off();
|
||||||
$("#rm_group_chat_name").on("input", async function () {
|
$("#rm_group_chat_name").on("input", async function () {
|
||||||
@ -753,6 +754,7 @@ function select_group_chats(chat_id, skipAnimation) {
|
|||||||
const groupHasMembers = !!$("#rm_group_members").children().length;
|
const groupHasMembers = !!$("#rm_group_members").children().length;
|
||||||
$("#rm_group_submit").prop("disabled", !groupHasMembers);
|
$("#rm_group_submit").prop("disabled", !groupHasMembers);
|
||||||
$("#rm_group_allow_self_responses").prop("checked", group && group.allow_self_responses);
|
$("#rm_group_allow_self_responses").prop("checked", group && group.allow_self_responses);
|
||||||
|
$("#rm_group_fav").prop("checked", group && group.fav);
|
||||||
|
|
||||||
// bottom buttons
|
// bottom buttons
|
||||||
if (chat_id) {
|
if (chat_id) {
|
||||||
@ -774,11 +776,22 @@ function select_group_chats(chat_id, skipAnimation) {
|
|||||||
callPopup("<h3>Delete the group?</h3>", "del_group");
|
callPopup("<h3>Delete the group?</h3>", "del_group");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#rm_group_fav").off();
|
||||||
|
$("#rm_group_fav").on("input", async function(){
|
||||||
|
if (group) {
|
||||||
|
let _thisGroup = groups.find((x) => x.id == chat_id);
|
||||||
|
const value = $(this).prop("checked");
|
||||||
|
_thisGroup.fav = value;
|
||||||
|
await editGroup(chat_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#rm_group_allow_self_responses").off();
|
$("#rm_group_allow_self_responses").off();
|
||||||
$("#rm_group_allow_self_responses").on("input", async function () {
|
$("#rm_group_allow_self_responses").on("input", async function () {
|
||||||
if (group) {
|
if (group) {
|
||||||
|
let _thisGroup = groups.find((x) => x.id == chat_id);
|
||||||
const value = $(this).prop("checked");
|
const value = $(this).prop("checked");
|
||||||
group.allow_self_responses = value;
|
_thisGroup.allow_self_responses = value;
|
||||||
await editGroup(chat_id);
|
await editGroup(chat_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -829,6 +842,9 @@ $(document).ready(() => {
|
|||||||
updateChatMetadata({}, true);
|
updateChatMetadata({}, true);
|
||||||
chat.length = 0;
|
chat.length = 0;
|
||||||
await getGroupChat(id);
|
await getGroupChat(id);
|
||||||
|
//to avoid the filter being lit up yellow and left at true while the list of character and group reseted.
|
||||||
|
$("#filter_by_fav").removeClass("fav_on");
|
||||||
|
filterByFav = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
select_group_chats(id);
|
select_group_chats(id);
|
||||||
@ -852,6 +868,7 @@ $(document).ready(() => {
|
|||||||
$("#rm_group_submit").click(async function () {
|
$("#rm_group_submit").click(async function () {
|
||||||
let name = $("#rm_group_chat_name").val();
|
let name = $("#rm_group_chat_name").val();
|
||||||
let allow_self_responses = !!$("#rm_group_allow_self_responses").prop("checked");
|
let allow_self_responses = !!$("#rm_group_allow_self_responses").prop("checked");
|
||||||
|
let fav = $("#rm_group_fav").prop("checked");
|
||||||
let activation_strategy = $('input[name="rm_group_activation_strategy"]:checked').val() ?? group_activation_strategy.NATURAL;
|
let activation_strategy = $('input[name="rm_group_activation_strategy"]:checked').val() ?? group_activation_strategy.NATURAL;
|
||||||
const members = $("#rm_group_members .group_member")
|
const members = $("#rm_group_members .group_member")
|
||||||
.map((_, x) => $(x).data("id"))
|
.map((_, x) => $(x).data("id"))
|
||||||
@ -877,6 +894,7 @@ $(document).ready(() => {
|
|||||||
allow_self_responses: allow_self_responses,
|
allow_self_responses: allow_self_responses,
|
||||||
activation_strategy: activation_strategy,
|
activation_strategy: activation_strategy,
|
||||||
chat_metadata: {},
|
chat_metadata: {},
|
||||||
|
fav: fav,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -909,6 +909,9 @@ select option:not(:checked) {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fav_on {
|
||||||
|
color: #ffff00 !important;
|
||||||
|
}
|
||||||
|
|
||||||
#api_url_text,
|
#api_url_text,
|
||||||
#textgenerationwebui_api_url_text {
|
#textgenerationwebui_api_url_text {
|
||||||
@ -1138,6 +1141,17 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
|||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fav_chara_wrap{
|
||||||
|
display: flex;
|
||||||
|
margin: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fav_chara {
|
||||||
|
border: none;
|
||||||
|
font-size: var(--mainFontSize);
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
#description_div {
|
#description_div {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -2444,6 +2458,9 @@ h5 {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: calc(100% - 110px);
|
width: calc(100% - 110px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rules for icon display */
|
/* Rules for icon display */
|
||||||
@ -2484,12 +2501,15 @@ h5 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.group_select .ch_name {
|
.group_select .ch_name {
|
||||||
flex-grow: 1;
|
|
||||||
max-width: calc(100% - 100px);
|
max-width: calc(100% - 100px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group_select .group_fav_icon{
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
#typing_indicator_template {
|
#typing_indicator_template {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
154
server.js
154
server.js
@ -1,3 +1,27 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const process = require('process')
|
||||||
|
const yargs = require('yargs/yargs');
|
||||||
|
const { hideBin } = require('yargs/helpers');
|
||||||
|
|
||||||
|
const cliArguments = yargs(hideBin(process.argv))
|
||||||
|
.option('ssl', {
|
||||||
|
type: 'boolean',
|
||||||
|
default: 'false',
|
||||||
|
describe: 'Enables SSL'
|
||||||
|
}).option('certPath', {
|
||||||
|
type: 'string',
|
||||||
|
default: 'certs/cert.pem',
|
||||||
|
describe: 'Path to your certificate file.'
|
||||||
|
}).option('keyPath', {
|
||||||
|
type: 'string',
|
||||||
|
default: 'certs/privkey.pem',
|
||||||
|
describe: 'Path to your private key file.'
|
||||||
|
}).argv;
|
||||||
|
|
||||||
|
// change all relative paths
|
||||||
|
process.chdir(__dirname)
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const compression = require('compression');
|
const compression = require('compression');
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -9,6 +33,7 @@ const open = require('open');
|
|||||||
|
|
||||||
const rimraf = require("rimraf");
|
const rimraf = require("rimraf");
|
||||||
const multer = require("multer");
|
const multer = require("multer");
|
||||||
|
const http = require("http");
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
//const PNG = require('pngjs').PNG;
|
//const PNG = require('pngjs').PNG;
|
||||||
const extract = require('png-chunks-extract');
|
const extract = require('png-chunks-extract');
|
||||||
@ -29,10 +54,10 @@ const ExifReader = require('exifreader');
|
|||||||
const exif = require('piexifjs');
|
const exif = require('piexifjs');
|
||||||
const webp = require('webp-converter');
|
const webp = require('webp-converter');
|
||||||
|
|
||||||
const config = require(path.join(process.cwd(), './config.conf'));
|
const config = require(path.join(__dirname, './config.conf'));
|
||||||
const server_port = process.env.SILLY_TAVERN_PORT || config.port;
|
const server_port = process.env.SILLY_TAVERN_PORT || config.port;
|
||||||
|
|
||||||
const whitelistPath = path.join(process.cwd(), "./whitelist.txt");
|
const whitelistPath = path.join(__dirname, "./whitelist.txt");
|
||||||
let whitelist = config.whitelist;
|
let whitelist = config.whitelist;
|
||||||
|
|
||||||
if (fs.existsSync(whitelistPath)) {
|
if (fs.existsSync(whitelistPath)) {
|
||||||
@ -43,7 +68,7 @@ if (fs.existsSync(whitelistPath)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const whitelistMode = config.whitelistMode;
|
const whitelistMode = config.whitelistMode;
|
||||||
const autorun = config.autorun;
|
const autorun = config.autorun && !cliArguments.ssl;
|
||||||
const enableExtensions = config.enableExtensions;
|
const enableExtensions = config.enableExtensions;
|
||||||
const listen = config.listen;
|
const listen = config.listen;
|
||||||
|
|
||||||
@ -183,8 +208,8 @@ app.use(function (req, res, next) { //Security
|
|||||||
|
|
||||||
//clientIp = req.connection.remoteAddress.split(':').pop();
|
//clientIp = req.connection.remoteAddress.split(':').pop();
|
||||||
if (whitelistMode === true && !whitelist.includes(clientIp)) {
|
if (whitelistMode === true && !whitelist.includes(clientIp)) {
|
||||||
console.log('Forbidden: Connection attempt from ' + clientIp + '. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of TavernAI folder.\n');
|
console.log('Forbidden: Connection attempt from ' + clientIp + '. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of SillyTavern folder.\n');
|
||||||
return res.status(403).send('<b>Forbidden</b>: Connection attempt from <b>' + clientIp + '</b>. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of TavernAI folder.');
|
return res.status(403).send('<b>Forbidden</b>: Connection attempt from <b>' + clientIp + '</b>. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of SillyTavern folder.');
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
@ -211,7 +236,7 @@ app.use((req, res, next) => {
|
|||||||
app.use(express.static(__dirname + "/public", { refresh: true }));
|
app.use(express.static(__dirname + "/public", { refresh: true }));
|
||||||
|
|
||||||
app.use('/backgrounds', (req, res) => {
|
app.use('/backgrounds', (req, res) => {
|
||||||
const filePath = decodeURIComponent(path.join(process.cwd(), 'public/backgrounds', req.url.replace(/%20/g, ' ')));
|
const filePath = decodeURIComponent(path.join(__dirname, 'public/backgrounds', req.url.replace(/%20/g, ' ')));
|
||||||
fs.readFile(filePath, (err, data) => {
|
fs.readFile(filePath, (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(404).send('File not found');
|
res.status(404).send('File not found');
|
||||||
@ -223,7 +248,7 @@ app.use('/backgrounds', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.use('/characters', (req, res) => {
|
app.use('/characters', (req, res) => {
|
||||||
const filePath = decodeURIComponent(path.join(process.cwd(), charactersPath, req.url.replace(/%20/g, ' ')));
|
const filePath = decodeURIComponent(path.join(__dirname, charactersPath, req.url.replace(/%20/g, ' ')));
|
||||||
fs.readFile(filePath, (err, data) => {
|
fs.readFile(filePath, (err, data) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.status(404).send('File not found');
|
res.status(404).send('File not found');
|
||||||
@ -368,7 +393,7 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
if (!!request.header('X-Response-Streaming')) {
|
if (!!request.header('X-Response-Streaming')) {
|
||||||
const fn_index = Number(request.header('X-Gradio-Streaming-Function'));
|
const fn_index = Number(request.header('X-Gradio-Streaming-Function'));
|
||||||
let isStreamingStopped = false;
|
let isStreamingStopped = false;
|
||||||
request.socket.on('close', function() {
|
request.socket.on('close', function () {
|
||||||
isStreamingStopped = true;
|
isStreamingStopped = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -675,7 +700,7 @@ function checkServer() {
|
|||||||
|
|
||||||
//***************** Main functions
|
//***************** Main functions
|
||||||
function charaFormatData(data) {
|
function charaFormatData(data) {
|
||||||
var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness };
|
var char = { "name": data.ch_name, "description": data.description, "personality": data.personality, "first_mes": data.first_mes, "avatar": 'none', "chat": data.ch_name + ' - ' + humanizedISO8601DateTime(), "mes_example": data.mes_example, "scenario": data.scenario, "create_date": humanizedISO8601DateTime(), "talkativeness": data.talkativeness, "fav": data.fav};
|
||||||
return char;
|
return char;
|
||||||
}
|
}
|
||||||
app.post("/createcharacter", urlencodedParser, function (request, response) {
|
app.post("/createcharacter", urlencodedParser, function (request, response) {
|
||||||
@ -729,10 +754,8 @@ app.post("/editcharacter", urlencodedParser, async function (request, response)
|
|||||||
var char = charaFormatData(request.body);//{"name": request.body.ch_name, "description": request.body.description, "personality": request.body.personality, "first_mes": request.body.first_mes, "avatar": request.body.avatar_url, "chat": request.body.chat, "last_mes": request.body.last_mes, "mes_example": ''};
|
var char = charaFormatData(request.body);//{"name": request.body.ch_name, "description": request.body.description, "personality": request.body.personality, "first_mes": request.body.first_mes, "avatar": request.body.avatar_url, "chat": request.body.chat, "last_mes": request.body.last_mes, "mes_example": ''};
|
||||||
char.chat = request.body.chat;
|
char.chat = request.body.chat;
|
||||||
char.create_date = request.body.create_date;
|
char.create_date = request.body.create_date;
|
||||||
|
|
||||||
char = JSON.stringify(char);
|
char = JSON.stringify(char);
|
||||||
let target_img = (request.body.avatar_url).replace('.png', '');
|
let target_img = (request.body.avatar_url).replace('.png', '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!filedata) {
|
if (!filedata) {
|
||||||
|
|
||||||
@ -1598,18 +1621,18 @@ app.post("/importchat", urlencodedParser, function (request, response) {
|
|||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
||||||
newChats.forEach(chat => fs.writeFile(
|
newChats.forEach(chat => fs.writeFile(
|
||||||
chatsPath + avatar_url + '/' + ch_name + ' - ' + humanizedISO8601DateTime() + ' imported.jsonl',
|
chatsPath + avatar_url + '/' + ch_name + ' - ' + humanizedISO8601DateTime() + ' imported.jsonl',
|
||||||
chat.map(JSON.stringify).join('\n'),
|
chat.map(JSON.stringify).join('\n'),
|
||||||
'utf8',
|
'utf8',
|
||||||
(err) => err ?? errors.push(err)
|
(err) => err ?? errors.push(err)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (0 < errors.length) {
|
if (0 < errors.length) {
|
||||||
response.send('Errors occurred while writing character files. Errors: ' + JSON.stringify(errors));
|
response.send('Errors occurred while writing character files. Errors: ' + JSON.stringify(errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
response.send({res: true});
|
response.send({ res: true });
|
||||||
} else {
|
} else {
|
||||||
response.send({ error: true });
|
response.send({ error: true });
|
||||||
}
|
}
|
||||||
@ -1755,6 +1778,7 @@ app.post('/creategroup', jsonParser, (request, response) => {
|
|||||||
allow_self_responses: !!request.body.allow_self_responses,
|
allow_self_responses: !!request.body.allow_self_responses,
|
||||||
activation_strategy: request.body.activation_strategy ?? 0,
|
activation_strategy: request.body.activation_strategy ?? 0,
|
||||||
chat_metadata: request.body.chat_metadata ?? {},
|
chat_metadata: request.body.chat_metadata ?? {},
|
||||||
|
fav: request.body.fav,
|
||||||
};
|
};
|
||||||
const pathToFile = path.join(directories.groups, `${id}.json`);
|
const pathToFile = path.join(directories.groups, `${id}.json`);
|
||||||
const fileData = JSON.stringify(chatMetadata);
|
const fileData = JSON.stringify(chatMetadata);
|
||||||
@ -1771,7 +1795,6 @@ app.post('/editgroup', jsonParser, (request, response) => {
|
|||||||
if (!request.body || !request.body.id) {
|
if (!request.body || !request.body.id) {
|
||||||
return response.sendStatus(400);
|
return response.sendStatus(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = request.body.id;
|
const id = request.body.id;
|
||||||
const pathToFile = path.join(directories.groups, `${id}.json`);
|
const pathToFile = path.join(directories.groups, `${id}.json`);
|
||||||
const fileData = JSON.stringify(request.body);
|
const fileData = JSON.stringify(request.body);
|
||||||
@ -1840,7 +1863,7 @@ app.post('/deletegroup', jsonParser, async (request, response) => {
|
|||||||
|
|
||||||
const POE_DEFAULT_BOT = 'a2';
|
const POE_DEFAULT_BOT = 'a2';
|
||||||
|
|
||||||
async function getPoeClient(token, useCache=false) {
|
async function getPoeClient(token, useCache = false) {
|
||||||
let client = new poe.Client(false, useCache);
|
let client = new poe.Client(false, useCache);
|
||||||
await client.init(token);
|
await client.init(token);
|
||||||
return client;
|
return client;
|
||||||
@ -1906,7 +1929,7 @@ app.post('/generate_poe', jsonParser, async (request, response) => {
|
|||||||
|
|
||||||
if (streaming) {
|
if (streaming) {
|
||||||
let isStreamingStopped = false;
|
let isStreamingStopped = false;
|
||||||
request.socket.on('close', function() {
|
request.socket.on('close', function () {
|
||||||
isStreamingStopped = true;
|
isStreamingStopped = true;
|
||||||
client.abortController.abort();
|
client.abortController.abort();
|
||||||
});
|
});
|
||||||
@ -1972,17 +1995,17 @@ app.get('/get_sprites', jsonParser, function (request, response) {
|
|||||||
try {
|
try {
|
||||||
if (fs.existsSync(spritesPath) && fs.statSync(spritesPath).isDirectory()) {
|
if (fs.existsSync(spritesPath) && fs.statSync(spritesPath).isDirectory()) {
|
||||||
sprites = fs.readdirSync(spritesPath)
|
sprites = fs.readdirSync(spritesPath)
|
||||||
.filter(file => {
|
.filter(file => {
|
||||||
const mimeType = mime.lookup(file);
|
const mimeType = mime.lookup(file);
|
||||||
return mimeType && mimeType.startsWith('image/');
|
return mimeType && mimeType.startsWith('image/');
|
||||||
})
|
})
|
||||||
.map((file) => {
|
.map((file) => {
|
||||||
const pathToSprite = path.join(spritesPath, file);
|
const pathToSprite = path.join(spritesPath, file);
|
||||||
return {
|
return {
|
||||||
label: path.parse(pathToSprite).name.toLowerCase(),
|
label: path.parse(pathToSprite).name.toLowerCase(),
|
||||||
path: `/characters/${name}/${file}`,
|
path: `/characters/${name}/${file}`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
@ -2152,12 +2175,42 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Shamelessly stolen from Agnai
|
||||||
|
app.post("/openai_usage", jsonParser, async function (_, response) {
|
||||||
|
if (!request.body) return response.sendStatus(400);
|
||||||
|
const key = request.body.key;
|
||||||
|
const api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${key}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setDate(1);
|
||||||
|
const start_date = date.toISOString().slice(0, 10);
|
||||||
|
|
||||||
|
date.setMonth(date.getMonth() + 1);
|
||||||
|
const end_date = date.toISOString().slice(0, 10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getAsync(
|
||||||
|
`${api_url}/dashboard/billing/usage?start_date=${start_date}&end_date=${end_date}`,
|
||||||
|
{ headers },
|
||||||
|
);
|
||||||
|
return response.send(res);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.post("/generate_openai", jsonParser, function (request, response_generate_openai) {
|
app.post("/generate_openai", jsonParser, function (request, response_generate_openai) {
|
||||||
if (!request.body) return response_generate_openai.sendStatus(400);
|
if (!request.body) return response_generate_openai.sendStatus(400);
|
||||||
const api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
const api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
request.socket.on('close', function() {
|
request.socket.on('close', function () {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2319,23 +2372,46 @@ function getAsync(url, args) {
|
|||||||
}
|
}
|
||||||
// ** END **
|
// ** END **
|
||||||
|
|
||||||
app.listen(server_port, (listen ? '0.0.0.0' : '127.0.0.1'), async function () {
|
const tavernUrl = new URL(
|
||||||
|
(cliArguments.ssl ? 'https://' : 'http://') +
|
||||||
|
(listen ? '0.0.0.0' : '127.0.0.1') +
|
||||||
|
(':' + server_port)
|
||||||
|
);
|
||||||
|
|
||||||
|
const setupTasks = async function () {
|
||||||
ensurePublicDirectoriesExist();
|
ensurePublicDirectoriesExist();
|
||||||
await ensureThumbnailCache();
|
await ensureThumbnailCache();
|
||||||
|
|
||||||
// Colab users could run the embedded tool
|
// Colab users could run the embedded tool
|
||||||
if (!is_colab) {
|
if (!is_colab) await convertWebp();
|
||||||
await convertWebp();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Launching...');
|
console.log('Launching...');
|
||||||
if (autorun) open('http://127.0.0.1:' + server_port);
|
|
||||||
console.log('TavernAI started: http://127.0.0.1:' + server_port);
|
if (autorun) open(tavernUrl);
|
||||||
|
console.log('SillyTavern started: ' + tavernUrl);
|
||||||
|
|
||||||
if (fs.existsSync('public/characters/update.txt') && !is_colab) {
|
if (fs.existsSync('public/characters/update.txt') && !is_colab) {
|
||||||
convertStage1();
|
convertStage1();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
if (true === cliArguments.ssl)
|
||||||
|
https.createServer(
|
||||||
|
{
|
||||||
|
cert: fs.readFileSync(cliArguments.certPath),
|
||||||
|
key: fs.readFileSync(cliArguments.keyPath)
|
||||||
|
}, app)
|
||||||
|
.listen(
|
||||||
|
tavernUrl.port,
|
||||||
|
tavernUrl.hostname,
|
||||||
|
setupTasks
|
||||||
|
);
|
||||||
|
else
|
||||||
|
http.createServer(app).listen(
|
||||||
|
tavernUrl.port,
|
||||||
|
tavernUrl.hostname,
|
||||||
|
setupTasks
|
||||||
|
);
|
||||||
|
|
||||||
//#####################CONVERTING IN NEW FORMAT########################
|
//#####################CONVERTING IN NEW FORMAT########################
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user